OpcUaCanOpen
CANopen OPC-UA server
exprtk.hpp
Go to the documentation of this file.
1 /*
2  ******************************************************************
3  * C++ Mathematical Expression Toolkit Library *
4  * *
5  * Author: Arash Partow (1999-2019) *
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 
93  inline bool is_whitespace(const char_t c)
94  {
95  return (' ' == c) || ('\n' == c) ||
96  ('\r' == c) || ('\t' == c) ||
97  ('\b' == c) || ('\v' == c) ||
98  ('\f' == c) ;
99  }
100 
101  inline bool is_operator_char(const char_t c)
102  {
103  return ('+' == c) || ('-' == c) ||
104  ('*' == c) || ('/' == c) ||
105  ('^' == 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  }
115 
116  inline bool is_letter(const char_t c)
117  {
118  return (('a' <= c) && (c <= 'z')) ||
119  (('A' <= c) && (c <= 'Z')) ;
120  }
121 
122  inline bool is_digit(const char_t c)
123  {
124  return ('0' <= c) && (c <= '9');
125  }
126 
127  inline bool is_letter_or_digit(const char_t c)
128  {
129  return is_letter(c) || is_digit(c);
130  }
131 
132  inline bool is_left_bracket(const char_t c)
133  {
134  return ('(' == c) || ('[' == c) || ('{' == c);
135  }
136 
137  inline bool is_right_bracket(const char_t c)
138  {
139  return (')' == c) || (']' == c) || ('}' == c);
140  }
141 
142  inline bool is_bracket(const char_t c)
143  {
144  return is_left_bracket(c) || is_right_bracket(c);
145  }
146 
147  inline bool is_sign(const char_t c)
148  {
149  return ('+' == c) || ('-' == c);
150  }
151 
152  inline bool is_invalid(const char_t c)
153  {
154  return !is_whitespace (c) &&
155  !is_operator_char(c) &&
156  !is_letter (c) &&
157  !is_digit (c) &&
158  ('.' != c) &&
159  ('_' != c) &&
160  ('$' != c) &&
161  ('~' != c) &&
162  ('\'' != c);
163  }
164 
165  #ifndef exprtk_disable_caseinsensitivity
166  inline void case_normalise(std::string& s)
167  {
168  for (std::size_t i = 0; i < s.size(); ++i)
169  {
170  s[i] = static_cast<std::string::value_type>(std::tolower(s[i]));
171  }
172  }
173 
174  inline bool imatch(const char_t c1, const char_t c2)
175  {
176  return std::tolower(c1) == std::tolower(c2);
177  }
178 
179  inline bool imatch(const std::string& s1, const std::string& s2)
180  {
181  if (s1.size() == s2.size())
182  {
183  for (std::size_t i = 0; i < s1.size(); ++i)
184  {
185  if (std::tolower(s1[i]) != std::tolower(s2[i]))
186  {
187  return false;
188  }
189  }
190 
191  return true;
192  }
193 
194  return false;
195  }
196 
198  {
199  inline bool operator() (const std::string& s1, const std::string& s2) const
200  {
201  const std::size_t length = std::min(s1.size(),s2.size());
202 
203  for (std::size_t i = 0; i < length; ++i)
204  {
205  const char_t c1 = static_cast<char>(std::tolower(s1[i]));
206  const char_t c2 = static_cast<char>(std::tolower(s2[i]));
207 
208  if (c1 > c2)
209  return false;
210  else if (c1 < c2)
211  return true;
212  }
213 
214  return s1.size() < s2.size();
215  }
216  };
217 
218  #else
219  inline void case_normalise(std::string&)
220  {}
221 
222  inline bool imatch(const char_t c1, const char_t c2)
223  {
224  return c1 == c2;
225  }
226 
227  inline bool imatch(const std::string& s1, const std::string& s2)
228  {
229  return s1 == s2;
230  }
231 
232  struct ilesscompare
233  {
234  inline bool operator() (const std::string& s1, const std::string& s2) const
235  {
236  return s1 < s2;
237  }
238  };
239  #endif
240 
241  inline bool is_valid_sf_symbol(const std::string& symbol)
242  {
243  // Special function: $f12 or $F34
244  return (4 == symbol.size()) &&
245  ('$' == symbol[0]) &&
246  imatch('f',symbol[1]) &&
247  is_digit(symbol[2]) &&
248  is_digit(symbol[3]);
249  }
250 
251  inline const char_t& front(const std::string& s)
252  {
253  return s[0];
254  }
255 
256  inline const char_t& back(const std::string& s)
257  {
258  return s[s.size() - 1];
259  }
260 
261  inline std::string to_str(int i)
262  {
263  if (0 == i)
264  return std::string("0");
265 
266  std::string result;
267 
268  if (i < 0)
269  {
270  for ( ; i; i /= 10)
271  {
272  result += '0' + char(-(i % 10));
273  }
274 
275  result += '-';
276  }
277  else
278  {
279  for ( ; i; i /= 10)
280  {
281  result += '0' + char(i % 10);
282  }
283  }
284 
285  std::reverse(result.begin(), result.end());
286 
287  return result;
288  }
289 
290  inline std::string to_str(std::size_t i)
291  {
292  return to_str(static_cast<int>(i));
293  }
294 
295  inline bool is_hex_digit(const std::string::value_type digit)
296  {
297  return (('0' <= digit) && (digit <= '9')) ||
298  (('A' <= digit) && (digit <= 'F')) ||
299  (('a' <= digit) && (digit <= 'f')) ;
300  }
301 
303  {
304  if (('0' <= h) && (h <= '9'))
305  return (h - '0');
306  else
307  return static_cast<unsigned char>(std::toupper(h) - 'A');
308  }
309 
310  template <typename Iterator>
311  inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
312  {
313  if (
314  (end != (itr )) &&
315  (end != (itr + 1)) &&
316  (end != (itr + 2)) &&
317  (end != (itr + 3)) &&
318  ('0' == *(itr )) &&
319  (
320  ('x' == *(itr + 1)) ||
321  ('X' == *(itr + 1))
322  ) &&
323  (is_hex_digit(*(itr + 2))) &&
324  (is_hex_digit(*(itr + 3)))
325  )
326  {
327  result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 |
328  hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ;
329  itr += 3;
330  }
331  else
332  result = '\0';
333  }
334 
335  inline void cleanup_escapes(std::string& s)
336  {
337  typedef std::string::iterator str_itr_t;
338 
339  str_itr_t itr1 = s.begin();
340  str_itr_t itr2 = s.begin();
341  str_itr_t end = s.end ();
342 
343  std::size_t removal_count = 0;
344 
345  while (end != itr1)
346  {
347  if ('\\' == (*itr1))
348  {
349  ++removal_count;
350 
351  if (end == ++itr1)
352  break;
353  else if ('\\' != (*itr1))
354  {
355  switch (*itr1)
356  {
357  case 'n' : (*itr1) = '\n'; break;
358  case 'r' : (*itr1) = '\r'; break;
359  case 't' : (*itr1) = '\t'; break;
360  case '0' : parse_hex(itr1, end, (*itr1));
361  removal_count += 3;
362  break;
363  }
364 
365  continue;
366  }
367  }
368 
369  if (itr1 != itr2)
370  {
371  (*itr2) = (*itr1);
372  }
373 
374  ++itr1;
375  ++itr2;
376  }
377 
378  s.resize(s.size() - removal_count);
379  }
380 
382  {
383  public:
384 
385  build_string(const std::size_t& initial_size = 64)
386  {
387  data_.reserve(initial_size);
388  }
389 
391  {
392  data_ += s;
393  return (*this);
394  }
395 
397  {
398  data_ += std::string(s);
399  return (*this);
400  }
401 
402  inline operator std::string () const
403  {
404  return data_;
405  }
406 
407  inline std::string as_string() const
408  {
409  return data_;
410  }
411 
412  private:
413 
415  };
416 
417  static const std::string reserved_words[] =
418  {
419  "break", "case", "continue", "default", "false", "for",
420  "if", "else", "ilike", "in", "like", "and", "nand", "nor",
421  "not", "null", "or", "repeat", "return", "shl", "shr",
422  "swap", "switch", "true", "until", "var", "while", "xnor",
423  "xor", "&", "|"
424  };
425 
426  static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
427 
428  static const std::string reserved_symbols[] =
429  {
430  "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
431  "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
432  "continue", "cos", "cosh", "cot", "csc", "default",
433  "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
434  "expm1", "false", "floor", "for", "frac", "grad2deg",
435  "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
436  "like", "log", "log10", "log2", "logn", "log1p", "mand",
437  "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
438  "not", "not_equal", "null", "or", "pow", "rad2deg",
439  "repeat", "return", "root", "round", "roundn", "sec", "sgn",
440  "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
441  "switch", "tan", "tanh", "true", "trunc", "until", "var",
442  "while", "xnor", "xor", "&", "|"
443  };
444 
445  static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
446 
448  {
449  "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
450  "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
451  "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
452  "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
453  "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
454  "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
455  "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
456  "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
457  "rad2deg", "grad2deg"
458  };
459 
460  static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
461 
462  static const std::string logic_ops_list[] =
463  {
464  "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
465  };
466 
467  static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
468 
470  {
471  "if", "switch", "for", "while", "repeat", "return"
472  };
473 
474  static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
475 
477  {
478  "+", "-", "*", "/", "%", "^"
479  };
480 
481  static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string);
482 
484  {
485  ":=", "+=", "-=",
486  "*=", "/=", "%="
487  };
488 
489  static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string);
490 
492  {
493  "<", "<=", "==",
494  "=", "!=", "<>",
495  ">=", ">"
496  };
497 
498  static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string);
499 
500  inline bool is_reserved_word(const std::string& symbol)
501  {
502  for (std::size_t i = 0; i < reserved_words_size; ++i)
503  {
504  if (imatch(symbol, reserved_words[i]))
505  {
506  return true;
507  }
508  }
509 
510  return false;
511  }
512 
513  inline bool is_reserved_symbol(const std::string& symbol)
514  {
515  for (std::size_t i = 0; i < reserved_symbols_size; ++i)
516  {
517  if (imatch(symbol, reserved_symbols[i]))
518  {
519  return true;
520  }
521  }
522 
523  return false;
524  }
525 
526  inline bool is_base_function(const std::string& function_name)
527  {
528  for (std::size_t i = 0; i < base_function_list_size; ++i)
529  {
530  if (imatch(function_name, base_function_list[i]))
531  {
532  return true;
533  }
534  }
535 
536  return false;
537  }
538 
539  inline bool is_control_struct(const std::string& cntrl_strct)
540  {
541  for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
542  {
543  if (imatch(cntrl_strct, cntrl_struct_list[i]))
544  {
545  return true;
546  }
547  }
548 
549  return false;
550  }
551 
552  inline bool is_logic_opr(const std::string& lgc_opr)
553  {
554  for (std::size_t i = 0; i < logic_ops_list_size; ++i)
555  {
556  if (imatch(lgc_opr, logic_ops_list[i]))
557  {
558  return true;
559  }
560  }
561 
562  return false;
563  }
564 
565  struct cs_match
566  {
567  static inline bool cmp(const char_t c0, const char_t c1)
568  {
569  return (c0 == c1);
570  }
571  };
572 
573  struct cis_match
574  {
575  static inline bool cmp(const char_t c0, const char_t c1)
576  {
577  return (std::tolower(c0) == std::tolower(c1));
578  }
579  };
580 
581  template <typename Iterator, typename Compare>
582  inline bool match_impl(const Iterator pattern_begin,
583  const Iterator pattern_end ,
584  const Iterator data_begin ,
585  const Iterator data_end ,
586  const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
587  const typename std::iterator_traits<Iterator>::value_type& zero_or_one )
588  {
589  const Iterator null_itr(0);
590 
591  Iterator d_itr = data_begin;
592  Iterator p_itr = pattern_begin;
593  Iterator tb_p_itr = null_itr;
594  Iterator tb_d_itr = null_itr;
595 
596  while (d_itr != data_end)
597  {
598  if (zero_or_more == *p_itr)
599  {
600  while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
601  {
602  ++p_itr;
603  }
604 
605  if (pattern_end == p_itr)
606  return true;
607 
608  const typename std::iterator_traits<Iterator>::value_type c = *(p_itr);
609 
610  while ((data_end != d_itr) && !Compare::cmp(c,*d_itr))
611  {
612  ++d_itr;
613  }
614 
615  tb_p_itr = p_itr;
616  tb_d_itr = d_itr;
617 
618  continue;
619  }
620  else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr))
621  {
622  if (null_itr == tb_d_itr)
623  return false;
624 
625  d_itr = tb_d_itr++;
626  p_itr = tb_p_itr;
627 
628  continue;
629  }
630 
631  ++p_itr;
632  ++d_itr;
633  }
634 
635  while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr)))
636  {
637  ++p_itr;
638  }
639 
640  return (pattern_end == p_itr);
641  }
642 
643  inline bool wc_match(const std::string& wild_card,
644  const std::string& str)
645  {
646  return match_impl<char_cptr,cs_match>(wild_card.data(),
647  wild_card.data() + wild_card.size(),
648  str.data(),
649  str.data() + str.size(),
650  '*',
651  '?');
652  }
653 
654  inline bool wc_imatch(const std::string& wild_card,
655  const std::string& str)
656  {
657  return match_impl<char_cptr,cis_match>(wild_card.data(),
658  wild_card.data() + wild_card.size(),
659  str.data(),
660  str.data() + str.size(),
661  '*',
662  '?');
663  }
664 
665  inline bool sequence_match(const std::string& pattern,
666  const std::string& str,
667  std::size_t& diff_index,
668  char_t& diff_value)
669  {
670  if (str.empty())
671  {
672  return ("Z" == pattern);
673  }
674  else if ('*' == pattern[0])
675  return false;
676 
677  typedef std::string::const_iterator itr_t;
678 
679  itr_t p_itr = pattern.begin();
680  itr_t s_itr = str .begin();
681 
682  itr_t p_end = pattern.end();
683  itr_t s_end = str .end();
684 
685  while ((s_end != s_itr) && (p_end != p_itr))
686  {
687  if ('*' == (*p_itr))
688  {
689  const char_t target = static_cast<char>(std::toupper(*(p_itr - 1)));
690 
691  if ('*' == target)
692  {
693  diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
694  diff_value = static_cast<char>(std::toupper(*p_itr));
695 
696  return false;
697  }
698  else
699  ++p_itr;
700 
701  while (s_itr != s_end)
702  {
703  if (target != std::toupper(*s_itr))
704  break;
705  else
706  ++s_itr;
707  }
708 
709  continue;
710  }
711  else if (
712  ('?' != *p_itr) &&
713  std::toupper(*p_itr) != std::toupper(*s_itr)
714  )
715  {
716  diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr));
717  diff_value = static_cast<char>(std::toupper(*p_itr));
718 
719  return false;
720  }
721 
722  ++p_itr;
723  ++s_itr;
724  }
725 
726  return (
727  (s_end == s_itr) &&
728  (
729  (p_end == p_itr) ||
730  ('*' == *p_itr)
731  )
732  );
733  }
734 
735  static const double pow10[] = {
736  1.0,
737  1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
738  1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
739  1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
740  1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
741  };
742 
743  static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
744 
745  namespace numeric
746  {
747  namespace constant
748  {
749  static const double e = 2.71828182845904523536028747135266249775724709369996;
750  static const double pi = 3.14159265358979323846264338327950288419716939937510;
751  static const double pi_2 = 1.57079632679489661923132169163975144209858469968755;
752  static const double pi_4 = 0.78539816339744830961566084581987572104929234984378;
753  static const double pi_180 = 0.01745329251994329576923690768488612713442871888542;
754  static const double _1_pi = 0.31830988618379067153776752674502872406891929148091;
755  static const double _2_pi = 0.63661977236758134307553505349005744813783858296183;
756  static const double _180_pi = 57.29577951308232087679815481410517033240547246656443;
757  static const double log2 = 0.69314718055994530941723212145817656807550013436026;
758  static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695;
759  }
760 
761  namespace details
762  {
764  struct real_type_tag { real_type_tag () {} };
766  struct int_type_tag { int_type_tag () {} };
767 
768  template <typename T>
769  struct number_type
770  {
773  };
774 
775  #define exprtk_register_real_type_tag(T) \
776  template<> struct number_type<T> \
777  { typedef real_type_tag type; number_type() {} }; \
778 
779  #define exprtk_register_complex_type_tag(T) \
780  template<> struct number_type<std::complex<T> > \
781  { typedef complex_type_tag type; number_type() {} }; \
782 
783  #define exprtk_register_int_type_tag(T) \
784  template<> struct number_type<T> \
785  { typedef int_type_tag type; number_type() {} }; \
786 
788  exprtk_register_real_type_tag(long double)
790 
794 
797  exprtk_register_int_type_tag(long long int )
798  exprtk_register_int_type_tag(unsigned short )
799  exprtk_register_int_type_tag(unsigned int )
800  exprtk_register_int_type_tag(unsigned long long int)
801 
802  #undef exprtk_register_real_type_tag
803  #undef exprtk_register_int_type_tag
804 
805  template <typename T>
806  struct epsilon_type
807  {
808  static inline T value()
809  {
810  const T epsilon = T(0.0000000001);
811  return epsilon;
812  }
813  };
814 
815  template <>
816  struct epsilon_type <float>
817  {
818  static inline float value()
819  {
820  const float epsilon = float(0.000001f);
821  return epsilon;
822  }
823  };
824 
825  template <>
826  struct epsilon_type <long double>
827  {
828  static inline long double value()
829  {
830  const long double epsilon = (long double)(0.000000000001);
831  return epsilon;
832  }
833  };
834 
835  template <typename T>
836  inline bool is_nan_impl(const T v, real_type_tag)
837  {
838  return std::not_equal_to<T>()(v,v);
839  }
840 
841  template <typename T>
842  inline int to_int32_impl(const T v, real_type_tag)
843  {
844  return static_cast<int>(v);
845  }
846 
847  template <typename T>
848  inline long long int to_int64_impl(const T v, real_type_tag)
849  {
850  return static_cast<long long int>(v);
851  }
852 
853  template <typename T>
854  inline bool is_true_impl(const T v)
855  {
856  return std::not_equal_to<T>()(T(0),v);
857  }
858 
859  template <typename T>
860  inline bool is_false_impl(const T v)
861  {
862  return std::equal_to<T>()(T(0),v);
863  }
864 
865  template <typename T>
866  inline T abs_impl(const T v, real_type_tag)
867  {
868  return ((v < T(0)) ? -v : v);
869  }
870 
871  template <typename T>
872  inline T min_impl(const T v0, const T v1, real_type_tag)
873  {
874  return std::min<T>(v0,v1);
875  }
876 
877  template <typename T>
878  inline T max_impl(const T v0, const T v1, real_type_tag)
879  {
880  return std::max<T>(v0,v1);
881  }
882 
883  template <typename T>
884  inline T equal_impl(const T v0, const T v1, real_type_tag)
885  {
886  const T epsilon = epsilon_type<T>::value();
887  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);
888  }
889 
890  inline float equal_impl(const float v0, const float v1, real_type_tag)
891  {
892  const float epsilon = epsilon_type<float>::value();
893  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;
894  }
895 
896  template <typename T>
897  inline T equal_impl(const T v0, const T v1, int_type_tag)
898  {
899  return (v0 == v1) ? 1 : 0;
900  }
901 
902  template <typename T>
903  inline T expm1_impl(const T v, real_type_tag)
904  {
905  // return std::expm1<T>(v);
906  if (abs_impl(v,real_type_tag()) < T(0.00001))
907  return v + (T(0.5) * v * v);
908  else
909  return std::exp(v) - T(1);
910  }
911 
912  template <typename T>
913  inline T expm1_impl(const T v, int_type_tag)
914  {
915  return T(std::exp<double>(v)) - T(1);
916  }
917 
918  template <typename T>
919  inline T nequal_impl(const T v0, const T v1, real_type_tag)
920  {
921  typedef real_type_tag rtg;
922  const T epsilon = epsilon_type<T>::value();
923  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);
924  }
925 
926  inline float nequal_impl(const float v0, const float v1, real_type_tag)
927  {
928  typedef real_type_tag rtg;
929  const float epsilon = epsilon_type<float>::value();
930  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;
931  }
932 
933  template <typename T>
934  inline T nequal_impl(const T v0, const T v1, int_type_tag)
935  {
936  return (v0 != v1) ? 1 : 0;
937  }
938 
939  template <typename T>
940  inline T modulus_impl(const T v0, const T v1, real_type_tag)
941  {
942  return std::fmod(v0,v1);
943  }
944 
945  template <typename T>
946  inline T modulus_impl(const T v0, const T v1, int_type_tag)
947  {
948  return v0 % v1;
949  }
950 
951  template <typename T>
952  inline T pow_impl(const T v0, const T v1, real_type_tag)
953  {
954  return std::pow(v0,v1);
955  }
956 
957  template <typename T>
958  inline T pow_impl(const T v0, const T v1, int_type_tag)
959  {
960  return std::pow(static_cast<double>(v0),static_cast<double>(v1));
961  }
962 
963  template <typename T>
964  inline T logn_impl(const T v0, const T v1, real_type_tag)
965  {
966  return std::log(v0) / std::log(v1);
967  }
968 
969  template <typename T>
970  inline T logn_impl(const T v0, const T v1, int_type_tag)
971  {
972  return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
973  }
974 
975  template <typename T>
976  inline T log1p_impl(const T v, real_type_tag)
977  {
978  if (v > T(-1))
979  {
980  if (abs_impl(v,real_type_tag()) > T(0.0001))
981  {
982  return std::log(T(1) + v);
983  }
984  else
985  return (T(-0.5) * v + T(1)) * v;
986  }
987  else
988  return std::numeric_limits<T>::quiet_NaN();
989  }
990 
991  template <typename T>
992  inline T log1p_impl(const T v, int_type_tag)
993  {
994  if (v > T(-1))
995  {
996  return std::log(T(1) + v);
997  }
998  else
999  return std::numeric_limits<T>::quiet_NaN();
1000  }
1001 
1002  template <typename T>
1003  inline T root_impl(const T v0, const T v1, real_type_tag)
1004  {
1005  if (v1 < T(0))
1006  return std::numeric_limits<T>::quiet_NaN();
1007 
1008  const std::size_t n = static_cast<std::size_t>(v1);
1009 
1010  if ((v0 < T(0)) && (0 == (n % 2)))
1011  return std::numeric_limits<T>::quiet_NaN();
1012 
1013  return std::pow(v0, T(1) / n);
1014  }
1015 
1016  template <typename T>
1017  inline T root_impl(const T v0, const T v1, int_type_tag)
1018  {
1019  return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
1020  }
1021 
1022  template <typename T>
1023  inline T round_impl(const T v, real_type_tag)
1024  {
1025  return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
1026  }
1027 
1028  template <typename T>
1029  inline T roundn_impl(const T v0, const T v1, real_type_tag)
1030  {
1031  const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
1032  const T p10 = T(pow10[index]);
1033 
1034  if (v0 < T(0))
1035  return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
1036  else
1037  return T(std::floor((v0 * p10) + T(0.5)) / p10);
1038  }
1039 
1040  template <typename T>
1041  inline T roundn_impl(const T v0, const T, int_type_tag)
1042  {
1043  return v0;
1044  }
1045 
1046  template <typename T>
1047  inline T hypot_impl(const T v0, const T v1, real_type_tag)
1048  {
1049  return std::sqrt((v0 * v0) + (v1 * v1));
1050  }
1051 
1052  template <typename T>
1053  inline T hypot_impl(const T v0, const T v1, int_type_tag)
1054  {
1055  return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
1056  }
1057 
1058  template <typename T>
1059  inline T atan2_impl(const T v0, const T v1, real_type_tag)
1060  {
1061  return std::atan2(v0,v1);
1062  }
1063 
1064  template <typename T>
1065  inline T atan2_impl(const T, const T, int_type_tag)
1066  {
1067  return 0;
1068  }
1069 
1070  template <typename T>
1071  inline T shr_impl(const T v0, const T v1, real_type_tag)
1072  {
1073  return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
1074  }
1075 
1076  template <typename T>
1077  inline T shr_impl(const T v0, const T v1, int_type_tag)
1078  {
1079  return v0 >> v1;
1080  }
1081 
1082  template <typename T>
1083  inline T shl_impl(const T v0, const T v1, real_type_tag)
1084  {
1085  return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
1086  }
1087 
1088  template <typename T>
1089  inline T shl_impl(const T v0, const T v1, int_type_tag)
1090  {
1091  return v0 << v1;
1092  }
1093 
1094  template <typename T>
1095  inline T sgn_impl(const T v, real_type_tag)
1096  {
1097  if (v > T(0)) return T(+1);
1098  else if (v < T(0)) return T(-1);
1099  else return T( 0);
1100  }
1101 
1102  template <typename T>
1103  inline T sgn_impl(const T v, int_type_tag)
1104  {
1105  if (v > T(0)) return T(+1);
1106  else if (v < T(0)) return T(-1);
1107  else return T( 0);
1108  }
1109 
1110  template <typename T>
1111  inline T and_impl(const T v0, const T v1, real_type_tag)
1112  {
1113  return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
1114  }
1115 
1116  template <typename T>
1117  inline T and_impl(const T v0, const T v1, int_type_tag)
1118  {
1119  return v0 && v1;
1120  }
1121 
1122  template <typename T>
1123  inline T nand_impl(const T v0, const T v1, real_type_tag)
1124  {
1125  return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
1126  }
1127 
1128  template <typename T>
1129  inline T nand_impl(const T v0, const T v1, int_type_tag)
1130  {
1131  return !(v0 && v1);
1132  }
1133 
1134  template <typename T>
1135  inline T or_impl(const T v0, const T v1, real_type_tag)
1136  {
1137  return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
1138  }
1139 
1140  template <typename T>
1141  inline T or_impl(const T v0, const T v1, int_type_tag)
1142  {
1143  return (v0 || v1);
1144  }
1145 
1146  template <typename T>
1147  inline T nor_impl(const T v0, const T v1, real_type_tag)
1148  {
1149  return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
1150  }
1151 
1152  template <typename T>
1153  inline T nor_impl(const T v0, const T v1, int_type_tag)
1154  {
1155  return !(v0 || v1);
1156  }
1157 
1158  template <typename T>
1159  inline T xor_impl(const T v0, const T v1, real_type_tag)
1160  {
1161  return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
1162  }
1163 
1164  template <typename T>
1165  inline T xor_impl(const T v0, const T v1, int_type_tag)
1166  {
1167  return v0 ^ v1;
1168  }
1169 
1170  template <typename T>
1171  inline T xnor_impl(const T v0, const T v1, real_type_tag)
1172  {
1173  const bool v0_true = is_true_impl(v0);
1174  const bool v1_true = is_true_impl(v1);
1175 
1176  if ((v0_true && v1_true) || (!v0_true && !v1_true))
1177  return T(1);
1178  else
1179  return T(0);
1180  }
1181 
1182  template <typename T>
1183  inline T xnor_impl(const T v0, const T v1, int_type_tag)
1184  {
1185  const bool v0_true = is_true_impl(v0);
1186  const bool v1_true = is_true_impl(v1);
1187 
1188  if ((v0_true && v1_true) || (!v0_true && !v1_true))
1189  return T(1);
1190  else
1191  return T(0);
1192  }
1193 
1194  #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1195  #define exprtk_define_erf(TT,impl) \
1196  inline TT erf_impl(TT v) { return impl(v); } \
1197 
1198  exprtk_define_erf( float,::erff)
1199  exprtk_define_erf( double,::erf )
1200  exprtk_define_erf(long double,::erfl)
1201  #undef exprtk_define_erf
1202  #endif
1203 
1204  template <typename T>
1205  inline T erf_impl(T v, real_type_tag)
1206  {
1207  #if defined(_MSC_VER) && (_MSC_VER < 1900)
1208  // Credits: Abramowitz & Stegun Equations 7.1.25-28
1209  static const T c[] = {
1210  T( 1.26551223), T(1.00002368),
1211  T( 0.37409196), T(0.09678418),
1212  T(-0.18628806), T(0.27886807),
1213  T(-1.13520398), T(1.48851587),
1214  T(-0.82215223), T(0.17087277)
1215  };
1216 
1217  const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
1218 
1219  T result = T(1) - t * std::exp((-v * v) -
1220  c[0] + t * (c[1] + t *
1221  (c[2] + t * (c[3] + t *
1222  (c[4] + t * (c[5] + t *
1223  (c[6] + t * (c[7] + t *
1224  (c[8] + t * (c[9]))))))))));
1225 
1226  return (v >= T(0)) ? result : -result;
1227  #else
1228  return erf_impl(v);
1229  #endif
1230  }
1231 
1232  template <typename T>
1233  inline T erf_impl(T v, int_type_tag)
1234  {
1235  return erf_impl(static_cast<double>(v),real_type_tag());
1236  }
1237 
1238  #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER)
1239  #define exprtk_define_erfc(TT,impl) \
1240  inline TT erfc_impl(TT v) { return impl(v); } \
1241 
1242  exprtk_define_erfc( float,::erfcf)
1243  exprtk_define_erfc( double,::erfc )
1244  exprtk_define_erfc(long double,::erfcl)
1245  #undef exprtk_define_erfc
1246  #endif
1247 
1248  template <typename T>
1249  inline T erfc_impl(T v, real_type_tag)
1250  {
1251  #if defined(_MSC_VER) && (_MSC_VER < 1900)
1252  return T(1) - erf_impl(v,real_type_tag());
1253  #else
1254  return erfc_impl(v);
1255  #endif
1256  }
1257 
1258  template <typename T>
1259  inline T erfc_impl(T v, int_type_tag)
1260  {
1261  return erfc_impl(static_cast<double>(v),real_type_tag());
1262  }
1263 
1264  template <typename T>
1265  inline T ncdf_impl(T v, real_type_tag)
1266  {
1267  T cnd = T(0.5) * (T(1) + erf_impl(
1268  abs_impl(v,real_type_tag()) /
1270  return (v < T(0)) ? (T(1) - cnd) : cnd;
1271  }
1272 
1273  template <typename T>
1274  inline T ncdf_impl(T v, int_type_tag)
1275  {
1276  return ncdf_impl(static_cast<double>(v),real_type_tag());
1277  }
1278 
1279  template <typename T>
1280  inline T sinc_impl(T v, real_type_tag)
1281  {
1282  if (std::abs(v) >= std::numeric_limits<T>::epsilon())
1283  return(std::sin(v) / v);
1284  else
1285  return T(1);
1286  }
1287 
1288  template <typename T>
1289  inline T sinc_impl(T v, int_type_tag)
1290  {
1291  return sinc_impl(static_cast<double>(v),real_type_tag());
1292  }
1293 
1294  template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
1295  template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
1296  template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
1297  template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
1298  template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
1299  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); }
1300  template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
1301  template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
1302  template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
1303  template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
1304  template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
1305  template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
1306  template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
1307  template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1308  template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
1309  template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
1310  template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
1311  template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
1312  template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
1313  template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
1314  template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
1315  template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
1316  template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
1317  template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
1318  template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
1319  template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
1320  template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
1321  template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
1322  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)); }
1323  template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
1324  template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
1325 
1326  template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); }
1327  template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); }
1328 
1329  template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
1330  template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
1331  template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
1332  template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
1333  template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
1334  template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
1335  template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
1336  template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
1337  template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
1338  template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
1339  template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
1340  template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
1341  template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
1342  template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
1343  template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1344  template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1345  template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1346  template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1347  template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1348  template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1349  template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1350  template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1351  template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1352  template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1353  template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1354  template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1355  template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1356  template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1357  template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
1358 
1359  template <typename T>
1360  inline bool is_integer_impl(const T& v, real_type_tag)
1361  {
1362  return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
1363  }
1364 
1365  template <typename T>
1366  inline bool is_integer_impl(const T&, int_type_tag)
1367  {
1368  return true;
1369  }
1370  }
1371 
1372  template <typename Type>
1373  struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
1374 
1375  template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
1376  template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
1377  template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
1378  template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
1379 
1380  template <typename T>
1381  inline int to_int32(const T v)
1382  {
1383  const typename details::number_type<T>::type num_type;
1384  return to_int32_impl(v, num_type);
1385  }
1386 
1387  template <typename T>
1388  inline long long int to_int64(const T v)
1389  {
1390  const typename details::number_type<T>::type num_type;
1391  return to_int64_impl(v, num_type);
1392  }
1393 
1394  template <typename T>
1395  inline bool is_nan(const T v)
1396  {
1397  const typename details::number_type<T>::type num_type;
1398  return is_nan_impl(v, num_type);
1399  }
1400 
1401  template <typename T>
1402  inline T min(const T v0, const T v1)
1403  {
1404  const typename details::number_type<T>::type num_type;
1405  return min_impl(v0, v1, num_type);
1406  }
1407 
1408  template <typename T>
1409  inline T max(const T v0, const T v1)
1410  {
1411  const typename details::number_type<T>::type num_type;
1412  return max_impl(v0, v1, num_type);
1413  }
1414 
1415  template <typename T>
1416  inline T equal(const T v0, const T v1)
1417  {
1418  const typename details::number_type<T>::type num_type;
1419  return equal_impl(v0, v1, num_type);
1420  }
1421 
1422  template <typename T>
1423  inline T nequal(const T v0, const T v1)
1424  {
1425  const typename details::number_type<T>::type num_type;
1426  return nequal_impl(v0, v1, num_type);
1427  }
1428 
1429  template <typename T>
1430  inline T modulus(const T v0, const T v1)
1431  {
1432  const typename details::number_type<T>::type num_type;
1433  return modulus_impl(v0, v1, num_type);
1434  }
1435 
1436  template <typename T>
1437  inline T pow(const T v0, const T v1)
1438  {
1439  const typename details::number_type<T>::type num_type;
1440  return pow_impl(v0, v1, num_type);
1441  }
1442 
1443  template <typename T>
1444  inline T logn(const T v0, const T v1)
1445  {
1446  const typename details::number_type<T>::type num_type;
1447  return logn_impl(v0, v1, num_type);
1448  }
1449 
1450  template <typename T>
1451  inline T root(const T v0, const T v1)
1452  {
1453  const typename details::number_type<T>::type num_type;
1454  return root_impl(v0, v1, num_type);
1455  }
1456 
1457  template <typename T>
1458  inline T roundn(const T v0, const T v1)
1459  {
1460  const typename details::number_type<T>::type num_type;
1461  return roundn_impl(v0, v1, num_type);
1462  }
1463 
1464  template <typename T>
1465  inline T hypot(const T v0, const T v1)
1466  {
1467  const typename details::number_type<T>::type num_type;
1468  return hypot_impl(v0, v1, num_type);
1469  }
1470 
1471  template <typename T>
1472  inline T atan2(const T v0, const T v1)
1473  {
1474  const typename details::number_type<T>::type num_type;
1475  return atan2_impl(v0, v1, num_type);
1476  }
1477 
1478  template <typename T>
1479  inline T shr(const T v0, const T v1)
1480  {
1481  const typename details::number_type<T>::type num_type;
1482  return shr_impl(v0, v1, num_type);
1483  }
1484 
1485  template <typename T>
1486  inline T shl(const T v0, const T v1)
1487  {
1488  const typename details::number_type<T>::type num_type;
1489  return shl_impl(v0, v1, num_type);
1490  }
1491 
1492  template <typename T>
1493  inline T and_opr(const T v0, const T v1)
1494  {
1495  const typename details::number_type<T>::type num_type;
1496  return and_impl(v0, v1, num_type);
1497  }
1498 
1499  template <typename T>
1500  inline T nand_opr(const T v0, const T v1)
1501  {
1502  const typename details::number_type<T>::type num_type;
1503  return nand_impl(v0, v1, num_type);
1504  }
1505 
1506  template <typename T>
1507  inline T or_opr(const T v0, const T v1)
1508  {
1509  const typename details::number_type<T>::type num_type;
1510  return or_impl(v0, v1, num_type);
1511  }
1512 
1513  template <typename T>
1514  inline T nor_opr(const T v0, const T v1)
1515  {
1516  const typename details::number_type<T>::type num_type;
1517  return nor_impl(v0, v1, num_type);
1518  }
1519 
1520  template <typename T>
1521  inline T xor_opr(const T v0, const T v1)
1522  {
1523  const typename details::number_type<T>::type num_type;
1524  return xor_impl(v0, v1, num_type);
1525  }
1526 
1527  template <typename T>
1528  inline T xnor_opr(const T v0, const T v1)
1529  {
1530  const typename details::number_type<T>::type num_type;
1531  return xnor_impl(v0, v1, num_type);
1532  }
1533 
1534  template <typename T>
1535  inline bool is_integer(const T v)
1536  {
1537  const typename details::number_type<T>::type num_type;
1538  return is_integer_impl(v, num_type);
1539  }
1540 
1541  template <typename T, unsigned int N>
1542  struct fast_exp
1543  {
1544  static inline T result(T v)
1545  {
1546  unsigned int k = N;
1547  T l = T(1);
1548 
1549  while (k)
1550  {
1551  if (k & 1)
1552  {
1553  l *= v;
1554  --k;
1555  }
1556 
1557  v *= v;
1558  k >>= 1;
1559  }
1560 
1561  return l;
1562  }
1563  };
1564 
1565  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; } };
1566  template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
1567  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; } };
1568  template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
1569  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; } };
1570  template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
1571  template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
1572  template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
1573  template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
1574  template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
1575  template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
1576 
1577  #define exprtk_define_unary_function(FunctionName) \
1578  template <typename T> \
1579  inline T FunctionName (const T v) \
1580  { \
1581  const typename details::number_type<T>::type num_type; \
1582  return FunctionName##_impl(v,num_type); \
1583  } \
1584 
1625  #undef exprtk_define_unary_function
1626  }
1627 
1628  template <typename T>
1629  inline T compute_pow10(T d, const int exponent)
1630  {
1631  static const double fract10[] =
1632  {
1633  0.0,
1634  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,
1635  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,
1636  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,
1637  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,
1638  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,
1639  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,
1640  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,
1641  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,
1642  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,
1643  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,
1644  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,
1645  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,
1646  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,
1647  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,
1648  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,
1649  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,
1650  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,
1651  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,
1652  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,
1653  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,
1654  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,
1655  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,
1656  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,
1657  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,
1658  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,
1659  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,
1660  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,
1661  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,
1662  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,
1663  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,
1664  1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
1665  };
1666 
1667  static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double));
1668 
1669  const int e = std::abs(exponent);
1670 
1671  if (exponent >= std::numeric_limits<T>::min_exponent10)
1672  {
1673  if (e < fract10_size)
1674  {
1675  if (exponent > 0)
1676  return T(d * fract10[e]);
1677  else
1678  return T(d / fract10[e]);
1679  }
1680  else
1681  return T(d * std::pow(10.0, 10.0 * exponent));
1682  }
1683  else
1684  {
1685  d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]);
1686  return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]);
1687  }
1688  }
1689 
1690  template <typename Iterator, typename T>
1691  inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result)
1692  {
1693  if (itr == end)
1694  return false;
1695 
1696  const bool negative = ('-' == (*itr));
1697 
1698  if (negative || ('+' == (*itr)))
1699  {
1700  if (end == ++itr)
1701  return false;
1702  }
1703 
1704  static const uchar_t zero = static_cast<uchar_t>('0');
1705 
1706  while ((end != itr) && (zero == (*itr))) ++itr;
1707 
1708  bool return_result = true;
1709  unsigned int digit = 0;
1710  const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1711 
1712  if (length <= 4)
1713  {
1715  switch (length)
1716  {
1717  #ifdef exprtk_use_lut
1718 
1719  #define exprtk_process_digit \
1720  if ((digit = details::digit_table[(int)*itr++]) < 10) \
1721  result = result * 10 + (digit); \
1722  else \
1723  { \
1724  return_result = false; \
1725  break; \
1726  } \
1727 
1728  #else
1729 
1730  #define exprtk_process_digit \
1731  if ((digit = (*itr++ - zero)) < 10) \
1732  result = result * T(10) + digit; \
1733  else \
1734  { \
1735  return_result = false; \
1736  break; \
1737  } \
1738 
1739  #endif
1740 
1741  case 4 : exprtk_process_digit
1742  case 3 : exprtk_process_digit
1743  case 2 : exprtk_process_digit
1744  case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; }
1745 
1746  #undef exprtk_process_digit
1747  }
1749  }
1750  else
1751  return_result = false;
1752 
1753  if (length && return_result)
1754  {
1755  result = result * 10 + static_cast<T>(digit);
1756  ++itr;
1757  }
1758 
1759  result = negative ? -result : result;
1760  return return_result;
1761  }
1762 
1763  template <typename Iterator, typename T>
1764  static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
1765  {
1767 
1768  static const std::size_t nan_length = 3;
1769 
1770  if (std::distance(itr,end) != static_cast<int>(nan_length))
1771  return false;
1772 
1773  if (static_cast<type>('n') == (*itr))
1774  {
1775  if (
1776  (static_cast<type>('a') != *(itr + 1)) ||
1777  (static_cast<type>('n') != *(itr + 2))
1778  )
1779  {
1780  return false;
1781  }
1782  }
1783  else if (
1784  (static_cast<type>('A') != *(itr + 1)) ||
1785  (static_cast<type>('N') != *(itr + 2))
1786  )
1787  {
1788  return false;
1789  }
1790 
1791  t = std::numeric_limits<T>::quiet_NaN();
1792 
1793  return true;
1794  }
1795 
1796  template <typename Iterator, typename T>
1797  static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
1798  {
1799  static const char_t inf_uc[] = "INFINITY";
1800  static const char_t inf_lc[] = "infinity";
1801  static const std::size_t inf_length = 8;
1802 
1803  const std::size_t length = static_cast<std::size_t>(std::distance(itr,end));
1804 
1805  if ((3 != length) && (inf_length != length))
1806  return false;
1807 
1808  char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
1809 
1810  while (end != itr)
1811  {
1812  if (*inf_itr == static_cast<char>(*itr))
1813  {
1814  ++itr;
1815  ++inf_itr;
1816  continue;
1817  }
1818  else
1819  return false;
1820  }
1821 
1822  if (negative)
1823  t = -std::numeric_limits<T>::infinity();
1824  else
1825  t = std::numeric_limits<T>::infinity();
1826 
1827  return true;
1828  }
1829 
1830  template <typename Iterator, typename T>
1831  inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag)
1832  {
1833  if (end == itr_external) return false;
1834 
1835  Iterator itr = itr_external;
1836 
1837  T d = T(0);
1838 
1839  const bool negative = ('-' == (*itr));
1840 
1841  if (negative || '+' == (*itr))
1842  {
1843  if (end == ++itr)
1844  return false;
1845  }
1846 
1847  bool instate = false;
1848 
1849  static const char_t zero = static_cast<uchar_t>('0');
1850 
1851  #define parse_digit_1(d) \
1852  if ((digit = (*itr - zero)) < 10) \
1853  { d = d * T(10) + digit; } \
1854  else \
1855  { break; } \
1856  if (end == ++itr) break; \
1857 
1858  #define parse_digit_2(d) \
1859  if ((digit = (*itr - zero)) < 10) \
1860  { d = d * T(10) + digit; } \
1861  else { break; } \
1862  ++itr; \
1863 
1864  if ('.' != (*itr))
1865  {
1866  const Iterator curr = itr;
1867 
1868  while ((end != itr) && (zero == (*itr))) ++itr;
1869 
1870  unsigned int digit;
1871 
1872  while (end != itr)
1873  {
1874  // Note: For 'physical' superscalar architectures it
1875  // is advised that the following loop be: 4xPD1 and 1xPD2
1876  #ifdef exprtk_enable_superscalar
1877  parse_digit_1(d)
1878  parse_digit_1(d)
1879  #endif
1880  parse_digit_1(d)
1881  parse_digit_1(d)
1882  parse_digit_2(d)
1883  }
1884 
1885  if (curr != itr) instate = true;
1886  }
1887 
1888  int exponent = 0;
1889 
1890  if (end != itr)
1891  {
1892  if ('.' == (*itr))
1893  {
1894  const Iterator curr = ++itr;
1895  unsigned int digit;
1896  T tmp_d = T(0);
1897 
1898  while (end != itr)
1899  {
1900  #ifdef exprtk_enable_superscalar
1901  parse_digit_1(tmp_d)
1902  parse_digit_1(tmp_d)
1903  parse_digit_1(tmp_d)
1904  #endif
1905  parse_digit_1(tmp_d)
1906  parse_digit_1(tmp_d)
1907  parse_digit_2(tmp_d)
1908  }
1909 
1910  if (curr != itr)
1911  {
1912  instate = true;
1913  d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr)));
1914  }
1915 
1916  #undef parse_digit_1
1917  #undef parse_digit_2
1918  }
1919 
1920  if (end != itr)
1921  {
1922  typename std::iterator_traits<Iterator>::value_type c = (*itr);
1923 
1924  if (('e' == c) || ('E' == c))
1925  {
1926  int exp = 0;
1927 
1928  if (!details::string_to_type_converter_impl_ref(++itr, end, exp))
1929  {
1930  if (end == itr)
1931  return false;
1932  else
1933  c = (*itr);
1934  }
1935 
1936  exponent += exp;
1937  }
1938 
1939  if (end != itr)
1940  {
1941  if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
1942  ++itr;
1943  else if ('#' == c)
1944  {
1945  if (end == ++itr)
1946  return false;
1947  else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1948  {
1949  if (('i' == (*itr)) || ('I' == (*itr)))
1950  {
1951  return parse_inf(itr, end, t, negative);
1952  }
1953  else if (('n' == (*itr)) || ('N' == (*itr)))
1954  {
1955  return parse_nan(itr, end, t);
1956  }
1957  else
1958  return false;
1959  }
1960  else
1961  return false;
1962  }
1963  else if (('I' <= (*itr)) && ((*itr) <= 'n'))
1964  {
1965  if (('i' == (*itr)) || ('I' == (*itr)))
1966  {
1967  return parse_inf(itr, end, t, negative);
1968  }
1969  else if (('n' == (*itr)) || ('N' == (*itr)))
1970  {
1971  return parse_nan(itr, end, t);
1972  }
1973  else
1974  return false;
1975  }
1976  else
1977  return false;
1978  }
1979  }
1980  }
1981 
1982  if ((end != itr) || (!instate))
1983  return false;
1984  else if (exponent)
1985  d = compute_pow10(d,exponent);
1986 
1987  t = static_cast<T>((negative) ? -d : d);
1988  return true;
1989  }
1990 
1991  template <typename T>
1992  inline bool string_to_real(const std::string& s, T& t)
1993  {
1994  const typename numeric::details::number_type<T>::type num_type;
1995 
1996  char_cptr begin = s.data();
1997  char_cptr end = s.data() + s.size();
1998 
1999  return string_to_real(begin, end, t, num_type);
2000  }
2001 
2002  template <typename T>
2003  struct functor_t
2004  {
2005  /*
2006  Note: The following definitions for Type, may require tweaking
2007  based on the compiler and target architecture. The benchmark
2008  should provide enough information to make the right choice.
2009  */
2010  //typedef T Type;
2011  //typedef const T Type;
2012  typedef const T& Type;
2013  typedef T& RefType;
2014  typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3);
2015  typedef T (*tfunc_t)(Type t0, Type t1, Type t2);
2016  typedef T (*bfunc_t)(Type t0, Type t1);
2017  typedef T (*ufunc_t)(Type t0);
2018  };
2019 
2020  } // namespace details
2021 
2022  namespace lexer
2023  {
2024  struct token
2025  {
2027  {
2028  e_none = 0, e_error = 1, e_err_symbol = 2,
2030  e_eof = 6, e_number = 7, e_symbol = 8,
2031  e_string = 9, e_assign = 10, e_addass = 11,
2032  e_subass = 12, e_mulass = 13, e_divass = 14,
2033  e_modass = 15, e_shr = 16, e_shl = 17,
2034  e_lte = 18, e_ne = 19, e_gte = 20,
2035  e_swap = 21, e_lt = '<', e_gt = '>',
2036  e_eq = '=', e_rbracket = ')', e_lbracket = '(',
2038  e_lcrlbracket = '{', e_comma = ',', e_add = '+',
2039  e_sub = '-', e_div = '/', e_mul = '*',
2040  e_mod = '%', e_pow = '^', e_colon = ':',
2042  };
2043 
2045  : type(e_none),
2046  value(""),
2047  position(std::numeric_limits<std::size_t>::max())
2048  {}
2049 
2050  void clear()
2051  {
2052  type = e_none;
2053  value = "";
2055  }
2056 
2057  template <typename Iterator>
2058  inline token& set_operator(const token_type tt,
2059  const Iterator begin, const Iterator end,
2060  const Iterator base_begin = Iterator(0))
2061  {
2062  type = tt;
2063  value.assign(begin,end);
2064  if (base_begin)
2065  position = static_cast<std::size_t>(std::distance(base_begin,begin));
2066  return (*this);
2067  }
2068 
2069  template <typename Iterator>
2070  inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2071  {
2072  type = e_symbol;
2073  value.assign(begin,end);
2074  if (base_begin)
2075  position = static_cast<std::size_t>(std::distance(base_begin,begin));
2076  return (*this);
2077  }
2078 
2079  template <typename Iterator>
2080  inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2081  {
2082  type = e_number;
2083  value.assign(begin,end);
2084  if (base_begin)
2085  position = static_cast<std::size_t>(std::distance(base_begin,begin));
2086  return (*this);
2087  }
2088 
2089  template <typename Iterator>
2090  inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0))
2091  {
2092  type = e_string;
2093  value.assign(begin,end);
2094  if (base_begin)
2095  position = static_cast<std::size_t>(std::distance(base_begin,begin));
2096  return (*this);
2097  }
2098 
2099  inline token& set_string(const std::string& s, const std::size_t p)
2100  {
2101  type = e_string;
2102  value = s;
2103  position = p;
2104  return (*this);
2105  }
2106 
2107  template <typename Iterator>
2108  inline token& set_error(const token_type et,
2109  const Iterator begin, const Iterator end,
2110  const Iterator base_begin = Iterator(0))
2111  {
2112  if (
2113  (e_error == et) ||
2114  (e_err_symbol == et) ||
2115  (e_err_number == et) ||
2116  (e_err_string == et) ||
2117  (e_err_sfunc == et)
2118  )
2119  {
2120  type = et;
2121  }
2122  else
2123  type = e_error;
2124 
2125  value.assign(begin,end);
2126 
2127  if (base_begin)
2128  position = static_cast<std::size_t>(std::distance(base_begin,begin));
2129 
2130  return (*this);
2131  }
2132 
2134  {
2135  switch (t)
2136  {
2137  case e_none : return "NONE";
2138  case e_error : return "ERROR";
2139  case e_err_symbol : return "ERROR_SYMBOL";
2140  case e_err_number : return "ERROR_NUMBER";
2141  case e_err_string : return "ERROR_STRING";
2142  case e_eof : return "EOF";
2143  case e_number : return "NUMBER";
2144  case e_symbol : return "SYMBOL";
2145  case e_string : return "STRING";
2146  case e_assign : return ":=";
2147  case e_addass : return "+=";
2148  case e_subass : return "-=";
2149  case e_mulass : return "*=";
2150  case e_divass : return "/=";
2151  case e_modass : return "%=";
2152  case e_shr : return ">>";
2153  case e_shl : return "<<";
2154  case e_lte : return "<=";
2155  case e_ne : return "!=";
2156  case e_gte : return ">=";
2157  case e_lt : return "<";
2158  case e_gt : return ">";
2159  case e_eq : return "=";
2160  case e_rbracket : return ")";
2161  case e_lbracket : return "(";
2162  case e_rsqrbracket : return "]";
2163  case e_lsqrbracket : return "[";
2164  case e_rcrlbracket : return "}";
2165  case e_lcrlbracket : return "{";
2166  case e_comma : return ",";
2167  case e_add : return "+";
2168  case e_sub : return "-";
2169  case e_div : return "/";
2170  case e_mul : return "*";
2171  case e_mod : return "%";
2172  case e_pow : return "^";
2173  case e_colon : return ":";
2174  case e_ternary : return "?";
2175  case e_swap : return "<=>";
2176  default : return "UNKNOWN";
2177  }
2178  }
2179 
2180  inline bool is_error() const
2181  {
2182  return (
2183  (e_error == type) ||
2184  (e_err_symbol == type) ||
2185  (e_err_number == type) ||
2186  (e_err_string == type) ||
2187  (e_err_sfunc == type)
2188  );
2189  }
2190 
2193  std::size_t position;
2194  };
2195 
2197  {
2198  public:
2199 
2200  typedef token token_t;
2201  typedef std::vector<token_t> token_list_t;
2202  typedef std::vector<token_t>::iterator token_list_itr_t;
2204 
2206  : base_itr_(0),
2207  s_itr_ (0),
2208  s_end_ (0)
2209  {
2210  clear();
2211  }
2212 
2213  inline void clear()
2214  {
2215  base_itr_ = 0;
2216  s_itr_ = 0;
2217  s_end_ = 0;
2218  token_list_.clear();
2219  token_itr_ = token_list_.end();
2220  store_token_itr_ = token_list_.end();
2221  }
2222 
2223  inline bool process(const std::string& str)
2224  {
2225  base_itr_ = str.data();
2226  s_itr_ = str.data();
2227  s_end_ = str.data() + str.size();
2228 
2230  token_list_.clear();
2231 
2232  while (!is_end(s_itr_))
2233  {
2234  scan_token();
2235 
2236  if (!token_list_.empty() && token_list_.back().is_error())
2237  return false;
2238  }
2239 
2240  return true;
2241  }
2242 
2243  inline bool empty() const
2244  {
2245  return token_list_.empty();
2246  }
2247 
2248  inline std::size_t size() const
2249  {
2250  return token_list_.size();
2251  }
2252 
2253  inline void begin()
2254  {
2255  token_itr_ = token_list_.begin();
2256  store_token_itr_ = token_list_.begin();
2257  }
2258 
2259  inline void store()
2260  {
2262  }
2263 
2264  inline void restore()
2265  {
2267  }
2268 
2270  {
2271  if (token_list_.end() != token_itr_)
2272  {
2273  return *token_itr_++;
2274  }
2275  else
2276  return eof_token_;
2277  }
2278 
2280  {
2281  if (token_list_.end() != token_itr_)
2282  {
2283  return *token_itr_;
2284  }
2285  else
2286  return eof_token_;
2287  }
2288 
2289  inline token_t& operator[](const std::size_t& index)
2290  {
2291  if (index < token_list_.size())
2292  return token_list_[index];
2293  else
2294  return eof_token_;
2295  }
2296 
2297  inline token_t operator[](const std::size_t& index) const
2298  {
2299  if (index < token_list_.size())
2300  return token_list_[index];
2301  else
2302  return eof_token_;
2303  }
2304 
2305  inline bool finished() const
2306  {
2307  return (token_list_.end() == token_itr_);
2308  }
2309 
2310  inline void insert_front(token_t::token_type tk_type)
2311  {
2312  if (
2313  !token_list_.empty() &&
2314  (token_list_.end() != token_itr_)
2315  )
2316  {
2317  token_t t = *token_itr_;
2318 
2319  t.type = tk_type;
2320  token_itr_ = token_list_.insert(token_itr_,t);
2321  }
2322  }
2323 
2324  inline std::string substr(const std::size_t& begin, const std::size_t& end)
2325  {
2326  const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_;
2327  const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_;
2328 
2329  return std::string(begin_itr,end_itr);
2330  }
2331 
2332  inline std::string remaining() const
2333  {
2334  if (finished())
2335  return "";
2336  else if (token_list_.begin() != token_itr_)
2337  return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_);
2338  else
2339  return std::string(base_itr_ + token_itr_->position,s_end_);
2340  }
2341 
2342  private:
2343 
2344  inline bool is_end(details::char_cptr itr)
2345  {
2346  return (s_end_ == itr);
2347  }
2348 
2350  {
2351  #ifndef exprtk_disable_comments
2352  const char_t c0 = *(itr + 0);
2353  const char_t c1 = *(itr + 1);
2354 
2355  if ('#' == c0)
2356  return true;
2357  else if (!is_end(itr + 1))
2358  {
2359  if (('/' == c0) && ('/' == c1)) return true;
2360  if (('/' == c0) && ('*' == c1)) return true;
2361  }
2362  #endif
2363  return false;
2364  }
2365 
2366  inline void skip_whitespace()
2367  {
2369  {
2370  ++s_itr_;
2371  }
2372  }
2373 
2374  inline void skip_comments()
2375  {
2376  #ifndef exprtk_disable_comments
2377  // The following comment styles are supported:
2378  // 1. // .... \n
2379  // 2. # .... \n
2380  // 3. /* .... */
2381  struct test
2382  {
2383  static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr)
2384  {
2385  mode = 0;
2386  if ('#' == c0) { mode = 1; incr = 1; }
2387  else if ('/' == c0)
2388  {
2389  if ('/' == c1) { mode = 1; incr = 2; }
2390  else if ('*' == c1) { mode = 2; incr = 2; }
2391  }
2392  return (0 != mode);
2393  }
2394 
2395  static inline bool comment_end(const char_t c0, const char_t c1, int& mode)
2396  {
2397  if (
2398  ((1 == mode) && ('\n' == c0)) ||
2399  ((2 == mode) && ( '*' == c0) && ('/' == c1))
2400  )
2401  {
2402  mode = 0;
2403  return true;
2404  }
2405  else
2406  return false;
2407  }
2408  };
2409 
2410  int mode = 0;
2411  int increment = 0;
2412 
2413  if (is_end(s_itr_))
2414  return;
2415  else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment))
2416  return;
2417 
2418  details::char_cptr cmt_start = s_itr_;
2419 
2420  s_itr_ += increment;
2421 
2422  while (!is_end(s_itr_))
2423  {
2424  if ((1 == mode) && test::comment_end(*s_itr_, 0, mode))
2425  {
2426  ++s_itr_;
2427  return;
2428  }
2429 
2430  if ((2 == mode))
2431  {
2432  if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode))
2433  {
2434  s_itr_ += 2;
2435  return;
2436  }
2437  }
2438 
2439  ++s_itr_;
2440  }
2441 
2442  if (2 == mode)
2443  {
2444  token_t t;
2445  t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_);
2446  token_list_.push_back(t);
2447  }
2448  #endif
2449  }
2450 
2451  inline void scan_token()
2452  {
2454  {
2455  skip_whitespace();
2456  return;
2457  }
2458  else if (is_comment_start(s_itr_))
2459  {
2460  skip_comments();
2461  return;
2462  }
2463  else if (details::is_operator_char(*s_itr_))
2464  {
2465  scan_operator();
2466  return;
2467  }
2468  else if (details::is_letter(*s_itr_))
2469  {
2470  scan_symbol();
2471  return;
2472  }
2473  else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_)))
2474  {
2475  scan_number();
2476  return;
2477  }
2478  else if ('$' == (*s_itr_))
2479  {
2481  return;
2482  }
2483  #ifndef exprtk_disable_string_capabilities
2484  else if ('\'' == (*s_itr_))
2485  {
2486  scan_string();
2487  return;
2488  }
2489  #endif
2490  else if ('~' == (*s_itr_))
2491  {
2492  token_t t;
2493  t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2494  token_list_.push_back(t);
2495  ++s_itr_;
2496  return;
2497  }
2498  else
2499  {
2500  token_t t;
2501  t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_);
2502  token_list_.push_back(t);
2503  ++s_itr_;
2504  }
2505  }
2506 
2507  inline void scan_operator()
2508  {
2509  token_t t;
2510 
2511  const char_t c0 = s_itr_[0];
2512 
2513  if (!is_end(s_itr_ + 1))
2514  {
2515  const char_t c1 = s_itr_[1];
2516 
2517  if (!is_end(s_itr_ + 2))
2518  {
2519  const char_t c2 = s_itr_[2];
2520 
2521  if ((c0 == '<') && (c1 == '=') && (c2 == '>'))
2522  {
2523  t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_);
2524  token_list_.push_back(t);
2525  s_itr_ += 3;
2526  return;
2527  }
2528  }
2529 
2531 
2532  if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte;
2533  else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte;
2534  else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne;
2535  else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne;
2536  else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq;
2537  else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign;
2538  else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl;
2539  else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr;
2540  else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass;
2541  else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass;
2542  else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass;
2543  else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass;
2544  else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass;
2545 
2546  if (token_t::e_none != ttype)
2547  {
2548  t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_);
2549  token_list_.push_back(t);
2550  s_itr_ += 2;
2551  return;
2552  }
2553  }
2554 
2555  if ('<' == c0)
2556  t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_);
2557  else if ('>' == c0)
2558  t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_);
2559  else if (';' == c0)
2560  t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_);
2561  else if ('&' == c0)
2562  t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2563  else if ('|' == c0)
2564  t.set_symbol(s_itr_, s_itr_ + 1, base_itr_);
2565  else
2566  t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_);
2567 
2568  token_list_.push_back(t);
2569  ++s_itr_;
2570  }
2571 
2572  inline void scan_symbol()
2573  {
2574  details::char_cptr initial_itr = s_itr_;
2575 
2576  while (!is_end(s_itr_))
2577  {
2578  if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_)))
2579  {
2580  if ('.' != (*s_itr_))
2581  break;
2582  /*
2583  Permit symbols that contain a 'dot'
2584  Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123
2585  Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...>
2586  */
2587  if (
2588  (s_itr_ != initial_itr) &&
2589  !is_end(s_itr_ + 1) &&
2591  ('_' != (*(s_itr_ + 1)))
2592  )
2593  break;
2594  }
2595 
2596  ++s_itr_;
2597  }
2598 
2599  token_t t;
2600  t.set_symbol(initial_itr,s_itr_,base_itr_);
2601  token_list_.push_back(t);
2602  }
2603 
2604  inline void scan_number()
2605  {
2606  /*
2607  Attempt to match a valid numeric value in one of the following formats:
2608  (01) 123456
2609  (02) 123456.
2610  (03) 123.456
2611  (04) 123.456e3
2612  (05) 123.456E3
2613  (06) 123.456e+3
2614  (07) 123.456E+3
2615  (08) 123.456e-3
2616  (09) 123.456E-3
2617  (00) .1234
2618  (11) .1234e3
2619  (12) .1234E+3
2620  (13) .1234e+3
2621  (14) .1234E-3
2622  (15) .1234e-3
2623  */
2624 
2625  details::char_cptr initial_itr = s_itr_;
2626  bool dot_found = false;
2627  bool e_found = false;
2628  bool post_e_sign_found = false;
2629  bool post_e_digit_found = false;
2630  token_t t;
2631 
2632  while (!is_end(s_itr_))
2633  {
2634  if ('.' == (*s_itr_))
2635  {
2636  if (dot_found)
2637  {
2638  t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2639  token_list_.push_back(t);
2640  return;
2641  }
2642 
2643  dot_found = true;
2644  ++s_itr_;
2645 
2646  continue;
2647  }
2648  else if ('e' == std::tolower(*s_itr_))
2649  {
2650  const char_t& c = *(s_itr_ + 1);
2651 
2652  if (is_end(s_itr_ + 1))
2653  {
2654  t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2655  token_list_.push_back(t);
2656 
2657  return;
2658  }
2659  else if (
2660  ('+' != c) &&
2661  ('-' != c) &&
2662  !details::is_digit(c)
2663  )
2664  {
2665  t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2666  token_list_.push_back(t);
2667 
2668  return;
2669  }
2670 
2671  e_found = true;
2672  ++s_itr_;
2673 
2674  continue;
2675  }
2676  else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found)
2677  {
2678  if (post_e_sign_found)
2679  {
2680  t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_);
2681  token_list_.push_back(t);
2682 
2683  return;
2684  }
2685 
2686  post_e_sign_found = true;
2687  ++s_itr_;
2688 
2689  continue;
2690  }
2691  else if (e_found && details::is_digit(*s_itr_))
2692  {
2693  post_e_digit_found = true;
2694  ++s_itr_;
2695 
2696  continue;
2697  }
2698  else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_))
2699  break;
2700  else
2701  ++s_itr_;
2702  }
2703 
2704  t.set_numeric(initial_itr, s_itr_, base_itr_);
2705  token_list_.push_back(t);
2706 
2707  return;
2708  }
2709 
2711  {
2712  details::char_cptr initial_itr = s_itr_;
2713  token_t t;
2714 
2715  // $fdd(x,x,x) = at least 11 chars
2716  if (std::distance(s_itr_,s_end_) < 11)
2717  {
2718  t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2719  token_list_.push_back(t);
2720 
2721  return;
2722  }
2723 
2724  if (
2725  !(('$' == *s_itr_) &&
2726  (details::imatch ('f',*(s_itr_ + 1))) &&
2727  (details::is_digit(*(s_itr_ + 2))) &&
2728  (details::is_digit(*(s_itr_ + 3))))
2729  )
2730  {
2731  t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_);
2732  token_list_.push_back(t);
2733 
2734  return;
2735  }
2736 
2737  s_itr_ += 4; // $fdd = 4chars
2738 
2739  t.set_symbol(initial_itr, s_itr_, base_itr_);
2740  token_list_.push_back(t);
2741 
2742  return;
2743  }
2744 
2745  #ifndef exprtk_disable_string_capabilities
2746  inline void scan_string()
2747  {
2748  details::char_cptr initial_itr = s_itr_ + 1;
2749  token_t t;
2750 
2751  if (std::distance(s_itr_,s_end_) < 2)
2752  {
2754  token_list_.push_back(t);
2755  return;
2756  }
2757 
2758  ++s_itr_;
2759 
2760  bool escaped_found = false;
2761  bool escaped = false;
2762 
2763  while (!is_end(s_itr_))
2764  {
2765  if (!escaped && ('\\' == *s_itr_))
2766  {
2767  escaped_found = true;
2768  escaped = true;
2769  ++s_itr_;
2770 
2771  continue;
2772  }
2773  else if (!escaped)
2774  {
2775  if ('\'' == *s_itr_)
2776  break;
2777  }
2778  else if (escaped)
2779  {
2780  if (!is_end(s_itr_) && ('0' == *(s_itr_)))
2781  {
2782  /*
2783  Note: The following 'awkward' conditional is
2784  due to various broken msvc compilers.
2785  */
2786  #if defined(_MSC_VER) && (_MSC_VER == 1600)
2787  const bool within_range = !is_end(s_itr_ + 2) &&
2788  !is_end(s_itr_ + 3) ;
2789  #else
2790  const bool within_range = !is_end(s_itr_ + 1) &&
2791  !is_end(s_itr_ + 2) &&
2792  !is_end(s_itr_ + 3) ;
2793  #endif
2794 
2795  const bool x_seperator = ('x' == *(s_itr_ + 1)) ||
2796  ('X' == *(s_itr_ + 1)) ;
2797 
2798  const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) &&
2799  details::is_hex_digit(*(s_itr_ + 3)) ;
2800 
2801  if (!within_range || !x_seperator || !both_digits)
2802  {
2803  t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2804  token_list_.push_back(t);
2805 
2806  return;
2807  }
2808  else
2809  s_itr_ += 3;
2810  }
2811 
2812  escaped = false;
2813  }
2814 
2815  ++s_itr_;
2816  }
2817 
2818  if (is_end(s_itr_))
2819  {
2820  t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_);
2821  token_list_.push_back(t);
2822 
2823  return;
2824  }
2825 
2826  if (!escaped_found)
2827  t.set_string(initial_itr, s_itr_, base_itr_);
2828  else
2829  {
2830  std::string parsed_string(initial_itr,s_itr_);
2831 
2832  details::cleanup_escapes(parsed_string);
2833 
2834  t.set_string(
2835  parsed_string,
2836  static_cast<std::size_t>(std::distance(base_itr_,initial_itr)));
2837  }
2838 
2839  token_list_.push_back(t);
2840  ++s_itr_;
2841 
2842  return;
2843  }
2844  #endif
2845 
2846  private:
2847 
2855 
2856  friend class token_scanner;
2857  friend class token_modifier;
2858  friend class token_inserter;
2859  friend class token_joiner;
2860  };
2861 
2863  {
2864  public:
2865 
2866  virtual void init() { }
2867  virtual void reset() { }
2868  virtual bool result() { return true; }
2869  virtual std::size_t process(generator&) { return 0; }
2870  virtual ~helper_interface() { }
2871  };
2872 
2874  {
2875  public:
2876 
2877  virtual ~token_scanner()
2878  {}
2879 
2880  explicit token_scanner(const std::size_t& stride)
2881  : stride_(stride)
2882  {
2883  if (stride > 4)
2884  {
2885  throw std::invalid_argument("token_scanner() - Invalid stride value");
2886  }
2887  }
2888 
2889  inline std::size_t process(generator& g)
2890  {
2891  if (g.token_list_.size() >= stride_)
2892  {
2893  for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
2894  {
2895  token t;
2896 
2897  switch (stride_)
2898  {
2899  case 1 :
2900  {
2901  const token& t0 = g.token_list_[i];
2902 
2903  if (!operator()(t0))
2904  {
2905  return i;
2906  }
2907  }
2908  break;
2909 
2910  case 2 :
2911  {
2912  const token& t0 = g.token_list_[i ];
2913  const token& t1 = g.token_list_[i + 1];
2914 
2915  if (!operator()(t0, t1))
2916  {
2917  return i;
2918  }
2919  }
2920  break;
2921 
2922  case 3 :
2923  {
2924  const token& t0 = g.token_list_[i ];
2925  const token& t1 = g.token_list_[i + 1];
2926  const token& t2 = g.token_list_[i + 2];
2927 
2928  if (!operator()(t0, t1, t2))
2929  {
2930  return i;
2931  }
2932  }
2933  break;
2934 
2935  case 4 :
2936  {
2937  const token& t0 = g.token_list_[i ];
2938  const token& t1 = g.token_list_[i + 1];
2939  const token& t2 = g.token_list_[i + 2];
2940  const token& t3 = g.token_list_[i + 3];
2941 
2942  if (!operator()(t0, t1, t2, t3))
2943  {
2944  return i;
2945  }
2946  }
2947  break;
2948  }
2949  }
2950  }
2951 
2952  return (g.token_list_.size() - stride_ + 1);
2953  }
2954 
2955  virtual bool operator() (const token&)
2956  {
2957  return false;
2958  }
2959 
2960  virtual bool operator() (const token&, const token&)
2961  {
2962  return false;
2963  }
2964 
2965  virtual bool operator() (const token&, const token&, const token&)
2966  {
2967  return false;
2968  }
2969 
2970  virtual bool operator() (const token&, const token&, const token&, const token&)
2971  {
2972  return false;
2973  }
2974 
2975  private:
2976 
2977  const std::size_t stride_;
2978  };
2979 
2981  {
2982  public:
2983 
2984  inline std::size_t process(generator& g)
2985  {
2986  std::size_t changes = 0;
2987 
2988  for (std::size_t i = 0; i < g.token_list_.size(); ++i)
2989  {
2990  if (modify(g.token_list_[i])) changes++;
2991  }
2992 
2993  return changes;
2994  }
2995 
2996  virtual bool modify(token& t) = 0;
2997  };
2998 
3000  {
3001  public:
3002 
3003  explicit token_inserter(const std::size_t& stride)
3004  : stride_(stride)
3005  {
3006  if (stride > 5)
3007  {
3008  throw std::invalid_argument("token_inserter() - Invalid stride value");
3009  }
3010  }
3011 
3012  inline std::size_t process(generator& g)
3013  {
3014  if (g.token_list_.empty())
3015  return 0;
3016  else if (g.token_list_.size() < stride_)
3017  return 0;
3018 
3019  std::size_t changes = 0;
3020 
3021  for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i)
3022  {
3023  int insert_index = -1;
3024  token t;
3025 
3026  switch (stride_)
3027  {
3028  case 1 : insert_index = insert(g.token_list_[i],t);
3029  break;
3030 
3031  case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t);
3032  break;
3033 
3034  case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t);
3035  break;
3036 
3037  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);
3038  break;
3039 
3040  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);
3041  break;
3042  }
3043 
3044  typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3045 
3046  if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1)))
3047  {
3048  g.token_list_.insert(
3049  g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t);
3050 
3051  changes++;
3052  }
3053  }
3054 
3055  return changes;
3056  }
3057 
3058  #define token_inserter_empty_body \
3059  { \
3060  return -1; \
3061  } \
3062 
3063  inline virtual int insert(const token&, token&)
3065 
3066  inline virtual int insert(const token&, const token&, token&)
3068 
3069  inline virtual int insert(const token&, const token&, const token&, token&)
3071 
3072  inline virtual int insert(const token&, const token&, const token&, const token&, token&)
3074 
3075  inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&)
3077 
3078  #undef token_inserter_empty_body
3079 
3080  private:
3081 
3082  const std::size_t stride_;
3083  };
3084 
3086  {
3087  public:
3088 
3089  explicit token_joiner(const std::size_t& stride)
3090  : stride_(stride)
3091  {}
3092 
3093  inline std::size_t process(generator& g)
3094  {
3095  if (g.token_list_.empty())
3096  return 0;
3097 
3098  switch (stride_)
3099  {
3100  case 2 : return process_stride_2(g);
3101  case 3 : return process_stride_3(g);
3102  default : return 0;
3103  }
3104  }
3105 
3106  virtual bool join(const token&, const token&, token&) { return false; }
3107  virtual bool join(const token&, const token&, const token&, token&) { return false; }
3108 
3109  private:
3110 
3111  inline std::size_t process_stride_2(generator& g)
3112  {
3113  typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3114 
3115  if (g.token_list_.size() < 2)
3116  return 0;
3117 
3118  std::size_t changes = 0;
3119 
3120  for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i)
3121  {
3122  token t;
3123 
3124  while (join(g[i], g[i + 1], t))
3125  {
3126  g.token_list_[i] = t;
3127 
3128  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1));
3129 
3130  ++changes;
3131 
3132  if (static_cast<std::size_t>(i + 1) >= g.token_list_.size())
3133  break;
3134  }
3135  }
3136 
3137  return changes;
3138  }
3139 
3140  inline std::size_t process_stride_3(generator& g)
3141  {
3142  typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t;
3143 
3144  if (g.token_list_.size() < 3)
3145  return 0;
3146 
3147  std::size_t changes = 0;
3148 
3149  for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i)
3150  {
3151  token t;
3152 
3153  while (join(g[i], g[i + 1], g[i + 2], t))
3154  {
3155  g.token_list_[i] = t;
3156 
3157  g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1),
3158  g.token_list_.begin() + static_cast<diff_t>(i + 3));
3159  ++changes;
3160 
3161  if (static_cast<std::size_t>(i + 2) >= g.token_list_.size())
3162  break;
3163  }
3164  }
3165 
3166  return changes;
3167  }
3168 
3169  const std::size_t stride_;
3170  };
3171 
3172  namespace helper
3173  {
3174 
3176  {
3177  for (std::size_t i = 0; i < generator.size(); ++i)
3178  {
3179  lexer::token t = generator[i];
3180  printf("Token[%02d] @ %03d %6s --> '%s'\n",
3181  static_cast<int>(i),
3182  static_cast<int>(t.position),
3183  t.to_str(t.type).c_str(),
3184  t.value.c_str());
3185  }
3186  }
3187 
3189  {
3190  public:
3191 
3193 
3195  : lexer::token_inserter(2)
3196  {}
3197 
3198  inline void ignore_symbol(const std::string& symbol)
3199  {
3200  ignore_set_.insert(symbol);
3201  }
3202 
3203  inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token)
3204  {
3205  bool match = false;
3206  new_token.type = lexer::token::e_mul;
3207  new_token.value = "*";
3208  new_token.position = t1.position;
3209 
3210  if (t0.type == lexer::token::e_symbol)
3211  {
3212  if (ignore_set_.end() != ignore_set_.find(t0.value))
3213  {
3214  return -1;
3215  }
3216  else if (!t0.value.empty() && ('$' == t0.value[0]))
3217  {
3218  return -1;
3219  }
3220  }
3221 
3222  if (t1.type == lexer::token::e_symbol)
3223  {
3224  if (ignore_set_.end() != ignore_set_.find(t1.value))
3225  {
3226  return -1;
3227  }
3228  }
3229  if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true;
3230  else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true;
3231  else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true;
3232  else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true;
3233  else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true;
3234  else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true;
3235  else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true;
3236  else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true;
3237  else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true;
3238  else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3239  else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true;
3240  else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true;
3241 
3242  return (match) ? 1 : -1;
3243  }
3244 
3245  private:
3246 
3247  std::set<std::string,details::ilesscompare> ignore_set_;
3248  };
3249 
3251  {
3252  public:
3253 
3254  explicit operator_joiner(const std::size_t& stride)
3255  : token_joiner(stride)
3256  {}
3257 
3258  inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t)
3259  {
3260  // ': =' --> ':='
3261  if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq))
3262  {
3263  t.type = lexer::token::e_assign;
3264  t.value = ":=";
3265  t.position = t0.position;
3266 
3267  return true;
3268  }
3269  // '+ =' --> '+='
3270  else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq))
3271  {
3272  t.type = lexer::token::e_addass;
3273  t.value = "+=";
3274  t.position = t0.position;
3275 
3276  return true;
3277  }
3278  // '- =' --> '-='
3279  else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq))
3280  {
3281  t.type = lexer::token::e_subass;
3282  t.value = "-=";
3283  t.position = t0.position;
3284 
3285  return true;
3286  }
3287  // '* =' --> '*='
3288  else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq))
3289  {
3290  t.type = lexer::token::e_mulass;
3291  t.value = "*=";
3292  t.position = t0.position;
3293 
3294  return true;
3295  }
3296  // '/ =' --> '/='
3297  else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq))
3298  {
3299  t.type = lexer::token::e_divass;
3300  t.value = "/=";
3301  t.position = t0.position;
3302 
3303  return true;
3304  }
3305  // '% =' --> '%='
3306  else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq))
3307  {
3308  t.type = lexer::token::e_modass;
3309  t.value = "%=";
3310  t.position = t0.position;
3311 
3312  return true;
3313  }
3314  // '> =' --> '>='
3315  else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq))
3316  {
3317  t.type = lexer::token::e_gte;
3318  t.value = ">=";
3319  t.position = t0.position;
3320 
3321  return true;
3322  }
3323  // '< =' --> '<='
3324  else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq))
3325  {
3326  t.type = lexer::token::e_lte;
3327  t.value = "<=";
3328  t.position = t0.position;
3329 
3330  return true;
3331  }
3332  // '= =' --> '=='
3333  else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq))
3334  {
3335  t.type = lexer::token::e_eq;
3336  t.value = "==";
3337  t.position = t0.position;
3338 
3339  return true;
3340  }
3341  // '! =' --> '!='
3342  else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq))
3343  {
3344  t.type = lexer::token::e_ne;
3345  t.value = "!=";
3346  t.position = t0.position;
3347 
3348  return true;
3349  }
3350  // '< >' --> '<>'
3351  else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt))
3352  {
3353  t.type = lexer::token::e_ne;
3354  t.value = "<>";
3355  t.position = t0.position;
3356 
3357  return true;
3358  }
3359  // '<= >' --> '<=>'
3360  else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt))
3361  {
3362  t.type = lexer::token::e_swap;
3363  t.value = "<=>";
3364  t.position = t0.position;
3365 
3366  return true;
3367  }
3368  // '+ -' --> '-'
3369  else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub))
3370  {
3371  t.type = lexer::token::e_sub;
3372  t.value = "-";
3373  t.position = t0.position;
3374 
3375  return true;
3376  }
3377  // '- +' --> '-'
3378  else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add))
3379  {
3380  t.type = lexer::token::e_sub;
3381  t.value = "-";
3382  t.position = t0.position;
3383 
3384  return true;
3385  }
3386  // '- -' --> '+'
3387  else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub))
3388  {
3389  /*
3390  Note: May need to reconsider this when wanting to implement
3391  pre/postfix decrement operator
3392  */
3393  t.type = lexer::token::e_add;
3394  t.value = "+";
3395  t.position = t0.position;
3396 
3397  return true;
3398  }
3399  else
3400  return false;
3401  }
3402 
3403  inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t)
3404  {
3405  // '[ * ]' --> '[*]'
3406  if (
3408  (t1.type == lexer::token::e_mul ) &&
3410  )
3411  {
3412  t.type = lexer::token::e_symbol;
3413  t.value = "[*]";
3414  t.position = t0.position;
3415 
3416  return true;
3417  }
3418  else
3419  return false;
3420  }
3421  };
3422 
3424  {
3425  public:
3426 
3427  using lexer::token_scanner::operator();
3428 
3430  : token_scanner(1),
3431  state_(true)
3432  {}
3433 
3434  bool result()
3435  {
3436  if (!stack_.empty())
3437  {
3438  lexer::token t;
3439  t.value = stack_.top().first;
3440  t.position = stack_.top().second;
3441  error_token_ = t;
3442  state_ = false;
3443 
3444  return false;
3445  }
3446  else
3447  return state_;
3448  }
3449 
3451  {
3452  return error_token_;
3453  }
3454 
3455  void reset()
3456  {
3457  // Why? because msvc doesn't support swap properly.
3458  stack_ = std::stack<std::pair<char,std::size_t> >();
3459  state_ = true;
3460  error_token_.clear();
3461  }
3462 
3464  {
3465  if (
3466  !t.value.empty() &&
3467  (lexer::token::e_string != t.type) &&
3468  (lexer::token::e_symbol != t.type) &&
3469  exprtk::details::is_bracket(t.value[0])
3470  )
3471  {
3472  details::char_t c = t.value[0];
3473 
3474  if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position));
3475  else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position));
3476  else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position));
3478  {
3479  if (stack_.empty())
3480  {
3481  state_ = false;
3482  error_token_ = t;
3483 
3484  return false;
3485  }
3486  else if (c != stack_.top().first)
3487  {
3488  state_ = false;
3489  error_token_ = t;
3490 
3491  return false;
3492  }
3493  else
3494  stack_.pop();
3495  }
3496  }
3497 
3498  return true;
3499  }
3500 
3501  private:
3502 
3503  bool state_;
3504  std::stack<std::pair<char,std::size_t> > stack_;
3506  };
3507 
3509  {
3510  public:
3511 
3512  using lexer::token_scanner::operator();
3513 
3515  : token_scanner (1),
3516  current_index_(0)
3517  {}
3518 
3519  bool result()
3520  {
3521  return error_list_.empty();
3522  }
3523 
3524  void reset()
3525  {
3526  error_list_.clear();
3527  current_index_ = 0;
3528  }
3529 
3531  {
3532  if (token::e_number == t.type)
3533  {
3534  double v;
3535 
3536  if (!exprtk::details::string_to_real(t.value,v))
3537  {
3538  error_list_.push_back(current_index_);
3539  }
3540  }
3541 
3542  ++current_index_;
3543 
3544  return true;
3545  }
3546 
3547  std::size_t error_count() const
3548  {
3549  return error_list_.size();
3550  }
3551 
3552  std::size_t error_index(const std::size_t& i)
3553  {
3554  if (i < error_list_.size())
3555  return error_list_[i];
3556  else
3558  }
3559 
3561  {
3562  error_list_.clear();
3563  }
3564 
3565  private:
3566 
3567  std::size_t current_index_;
3568  std::vector<std::size_t> error_list_;
3569  };
3570 
3572  {
3573  private:
3574 
3575  typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t;
3576 
3577  public:
3578 
3579  bool remove(const std::string& target_symbol)
3580  {
3581  const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3582 
3583  if (replace_map_.end() == itr)
3584  return false;
3585 
3586  replace_map_.erase(itr);
3587 
3588  return true;
3589  }
3590 
3591  bool add_replace(const std::string& target_symbol,
3592  const std::string& replace_symbol,
3594  {
3595  const replace_map_t::iterator itr = replace_map_.find(target_symbol);
3596 
3597  if (replace_map_.end() != itr)
3598  {
3599  return false;
3600  }
3601 
3602  replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type);
3603 
3604  return true;
3605  }
3606 
3607  void clear()
3608  {
3609  replace_map_.clear();
3610  }
3611 
3612  private:
3613 
3615  {
3616  if (lexer::token::e_symbol == t.type)
3617  {
3618  if (replace_map_.empty())
3619  return false;
3620 
3621  const replace_map_t::iterator itr = replace_map_.find(t.value);
3622 
3623  if (replace_map_.end() != itr)
3624  {
3625  t.value = itr->second.first;
3626  t.type = itr->second.second;
3627 
3628  return true;
3629  }
3630  }
3631 
3632  return false;
3633  }
3634 
3636  };
3637 
3639  {
3640  private:
3641 
3642  typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t;
3643  typedef std::set<token_pair_t> set_t;
3644 
3645  public:
3646 
3647  using lexer::token_scanner::operator();
3648 
3650  : lexer::token_scanner(2)
3651  {
3674  }
3675 
3676  bool result()
3677  {
3678  return error_list_.empty();
3679  }
3680 
3681  bool operator() (const lexer::token& t0, const lexer::token& t1)
3682  {
3683  const set_t::value_type p = std::make_pair(t0.type,t1.type);
3684 
3685  if (invalid_bracket_check(t0.type,t1.type))
3686  {
3687  error_list_.push_back(std::make_pair(t0,t1));
3688  }
3689  else if (invalid_comb_.find(p) != invalid_comb_.end())
3690  {
3691  error_list_.push_back(std::make_pair(t0,t1));
3692  }
3693 
3694  return true;
3695  }
3696 
3697  std::size_t error_count() const
3698  {
3699  return error_list_.size();
3700  }
3701 
3702  std::pair<lexer::token,lexer::token> error(const std::size_t index)
3703  {
3704  if (index < error_list_.size())
3705  {
3706  return error_list_[index];
3707  }
3708  else
3709  {
3710  static const lexer::token error_token;
3711  return std::make_pair(error_token,error_token);
3712  }
3713  }
3714 
3716  {
3717  error_list_.clear();
3718  }
3719 
3720  private:
3721 
3723  {
3724  invalid_comb_.insert(std::make_pair(base,t));
3725  }
3726 
3728  {
3744  }
3745 
3747  {
3748  if (details::is_right_bracket(static_cast<char>(base)))
3749  {
3750  switch (t)
3751  {
3752  case lexer::token::e_assign : return (']' != base);
3753  case lexer::token::e_string : return true;
3754  default : return false;
3755  }
3756  }
3757  else if (details::is_left_bracket(static_cast<char>(base)))
3758  {
3759  if (details::is_right_bracket(static_cast<char>(t)))
3760  return false;
3761  else if (details::is_left_bracket(static_cast<char>(t)))
3762  return false;
3763  else
3764  {
3765  switch (t)
3766  {
3767  case lexer::token::e_number : return false;
3768  case lexer::token::e_symbol : return false;
3769  case lexer::token::e_string : return false;
3770  case lexer::token::e_add : return false;
3771  case lexer::token::e_sub : return false;
3772  case lexer::token::e_colon : return false;
3773  case lexer::token::e_ternary : return false;
3774  default : return true ;
3775  }
3776  }
3777  }
3778  else if (details::is_right_bracket(static_cast<char>(t)))
3779  {
3780  switch (base)
3781  {
3782  case lexer::token::e_number : return false;
3783  case lexer::token::e_symbol : return false;
3784  case lexer::token::e_string : return false;
3785  case lexer::token::e_eof : return false;
3786  case lexer::token::e_colon : return false;
3787  case lexer::token::e_ternary : return false;
3788  default : return true ;
3789  }
3790  }
3791  else if (details::is_left_bracket(static_cast<char>(t)))
3792  {
3793  switch (base)
3794  {
3795  case lexer::token::e_rbracket : return true;
3796  case lexer::token::e_rsqrbracket : return true;
3797  case lexer::token::e_rcrlbracket : return true;
3798  default : return false;
3799  }
3800  }
3801 
3802  return false;
3803  }
3804 
3806  std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3807  };
3808 
3810  {
3811  private:
3812 
3814  typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t;
3815  typedef std::set<token_triplet_t> set_t;
3816 
3817  public:
3818 
3819  using lexer::token_scanner::operator();
3820 
3822  : lexer::token_scanner(3)
3823  {
3827 
3834 
3841  }
3842 
3843  bool result()
3844  {
3845  return error_list_.empty();
3846  }
3847 
3848  bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2)
3849  {
3850  const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type));
3851 
3852  if (invalid_comb_.find(p) != invalid_comb_.end())
3853  {
3854  error_list_.push_back(std::make_pair(t0,t1));
3855  }
3856 
3857  return true;
3858  }
3859 
3860  std::size_t error_count() const
3861  {
3862  return error_list_.size();
3863  }
3864 
3865  std::pair<lexer::token,lexer::token> error(const std::size_t index)
3866  {
3867  if (index < error_list_.size())
3868  {
3869  return error_list_[index];
3870  }
3871  else
3872  {
3873  static const lexer::token error_token;
3874  return std::make_pair(error_token,error_token);
3875  }
3876  }
3877 
3879  {
3880  error_list_.clear();
3881  }
3882 
3883  private:
3884 
3886  {
3887  invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2)));
3888  }
3889 
3891  std::vector<std::pair<lexer::token,lexer::token> > error_list_;
3892  };
3893 
3895  {
3897  {
3898  if (token_scanner_list.end() != std::find(token_scanner_list.begin(),
3899  token_scanner_list.end (),
3900  scanner))
3901  {
3902  return false;
3903  }
3904 
3905  token_scanner_list.push_back(scanner);
3906 
3907  return true;
3908  }
3909 
3911  {
3912  if (token_modifier_list.end() != std::find(token_modifier_list.begin(),
3913  token_modifier_list.end (),
3914  modifier))
3915  {
3916  return false;
3917  }
3918 
3919  token_modifier_list.push_back(modifier);
3920 
3921  return true;
3922  }
3923 
3925  {
3926  if (token_joiner_list.end() != std::find(token_joiner_list.begin(),
3927  token_joiner_list.end (),
3928  joiner))
3929  {
3930  return false;
3931  }
3932 
3933  token_joiner_list.push_back(joiner);
3934 
3935  return true;
3936  }
3937 
3939  {
3940  if (token_inserter_list.end() != std::find(token_inserter_list.begin(),
3941  token_inserter_list.end (),
3942  inserter))
3943  {
3944  return false;
3945  }
3946 
3947  token_inserter_list.push_back(inserter);
3948 
3949  return true;
3950  }
3951 
3953  {
3954  error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0);
3955 
3956  for (std::size_t i = 0; i < token_modifier_list.size(); ++i)
3957  {
3958  lexer::token_modifier& modifier = (*token_modifier_list[i]);
3959 
3960  modifier.reset();
3961  modifier.process(g);
3962 
3963  if (!modifier.result())
3964  {
3966 
3967  return false;
3968  }
3969  }
3970 
3971  return true;
3972  }
3973 
3975  {
3976  error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0);
3977 
3978  for (std::size_t i = 0; i < token_joiner_list.size(); ++i)
3979  {
3980  lexer::token_joiner& joiner = (*token_joiner_list[i]);
3981 
3982  joiner.reset();
3983  joiner.process(g);
3984 
3985  if (!joiner.result())
3986  {
3988 
3989  return false;
3990  }
3991  }
3992 
3993  return true;
3994  }
3995 
3997  {
3998  error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0);
3999 
4000  for (std::size_t i = 0; i < token_inserter_list.size(); ++i)
4001  {
4002  lexer::token_inserter& inserter = (*token_inserter_list[i]);
4003 
4004  inserter.reset();
4005  inserter.process(g);
4006 
4007  if (!inserter.result())
4008  {
4010 
4011  return false;
4012  }
4013  }
4014 
4015  return true;
4016  }
4017 
4019  {
4020  error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0);
4021 
4022  for (std::size_t i = 0; i < token_scanner_list.size(); ++i)
4023  {
4024  lexer::token_scanner& scanner = (*token_scanner_list[i]);
4025 
4026  scanner.reset();
4027  scanner.process(g);
4028 
4029  if (!scanner.result())
4030  {
4032 
4033  return false;
4034  }
4035  }
4036 
4037  return true;
4038  }
4039 
4040  std::vector<lexer::token_scanner*> token_scanner_list;
4041  std::vector<lexer::token_modifier*> token_modifier_list;
4042  std::vector<lexer::token_joiner*> token_joiner_list;
4043  std::vector<lexer::token_inserter*> token_inserter_list;
4044 
4049  };
4050  }
4051 
4053  {
4054  public:
4055 
4056  typedef token token_t;
4058 
4059  inline bool init(const std::string& str)
4060  {
4061  if (!lexer_.process(str))
4062  {
4063  return false;
4064  }
4065 
4066  lexer_.begin();
4067 
4068  next_token();
4069 
4070  return true;
4071  }
4072 
4073  inline generator_t& lexer()
4074  {
4075  return lexer_;
4076  }
4077 
4078  inline const generator_t& lexer() const
4079  {
4080  return lexer_;
4081  }
4082 
4083  inline void store_token()
4084  {
4085  lexer_.store();
4087  }
4088 
4089  inline void restore_token()
4090  {
4091  lexer_.restore();
4093  }
4094 
4095  inline void next_token()
4096  {
4098  }
4099 
4100  inline const token_t& current_token() const
4101  {
4102  return current_token_;
4103  }
4104 
4106  {
4107  e_hold = 0,
4109  };
4110 
4111  inline void advance_token(const token_advance_mode mode)
4112  {
4113  if (e_advance == mode)
4114  {
4115  next_token();
4116  }
4117  }
4118 
4119  inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance)
4120  {
4121  if (current_token().type != ttype)
4122  {
4123  return false;
4124  }
4125 
4126  advance_token(mode);
4127 
4128  return true;
4129  }
4130 
4131  inline bool token_is(const token_t::token_type& ttype,
4132  const std::string& value,
4133  const token_advance_mode mode = e_advance)
4134  {
4135  if (
4136  (current_token().type != ttype) ||
4138  )
4139  {
4140  return false;
4141  }
4142 
4143  advance_token(mode);
4144 
4145  return true;
4146  }
4147 
4148  inline bool peek_token_is(const token_t::token_type& ttype)
4149  {
4150  return (lexer_.peek_next_token().type == ttype);
4151  }
4152 
4153  inline bool peek_token_is(const std::string& s)
4154  {
4156  }
4157 
4158  private:
4159 
4163  };
4164  }
4165 
4166  template <typename T>
4168  {
4169  public:
4170 
4171  typedef T* data_ptr_t;
4172 
4173  vector_view(data_ptr_t data, const std::size_t& size)
4174  : size_(size),
4175  data_(data),
4176  data_ref_(0)
4177  {}
4178 
4180  : size_(vv.size_),
4181  data_(vv.data_),
4182  data_ref_(0)
4183  {}
4184 
4185  inline void rebase(data_ptr_t data)
4186  {
4187  data_ = data;
4188 
4189  if (!data_ref_.empty())
4190  {
4191  for (std::size_t i = 0; i < data_ref_.size(); ++i)
4192  {
4193  (*data_ref_[i]) = data;
4194  }
4195  }
4196  }
4197 
4198  inline data_ptr_t data() const
4199  {
4200  return data_;
4201  }
4202 
4203  inline std::size_t size() const
4204  {
4205  return size_;
4206  }
4207 
4208  inline const T& operator[](const std::size_t index) const
4209  {
4210  return data_[index];
4211  }
4212 
4213  inline T& operator[](const std::size_t index)
4214  {
4215  return data_[index];
4216  }
4217 
4218  void set_ref(data_ptr_t* data_ref)
4219  {
4220  data_ref_.push_back(data_ref);
4221  }
4222 
4223  private:
4224 
4225  const std::size_t size_;
4227  std::vector<data_ptr_t*> data_ref_;
4228  };
4229 
4230  template <typename T>
4232  const std::size_t size, const std::size_t offset = 0)
4233  {
4234  return vector_view<T>(data + offset,size);
4235  }
4236 
4237  template <typename T>
4238  inline vector_view<T> make_vector_view(std::vector<T>& v,
4239  const std::size_t size, const std::size_t offset = 0)
4240  {
4241  return vector_view<T>(v.data() + offset,size);
4242  }
4243 
4244  template <typename T> class results_context;
4245 
4246  template <typename T>
4247  struct type_store
4248  {
4250  {
4255  };
4256 
4258  : data(0),
4259  size(0),
4260  type(e_unknown)
4261  {}
4262 
4263  union
4264  {
4265  void* data;
4267  };
4268 
4269  std::size_t size;
4271 
4273  {
4274  public:
4275 
4276  parameter_list(std::vector<type_store>& pl)
4277  : parameter_list_(pl)
4278  {}
4279 
4280  inline bool empty() const
4281  {
4282  return parameter_list_.empty();
4283  }
4284 
4285  inline std::size_t size() const
4286  {
4287  return parameter_list_.size();
4288  }
4289 
4290  inline type_store& operator[](const std::size_t& index)
4291  {
4292  return parameter_list_[index];
4293  }
4294 
4295  inline const type_store& operator[](const std::size_t& index) const
4296  {
4297  return parameter_list_[index];
4298  }
4299 
4300  inline type_store& front()
4301  {
4302  return parameter_list_[0];
4303  }
4304 
4305  inline const type_store& front() const
4306  {
4307  return parameter_list_[0];
4308  }
4309 
4310  inline type_store& back()
4311  {
4312  return parameter_list_.back();
4313  }
4314 
4315  inline const type_store& back() const
4316  {
4317  return parameter_list_.back();
4318  }
4319 
4320  private:
4321 
4322  std::vector<type_store>& parameter_list_;
4323 
4324  friend class results_context<T>;
4325  };
4326 
4327  template <typename ViewType>
4328  struct type_view
4329  {
4331  typedef ViewType value_t;
4332 
4334  : ts_(ts),
4335  data_(reinterpret_cast<value_t*>(ts_.data))
4336  {}
4337 
4339  : ts_(const_cast<type_store_t&>(ts)),
4340  data_(reinterpret_cast<value_t*>(ts_.data))
4341  {}
4342 
4343  inline std::size_t size() const
4344  {
4345  return ts_.size;
4346  }
4347 
4348  inline value_t& operator[](const std::size_t& i)
4349  {
4350  return data_[i];
4351  }
4352 
4353  inline const value_t& operator[](const std::size_t& i) const
4354  {
4355  return data_[i];
4356  }
4357 
4358  inline const value_t* begin() const { return data_; }
4359  inline value_t* begin() { return data_; }
4360 
4361  inline const value_t* end() const
4362  {
4363  return static_cast<value_t*>(data_ + ts_.size);
4364  }
4365 
4366  inline value_t* end()
4367  {
4368  return static_cast<value_t*>(data_ + ts_.size);
4369  }
4370 
4373  };
4374 
4377 
4379  {
4381  typedef T value_t;
4382 
4384  : v_(*reinterpret_cast<value_t*>(ts.data))
4385  {}
4386 
4388  : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data))
4389  {}
4390 
4392  {
4393  return v_;
4394  }
4395 
4396  inline const value_t& operator() () const
4397  {
4398  return v_;
4399  }
4400 
4401  template <typename IntType>
4402  inline bool to_int(IntType& i) const
4403  {
4405  return false;
4406 
4407  i = static_cast<IntType>(v_);
4408 
4409  return true;
4410  }
4411 
4412  template <typename UIntType>
4413  inline bool to_uint(UIntType& u) const
4414  {
4415  if (v_ < T(0))
4416  return false;
4418  return false;
4419 
4420  u = static_cast<UIntType>(v_);
4421 
4422  return true;
4423  }
4424 
4425  T& v_;
4426  };
4427  };
4428 
4429  template <typename StringView>
4430  inline std::string to_str(const StringView& view)
4431  {
4432  return std::string(view.begin(),view.size());
4433  }
4434 
4435  #ifndef exprtk_disable_return_statement
4436  namespace details
4437  {
4438  template <typename T> class return_node;
4439  template <typename T> class return_envelope_node;
4440  }
4441  #endif
4442 
4443  template <typename T>
4444  class results_context
4445  {
4446  public:
4447 
4449 
4451  : results_available_(false)
4452  {}
4453 
4454  inline std::size_t count() const
4455  {
4456  if (results_available_)
4457  return parameter_list_.size();
4458  else
4459  return 0;
4460  }
4461 
4462  inline type_store_t& operator[](const std::size_t& index)
4463  {
4464  return parameter_list_[index];
4465  }
4466 
4467  inline const type_store_t& operator[](const std::size_t& index) const
4468  {
4469  return parameter_list_[index];
4470  }
4471 
4472  private:
4473 
4474  inline void clear()
4475  {
4476  results_available_ = false;
4477  }
4478 
4479  typedef std::vector<type_store_t> ts_list_t;
4481 
4482  inline void assign(const parameter_list_t& pl)
4483  {
4485  results_available_ = true;
4486  }
4487 
4490 
4491  #ifndef exprtk_disable_return_statement
4492  friend class details::return_node<T>;
4494  #endif
4495  };
4496 
4497  namespace details
4498  {
4500  {
4525 
4526  // Do not add new functions/operators after this point.
4527  e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003,
4528  e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007,
4529  e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011,
4530  e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015,
4531  e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019,
4532  e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023,
4533  e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027,
4534  e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031,
4535  e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035,
4536  e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039,
4537  e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043,
4538  e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047,
4539  e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051,
4540  e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055,
4541  e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059,
4542  e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063,
4543  e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067,
4544  e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071,
4545  e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075,
4546  e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079,
4547  e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083,
4548  e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087,
4549  e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091,
4550  e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095,
4551  e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099,
4552  e_sffinal = 1100,
4553  e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003,
4554  e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007,
4555  e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011,
4556  e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015,
4557  e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019,
4558  e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023,
4559  e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027,
4560  e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031,
4561  e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035,
4562  e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039,
4563  e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043,
4564  e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047,
4565  e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051,
4566  e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055,
4567  e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059,
4568  e_sf4ext60 = 2060, e_sf4ext61 = 2061
4569  };
4570 
4572  {
4573  switch (opr)
4574  {
4575  case e_add : return "+";
4576  case e_sub : return "-";
4577  case e_mul : return "*";
4578  case e_div : return "/";
4579  case e_mod : return "%";
4580  case e_pow : return "^";
4581  case e_assign : return ":=";
4582  case e_addass : return "+=";
4583  case e_subass : return "-=";
4584  case e_mulass : return "*=";
4585  case e_divass : return "/=";
4586  case e_modass : return "%=";
4587  case e_lt : return "<";
4588  case e_lte : return "<=";
4589  case e_eq : return "==";
4590  case e_equal : return "=";
4591  case e_ne : return "!=";
4592  case e_nequal : return "<>";
4593  case e_gte : return ">=";
4594  case e_gt : return ">";
4595  default : return"N/A";
4596  }
4597  }
4598 
4600  {
4601  base_operation_t(const operator_type t, const unsigned int& np)
4602  : type(t),
4603  num_params(np)
4604  {}
4605 
4607  unsigned int num_params;
4608  };
4609 
4610  namespace loop_unroll
4611  {
4612  #ifndef exprtk_disable_superscalar_unroll
4613  const unsigned int global_loop_batch_size = 16;
4614  #else
4615  const unsigned int global_loop_batch_size = 4;
4616  #endif
4617 
4618  struct details
4619  {
4620  details(const std::size_t& vsize,
4621  const unsigned int loop_batch_size = global_loop_batch_size)
4622  : batch_size(loop_batch_size ),
4623  remainder (vsize % batch_size),
4624  upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0)))
4625  {}
4626 
4627  unsigned int batch_size;
4630  };
4631  }
4632 
4633  #ifdef exprtk_enable_debugging
4634  inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0)
4635  {
4636  if (size)
4637  exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
4638  else
4639  exprtk_debug(("%s - addr: %p size: %d\n",
4640  s.c_str(),
4641  ptr,
4642  static_cast<unsigned int>(size)));
4643  }
4644  #else
4645  inline void dump_ptr(const std::string&, const void*) {}
4646  inline void dump_ptr(const std::string&, const void*, const std::size_t) {}
4647  #endif
4648 
4649  template <typename T>
4651  {
4652  public:
4653 
4655  typedef T* data_t;
4656 
4657  private:
4658 
4660  {
4662  : ref_count(1),
4663  size (0),
4664  data (0),
4665  destruct (true)
4666  {}
4667 
4668  control_block(const std::size_t& dsize)
4669  : ref_count(1 ),
4670  size (dsize),
4671  data (0 ),
4672  destruct (true )
4673  { create_data(); }
4674 
4675  control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
4676  : ref_count(1 ),
4677  size (dsize ),
4678  data (dptr ),
4679  destruct (dstrct)
4680  {}
4681 
4683  {
4684  if (data && destruct && (0 == ref_count))
4685  {
4686  dump_ptr("~control_block() data",data);
4687  delete[] data;
4688  data = reinterpret_cast<data_t>(0);
4689  }
4690  }
4691 
4692  static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false)
4693  {
4694  if (dsize)
4695  {
4696  if (0 == data_ptr)
4697  return (new control_block(dsize));
4698  else
4699  return (new control_block(dsize, data_ptr, dstrct));
4700  }
4701  else
4702  return (new control_block);
4703  }
4704 
4705  static inline void destroy(control_block*& cntrl_blck)
4706  {
4707  if (cntrl_blck)
4708  {
4709  if (
4710  (0 != cntrl_blck->ref_count) &&
4711  (0 == --cntrl_blck->ref_count)
4712  )
4713  {
4714  delete cntrl_blck;
4715  }
4716 
4717  cntrl_blck = 0;
4718  }
4719  }
4720 
4721  std::size_t ref_count;
4722  std::size_t size;
4724  bool destruct;
4725 
4726  private:
4727 
4728  control_block(const control_block&);
4730 
4731  inline void create_data()
4732  {
4733  destruct = true;
4734  data = new T[size];
4735  std::fill_n(data,size,T(0));
4736  dump_ptr("control_block::create_data() - data",data,size);
4737  }
4738  };
4739 
4740  public:
4741 
4743  : control_block_(control_block::create(0))
4744  {}
4745 
4746  vec_data_store(const std::size_t& size)
4747  : control_block_(control_block::create(size,(data_t)(0),true))
4748  {}
4749 
4750  vec_data_store(const std::size_t& size, data_t data, bool dstrct = false)
4751  : control_block_(control_block::create(size, data, dstrct))
4752  {}
4753 
4754  vec_data_store(const type& vds)
4755  {
4758  }
4759 
4761  {
4763  }
4764 
4765  type& operator=(const type& vds)
4766  {
4767  if (this != &vds)
4768  {
4769  std::size_t final_size = min_size(control_block_, vds.control_block_);
4770 
4771  vds.control_block_->size = final_size;
4772  control_block_->size = final_size;
4773 
4774  if (control_block_->destruct || (0 == control_block_->data))
4775  {
4777 
4780  }
4781  }
4782 
4783  return (*this);
4784  }
4785 
4786  inline data_t data()
4787  {
4788  return control_block_->data;
4789  }
4790 
4791  inline data_t data() const
4792  {
4793  return control_block_->data;
4794  }
4795 
4796  inline std::size_t size()
4797  {
4798  return control_block_->size;
4799  }
4800 
4801  inline std::size_t size() const
4802  {
4803  return control_block_->size;
4804  }
4805 
4806  inline data_t& ref()
4807  {
4808  return control_block_->data;
4809  }
4810 
4811  inline void dump() const
4812  {
4813  #ifdef exprtk_enable_debugging
4814  exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
4815  size(),
4816  data(),
4817  (control_block_->destruct ? 'T' : 'F')));
4818 
4819  for (std::size_t i = 0; i < size(); ++i)
4820  {
4821  if (5 == i)
4822  exprtk_debug(("\n"));
4823 
4824  exprtk_debug(("%15.10f ",data()[i]));
4825  }
4826  exprtk_debug(("\n"));
4827  #endif
4828  }
4829 
4830  static inline void match_sizes(type& vds0, type& vds1)
4831  {
4832  std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
4833  vds0.control_block_->size = size;
4834  vds1.control_block_->size = size;
4835  }
4836 
4837  private:
4838 
4839  static inline std::size_t min_size(control_block* cb0, control_block* cb1)
4840  {
4841  const std::size_t size0 = cb0->size;
4842  const std::size_t size1 = cb1->size;
4843 
4844  if (size0 && size1)
4845  return std::min(size0,size1);
4846  else
4847  return (size0) ? size0 : size1;
4848  }
4849 
4851  };
4852 
4853  namespace numeric
4854  {
4855  namespace details
4856  {
4857  template <typename T>
4858  inline T process_impl(const operator_type operation, const T arg)
4859  {
4860  switch (operation)
4861  {
4862  case e_abs : return numeric::abs (arg);
4863  case e_acos : return numeric::acos (arg);
4864  case e_acosh : return numeric::acosh(arg);
4865  case e_asin : return numeric::asin (arg);
4866  case e_asinh : return numeric::asinh(arg);
4867  case e_atan : return numeric::atan (arg);
4868  case e_atanh : return numeric::atanh(arg);
4869  case e_ceil : return numeric::ceil (arg);
4870  case e_cos : return numeric::cos (arg);
4871  case e_cosh : return numeric::cosh (arg);
4872  case e_exp : return numeric::exp (arg);
4873  case e_expm1 : return numeric::expm1(arg);
4874  case e_floor : return numeric::floor(arg);
4875  case e_log : return numeric::log (arg);
4876  case e_log10 : return numeric::log10(arg);
4877  case e_log2 : return numeric::log2 (arg);
4878  case e_log1p : return numeric::log1p(arg);
4879  case e_neg : return numeric::neg (arg);
4880  case e_pos : return numeric::pos (arg);
4881  case e_round : return numeric::round(arg);
4882  case e_sin : return numeric::sin (arg);
4883  case e_sinc : return numeric::sinc (arg);
4884  case e_sinh : return numeric::sinh (arg);
4885  case e_sqrt : return numeric::sqrt (arg);
4886  case e_tan : return numeric::tan (arg);
4887  case e_tanh : return numeric::tanh (arg);
4888  case e_cot : return numeric::cot (arg);
4889  case e_sec : return numeric::sec (arg);
4890  case e_csc : return numeric::csc (arg);
4891  case e_r2d : return numeric::r2d (arg);
4892  case e_d2r : return numeric::d2r (arg);
4893  case e_d2g : return numeric::d2g (arg);
4894  case e_g2d : return numeric::g2d (arg);
4895  case e_notl : return numeric::notl (arg);
4896  case e_sgn : return numeric::sgn (arg);
4897  case e_erf : return numeric::erf (arg);
4898  case e_erfc : return numeric::erfc (arg);
4899  case e_ncdf : return numeric::ncdf (arg);
4900  case e_frac : return numeric::frac (arg);
4901  case e_trunc : return numeric::trunc(arg);
4902 
4903  default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n"));
4904  return std::numeric_limits<T>::quiet_NaN();
4905  }
4906  }
4907 
4908  template <typename T>
4909  inline T process_impl(const operator_type operation, const T arg0, const T arg1)
4910  {
4911  switch (operation)
4912  {
4913  case e_add : return (arg0 + arg1);
4914  case e_sub : return (arg0 - arg1);
4915  case e_mul : return (arg0 * arg1);
4916  case e_div : return (arg0 / arg1);
4917  case e_mod : return modulus<T>(arg0,arg1);
4918  case e_pow : return pow<T>(arg0,arg1);
4919  case e_atan2 : return atan2<T>(arg0,arg1);
4920  case e_min : return std::min<T>(arg0,arg1);
4921  case e_max : return std::max<T>(arg0,arg1);
4922  case e_logn : return logn<T>(arg0,arg1);
4923  case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4924  case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4925  case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4926  case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0);
4927  case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4928  case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4929  case e_and : return and_opr <T>(arg0,arg1);
4930  case e_nand : return nand_opr<T>(arg0,arg1);
4931  case e_or : return or_opr <T>(arg0,arg1);
4932  case e_nor : return nor_opr <T>(arg0,arg1);
4933  case e_xor : return xor_opr <T>(arg0,arg1);
4934  case e_xnor : return xnor_opr<T>(arg0,arg1);
4935  case e_root : return root <T>(arg0,arg1);
4936  case e_roundn : return roundn <T>(arg0,arg1);
4937  case e_equal : return equal (arg0,arg1);
4938  case e_nequal : return nequal (arg0,arg1);
4939  case e_hypot : return hypot <T>(arg0,arg1);
4940  case e_shr : return shr <T>(arg0,arg1);
4941  case e_shl : return shl <T>(arg0,arg1);
4942 
4943  default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n"));
4944  return std::numeric_limits<T>::quiet_NaN();
4945  }
4946  }
4947 
4948  template <typename T>
4949  inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag)
4950  {
4951  switch (operation)
4952  {
4953  case e_add : return (arg0 + arg1);
4954  case e_sub : return (arg0 - arg1);
4955  case e_mul : return (arg0 * arg1);
4956  case e_div : return (arg0 / arg1);
4957  case e_mod : return arg0 % arg1;
4958  case e_pow : return pow<T>(arg0,arg1);
4959  case e_min : return std::min<T>(arg0,arg1);
4960  case e_max : return std::max<T>(arg0,arg1);
4961  case e_logn : return logn<T>(arg0,arg1);
4962  case e_lt : return (arg0 < arg1) ? T(1) : T(0);
4963  case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
4964  case e_eq : return (arg0 == arg1) ? T(1) : T(0);
4965  case e_ne : return (arg0 != arg1) ? T(1) : T(0);
4966  case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
4967  case e_gt : return (arg0 > arg1) ? T(1) : T(0);
4968  case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
4969  case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
4970  case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
4971  case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
4972  case e_xor : return arg0 ^ arg1;
4973  case e_xnor : return !(arg0 ^ arg1);
4974  case e_root : return root<T>(arg0,arg1);
4975  case e_equal : return arg0 == arg1;
4976  case e_nequal : return arg0 != arg1;
4977  case e_hypot : return hypot<T>(arg0,arg1);
4978  case e_shr : return arg0 >> arg1;
4979  case e_shl : return arg0 << arg1;
4980 
4981  default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n"));
4982  return std::numeric_limits<T>::quiet_NaN();
4983  }
4984  }
4985  }
4986 
4987  template <typename T>
4988  inline T process(const operator_type operation, const T arg)
4989  {
4991  }
4992 
4993  template <typename T>
4994  inline T process(const operator_type operation, const T arg0, const T arg1)
4995  {
4996  return exprtk::details::numeric::details::process_impl(operation, arg0, arg1);
4997  }
4998  }
4999 
5000  template <typename T>
5002  {
5003  public:
5004 
5006  {
5044  };
5045 
5046  typedef T value_type;
5048 
5050  {}
5051 
5052  inline virtual T value() const
5053  {
5054  return std::numeric_limits<T>::quiet_NaN();
5055  }
5056 
5057  inline virtual expression_node<T>* branch(const std::size_t& index = 0) const
5058  {
5059  return reinterpret_cast<expression_ptr>(index * 0);
5060  }
5061 
5062  inline virtual node_type type() const
5063  {
5064  return e_none;
5065  }
5066  };
5067 
5068  template <typename T>
5069  inline bool is_generally_string_node(const expression_node<T>* node);
5070 
5071  inline bool is_true(const double v)
5072  {
5073  return std::not_equal_to<double>()(0.0,v);
5074  }
5075 
5076  inline bool is_true(const long double v)
5077  {
5078  return std::not_equal_to<long double>()(0.0L,v);
5079  }
5080 
5081  inline bool is_true(const float v)
5082  {
5083  return std::not_equal_to<float>()(0.0f,v);
5084  }
5085 
5086  template <typename T>
5087  inline bool is_true(const std::complex<T>& v)
5088  {
5089  return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v);
5090  }
5091 
5092  template <typename T>
5093  inline bool is_true(const expression_node<T>* node)
5094  {
5095  return std::not_equal_to<T>()(T(0),node->value());
5096  }
5097 
5098  template <typename T>
5099  inline bool is_false(const expression_node<T>* node)
5100  {
5101  return std::equal_to<T>()(T(0),node->value());
5102  }
5103 
5104  template <typename T>
5105  inline bool is_unary_node(const expression_node<T>* node)
5106  {
5107  return node && (details::expression_node<T>::e_unary == node->type());
5108  }
5109 
5110  template <typename T>
5111  inline bool is_neg_unary_node(const expression_node<T>* node)
5112  {
5113  return node && (details::expression_node<T>::e_neg == node->type());
5114  }
5115 
5116  template <typename T>
5117  inline bool is_binary_node(const expression_node<T>* node)
5118  {
5119  return node && (details::expression_node<T>::e_binary == node->type());
5120  }
5121 
5122  template <typename T>
5123  inline bool is_variable_node(const expression_node<T>* node)
5124  {
5125  return node && (details::expression_node<T>::e_variable == node->type());
5126  }
5127 
5128  template <typename T>
5129  inline bool is_ivariable_node(const expression_node<T>* node)
5130  {
5131  return node &&
5132  (
5137  );
5138  }
5139 
5140  template <typename T>
5141  inline bool is_vector_elem_node(const expression_node<T>* node)
5142  {
5143  return node && (details::expression_node<T>::e_vecelem == node->type());
5144  }
5145 
5146  template <typename T>
5148  {
5149  return node && (details::expression_node<T>::e_rbvecelem == node->type());
5150  }
5151 
5152  template <typename T>
5154  {
5155  return node && (details::expression_node<T>::e_rbveccelem == node->type());
5156  }
5157 
5158  template <typename T>
5159  inline bool is_vector_node(const expression_node<T>* node)
5160  {
5161  return node && (details::expression_node<T>::e_vector == node->type());
5162  }
5163 
5164  template <typename T>
5165  inline bool is_ivector_node(const expression_node<T>* node)
5166  {
5167  if (node)
5168  {
5169  switch (node->type())
5170  {
5180  case details::expression_node<T>::e_vecunaryop : return true;
5181  default : return false;
5182  }
5183  }
5184  else
5185  return false;
5186  }
5187 
5188  template <typename T>
5189  inline bool is_constant_node(const expression_node<T>* node)
5190  {
5191  return node && (details::expression_node<T>::e_constant == node->type());
5192  }
5193 
5194  template <typename T>
5195  inline bool is_null_node(const expression_node<T>* node)
5196  {
5197  return node && (details::expression_node<T>::e_null == node->type());
5198  }
5199 
5200  template <typename T>
5201  inline bool is_break_node(const expression_node<T>* node)
5202  {
5203  return node && (details::expression_node<T>::e_break == node->type());
5204  }
5205 
5206  template <typename T>
5207  inline bool is_continue_node(const expression_node<T>* node)
5208  {
5209  return node && (details::expression_node<T>::e_continue == node->type());
5210  }
5211 
5212  template <typename T>
5213  inline bool is_swap_node(const expression_node<T>* node)
5214  {
5215  return node && (details::expression_node<T>::e_swap == node->type());
5216  }
5217 
5218  template <typename T>
5219  inline bool is_function(const expression_node<T>* node)
5220  {
5221  return node && (details::expression_node<T>::e_function == node->type());
5222  }
5223 
5224  template <typename T>
5225  inline bool is_return_node(const expression_node<T>* node)
5226  {
5227  return node && (details::expression_node<T>::e_return == node->type());
5228  }
5229 
5230  template <typename T> class unary_node;
5231 
5232  template <typename T>
5233  inline bool is_negate_node(const expression_node<T>* node)
5234  {
5235  if (node && is_unary_node(node))
5236  {
5237  return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation());
5238  }
5239  else
5240  return false;
5241  }
5242 
5243  template <typename T>
5245  {
5246  return !is_variable_node(node) &&
5247  !is_string_node (node) ;
5248  }
5249 
5250  template <std::size_t N, typename T>
5251  inline bool all_nodes_valid(expression_node<T>* (&b)[N])
5252  {
5253  for (std::size_t i = 0; i < N; ++i)
5254  {
5255  if (0 == b[i]) return false;
5256  }
5257 
5258  return true;
5259  }
5260 
5261  template <typename T,
5262  typename Allocator,
5263  template <typename, typename> class Sequence>
5264  inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b)
5265  {
5266  for (std::size_t i = 0; i < b.size(); ++i)
5267  {
5268  if (0 == b[i]) return false;
5269  }
5270 
5271  return true;
5272  }
5273 
5274  template <std::size_t N, typename T>
5276  {
5277  for (std::size_t i = 0; i < N; ++i)
5278  {
5279  if (0 == b[i])
5280  return false;
5281  else if (!is_variable_node(b[i]))
5282  return false;
5283  }
5284 
5285  return true;
5286  }
5287 
5288  template <typename T,
5289  typename Allocator,
5290  template <typename, typename> class Sequence>
5291  inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b)
5292  {
5293  for (std::size_t i = 0; i < b.size(); ++i)
5294  {
5295  if (0 == b[i])
5296  return false;
5297  else if (!is_variable_node(b[i]))
5298  return false;
5299  }
5300 
5301  return true;
5302  }
5303 
5304  template <typename NodeAllocator, typename T, std::size_t N>
5305  inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N])
5306  {
5307  for (std::size_t i = 0; i < N; ++i)
5308  {
5309  free_node(node_allocator,b[i]);
5310  }
5311  }
5312 
5313  template <typename NodeAllocator,
5314  typename T,
5315  typename Allocator,
5316  template <typename, typename> class Sequence>
5317  inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b)
5318  {
5319  for (std::size_t i = 0; i < b.size(); ++i)
5320  {
5321  free_node(node_allocator,b[i]);
5322  }
5323 
5324  b.clear();
5325  }
5326 
5327  template <typename NodeAllocator, typename T>
5328  inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false)
5329  {
5330  if (0 != node)
5331  {
5332  if (
5333  (is_variable_node(node) || is_string_node(node)) ||
5334  force_delete
5335  )
5336  return;
5337 
5338  node_allocator.free(node);
5339  node = reinterpret_cast<expression_node<T>*>(0);
5340  }
5341  }
5342 
5343  template <typename T>
5344  inline void destroy_node(expression_node<T>*& node)
5345  {
5346  delete node;
5347  node = reinterpret_cast<expression_node<T>*>(0);
5348  }
5349 
5350  template <typename Type>
5352  {
5353  private:
5354 
5355  typedef Type value_type;
5358 
5360  {
5361  public:
5362 
5363  virtual ~vector_holder_base() {}
5364 
5365  inline value_ptr operator[](const std::size_t& index) const
5366  {
5367  return value_at(index);
5368  }
5369 
5370  inline std::size_t size() const
5371  {
5372  return vector_size();
5373  }
5374 
5375  inline value_ptr data() const
5376  {
5377  return value_at(0);
5378  }
5379 
5380  virtual inline bool rebaseable() const
5381  {
5382  return false;
5383  }
5384 
5385  virtual void set_ref(value_ptr*) {}
5386 
5387  protected:
5388 
5389  virtual value_ptr value_at(const std::size_t&) const = 0;
5390  virtual std::size_t vector_size() const = 0;
5391  };
5392 
5394  {
5395  public:
5396 
5397  array_vector_impl(const Type* vec, const std::size_t& vec_size)
5398  : vec_(vec),
5399  size_(vec_size)
5400  {}
5401 
5402  protected:
5403 
5404  value_ptr value_at(const std::size_t& index) const
5405  {
5406  if (index < size_)
5407  return const_cast<const_value_ptr>(vec_ + index);
5408  else
5409  return const_value_ptr(0);
5410  }
5411 
5412  std::size_t vector_size() const
5413  {
5414  return size_;
5415  }
5416 
5417  private:
5418 
5420 
5421  const Type* vec_;
5422  const std::size_t size_;
5423  };
5424 
5425  template <typename Allocator,
5426  template <typename, typename> class Sequence>
5428  {
5429  public:
5430 
5431  typedef Sequence<Type,Allocator> sequence_t;
5432 
5434  : sequence_(seq)
5435  {}
5436 
5437  protected:
5438 
5439  value_ptr value_at(const std::size_t& index) const
5440  {
5441  return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0);
5442  }
5443 
5444  std::size_t vector_size() const
5445  {
5446  return sequence_.size();
5447  }
5448 
5449  private:
5450 
5452 
5454  };
5455 
5457  {
5458  public:
5459 
5461 
5463  : vec_view_(vec_view)
5464  {}
5465 
5466  void set_ref(value_ptr* ref)
5467  {
5468  vec_view_.set_ref(ref);
5469  }
5470 
5471  virtual inline bool rebaseable() const
5472  {
5473  return true;
5474  }
5475 
5476  protected:
5477 
5478  value_ptr value_at(const std::size_t& index) const
5479  {
5480  return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0);
5481  }
5482 
5483  std::size_t vector_size() const
5484  {
5485  return vec_view_.size();
5486  }
5487 
5488  private:
5489 
5491 
5493  };
5494 
5495  public:
5496 
5498 
5499  vector_holder(Type* vec, const std::size_t& vec_size)
5500  : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
5501  {}
5502 
5503  vector_holder(const vds_t& vds)
5504  : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
5505  {}
5506 
5507  template <typename Allocator>
5508  vector_holder(std::vector<Type,Allocator>& vec)
5509  : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
5510  {}
5511 
5513  : vector_holder_base_(new(buffer)vector_view_impl(vec))
5514  {}
5515 
5516  inline value_ptr operator[](const std::size_t& index) const
5517  {
5518  return (*vector_holder_base_)[index];
5519  }
5520 
5521  inline std::size_t size() const
5522  {
5523  return vector_holder_base_->size();
5524  }
5525 
5526  inline value_ptr data() const
5527  {
5528  return vector_holder_base_->data();
5529  }
5530 
5531  void set_ref(value_ptr* ref)
5532  {
5534  }
5535 
5536  bool rebaseable() const
5537  {
5538  return vector_holder_base_->rebaseable();
5539  }
5540 
5541  private:
5542 
5543  mutable vector_holder_base* vector_holder_base_;
5545  };
5546 
5547  template <typename T>
5548  class null_node : public expression_node<T>
5549  {
5550  public:
5551 
5552  inline T value() const
5553  {
5554  return std::numeric_limits<T>::quiet_NaN();
5555  }
5556 
5557  inline typename expression_node<T>::node_type type() const
5558  {
5560  }
5561  };
5562 
5563  template <typename T>
5564  class null_eq_node : public expression_node<T>
5565  {
5566  public:
5567 
5569 
5570  null_eq_node(expression_ptr brnch, const bool equality = true)
5571  : branch_(brnch),
5573  equality_(equality)
5574  {}
5575 
5577  {
5578  if (branch_ && branch_deletable_)
5579  {
5581  }
5582  }
5583 
5584  inline T value() const
5585  {
5586  const T v = branch_->value();
5587  const bool result = details::numeric::is_nan(v);
5588 
5589  if (result)
5590  return (equality_) ? T(1) : T(0);
5591  else
5592  return (equality_) ? T(0) : T(1);
5593  }
5594 
5595  inline typename expression_node<T>::node_type type() const
5596  {
5598  }
5599 
5600  inline operator_type operation() const
5601  {
5602  return details::e_eq;
5603  }
5604 
5605  inline expression_node<T>* branch(const std::size_t&) const
5606  {
5607  return branch_;
5608  }
5609 
5610  private:
5611 
5613  const bool branch_deletable_;
5615  };
5616 
5617  template <typename T>
5618  class literal_node : public expression_node<T>
5619  {
5620  public:
5621 
5622  explicit literal_node(const T& v)
5623  : value_(v)
5624  {}
5625 
5626  inline T value() const
5627  {
5628  return value_;
5629  }
5630 
5631  inline typename expression_node<T>::node_type type() const
5632  {
5634  }
5635 
5636  inline expression_node<T>* branch(const std::size_t&) const
5637  {
5638  return reinterpret_cast<expression_node<T>*>(0);
5639  }
5640 
5641  private:
5642 
5645 
5646  const T value_;
5647  };
5648 
5649  template <typename T>
5650  struct range_pack;
5651 
5652  template <typename T>
5654 
5655  template <typename T>
5657  {
5658  public:
5659 
5661 
5663  {}
5664 
5665  virtual range_t& range_ref() = 0;
5666 
5667  virtual const range_t& range_ref() const = 0;
5668  };
5669 
5670  #ifndef exprtk_disable_string_capabilities
5671  template <typename T>
5673  {
5674  public:
5675 
5677 
5679  {}
5680 
5681  virtual std::string str () const = 0;
5682 
5683  virtual char_cptr base() const = 0;
5684 
5685  virtual std::size_t size() const = 0;
5686  };
5687 
5688  template <typename T>
5690  public string_base_node<T>,
5691  public range_interface <T>
5692  {
5693  public:
5694 
5696 
5698  : value_(v)
5699  {
5700  rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
5701  rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
5702  rp_.cache.first = rp_.n0_c.second;
5703  rp_.cache.second = rp_.n1_c.second;
5704  }
5705 
5706  inline T value() const
5707  {
5708  return std::numeric_limits<T>::quiet_NaN();
5709  }
5710 
5711  inline typename expression_node<T>::node_type type() const
5712  {
5714  }
5715 
5716  inline expression_node<T>* branch(const std::size_t&) const
5717  {
5718  return reinterpret_cast<expression_node<T>*>(0);
5719  }
5720 
5722  {
5723  return value_;
5724  }
5725 
5726  char_cptr base() const
5727  {
5728  return value_.data();
5729  }
5730 
5731  std::size_t size() const
5732  {
5733  return value_.size();
5734  }
5735 
5737  {
5738  return rp_;
5739  }
5740 
5741  const range_t& range_ref() const
5742  {
5743  return rp_;
5744  }
5745 
5746  private:
5747 
5750 
5753  };
5754  #endif
5755 
5756  template <typename T>
5757  class unary_node : public expression_node<T>
5758  {
5759  public:
5760 
5762 
5764  expression_ptr brnch)
5765  : operation_(opr),
5766  branch_(brnch),
5768  {}
5769 
5771  {
5772  if (branch_ && branch_deletable_)
5773  {
5775  }
5776  }
5777 
5778  inline T value() const
5779  {
5780  const T arg = branch_->value();
5781 
5782  return numeric::process<T>(operation_,arg);
5783  }
5784 
5785  inline typename expression_node<T>::node_type type() const
5786  {
5788  }
5789 
5790  inline operator_type operation() const
5791  {
5792  return operation_;
5793  }
5794 
5795  inline expression_node<T>* branch(const std::size_t&) const
5796  {
5797  return branch_;
5798  }
5799 
5800  inline void release()
5801  {
5802  branch_deletable_ = false;
5803  }
5804 
5805  protected:
5806 
5810  };
5811 
5812  template <typename T, std::size_t D, bool B>
5814  {
5815  template <std::size_t N>
5816  static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
5817  {}
5818  };
5819 
5820  template <typename T, std::size_t D>
5821  struct construct_branch_pair<T,D,true>
5822  {
5823  template <std::size_t N>
5824  static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
5825  {
5826  if (b)
5827  {
5828  branch[D] = std::make_pair(b,branch_deletable(b));
5829  }
5830  }
5831  };
5832 
5833  template <std::size_t N, typename T>
5834  inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
5835  expression_node<T>* b0,
5836  expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
5837  expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
5838  expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
5839  expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
5840  expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
5841  expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
5842  expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
5843  expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
5844  expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
5845  {
5846  construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
5847  construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
5848  construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
5849  construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
5850  construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
5851  construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
5852  construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
5853  construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
5854  construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
5855  construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
5856  }
5857 
5859  {
5860  template <typename T, std::size_t N>
5861  static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
5862  {
5863  for (std::size_t i = 0; i < N; ++i)
5864  {
5865  if (branch[i].first && branch[i].second)
5866  {
5867  destroy_node(branch[i].first);
5868  }
5869  }
5870  }
5871 
5872  template <typename T,
5873  typename Allocator,
5874  template <typename, typename> class Sequence>
5875  static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch)
5876  {
5877  for (std::size_t i = 0; i < branch.size(); ++i)
5878  {
5879  if (branch[i].first && branch[i].second)
5880  {
5881  destroy_node(branch[i].first);
5882  }
5883  }
5884  }
5885  };
5886 
5887  template <typename T>
5888  class binary_node : public expression_node<T>
5889  {
5890  public:
5891 
5893  typedef std::pair<expression_ptr,bool> branch_t;
5894 
5896  expression_ptr branch0,
5897  expression_ptr branch1)
5898  : operation_(opr)
5899  {
5900  init_branches<2>(branch_, branch0, branch1);
5901  }
5902 
5904  {
5905  cleanup_branches::execute<T,2>(branch_);
5906  }
5907 
5908  inline T value() const
5909  {
5910  const T arg0 = branch_[0].first->value();
5911  const T arg1 = branch_[1].first->value();
5912 
5913  return numeric::process<T>(operation_,arg0,arg1);
5914  }
5915 
5916  inline typename expression_node<T>::node_type type() const
5917  {
5919  }
5920 
5922  {
5923  return operation_;
5924  }
5925 
5926  inline expression_node<T>* branch(const std::size_t& index = 0) const
5927  {
5928  if (0 == index)
5929  return branch_[0].first;
5930  else if (1 == index)
5931  return branch_[1].first;
5932  else
5933  return reinterpret_cast<expression_ptr>(0);
5934  }
5935 
5936  protected:
5937 
5940  };
5941 
5942  template <typename T, typename Operation>
5944  {
5945  public:
5946 
5948  typedef std::pair<expression_ptr,bool> branch_t;
5949 
5951  {
5952  init_branches<2>(branch_, branch0, branch1);
5953  }
5954 
5956  {
5957  cleanup_branches::execute<T,2>(branch_);
5958  }
5959 
5960  inline T value() const
5961  {
5962  const T arg0 = branch_[0].first->value();
5963  const T arg1 = branch_[1].first->value();
5964 
5965  return Operation::process(arg0,arg1);
5966  }
5967 
5968  inline typename expression_node<T>::node_type type() const
5969  {
5971  }
5972 
5974  {
5975  return Operation::operation();
5976  }
5977 
5978  inline expression_node<T>* branch(const std::size_t& index = 0) const
5979  {
5980  if (0 == index)
5981  return branch_[0].first;
5982  else if (1 == index)
5983  return branch_[1].first;
5984  else
5985  return reinterpret_cast<expression_ptr>(0);
5986  }
5987 
5988  protected:
5989 
5991  };
5992 
5993  template <typename T>
5994  class trinary_node : public expression_node<T>
5995  {
5996  public:
5997 
5999  typedef std::pair<expression_ptr,bool> branch_t;
6000 
6002  expression_ptr branch0,
6003  expression_ptr branch1,
6004  expression_ptr branch2)
6005  : operation_(opr)
6006  {
6007  init_branches<3>(branch_, branch0, branch1, branch2);
6008  }
6009 
6011  {
6012  cleanup_branches::execute<T,3>(branch_);
6013  }
6014 
6015  inline T value() const
6016  {
6017  const T arg0 = branch_[0].first->value();
6018  const T arg1 = branch_[1].first->value();
6019  const T arg2 = branch_[2].first->value();
6020 
6021  switch (operation_)
6022  {
6023  case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
6024 
6025  case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
6026 
6027  case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2))
6028  return arg1;
6029  else
6030  return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2);
6031 
6032  default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n"));
6033  return std::numeric_limits<T>::quiet_NaN();
6034  }
6035  }
6036 
6037  inline typename expression_node<T>::node_type type() const
6038  {
6040  }
6041 
6042  protected:
6043 
6046  };
6047 
6048  template <typename T>
6050  {
6051  public:
6052 
6054  typedef std::pair<expression_ptr,bool> branch_t;
6055 
6057  expression_ptr branch0,
6058  expression_ptr branch1,
6059  expression_ptr branch2,
6060  expression_ptr branch3)
6061  : operation_(opr)
6062  {
6063  init_branches<4>(branch_, branch0, branch1, branch2, branch3);
6064  }
6065 
6067  {
6068  cleanup_branches::execute<T,4>(branch_);
6069  }
6070 
6071  inline T value() const
6072  {
6073  return std::numeric_limits<T>::quiet_NaN();
6074  }
6075 
6076  inline typename expression_node<T>::node_type type() const
6077  {
6079  }
6080 
6081  protected:
6082 
6085  };
6086 
6087  template <typename T>
6089  {
6090  public:
6091 
6093 
6095  expression_ptr consequent,
6096  expression_ptr alternative)
6097  : test_(test),
6098  consequent_(consequent),
6099  alternative_(alternative),
6103  {}
6104 
6106  {
6107  if (test_ && test_deletable_)
6108  {
6110  }
6111 
6113  {
6115  }
6116 
6118  {
6120  }
6121  }
6122 
6123  inline T value() const
6124  {
6125  if (is_true(test_))
6126  return consequent_->value();
6127  else
6128  return alternative_->value();
6129  }
6130 
6131  inline typename expression_node<T>::node_type type() const
6132  {
6134  }
6135 
6136  private:
6137 
6141  const bool test_deletable_;
6144  };
6145 
6146  template <typename T>
6148  {
6149  public:
6150 
6151  // Consequent only conditional statement node
6153 
6155  expression_ptr consequent)
6156  : test_(test),
6157  consequent_(consequent),
6160  {}
6161 
6163  {
6164  if (test_ && test_deletable_)
6165  {
6167  }
6168 
6170  {
6172  }
6173  }
6174 
6175  inline T value() const
6176  {
6177  if (is_true(test_))
6178  return consequent_->value();
6179  else
6180  return std::numeric_limits<T>::quiet_NaN();
6181  }
6182 
6183  inline typename expression_node<T>::node_type type() const
6184  {
6186  }
6187 
6188  private:
6189 
6192  const bool test_deletable_;
6194  };
6195 
6196  #ifndef exprtk_disable_break_continue
6197  template <typename T>
6199  {
6200  public:
6201 
6202  break_exception(const T& v)
6203  : value(v)
6204  {}
6205 
6207  };
6208 
6210  {};
6211 
6212  template <typename T>
6213  class break_node : public expression_node<T>
6214  {
6215  public:
6216 
6218 
6220  : return_(ret),
6222  {}
6223 
6225  {
6226  if (return_deletable_)
6227  {
6229  }
6230  }
6231 
6232  inline T value() const
6233  {
6234  throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN());
6235  #ifndef _MSC_VER
6236  return std::numeric_limits<T>::quiet_NaN();
6237  #endif
6238  }
6239 
6240  inline typename expression_node<T>::node_type type() const
6241  {
6243  }
6244 
6245  private:
6246 
6248  const bool return_deletable_;
6249  };
6250 
6251  template <typename T>
6252  class continue_node : public expression_node<T>
6253  {
6254  public:
6255 
6256  inline T value() const
6257  {
6258  throw continue_exception();
6259  #ifndef _MSC_VER
6260  return std::numeric_limits<T>::quiet_NaN();
6261  #endif
6262  }
6263 
6264  inline typename expression_node<T>::node_type type() const
6265  {
6267  }
6268  };
6269  #endif
6270 
6271  template <typename T>
6273  {
6274  public:
6275 
6277 
6279  : condition_(condition),
6280  loop_body_(loop_body),
6283  {}
6284 
6286  {
6288  {
6290  }
6291 
6293  {
6295  }
6296  }
6297 
6298  inline T value() const
6299  {
6300  T result = T(0);
6301 
6302  while (is_true(condition_))
6303  {
6304  result = loop_body_->value();
6305  }
6306 
6307  return result;
6308  }
6309 
6310  inline typename expression_node<T>::node_type type() const
6311  {
6313  }
6314 
6315  private:
6316 
6321  };
6322 
6323  template <typename T>
6325  {
6326  public:
6327 
6329 
6331  : condition_(condition),
6332  loop_body_(loop_body),
6335  {}
6336 
6338  {
6340  {
6342  }
6343 
6345  {
6347  }
6348  }
6349 
6350  inline T value() const
6351  {
6352  T result = T(0);
6353 
6354  do
6355  {
6356  result = loop_body_->value();
6357  }
6358  while (is_false(condition_));
6359 
6360  return result;
6361  }
6362 
6363  inline typename expression_node<T>::node_type type() const
6364  {
6366  }
6367 
6368  private:
6369 
6374  };
6375 
6376  template <typename T>
6377  class for_loop_node : public expression_node<T>
6378  {
6379  public:
6380 
6382 
6384  expression_ptr condition,
6385  expression_ptr incrementor,
6386  expression_ptr loop_body)
6387  : initialiser_(initialiser),
6388  condition_ (condition ),
6389  incrementor_(incrementor),
6390  loop_body_ (loop_body ),
6395  {}
6396 
6398  {
6400  {
6402  }
6403 
6405  {
6407  }
6408 
6410  {
6412  }
6413 
6415  {
6417  }
6418  }
6419 
6420  inline T value() const
6421  {
6422  T result = T(0);
6423 
6424  if (initialiser_)
6425  initialiser_->value();
6426 
6427  if (incrementor_)
6428  {
6429  while (is_true(condition_))
6430  {
6431  result = loop_body_->value();
6432  incrementor_->value();
6433  }
6434  }
6435  else
6436  {
6437  while (is_true(condition_))
6438  {
6439  result = loop_body_->value();
6440  }
6441  }
6442 
6443  return result;
6444  }
6445 
6446  inline typename expression_node<T>::node_type type() const
6447  {
6449  }
6450 
6451  private:
6452 
6461  };
6462 
6463  #ifndef exprtk_disable_break_continue
6464  template <typename T>
6466  {
6467  public:
6468 
6470 
6472  : condition_(condition),
6473  loop_body_(loop_body),
6476  {}
6477 
6479  {
6481  {
6483  }
6484 
6486  {
6488  }
6489  }
6490 
6491  inline T value() const
6492  {
6493  T result = T(0);
6494 
6495  while (is_true(condition_))
6496  {
6497  try
6498  {
6499  result = loop_body_->value();
6500  }
6501  catch(const break_exception<T>& e)
6502  {
6503  return e.value;
6504  }
6505  catch(const continue_exception&)
6506  {}
6507  }
6508 
6509  return result;
6510  }
6511 
6512  inline typename expression_node<T>::node_type type() const
6513  {
6515  }
6516 
6517  private:
6518 
6523  };
6524 
6525  template <typename T>
6527  {
6528  public:
6529 
6531 
6533  : condition_(condition),
6534  loop_body_(loop_body),
6537  {}
6538 
6540  {
6542  {
6544  }
6545 
6547  {
6549  }
6550  }
6551 
6552  inline T value() const
6553  {
6554  T result = T(0);
6555 
6556  do
6557  {
6558  try
6559  {
6560  result = loop_body_->value();
6561  }
6562  catch(const break_exception<T>& e)
6563  {
6564  return e.value;
6565  }
6566  catch(const continue_exception&)
6567  {}
6568  }
6569  while (is_false(condition_));
6570 
6571  return result;
6572  }
6573 
6574  inline typename expression_node<T>::node_type type() const
6575  {
6577  }
6578 
6579  private:
6580 
6585  };
6586 
6587  template <typename T>
6589  {
6590  public:
6591 
6593 
6595  expression_ptr condition,
6596  expression_ptr incrementor,
6597  expression_ptr loop_body)
6598  : initialiser_(initialiser),
6599  condition_ (condition ),
6600  incrementor_(incrementor),
6601  loop_body_ (loop_body ),
6606  {}
6607 
6609  {
6611  {
6613  }
6614 
6616  {
6618  }
6619 
6621  {
6623  }
6624 
6626  {
6628  }
6629  }
6630 
6631  inline T value() const
6632  {
6633  T result = T(0);
6634 
6635  if (initialiser_)
6636  initialiser_->value();
6637 
6638  if (incrementor_)
6639  {
6640  while (is_true(condition_))
6641  {
6642  try
6643  {
6644  result = loop_body_->value();
6645  }
6646  catch(const break_exception<T>& e)
6647  {
6648  return e.value;
6649  }
6650  catch(const continue_exception&)
6651  {}
6652 
6653  incrementor_->value();
6654  }
6655  }
6656  else
6657  {
6658  while (is_true(condition_))
6659  {
6660  try
6661  {
6662  result = loop_body_->value();
6663  }
6664  catch(const break_exception<T>& e)
6665  {
6666  return e.value;
6667  }
6668  catch(const continue_exception&)
6669  {}
6670  }
6671  }
6672 
6673  return result;
6674  }
6675 
6676  inline typename expression_node<T>::node_type type() const
6677  {
6679  }
6680 
6681  private:
6682 
6691  };
6692  #endif
6693 
6694  template <typename T>
6695  class switch_node : public expression_node<T>
6696  {
6697  public:
6698 
6700 
6701  template <typename Allocator,
6702  template <typename, typename> class Sequence>
6703  explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6704  {
6705  if (1 != (arg_list.size() & 1))
6706  return;
6707 
6708  arg_list_.resize(arg_list.size());
6709  delete_branch_.resize(arg_list.size());
6710 
6711  for (std::size_t i = 0; i < arg_list.size(); ++i)
6712  {
6713  if (arg_list[i])
6714  {
6715  arg_list_[i] = arg_list[i];
6716  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6717  }
6718  else
6719  {
6720  arg_list_.clear();
6721  delete_branch_.clear();
6722  return;
6723  }
6724  }
6725  }
6726 
6728  {
6729  for (std::size_t i = 0; i < arg_list_.size(); ++i)
6730  {
6731  if (arg_list_[i] && delete_branch_[i])
6732  {
6733  destroy_node(arg_list_[i]);
6734  }
6735  }
6736  }
6737 
6738  inline T value() const
6739  {
6740  if (!arg_list_.empty())
6741  {
6742  const std::size_t upper_bound = (arg_list_.size() - 1);
6743 
6744  for (std::size_t i = 0; i < upper_bound; i += 2)
6745  {
6746  expression_ptr condition = arg_list_[i ];
6747  expression_ptr consequent = arg_list_[i + 1];
6748 
6749  if (is_true(condition))
6750  {
6751  return consequent->value();
6752  }
6753  }
6754 
6755  return arg_list_[upper_bound]->value();
6756  }
6757  else
6758  return std::numeric_limits<T>::quiet_NaN();
6759  }
6760 
6761  inline typename expression_node<T>::node_type type() const
6762  {
6764  }
6765 
6766  protected:
6767 
6768  std::vector<expression_ptr> arg_list_;
6769  std::vector<unsigned char> delete_branch_;
6770  };
6771 
6772  template <typename T, typename Switch_N>
6773  class switch_n_node : public switch_node<T>
6774  {
6775  public:
6776 
6778 
6779  template <typename Allocator,
6780  template <typename, typename> class Sequence>
6781  explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list)
6782  : switch_node<T>(arg_list)
6783  {}
6784 
6785  inline T value() const
6786  {
6788  }
6789  };
6790 
6791  template <typename T>
6793  {
6794  public:
6795 
6797 
6798  template <typename Allocator,
6799  template <typename, typename> class Sequence>
6800  explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list)
6801  {
6802  if (0 != (arg_list.size() & 1))
6803  return;
6804 
6805  arg_list_.resize(arg_list.size());
6806  delete_branch_.resize(arg_list.size());
6807 
6808  for (std::size_t i = 0; i < arg_list.size(); ++i)
6809  {
6810  if (arg_list[i])
6811  {
6812  arg_list_[i] = arg_list[i];
6813  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
6814  }
6815  else
6816  {
6817  arg_list_.clear();
6818  delete_branch_.clear();
6819  return;
6820  }
6821  }
6822  }
6823 
6825  {
6826  for (std::size_t i = 0; i < arg_list_.size(); ++i)
6827  {
6828  if (arg_list_[i] && delete_branch_[i])
6829  {
6830  destroy_node(arg_list_[i]);
6831  }
6832  }
6833  }
6834 
6835  inline T value() const
6836  {
6837  T result = T(0);
6838 
6839  if (arg_list_.empty())
6840  {
6841  return std::numeric_limits<T>::quiet_NaN();
6842  }
6843 
6844  const std::size_t upper_bound = (arg_list_.size() - 1);
6845 
6846  for (std::size_t i = 0; i < upper_bound; i += 2)
6847  {
6848  expression_ptr condition = arg_list_[i ];
6849  expression_ptr consequent = arg_list_[i + 1];
6850 
6851  if (is_true(condition))
6852  {
6853  result = consequent->value();
6854  }
6855  }
6856 
6857  return result;
6858  }
6859 
6860  inline typename expression_node<T>::node_type type() const
6861  {
6863  }
6864 
6865  private:
6866 
6867  std::vector<expression_ptr> arg_list_;
6868  std::vector<unsigned char> delete_branch_;
6869  };
6870 
6871  template <typename T>
6873  {
6874  public:
6875 
6876  virtual ~ivariable()
6877  {}
6878 
6879  virtual T& ref() = 0;
6880  virtual const T& ref() const = 0;
6881  };
6882 
6883  template <typename T>
6884  class variable_node : public expression_node<T>,
6885  public ivariable <T>
6886  {
6887  public:
6888 
6889  static T null_value;
6890 
6891  explicit variable_node()
6892  : value_(&null_value)
6893  {}
6894 
6895  explicit variable_node(T& v)
6896  : value_(&v)
6897  {}
6898 
6899  inline bool operator <(const variable_node<T>& v) const
6900  {
6901  return this < (&v);
6902  }
6903 
6904  inline T value() const
6905  {
6906  return (*value_);
6907  }
6908 
6909  inline T& ref()
6910  {
6911  return (*value_);
6912  }
6913 
6914  inline const T& ref() const
6915  {
6916  return (*value_);
6917  }
6918 
6919  inline typename expression_node<T>::node_type type() const
6920  {
6922  }
6923 
6924  private:
6925 
6927  };
6928 
6929  template <typename T>
6930  T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
6931 
6932  template <typename T>
6933  struct range_pack
6934  {
6936  typedef std::pair<std::size_t,std::size_t> cached_range_t;
6937 
6939  : n0_e (std::make_pair(false,expression_node_ptr(0))),
6940  n1_e (std::make_pair(false,expression_node_ptr(0))),
6941  n0_c (std::make_pair(false,0)),
6942  n1_c (std::make_pair(false,0)),
6943  cache(std::make_pair(0,0))
6944  {}
6945 
6946  void clear()
6947  {
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 free()
6956  {
6957  if (n0_e.first && n0_e.second)
6958  {
6959  n0_e.first = false;
6960 
6961  if (
6962  !is_variable_node(n0_e.second) &&
6963  !is_string_node (n0_e.second)
6964  )
6965  {
6966  destroy_node(n0_e.second);
6967  }
6968  }
6969 
6970  if (n1_e.first && n1_e.second)
6971  {
6972  n1_e.first = false;
6973 
6974  if (
6975  !is_variable_node(n1_e.second) &&
6976  !is_string_node (n1_e.second)
6977  )
6978  {
6979  destroy_node(n1_e.second);
6980  }
6981  }
6982  }
6983 
6985  {
6986  return ( n0_c.first && n1_c.first) &&
6987  (!n0_e.first && !n1_e.first);
6988  }
6989 
6990  bool var_range()
6991  {
6992  return ( n0_e.first && n1_e.first) &&
6993  (!n0_c.first && !n1_c.first);
6994  }
6995 
6996  bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const
6997  {
6998  if (n0_c.first)
6999  r0 = n0_c.second;
7000  else if (n0_e.first)
7001  {
7002  T r0_value = n0_e.second->value();
7003 
7004  if (r0_value < 0)
7005  return false;
7006  else
7007  r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
7008  }
7009  else
7010  return false;
7011 
7012  if (n1_c.first)
7013  r1 = n1_c.second;
7014  else if (n1_e.first)
7015  {
7016  T r1_value = n1_e.second->value();
7017 
7018  if (r1_value < 0)
7019  return false;
7020  else
7021  r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
7022  }
7023  else
7024  return false;
7025 
7026  if (
7029  )
7030  {
7031  r1 = size - 1;
7032  }
7033 
7034  cache.first = r0;
7035  cache.second = r1;
7036 
7037  return (r0 <= r1);
7038  }
7039 
7040  inline std::size_t const_size() const
7041  {
7042  return (n1_c.second - n0_c.second + 1);
7043  }
7044 
7045  inline std::size_t cache_size() const
7046  {
7047  return (cache.second - cache.first + 1);
7048  }
7049 
7050  std::pair<bool,expression_node_ptr> n0_e;
7051  std::pair<bool,expression_node_ptr> n1_e;
7052  std::pair<bool,std::size_t > n0_c;
7053  std::pair<bool,std::size_t > n1_c;
7055  };
7056 
7057  template <typename T>
7058  class string_base_node;
7059 
7060  template <typename T>
7061  struct range_data_type
7062  {
7065 
7067  : range(0),
7068  data (0),
7069  size (0),
7070  type_size(0),
7071  str_node (0)
7072  {}
7073 
7075  void* data;
7076  std::size_t size;
7077  std::size_t type_size;
7079  };
7080 
7081  template <typename T> class vector_node;
7082 
7083  template <typename T>
7085  {
7086  public:
7087 
7090 
7092  {}
7093 
7094  virtual std::size_t size () const = 0;
7095 
7096  virtual vector_node_ptr vec() const = 0;
7097 
7098  virtual vector_node_ptr vec() = 0;
7099 
7100  virtual vds_t& vds () = 0;
7101 
7102  virtual const vds_t& vds () const = 0;
7103 
7104  virtual bool side_effect () const { return false; }
7105  };
7106 
7107  template <typename T>
7108  class vector_node : public expression_node <T>,
7109  public vector_interface<T>
7110  {
7111  public:
7112 
7117 
7119  : vector_holder_(vh),
7121  {
7123  }
7124 
7126  : vector_holder_(vh),
7127  vds_(vds)
7128  {}
7129 
7130  inline T value() const
7131  {
7132  return vds().data()[0];
7133  }
7134 
7136  {
7137  return const_cast<vector_node_ptr>(this);
7138  }
7139 
7141  {
7142  return this;
7143  }
7144 
7145  inline typename expression_node<T>::node_type type() const
7146  {
7148  }
7149 
7150  std::size_t size() const
7151  {
7152  return vds().size();
7153  }
7154 
7156  {
7157  return vds_;
7158  }
7159 
7160  const vds_t& vds() const
7161  {
7162  return vds_;
7163  }
7164 
7166  {
7167  return (*vector_holder_);
7168  }
7169 
7170  private:
7171 
7174  };
7175 
7176  template <typename T>
7178  public ivariable <T>
7179  {
7180  public:
7181 
7185 
7187  : index_(index),
7189  vector_base_((*vec_holder)[0]),
7191  {}
7192 
7194  {
7195  if (index_ && index_deletable_)
7196  {
7198  }
7199  }
7200 
7201  inline T value() const
7202  {
7203  return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7204  }
7205 
7206  inline T& ref()
7207  {
7208  return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7209  }
7210 
7211  inline const T& ref() const
7212  {
7213  return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7214  }
7215 
7216  inline typename expression_node<T>::node_type type() const
7217  {
7219  }
7220 
7222  {
7223  return (*vec_holder_);
7224  }
7225 
7226  private:
7227 
7231  const bool index_deletable_;
7232  };
7233 
7234  template <typename T>
7236  public ivariable <T>
7237  {
7238  public:
7239 
7244 
7246  : index_(index),
7249  vds_((*vector_holder_).size(),(*vector_holder_)[0])
7250  {
7252  }
7253 
7255  {
7256  if (index_ && index_deletable_)
7257  {
7259  }
7260  }
7261 
7262  inline T value() const
7263  {
7264  return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7265  }
7266 
7267  inline T& ref()
7268  {
7269  return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7270  }
7271 
7272  inline const T& ref() const
7273  {
7274  return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value())));
7275  }
7276 
7277  inline typename expression_node<T>::node_type type() const
7278  {
7280  }
7281 
7283  {
7284  return (*vector_holder_);
7285  }
7286 
7287  private:
7288 
7290  const bool index_deletable_;
7293  };
7294 
7295  template <typename T>
7297  public ivariable <T>
7298  {
7299  public:
7300 
7305 
7307  : index_(index),
7309  vds_((*vector_holder_).size(),(*vector_holder_)[0])
7310  {
7312  }
7313 
7314  inline T value() const
7315  {
7316  return *(vds_.data() + index_);
7317  }
7318 
7319  inline T& ref()
7320  {
7321  return *(vds_.data() + index_);
7322  }
7323 
7324  inline const T& ref() const
7325  {
7326  return *(vds_.data() + index_);
7327  }
7328 
7329  inline typename expression_node<T>::node_type type() const
7330  {
7332  }
7333 
7335  {
7336  return (*vector_holder_);
7337  }
7338 
7339  private:
7340 
7341  const std::size_t index_;
7344  };
7345 
7346  template <typename T>
7348  {
7349  public:
7350 
7352 
7353  vector_assignment_node(T* vector_base,
7354  const std::size_t& size,
7355  const std::vector<expression_ptr>& initialiser_list,
7356  const bool single_value_initialse)
7357  : vector_base_(vector_base),
7358  initialiser_list_(initialiser_list),
7359  size_(size),
7360  single_value_initialse_(single_value_initialse)
7361  {}
7362 
7364  {
7365  for (std::size_t i = 0; i < initialiser_list_.size(); ++i)
7366  {
7368  {
7370  }
7371  }
7372  }
7373 
7374  inline T value() const
7375  {
7377  {
7378  for (std::size_t i = 0; i < size_; ++i)
7379  {
7380  *(vector_base_ + i) = initialiser_list_[0]->value();
7381  }
7382  }
7383  else
7384  {
7385  std::size_t il_size = initialiser_list_.size();
7386 
7387  for (std::size_t i = 0; i < il_size; ++i)
7388  {
7389  *(vector_base_ + i) = initialiser_list_[i]->value();
7390  }
7391 
7392  if (il_size < size_)
7393  {
7394  for (std::size_t i = il_size; i < size_; ++i)
7395  {
7396  *(vector_base_ + i) = T(0);
7397  }
7398  }
7399  }
7400 
7401  return *(vector_base_);
7402  }
7403 
7404  inline typename expression_node<T>::node_type type() const
7405  {
7407  }
7408 
7409  private:
7410 
7412 
7413  mutable T* vector_base_;
7414  std::vector<expression_ptr> initialiser_list_;
7415  const std::size_t size_;
7417  };
7418 
7419  template <typename T>
7420  class swap_node : public expression_node<T>
7421  {
7422  public:
7423 
7426 
7428  : var0_(var0),
7429  var1_(var1)
7430  {}
7431 
7432  inline T value() const
7433  {
7434  std::swap(var0_->ref(),var1_->ref());
7435  return var1_->ref();
7436  }
7437 
7438  inline typename expression_node<T>::node_type type() const
7439  {
7441  }
7442 
7443  private:
7444 
7447  };
7448 
7449  template <typename T>
7450  class swap_generic_node : public binary_node<T>
7451  {
7452  public:
7453 
7456 
7458  : binary_node<T>(details::e_swap, var0, var1),
7459  var0_(dynamic_cast<ivariable_ptr>(var0)),
7460  var1_(dynamic_cast<ivariable_ptr>(var1))
7461  {}
7462 
7463  inline T value() const
7464  {
7465  std::swap(var0_->ref(),var1_->ref());
7466  return var1_->ref();
7467  }
7468 
7469  inline typename expression_node<T>::node_type type() const
7470  {
7472  }
7473 
7474  private:
7475 
7478  };
7479 
7480  template <typename T>
7481  class swap_vecvec_node : public binary_node <T>,
7482  public vector_interface<T>
7483  {
7484  public:
7485 
7489 
7491  expression_ptr branch1)
7492  : binary_node<T>(details::e_swap, branch0, branch1),
7493  vec0_node_ptr_(0),
7494  vec1_node_ptr_(0),
7495  vec_size_ (0),
7496  initialised_ (false)
7497  {
7499  {
7500  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7501 
7502  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
7503  {
7504  vec0_node_ptr_ = vi->vec();
7505  vds() = vi->vds();
7506  }
7507  }
7508 
7510  {
7511  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
7512 
7513  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
7514  {
7515  vec1_node_ptr_ = vi->vec();
7516  }
7517  }
7518 
7520  {
7521  vec_size_ = std::min(vec0_node_ptr_->vds().size(),
7522  vec1_node_ptr_->vds().size());
7523 
7524  initialised_ = true;
7525  }
7526  }
7527 
7528  inline T value() const
7529  {
7530  if (initialised_)
7531  {
7532  binary_node<T>::branch_[0].first->value();
7533  binary_node<T>::branch_[1].first->value();
7534 
7535  T* vec0 = vec0_node_ptr_->vds().data();
7536  T* vec1 = vec1_node_ptr_->vds().data();
7537 
7538  for (std::size_t i = 0; i < vec_size_; ++i)
7539  {
7540  std::swap(vec0[i],vec1[i]);
7541  }
7542 
7543  return vec1_node_ptr_->value();
7544  }
7545  else
7546  return std::numeric_limits<T>::quiet_NaN();
7547  }
7548 
7550  {
7551  return vec0_node_ptr_;
7552  }
7553 
7555  {
7556  return vec0_node_ptr_;
7557  }
7558 
7559  inline typename expression_node<T>::node_type type() const
7560  {
7562  }
7563 
7564  std::size_t size() const
7565  {
7566  return vec_size_;
7567  }
7568 
7570  {
7571  return vds_;
7572  }
7573 
7574  const vds_t& vds() const
7575  {
7576  return vds_;
7577  }
7578 
7579  private:
7580 
7583  std::size_t vec_size_;
7586  };
7587 
7588  #ifndef exprtk_disable_string_capabilities
7589  template <typename T>
7590  class stringvar_node : public expression_node <T>,
7591  public string_base_node<T>,
7592  public range_interface <T>
7593  {
7594  public:
7595 
7597 
7599 
7600  explicit stringvar_node()
7601  : value_(&null_value)
7602  {}
7603 
7605  : value_(&v)
7606  {
7607  rp_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7608  rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1);
7609  rp_.cache.first = rp_.n0_c.second;
7610  rp_.cache.second = rp_.n1_c.second;
7611  }
7612 
7613  inline bool operator <(const stringvar_node<T>& v) const
7614  {
7615  return this < (&v);
7616  }
7617 
7618  inline T value() const
7619  {
7620  rp_.n1_c.second = (*value_).size() - 1;
7621  rp_.cache.second = rp_.n1_c.second;
7622 
7623  return std::numeric_limits<T>::quiet_NaN();
7624  }
7625 
7627  {
7628  return ref();
7629  }
7630 
7631  char_cptr base() const
7632  {
7633  return &(*value_)[0];
7634  }
7635 
7636  std::size_t size() const
7637  {
7638  return ref().size();
7639  }
7640 
7642  {
7643  return (*value_);
7644  }
7645 
7646  const std::string& ref() const
7647  {
7648  return (*value_);
7649  }
7650 
7652  {
7653  return rp_;
7654  }
7655 
7656  const range_t& range_ref() const
7657  {
7658  return rp_;
7659  }
7660 
7661  inline typename expression_node<T>::node_type type() const
7662  {
7664  }
7665 
7666  private:
7667 
7669  mutable range_t rp_;
7670  };
7671 
7672  template <typename T>
7674 
7675  template <typename T>
7677  public string_base_node<T>,
7678  public range_interface <T>
7679  {
7680  public:
7681 
7683 
7685 
7686  explicit string_range_node(std::string& v, const range_t& rp)
7687  : value_(&v),
7688  rp_(rp)
7689  {}
7690 
7692  {
7693  rp_.free();
7694  }
7695 
7696  inline bool operator <(const string_range_node<T>& v) const
7697  {
7698  return this < (&v);
7699  }
7700 
7701  inline T value() const
7702  {
7703  return std::numeric_limits<T>::quiet_NaN();
7704  }
7705 
7706  inline std::string str() const
7707  {
7708  return (*value_);
7709  }
7710 
7711  char_cptr base() const
7712  {
7713  return &(*value_)[0];
7714  }
7715 
7716  std::size_t size() const
7717  {
7718  return ref().size();
7719  }
7720 
7721  inline range_t range() const
7722  {
7723  return rp_;
7724  }
7725 
7726  inline virtual std::string& ref()
7727  {
7728  return (*value_);
7729  }
7730 
7731  inline virtual const std::string& ref() const
7732  {
7733  return (*value_);
7734  }
7735 
7736  inline range_t& range_ref()
7737  {
7738  return rp_;
7739  }
7740 
7741  inline const range_t& range_ref() const
7742  {
7743  return rp_;
7744  }
7745 
7746  inline typename expression_node<T>::node_type type() const
7747  {
7749  }
7750 
7751  private:
7752 
7755  };
7756 
7757  template <typename T>
7759 
7760  template <typename T>
7762  public string_base_node<T>,
7763  public range_interface <T>
7764  {
7765  public:
7766 
7768 
7769  explicit const_string_range_node(const std::string& v, const range_t& rp)
7770  : value_(v),
7771  rp_(rp)
7772  {}
7773 
7775  {
7776  rp_.free();
7777  }
7778 
7779  inline T value() const
7780  {
7781  return std::numeric_limits<T>::quiet_NaN();
7782  }
7783 
7785  {
7786  return value_;
7787  }
7788 
7789  char_cptr base() const
7790  {
7791  return value_.data();
7792  }
7793 
7794  std::size_t size() const
7795  {
7796  return value_.size();
7797  }
7798 
7799  range_t range() const
7800  {
7801  return rp_;
7802  }
7803 
7805  {
7806  return rp_;
7807  }
7808 
7809  const range_t& range_ref() const
7810  {
7811  return rp_;
7812  }
7813 
7814  inline typename expression_node<T>::node_type type() const
7815  {
7817  }
7818 
7819  private:
7820 
7822 
7825  };
7826 
7827  template <typename T>
7829  public string_base_node<T>,
7830  public range_interface <T>
7831  {
7832  public:
7833 
7838  typedef range_t* range_ptr;
7841 
7843  : initialised_(false),
7844  branch_(str_branch),
7846  str_base_ptr_ (0),
7847  str_range_ptr_(0),
7848  base_range_(brange)
7849  {
7850  range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7851  range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7852  range_.cache.first = range_.n0_c.second;
7853  range_.cache.second = range_.n1_c.second;
7854 
7856  {
7857  str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
7858 
7859  if (0 == str_base_ptr_)
7860  return;
7861 
7862  str_range_ptr_ = dynamic_cast<irange_ptr>(branch_);
7863 
7864  if (0 == str_range_ptr_)
7865  return;
7866  }
7867 
7869  }
7870 
7872  {
7873  base_range_.free();
7874 
7875  if (branch_ && branch_deletable_)
7876  {
7878  }
7879  }
7880 
7881  inline T value() const
7882  {
7883  if (initialised_)
7884  {
7885  branch_->value();
7886 
7887  std::size_t str_r0 = 0;
7888  std::size_t str_r1 = 0;
7889 
7890  std::size_t r0 = 0;
7891  std::size_t r1 = 0;
7892 
7893  range_t& range = str_range_ptr_->range_ref();
7894 
7895  const std::size_t base_str_size = str_base_ptr_->size();
7896 
7897  if (
7898  range (str_r0,str_r1,base_str_size) &&
7899  base_range_( r0, r1,base_str_size)
7900  )
7901  {
7902  const std::size_t size = (r1 - r0) + 1;
7903 
7904  range_.n1_c.second = size - 1;
7905  range_.cache.second = range_.n1_c.second;
7906 
7907  value_.assign(str_base_ptr_->base() + str_r0 + r0, size);
7908  }
7909  }
7910 
7911  return std::numeric_limits<T>::quiet_NaN();
7912  }
7913 
7915  {
7916  return value_;
7917  }
7918 
7919  char_cptr base() const
7920  {
7921  return &value_[0];
7922  }
7923 
7924  std::size_t size() const
7925  {
7926  return value_.size();
7927  }
7928 
7930  {
7931  return range_;
7932  }
7933 
7934  const range_t& range_ref() const
7935  {
7936  return range_;
7937  }
7938 
7939  inline typename expression_node<T>::node_type type() const
7940  {
7942  }
7943 
7944  private:
7945 
7948  const bool branch_deletable_;
7952  mutable range_t range_;
7954  };
7955 
7956  template <typename T>
7957  class string_concat_node : public binary_node <T>,
7958  public string_base_node<T>,
7959  public range_interface <T>
7960  {
7961  public:
7962 
7966  typedef range_t* range_ptr;
7969 
7971  expression_ptr branch0,
7972  expression_ptr branch1)
7973  : binary_node<T>(opr, branch0, branch1),
7974  initialised_(false),
7975  str0_base_ptr_ (0),
7976  str1_base_ptr_ (0),
7977  str0_range_ptr_(0),
7978  str1_range_ptr_(0)
7979  {
7980  range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
7981  range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
7982 
7983  range_.cache.first = range_.n0_c.second;
7984  range_.cache.second = range_.n1_c.second;
7985 
7987  {
7988  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
7989 
7990  if (0 == str0_base_ptr_)
7991  return;
7992 
7993  str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
7994 
7995  if (0 == str0_range_ptr_)
7996  return;
7997  }
7998 
8000  {
8001  str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8002 
8003  if (0 == str1_base_ptr_)
8004  return;
8005 
8006  str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8007 
8008  if (0 == str1_range_ptr_)
8009  return;
8010  }
8011 
8013  str1_base_ptr_ &&
8014  str0_range_ptr_ &&
8015  str1_range_ptr_ ;
8016  }
8017 
8018  inline T value() const
8019  {
8020  if (initialised_)
8021  {
8022  binary_node<T>::branch_[0].first->value();
8023  binary_node<T>::branch_[1].first->value();
8024 
8025  std::size_t str0_r0 = 0;
8026  std::size_t str0_r1 = 0;
8027 
8028  std::size_t str1_r0 = 0;
8029  std::size_t str1_r1 = 0;
8030 
8031  range_t& range0 = str0_range_ptr_->range_ref();
8032  range_t& range1 = str1_range_ptr_->range_ref();
8033 
8034  if (
8035  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8036  range1(str1_r0, str1_r1, str1_base_ptr_->size())
8037  )
8038  {
8039  const std::size_t size0 = (str0_r1 - str0_r0) + 1;
8040  const std::size_t size1 = (str1_r1 - str1_r0) + 1;
8041 
8042  value_.assign(str0_base_ptr_->base() + str0_r0, size0);
8043  value_.append(str1_base_ptr_->base() + str1_r0, size1);
8044 
8045  range_.n1_c.second = value_.size() - 1;
8046  range_.cache.second = range_.n1_c.second;
8047  }
8048  }
8049 
8050  return std::numeric_limits<T>::quiet_NaN();
8051  }
8052 
8054  {
8055  return value_;
8056  }
8057 
8058  char_cptr base() const
8059  {
8060  return &value_[0];
8061  }
8062 
8063  std::size_t size() const
8064  {
8065  return value_.size();
8066  }
8067 
8069  {
8070  return range_;
8071  }
8072 
8073  const range_t& range_ref() const
8074  {
8075  return range_;
8076  }
8077 
8078  inline typename expression_node<T>::node_type type() const
8079  {
8081  }
8082 
8083  private:
8084 
8090  mutable range_t range_;
8092  };
8093 
8094  template <typename T>
8095  class swap_string_node : public binary_node <T>,
8096  public string_base_node<T>,
8097  public range_interface <T>
8098  {
8099  public:
8100 
8105  typedef range_t* range_ptr;
8108 
8110  : binary_node<T>(details::e_swap, branch0, branch1),
8111  initialised_(false),
8112  str0_node_ptr_(0),
8113  str1_node_ptr_(0)
8114  {
8116  {
8117  str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8118  }
8119 
8121  {
8122  str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first);
8123  }
8124 
8126  }
8127 
8128  inline T value() const
8129  {
8130  if (initialised_)
8131  {
8132  binary_node<T>::branch_[0].first->value();
8133  binary_node<T>::branch_[1].first->value();
8134 
8135  std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref());
8136  }
8137 
8138  return std::numeric_limits<T>::quiet_NaN();
8139  }
8140 
8142  {
8143  return str0_node_ptr_->str();
8144  }
8145 
8146  char_cptr base() const
8147  {
8148  return str0_node_ptr_->base();
8149  }
8150 
8151  std::size_t size() const
8152  {
8153  return str0_node_ptr_->size();
8154  }
8155 
8157  {
8158  return str0_node_ptr_->range_ref();
8159  }
8160 
8161  const range_t& range_ref() const
8162  {
8163  return str0_node_ptr_->range_ref();
8164  }
8165 
8166  inline typename expression_node<T>::node_type type() const
8167  {
8169  }
8170 
8171  private:
8172 
8176  };
8177 
8178  template <typename T>
8180  {
8181  public:
8182 
8186  typedef range_t* range_ptr;
8189 
8191  expression_ptr branch1)
8192  : binary_node<T>(details::e_default, branch0, branch1),
8193  str0_base_ptr_ (0),
8194  str1_base_ptr_ (0),
8195  str0_range_ptr_(0),
8196  str1_range_ptr_(0),
8197  initialised_(false)
8198  {
8200  {
8201  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8202 
8203  if (0 == str0_base_ptr_)
8204  return;
8205 
8206  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8207 
8208  if (0 == range)
8209  return;
8210 
8211  str0_range_ptr_ = &(range->range_ref());
8212  }
8213 
8215  {
8216  str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8217 
8218  if (0 == str1_base_ptr_)
8219  return;
8220 
8221  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8222 
8223  if (0 == range)
8224  return;
8225 
8226  str1_range_ptr_ = &(range->range_ref());
8227  }
8228 
8230  str1_base_ptr_ &&
8231  str0_range_ptr_ &&
8232  str1_range_ptr_ ;
8233  }
8234 
8235  inline T value() const
8236  {
8237  if (initialised_)
8238  {
8239  binary_node<T>::branch_[0].first->value();
8240  binary_node<T>::branch_[1].first->value();
8241 
8242  std::size_t str0_r0 = 0;
8243  std::size_t str0_r1 = 0;
8244 
8245  std::size_t str1_r0 = 0;
8246  std::size_t str1_r1 = 0;
8247 
8248  range_t& range0 = (*str0_range_ptr_);
8249  range_t& range1 = (*str1_range_ptr_);
8250 
8251  if (
8252  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
8253  range1(str1_r0, str1_r1, str1_base_ptr_->size())
8254  )
8255  {
8256  const std::size_t size0 = range0.cache_size();
8257  const std::size_t size1 = range1.cache_size();
8258  const std::size_t max_size = std::min(size0,size1);
8259 
8260  char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0);
8261  char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0);
8262 
8263  loop_unroll::details lud(max_size);
8264  char_cptr upper_bound = s0 + lud.upper_bound;
8265 
8266  while (s0 < upper_bound)
8267  {
8268  #define exprtk_loop(N) \
8269  std::swap(s0[N], s1[N]); \
8270 
8271  exprtk_loop( 0) exprtk_loop( 1)
8272  exprtk_loop( 2) exprtk_loop( 3)
8273  #ifndef exprtk_disable_superscalar_unroll
8274  exprtk_loop( 4) exprtk_loop( 5)
8275  exprtk_loop( 6) exprtk_loop( 7)
8276  exprtk_loop( 8) exprtk_loop( 9)
8277  exprtk_loop(10) exprtk_loop(11)
8278  exprtk_loop(12) exprtk_loop(13)
8279  exprtk_loop(14) exprtk_loop(15)
8280  #endif
8281 
8282  s0 += lud.batch_size;
8283  s1 += lud.batch_size;
8284  }
8285 
8286  int i = 0;
8287 
8289  switch (lud.remainder)
8290  {
8291  #define case_stmt(N) \
8292  case N : { std::swap(s0[i],s1[i]); ++i; } \
8293 
8294  #ifndef exprtk_disable_superscalar_unroll
8295  case_stmt(15) case_stmt(14)
8296  case_stmt(13) case_stmt(12)
8297  case_stmt(11) case_stmt(10)
8298  case_stmt( 9) case_stmt( 8)
8299  case_stmt( 7) case_stmt( 6)
8300  case_stmt( 5) case_stmt( 4)
8301  #endif
8302  case_stmt( 3) case_stmt( 2)
8303  case_stmt( 1)
8304  }
8306 
8307  #undef exprtk_loop
8308  #undef case_stmt
8309  }
8310  }
8311 
8312  return std::numeric_limits<T>::quiet_NaN();
8313  }
8314 
8315  inline typename expression_node<T>::node_type type() const
8316  {
8318  }
8319 
8320  private:
8321 
8324 
8330  };
8331 
8332  template <typename T>
8334  {
8335  public:
8336 
8338 
8340  : value_(&null_value)
8341  {}
8342 
8344  : value_(&v)
8345  {}
8346 
8347  inline T value() const
8348  {
8349  return T((*value_).size());
8350  }
8351 
8352  inline typename expression_node<T>::node_type type() const
8353  {
8355  }
8356 
8357  private:
8358 
8360  };
8361 
8362  template <typename T>
8364 
8365  template <typename T>
8367  {
8368  public:
8369 
8372 
8374  : branch_(brnch),
8376  str_base_ptr_(0)
8377  {
8379  {
8380  str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_);
8381 
8382  if (0 == str_base_ptr_)
8383  return;
8384  }
8385  }
8386 
8388  {
8389  if (branch_ && branch_deletable_)
8390  {
8392  }
8393  }
8394 
8395  inline T value() const
8396  {
8397  T result = std::numeric_limits<T>::quiet_NaN();
8398 
8399  if (str_base_ptr_)
8400  {
8401  branch_->value();
8402  result = T(str_base_ptr_->size());
8403  }
8404 
8405  return result;
8406  }
8407 
8408  inline typename expression_node<T>::node_type type() const
8409  {
8411  }
8412 
8413  private:
8414 
8416  const bool branch_deletable_;
8418  };
8419 
8421  {
8422  static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8423  { s.assign(data,size); }
8424  };
8425 
8427  {
8428  static inline void execute(std::string& s, char_cptr data, const std::size_t size)
8429  { s.append(data,size); }
8430  };
8431 
8432  template <typename T, typename AssignmentProcess = asn_assignment>
8434  public string_base_node<T>,
8435  public range_interface <T>
8436  {
8437  public:
8438 
8443  typedef range_t* range_ptr;
8446 
8448  expression_ptr branch0,
8449  expression_ptr branch1)
8450  : binary_node<T>(opr, branch0, branch1),
8451  initialised_(false),
8452  str0_base_ptr_ (0),
8453  str1_base_ptr_ (0),
8454  str0_node_ptr_ (0),
8455  str1_range_ptr_(0)
8456  {
8458  {
8459  str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8460 
8461  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8462  }
8463 
8465  {
8466  str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8467 
8468  if (0 == str1_base_ptr_)
8469  return;
8470 
8471  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8472 
8473  if (0 == range)
8474  return;
8475 
8476  str1_range_ptr_ = &(range->range_ref());
8477  }
8478 
8480  str1_base_ptr_ &&
8481  str0_node_ptr_ &&
8482  str1_range_ptr_ ;
8483  }
8484 
8485  inline T value() const
8486  {
8487  if (initialised_)
8488  {
8489  binary_node<T>::branch_[1].first->value();
8490 
8491  std::size_t r0 = 0;
8492  std::size_t r1 = 0;
8493 
8494  range_t& range = (*str1_range_ptr_);
8495 
8496  if (range(r0, r1, str1_base_ptr_->size()))
8497  {
8498  AssignmentProcess::execute(str0_node_ptr_->ref(),
8499  str1_base_ptr_->base() + r0,
8500  (r1 - r0) + 1);
8501 
8502  binary_node<T>::branch_[0].first->value();
8503  }
8504  }
8505 
8506  return std::numeric_limits<T>::quiet_NaN();
8507  }
8508 
8510  {
8511  return str0_node_ptr_->str();
8512  }
8513 
8514  char_cptr base() const
8515  {
8516  return str0_node_ptr_->base();
8517  }
8518 
8519  std::size_t size() const
8520  {
8521  return str0_node_ptr_->size();
8522  }
8523 
8525  {
8526  return str0_node_ptr_->range_ref();
8527  }
8528 
8529  const range_t& range_ref() const
8530  {
8531  return str0_node_ptr_->range_ref();
8532  }
8533 
8534  inline typename expression_node<T>::node_type type() const
8535  {
8537  }
8538 
8539  private:
8540 
8546  };
8547 
8548  template <typename T, typename AssignmentProcess = asn_assignment>
8550  public string_base_node<T>,
8551  public range_interface <T>
8552  {
8553  public:
8554 
8559  typedef range_t* range_ptr;
8562 
8564  expression_ptr branch0,
8565  expression_ptr branch1)
8566  : binary_node<T>(opr, branch0, branch1),
8567  initialised_(false),
8568  str0_base_ptr_ (0),
8569  str1_base_ptr_ (0),
8570  str0_node_ptr_ (0),
8571  str0_range_ptr_(0),
8572  str1_range_ptr_(0)
8573  {
8575  {
8576  str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first);
8577 
8578  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8579 
8580  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8581 
8582  if (0 == range)
8583  return;
8584 
8585  str0_range_ptr_ = &(range->range_ref());
8586  }
8587 
8589  {
8590  str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
8591 
8592  if (0 == str1_base_ptr_)
8593  return;
8594 
8595  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
8596 
8597  if (0 == range)
8598  return;
8599 
8600  str1_range_ptr_ = &(range->range_ref());
8601  }
8602 
8604  str1_base_ptr_ &&
8605  str0_node_ptr_ &&
8606  str0_range_ptr_ &&
8607  str1_range_ptr_ ;
8608  }
8609 
8610  inline T value() const
8611  {
8612  if (initialised_)
8613  {
8614  binary_node<T>::branch_[0].first->value();
8615  binary_node<T>::branch_[1].first->value();
8616 
8617  std::size_t s0_r0 = 0;
8618  std::size_t s0_r1 = 0;
8619 
8620  std::size_t s1_r0 = 0;
8621  std::size_t s1_r1 = 0;
8622 
8623  range_t& range0 = (*str0_range_ptr_);
8624  range_t& range1 = (*str1_range_ptr_);
8625 
8626  if (
8627  range0(s0_r0, s0_r1, str0_base_ptr_->size()) &&
8628  range1(s1_r0, s1_r1, str1_base_ptr_->size())
8629  )
8630  {
8631  std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1;
8632 
8633  std::copy(str1_base_ptr_->base() + s1_r0,
8634  str1_base_ptr_->base() + s1_r0 + size,
8635  const_cast<char_ptr>(base() + s0_r0));
8636  }
8637  }
8638 
8639  return std::numeric_limits<T>::quiet_NaN();
8640  }
8641 
8643  {
8644  return str0_node_ptr_->str();
8645  }
8646 
8647  char_cptr base() const
8648  {
8649  return str0_node_ptr_->base();
8650  }
8651 
8652  std::size_t size() const
8653  {
8654  return str0_node_ptr_->size();
8655  }
8656 
8658  {
8659  return str0_node_ptr_->range_ref();
8660  }
8661 
8662  const range_t& range_ref() const
8663  {
8664  return str0_node_ptr_->range_ref();
8665  }
8666 
8667  inline typename expression_node<T>::node_type type() const
8668  {
8670  }
8671 
8672  private:
8673 
8680  };
8681 
8682  template <typename T>
8684  public string_base_node<T>,
8685  public range_interface <T>
8686  {
8687  public:
8688 
8692  typedef range_t* range_ptr;
8695 
8697  expression_ptr consequent,
8698  expression_ptr alternative)
8699  : trinary_node<T>(details::e_default,consequent,alternative,test),
8700  initialised_(false),
8701  str0_base_ptr_ (0),
8702  str1_base_ptr_ (0),
8703  str0_range_ptr_(0),
8704  str1_range_ptr_(0),
8705  test_ (test),
8706  consequent_ (consequent),
8707  alternative_(alternative)
8708  {
8709  range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8710  range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8711 
8712  range_.cache.first = range_.n0_c.second;
8713  range_.cache.second = range_.n1_c.second;
8714 
8716  {
8717  str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first);
8718 
8719  if (0 == str0_base_ptr_)
8720  return;
8721 
8722  str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first);
8723 
8724  if (0 == str0_range_ptr_)
8725  return;
8726  }
8727 
8729  {
8730  str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first);
8731 
8732  if (0 == str1_base_ptr_)
8733  return;
8734 
8735  str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first);
8736 
8737  if (0 == str1_range_ptr_)
8738  return;
8739  }
8740 
8742  str1_base_ptr_ &&
8743  str0_range_ptr_ &&
8744  str1_range_ptr_ ;
8745 
8746  }
8747 
8748  inline T value() const
8749  {
8750  if (initialised_)
8751  {
8752  std::size_t r0 = 0;
8753  std::size_t r1 = 0;
8754 
8755  if (is_true(test_))
8756  {
8757  consequent_->value();
8758 
8759  range_t& range = str0_range_ptr_->range_ref();
8760 
8761  if (range(r0, r1, str0_base_ptr_->size()))
8762  {
8763  const std::size_t size = (r1 - r0) + 1;
8764 
8765  value_.assign(str0_base_ptr_->base() + r0, size);
8766 
8767  range_.n1_c.second = value_.size() - 1;
8768  range_.cache.second = range_.n1_c.second;
8769 
8770  return T(1);
8771  }
8772  }
8773  else
8774  {
8775  alternative_->value();
8776 
8777  range_t& range = str1_range_ptr_->range_ref();
8778 
8779  if (range(r0, r1, str1_base_ptr_->size()))
8780  {
8781  const std::size_t size = (r1 - r0) + 1;
8782 
8783  value_.assign(str1_base_ptr_->base() + r0, size);
8784 
8785  range_.n1_c.second = value_.size() - 1;
8786  range_.cache.second = range_.n1_c.second;
8787 
8788  return T(0);
8789  }
8790  }
8791  }
8792 
8793  return std::numeric_limits<T>::quiet_NaN();
8794  }
8795 
8797  {
8798  return value_;
8799  }
8800 
8801  char_cptr base() const
8802  {
8803  return &value_[0];
8804  }
8805 
8806  std::size_t size() const
8807  {
8808  return value_.size();
8809  }
8810 
8812  {
8813  return range_;
8814  }
8815 
8816  const range_t& range_ref() const
8817  {
8818  return range_;
8819  }
8820 
8821  inline typename expression_node<T>::node_type type() const
8822  {
8824  }
8825 
8826  private:
8827 
8833  mutable range_t range_;
8835 
8839  };
8840 
8841  template <typename T>
8843  public string_base_node<T>,
8844  public range_interface <T>
8845  {
8846  public:
8847 
8851  typedef range_t* range_ptr;
8854 
8856  expression_ptr consequent)
8857  : binary_node<T>(details::e_default, consequent, test),
8858  initialised_(false),
8859  str0_base_ptr_ (0),
8860  str0_range_ptr_(0),
8861  test_ (test),
8862  consequent_(consequent)
8863  {
8864  range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
8865  range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
8866 
8867  range_.cache.first = range_.n0_c.second;
8868  range_.cache.second = range_.n1_c.second;
8869 
8871  {
8872  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
8873 
8874  if (0 == str0_base_ptr_)
8875  return;
8876 
8877  str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
8878 
8879  if (0 == str0_range_ptr_)
8880  return;
8881  }
8882 
8884  }
8885 
8886  inline T value() const
8887  {
8888  if (initialised_)
8889  {
8890  if (is_true(test_))
8891  {
8892  consequent_->value();
8893 
8894  range_t& range = str0_range_ptr_->range_ref();
8895 
8896  std::size_t r0 = 0;
8897  std::size_t r1 = 0;
8898 
8899  if (range(r0, r1, str0_base_ptr_->size()))
8900  {
8901  const std::size_t size = (r1 - r0) + 1;
8902 
8903  value_.assign(str0_base_ptr_->base() + r0, size);
8904 
8905  range_.n1_c.second = value_.size() - 1;
8906  range_.cache.second = range_.n1_c.second;
8907 
8908  return T(1);
8909  }
8910  }
8911  }
8912 
8913  return std::numeric_limits<T>::quiet_NaN();
8914  }
8915 
8917  {
8918  return value_;
8919  }
8920 
8921  char_cptr base() const
8922  {
8923  return &value_[0];
8924  }
8925 
8926  std::size_t size() const
8927  {
8928  return value_.size();
8929  }
8930 
8932  {
8933  return range_;
8934  }
8935 
8936  const range_t& range_ref() const
8937  {
8938  return range_;
8939  }
8940 
8941  inline typename expression_node<T>::node_type type() const
8942  {
8944  }
8945 
8946  private:
8947 
8951  mutable range_t range_;
8953 
8956  };
8957 
8958  template <typename T, typename VarArgFunction>
8959  class str_vararg_node : public expression_node <T>,
8960  public string_base_node<T>,
8961  public range_interface <T>
8962  {
8963  public:
8964 
8968  typedef range_t* range_ptr;
8971 
8972  template <typename Allocator,
8973  template <typename, typename> class Sequence>
8974  explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
8975  : final_node_(arg_list.back()),
8977  initialised_(false),
8978  str_base_ptr_ (0),
8979  str_range_ptr_(0)
8980  {
8981  if (0 == final_node_)
8982  return;
8984  return;
8985 
8986  str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_);
8987 
8988  if (0 == str_base_ptr_)
8989  return;
8990 
8991  str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_);
8992 
8993  if (0 == str_range_ptr_)
8994  return;
8995 
8997 
8998  if (arg_list.size() > 1)
8999  {
9000  const std::size_t arg_list_size = arg_list.size() - 1;
9001 
9002  arg_list_.resize(arg_list_size);
9003  delete_branch_.resize(arg_list_size);
9004 
9005  for (std::size_t i = 0; i < arg_list_size; ++i)
9006  {
9007  if (arg_list[i])
9008  {
9009  arg_list_[i] = arg_list[i];
9010  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9011  }
9012  else
9013  {
9014  arg_list_ .clear();
9015  delete_branch_.clear();
9016  return;
9017  }
9018  }
9019  }
9020  }
9021 
9023  {
9025  {
9027  }
9028 
9029  for (std::size_t i = 0; i < arg_list_.size(); ++i)
9030  {
9031  if (arg_list_[i] && delete_branch_[i])
9032  {
9033  destroy_node(arg_list_[i]);
9034  }
9035  }
9036  }
9037 
9038  inline T value() const
9039  {
9040  if (!arg_list_.empty())
9041  {
9043  }
9044 
9045  final_node_->value();
9046 
9047  return std::numeric_limits<T>::quiet_NaN();
9048  }
9049 
9051  {
9052  return str_base_ptr_->str();
9053  }
9054 
9055  char_cptr base() const
9056  {
9057  return str_base_ptr_->base();
9058  }
9059 
9060  std::size_t size() const
9061  {
9062  return str_base_ptr_->size();
9063  }
9064 
9066  {
9067  return str_range_ptr_->range_ref();
9068  }
9069 
9070  const range_t& range_ref() const
9071  {
9072  return str_range_ptr_->range_ref();
9073  }
9074 
9075  inline typename expression_node<T>::node_type type() const
9076  {
9078  }
9079 
9080  private:
9081 
9087  std::vector<expression_ptr> arg_list_;
9088  std::vector<unsigned char> delete_branch_;
9089  };
9090  #endif
9091 
9092  template <typename T, std::size_t N>
9093  inline T axn(T a, T x)
9094  {
9095  // a*x^n
9097  }
9098 
9099  template <typename T, std::size_t N>
9100  inline T axnb(T a, T x, T b)
9101  {
9102  // a*x^n+b
9104  }
9105 
9106  template <typename T>
9107  struct sf_base
9108  {
9115  };
9116 
9117  #define define_sfop3(NN,OP0,OP1) \
9118  template <typename T> \
9119  struct sf##NN##_op : public sf_base<T> \
9120  { \
9121  typedef typename sf_base<T>::Type Type; \
9122  static inline T process(Type x, Type y, Type z) \
9123  { \
9124  return (OP0); \
9125  } \
9126  static inline std::string id() \
9127  { \
9128  return OP1; \
9129  } \
9130  }; \
9131 
9132  define_sfop3(00,(x + y) / z ,"(t+t)/t")
9133  define_sfop3(01,(x + y) * z ,"(t+t)*t")
9134  define_sfop3(02,(x + y) - z ,"(t+t)-t")
9135  define_sfop3(03,(x + y) + z ,"(t+t)+t")
9136  define_sfop3(04,(x - y) + z ,"(t-t)+t")
9137  define_sfop3(05,(x - y) / z ,"(t-t)/t")
9138  define_sfop3(06,(x - y) * z ,"(t-t)*t")
9139  define_sfop3(07,(x * y) + z ,"(t*t)+t")
9140  define_sfop3(08,(x * y) - z ,"(t*t)-t")
9141  define_sfop3(09,(x * y) / z ,"(t*t)/t")
9142  define_sfop3(10,(x * y) * z ,"(t*t)*t")
9143  define_sfop3(11,(x / y) + z ,"(t/t)+t")
9144  define_sfop3(12,(x / y) - z ,"(t/t)-t")
9145  define_sfop3(13,(x / y) / z ,"(t/t)/t")
9146  define_sfop3(14,(x / y) * z ,"(t/t)*t")
9147  define_sfop3(15,x / (y + z) ,"t/(t+t)")
9148  define_sfop3(16,x / (y - z) ,"t/(t-t)")
9149  define_sfop3(17,x / (y * z) ,"t/(t*t)")
9150  define_sfop3(18,x / (y / z) ,"t/(t/t)")
9151  define_sfop3(19,x * (y + z) ,"t*(t+t)")
9152  define_sfop3(20,x * (y - z) ,"t*(t-t)")
9153  define_sfop3(21,x * (y * z) ,"t*(t*t)")
9154  define_sfop3(22,x * (y / z) ,"t*(t/t)")
9155  define_sfop3(23,x - (y + z) ,"t-(t+t)")
9156  define_sfop3(24,x - (y - z) ,"t-(t-t)")
9157  define_sfop3(25,x - (y / z) ,"t-(t/t)")
9158  define_sfop3(26,x - (y * z) ,"t-(t*t)")
9159  define_sfop3(27,x + (y * z) ,"t+(t*t)")
9160  define_sfop3(28,x + (y / z) ,"t+(t/t)")
9161  define_sfop3(29,x + (y + z) ,"t+(t+t)")
9162  define_sfop3(30,x + (y - z) ,"t+(t-t)")
9163  define_sfop3(31,(axnb<T,2>(x,y,z))," ")
9164  define_sfop3(32,(axnb<T,3>(x,y,z))," ")
9165  define_sfop3(33,(axnb<T,4>(x,y,z))," ")
9166  define_sfop3(34,(axnb<T,5>(x,y,z))," ")
9167  define_sfop3(35,(axnb<T,6>(x,y,z))," ")
9168  define_sfop3(36,(axnb<T,7>(x,y,z))," ")
9169  define_sfop3(37,(axnb<T,8>(x,y,z))," ")
9170  define_sfop3(38,(axnb<T,9>(x,y,z))," ")
9171  define_sfop3(39,x * numeric::log(y) + z,"")
9172  define_sfop3(40,x * numeric::log(y) - z,"")
9173  define_sfop3(41,x * numeric::log10(y) + z,"")
9174  define_sfop3(42,x * numeric::log10(y) - z,"")
9175  define_sfop3(43,x * numeric::sin(y) + z ,"")
9176  define_sfop3(44,x * numeric::sin(y) - z ,"")
9177  define_sfop3(45,x * numeric::cos(y) + z ,"")
9178  define_sfop3(46,x * numeric::cos(y) - z ,"")
9179  define_sfop3(47,details::is_true(x) ? y : z,"")
9180 
9181  #define define_sfop4(NN,OP0,OP1) \
9182  template <typename T> \
9183  struct sf##NN##_op : public sf_base<T> \
9184  { \
9185  typedef typename sf_base<T>::Type Type; \
9186  static inline T process(Type x, Type y, Type z, Type w) \
9187  { \
9188  return (OP0); \
9189  } \
9190  static inline std::string id() { return OP1; } \
9191  }; \
9192 
9193  define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)")
9194  define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)")
9195  define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)")
9196  define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)")
9197  define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)")
9198  define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)")
9199  define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)")
9200  define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)")
9201  define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)")
9202  define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)")
9203  define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)")
9204  define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)")
9205  define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)")
9206  define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)")
9207  define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)")
9208  define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)")
9209  define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)")
9210  define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t")
9211  define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t")
9212  define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t")
9213  define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t")
9214  define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t")
9215  define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t")
9216  define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t")
9217  define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t")
9218  define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)")
9219  define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)")
9220  define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)")
9221  define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)")
9222  define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)")
9223  define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)")
9224  define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)")
9225  define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))")
9226  define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))")
9227  define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))")
9228  define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))")
9229 
9230  define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"")
9231  define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"")
9232  define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"")
9233  define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"")
9234  define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"")
9235  define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"")
9236  define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"")
9237  define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"")
9238  define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"")
9239  define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"")
9240  define_sfop4(94,((x < y) ? z : w),"")
9241  define_sfop4(95,((x <= y) ? z : w),"")
9242  define_sfop4(96,((x > y) ? z : w),"")
9243  define_sfop4(97,((x >= y) ? z : w),"")
9244  define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"")
9245  define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"")
9246 
9247  define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)")
9248  define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)")
9249  define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)")
9250  define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)")
9251  define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)")
9252  define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)")
9253  define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)")
9254  define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)")
9255  define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)")
9256  define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)")
9257  define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)")
9258  define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)")
9259  define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)")
9260  define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)")
9261  define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)")
9262  define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)")
9263  define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)")
9264  define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)")
9265  define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)")
9266  define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)")
9267  define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)")
9268  define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)")
9269  define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)")
9270  define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)")
9271  define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)")
9272  define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)")
9273  define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)")
9274  define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)")
9275  define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)")
9276  define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)")
9277  define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)")
9278  define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)")
9279  define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)")
9280  define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)")
9281  define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)")
9282  define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)")
9283  define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)")
9284  define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)")
9285  define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)")
9286  define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)")
9287  define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)")
9288  define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)")
9289  define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)")
9290  define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)")
9291  define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))")
9292  define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))")
9293  define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))")
9294  define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))")
9295  define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t")
9296  define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t")
9297  define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t")
9298  define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t")
9299  define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t")
9300  define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t")
9301  define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)")
9302  define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)")
9303  define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)")
9304  define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)")
9305  define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)")
9306  define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)")
9307  define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)")
9308  define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t")
9309 
9310  #undef define_sfop3
9311  #undef define_sfop4
9312 
9313  template <typename T, typename SpecialFunction>
9314  class sf3_node : public trinary_node<T>
9315  {
9316  public:
9317 
9318  typedef expression_node<T>* expression_ptr;
9319 
9320  sf3_node(const operator_type& opr,
9321  expression_ptr branch0,
9322  expression_ptr branch1,
9323  expression_ptr branch2)
9324  : trinary_node<T>(opr, branch0, branch1, branch2)
9325  {}
9326 
9327  inline T value() const
9328  {
9329  const T x = trinary_node<T>::branch_[0].first->value();
9330  const T y = trinary_node<T>::branch_[1].first->value();
9331  const T z = trinary_node<T>::branch_[2].first->value();
9332 
9333  return SpecialFunction::process(x, y, z);
9334  }
9335  };
9336 
9337  template <typename T, typename SpecialFunction>
9338  class sf4_node : public quaternary_node<T>
9339  {
9340  public:
9341 
9343 
9345  expression_ptr branch0,
9346  expression_ptr branch1,
9347  expression_ptr branch2,
9348  expression_ptr branch3)
9349  : quaternary_node<T>(opr, branch0, branch1, branch2, branch3)
9350  {}
9351 
9352  inline T value() const
9353  {
9354  const T x = quaternary_node<T>::branch_[0].first->value();
9355  const T y = quaternary_node<T>::branch_[1].first->value();
9356  const T z = quaternary_node<T>::branch_[2].first->value();
9357  const T w = quaternary_node<T>::branch_[3].first->value();
9358 
9359  return SpecialFunction::process(x, y, z, w);
9360  }
9361  };
9362 
9363  template <typename T, typename SpecialFunction>
9364  class sf3_var_node : public expression_node<T>
9365  {
9366  public:
9367 
9369 
9370  sf3_var_node(const T& v0, const T& v1, const T& v2)
9371  : v0_(v0),
9372  v1_(v1),
9373  v2_(v2)
9374  {}
9375 
9376  inline T value() const
9377  {
9378  return SpecialFunction::process(v0_, v1_, v2_);
9379  }
9380 
9381  inline typename expression_node<T>::node_type type() const
9382  {
9384  }
9385 
9386  private:
9387 
9390 
9391  const T& v0_;
9392  const T& v1_;
9393  const T& v2_;
9394  };
9395 
9396  template <typename T, typename SpecialFunction>
9397  class sf4_var_node : public expression_node<T>
9398  {
9399  public:
9400 
9402 
9403  sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3)
9404  : v0_(v0),
9405  v1_(v1),
9406  v2_(v2),
9407  v3_(v3)
9408  {}
9409 
9410  inline T value() const
9411  {
9412  return SpecialFunction::process(v0_, v1_, v2_, v3_);
9413  }
9414 
9415  inline typename expression_node<T>::node_type type() const
9416  {
9418  }
9419 
9420  private:
9421 
9424 
9425  const T& v0_;
9426  const T& v1_;
9427  const T& v2_;
9428  const T& v3_;
9429  };
9430 
9431  template <typename T, typename VarArgFunction>
9432  class vararg_node : public expression_node<T>
9433  {
9434  public:
9435 
9437 
9438  template <typename Allocator,
9439  template <typename, typename> class Sequence>
9440  explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list)
9441  {
9442  arg_list_ .resize(arg_list.size());
9443  delete_branch_.resize(arg_list.size());
9444 
9445  for (std::size_t i = 0; i < arg_list.size(); ++i)
9446  {
9447  if (arg_list[i])
9448  {
9449  arg_list_[i] = arg_list[i];
9450  delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0);
9451  }
9452  else
9453  {
9454  arg_list_.clear();
9455  delete_branch_.clear();
9456  return;
9457  }
9458  }
9459  }
9460 
9462  {
9463  for (std::size_t i = 0; i < arg_list_.size(); ++i)
9464  {
9465  if (arg_list_[i] && delete_branch_[i])
9466  {
9467  destroy_node(arg_list_[i]);
9468  }
9469  }
9470  }
9471 
9472  inline T value() const
9473  {
9474  if (!arg_list_.empty())
9476  else
9477  return std::numeric_limits<T>::quiet_NaN();
9478  }
9479 
9480  inline typename expression_node<T>::node_type type() const
9481  {
9483  }
9484 
9485  private:
9486 
9487  std::vector<expression_ptr> arg_list_;
9488  std::vector<unsigned char> delete_branch_;
9489  };
9490 
9491  template <typename T, typename VarArgFunction>
9493  {
9494  public:
9495 
9497 
9498  template <typename Allocator,
9499  template <typename, typename> class Sequence>
9500  explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list)
9501  {
9502  arg_list_.resize(arg_list.size());
9503 
9504  for (std::size_t i = 0; i < arg_list.size(); ++i)
9505  {
9506  if (arg_list[i] && is_variable_node(arg_list[i]))
9507  {
9508  variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]);
9509  arg_list_[i] = (&var_node_ptr->ref());
9510  }
9511  else
9512  {
9513  arg_list_.clear();
9514  return;
9515  }
9516  }
9517  }
9518 
9519  inline T value() const
9520  {
9521  if (!arg_list_.empty())
9523  else
9524  return std::numeric_limits<T>::quiet_NaN();
9525  }
9526 
9527  inline typename expression_node<T>::node_type type() const
9528  {
9530  }
9531 
9532  private:
9533 
9534  std::vector<const T*> arg_list_;
9535  };
9536 
9537  template <typename T, typename VecFunction>
9539  {
9540  public:
9541 
9543 
9544  explicit vectorize_node(const expression_ptr v)
9545  : ivec_ptr_(0),
9546  v_(v),
9548  {
9549  if (is_ivector_node(v))
9550  {
9551  ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v);
9552  }
9553  else
9554  ivec_ptr_ = 0;
9555  }
9556 
9558  {
9559  if (v_ && v_deletable_)
9560  {
9561  destroy_node(v_);
9562  }
9563  }
9564 
9565  inline T value() const
9566  {
9567  if (ivec_ptr_)
9568  {
9569  v_->value();
9571  }
9572  else
9573  return std::numeric_limits<T>::quiet_NaN();
9574  }
9575 
9576  inline typename expression_node<T>::node_type type() const
9577  {
9579  }
9580 
9581  private:
9582 
9585  const bool v_deletable_;
9586  };
9587 
9588  template <typename T>
9589  class assignment_node : public binary_node<T>
9590  {
9591  public:
9592 
9594 
9596  expression_ptr branch0,
9597  expression_ptr branch1)
9598  : binary_node<T>(opr, branch0, branch1),
9599  var_node_ptr_(0)
9600  {
9602  {
9603  var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
9604  }
9605  }
9606 
9607  inline T value() const
9608  {
9609  if (var_node_ptr_)
9610  {
9611  T& result = var_node_ptr_->ref();
9612 
9613  result = binary_node<T>::branch_[1].first->value();
9614 
9615  return result;
9616  }
9617  else
9618  return std::numeric_limits<T>::quiet_NaN();
9619  }
9620 
9621  private:
9622 
9624  };
9625 
9626  template <typename T>
9628  {
9629  public:
9630 
9632 
9634  expression_ptr branch0,
9635  expression_ptr branch1)
9636  : binary_node<T>(opr, branch0, branch1),
9637  vec_node_ptr_(0)
9638  {
9640  {
9641  vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
9642  }
9643  }
9644 
9645  inline T value() const
9646  {
9647  if (vec_node_ptr_)
9648  {
9649  T& result = vec_node_ptr_->ref();
9650 
9651  result = binary_node<T>::branch_[1].first->value();
9652 
9653  return result;
9654  }
9655  else
9656  return std::numeric_limits<T>::quiet_NaN();
9657  }
9658 
9659  private:
9660 
9662  };
9663 
9664  template <typename T>
9666  {
9667  public:
9668 
9670 
9672  expression_ptr branch0,
9673  expression_ptr branch1)
9674  : binary_node<T>(opr, branch0, branch1),
9675  rbvec_node_ptr_(0)
9676  {
9678  {
9680  }
9681  }
9682 
9683  inline T value() const
9684  {
9685  if (rbvec_node_ptr_)
9686  {
9687  T& result = rbvec_node_ptr_->ref();
9688 
9689  result = binary_node<T>::branch_[1].first->value();
9690 
9691  return result;
9692  }
9693  else
9694  return std::numeric_limits<T>::quiet_NaN();
9695  }
9696 
9697  private:
9698 
9700  };
9701 
9702  template <typename T>
9704  {
9705  public:
9706 
9708 
9710  expression_ptr branch0,
9711  expression_ptr branch1)
9712  : binary_node<T>(opr, branch0, branch1),
9713  rbvec_node_ptr_(0)
9714  {
9716  {
9718  }
9719  }
9720 
9721  inline T value() const
9722  {
9723  if (rbvec_node_ptr_)
9724  {
9725  T& result = rbvec_node_ptr_->ref();
9726 
9727  result = binary_node<T>::branch_[1].first->value();
9728 
9729  return result;
9730  }
9731  else
9732  return std::numeric_limits<T>::quiet_NaN();
9733  }
9734 
9735  private:
9736 
9738  };
9739 
9740  template <typename T>
9741  class assignment_vec_node : public binary_node <T>,
9742  public vector_interface<T>
9743  {
9744  public:
9745 
9749 
9751  expression_ptr branch0,
9752  expression_ptr branch1)
9753  : binary_node<T>(opr, branch0, branch1),
9754  vec_node_ptr_(0)
9755  {
9757  {
9758  vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9759  vds() = vec_node_ptr_->vds();
9760  }
9761  }
9762 
9763  inline T value() const
9764  {
9765  if (vec_node_ptr_)
9766  {
9767  const T v = binary_node<T>::branch_[1].first->value();
9768 
9769  T* vec = vds().data();
9770 
9771  loop_unroll::details lud(size());
9772  const T* upper_bound = vec + lud.upper_bound;
9773 
9774  while (vec < upper_bound)
9775  {
9776  #define exprtk_loop(N) \
9777  vec[N] = v; \
9778 
9779  exprtk_loop( 0) exprtk_loop( 1)
9780  exprtk_loop( 2) exprtk_loop( 3)
9781  #ifndef exprtk_disable_superscalar_unroll
9782  exprtk_loop( 4) exprtk_loop( 5)
9783  exprtk_loop( 6) exprtk_loop( 7)
9784  exprtk_loop( 8) exprtk_loop( 9)
9785  exprtk_loop(10) exprtk_loop(11)
9786  exprtk_loop(12) exprtk_loop(13)
9787  exprtk_loop(14) exprtk_loop(15)
9788  #endif
9789 
9790  vec += lud.batch_size;
9791  }
9792 
9794  switch (lud.remainder)
9795  {
9796  #define case_stmt(N) \
9797  case N : *vec++ = v; \
9798 
9799  #ifndef exprtk_disable_superscalar_unroll
9800  case_stmt(15) case_stmt(14)
9801  case_stmt(13) case_stmt(12)
9802  case_stmt(11) case_stmt(10)
9803  case_stmt( 9) case_stmt( 8)
9804  case_stmt( 7) case_stmt( 6)
9805  case_stmt( 5) case_stmt( 4)
9806  #endif
9807  case_stmt( 3) case_stmt( 2)
9808  case_stmt( 1)
9809  }
9811 
9812  #undef exprtk_loop
9813  #undef case_stmt
9814 
9815  return vec_node_ptr_->value();
9816  }
9817  else
9818  return std::numeric_limits<T>::quiet_NaN();
9819  }
9820 
9822  {
9823  return vec_node_ptr_;
9824  }
9825 
9827  {
9828  return vec_node_ptr_;
9829  }
9830 
9831  inline typename expression_node<T>::node_type type() const
9832  {
9834  }
9835 
9836  std::size_t size() const
9837  {
9838  return vds().size();
9839  }
9840 
9842  {
9843  return vds_;
9844  }
9845 
9846  const vds_t& vds() const
9847  {
9848  return vds_;
9849  }
9850 
9851  private:
9852 
9855  };
9856 
9857  template <typename T>
9859  public vector_interface<T>
9860  {
9861  public:
9862 
9866 
9868  expression_ptr branch0,
9869  expression_ptr branch1)
9870  : binary_node<T>(opr, branch0, branch1),
9871  vec0_node_ptr_(0),
9872  vec1_node_ptr_(0),
9873  initialised_(false),
9874  src_is_ivec_(false)
9875  {
9877  {
9878  vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
9879  vds() = vec0_node_ptr_->vds();
9880  }
9881 
9883  {
9884  vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
9886  }
9887  else if (is_ivector_node(binary_node<T>::branch_[1].first))
9888  {
9889  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
9890 
9891  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
9892  {
9893  vec1_node_ptr_ = vi->vec();
9894 
9895  if (!vi->side_effect())
9896  {
9897  vi->vds() = vds();
9898  src_is_ivec_ = true;
9899  }
9900  else
9901  vds_t::match_sizes(vds(),vi->vds());
9902  }
9903  }
9904 
9906  }
9907 
9908  inline T value() const
9909  {
9910  if (initialised_)
9911  {
9912  binary_node<T>::branch_[1].first->value();
9913 
9914  if (src_is_ivec_)
9915  return vec0_node_ptr_->value();
9916 
9917  T* vec0 = vec0_node_ptr_->vds().data();
9918  T* vec1 = vec1_node_ptr_->vds().data();
9919 
9920  loop_unroll::details lud(size());
9921  const T* upper_bound = vec0 + lud.upper_bound;
9922 
9923  while (vec0 < upper_bound)
9924  {
9925  #define exprtk_loop(N) \
9926  vec0[N] = vec1[N]; \
9927 
9928  exprtk_loop( 0) exprtk_loop( 1)
9929  exprtk_loop( 2) exprtk_loop( 3)
9930  #ifndef exprtk_disable_superscalar_unroll
9931  exprtk_loop( 4) exprtk_loop( 5)
9932  exprtk_loop( 6) exprtk_loop( 7)
9933  exprtk_loop( 8) exprtk_loop( 9)
9934  exprtk_loop(10) exprtk_loop(11)
9935  exprtk_loop(12) exprtk_loop(13)
9936  exprtk_loop(14) exprtk_loop(15)
9937  #endif
9938 
9939  vec0 += lud.batch_size;
9940  vec1 += lud.batch_size;
9941  }
9942 
9944  switch (lud.remainder)
9945  {
9946  #define case_stmt(N) \
9947  case N : *vec0++ = *vec1++; \
9948 
9949  #ifndef exprtk_disable_superscalar_unroll
9950  case_stmt(15) case_stmt(14)
9951  case_stmt(13) case_stmt(12)
9952  case_stmt(11) case_stmt(10)
9953  case_stmt( 9) case_stmt( 8)
9954  case_stmt( 7) case_stmt( 6)
9955  case_stmt( 5) case_stmt( 4)
9956  #endif
9957  case_stmt( 3) case_stmt( 2)
9958  case_stmt( 1)
9959  }
9961 
9962  #undef exprtk_loop
9963  #undef case_stmt
9964 
9965  return vec0_node_ptr_->value();
9966  }
9967  else
9968  return std::numeric_limits<T>::quiet_NaN();
9969  }
9970 
9972  {
9973  return vec0_node_ptr_;
9974  }
9975 
9977  {
9978  return vec0_node_ptr_;
9979  }
9980 
9981  inline typename expression_node<T>::node_type type() const
9982  {
9984  }
9985 
9986  std::size_t size() const
9987  {
9988  return vds().size();
9989  }
9990 
9992  {
9993  return vds_;
9994  }
9995 
9996  const vds_t& vds() const
9997  {
9998  return vds_;
9999  }
10000 
10001  private:
10002 
10008  };
10009 
10010  template <typename T, typename Operation>
10012  {
10013  public:
10014 
10016 
10018  expression_ptr branch0,
10019  expression_ptr branch1)
10020  : binary_node<T>(opr, branch0, branch1),
10021  var_node_ptr_(0)
10022  {
10024  {
10025  var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
10026  }
10027  }
10028 
10029  inline T value() const
10030  {
10031  if (var_node_ptr_)
10032  {
10033  T& v = var_node_ptr_->ref();
10035 
10036  return v;
10037  }
10038  else
10039  return std::numeric_limits<T>::quiet_NaN();
10040  }
10041 
10042  private:
10043 
10045  };
10046 
10047  template <typename T, typename Operation>
10049  {
10050  public:
10051 
10053 
10055  expression_ptr branch0,
10056  expression_ptr branch1)
10057  : binary_node<T>(opr, branch0, branch1),
10058  vec_node_ptr_(0)
10059  {
10061  {
10062  vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first);
10063  }
10064  }
10065 
10066  inline T value() const
10067  {
10068  if (vec_node_ptr_)
10069  {
10070  T& v = vec_node_ptr_->ref();
10072 
10073  return v;
10074  }
10075  else
10076  return std::numeric_limits<T>::quiet_NaN();
10077  }
10078 
10079  private:
10080 
10082  };
10083 
10084  template <typename T, typename Operation>
10086  {
10087  public:
10088 
10090 
10092  expression_ptr branch0,
10093  expression_ptr branch1)
10094  : binary_node<T>(opr, branch0, branch1),
10095  rbvec_node_ptr_(0)
10096  {
10098  {
10100  }
10101  }
10102 
10103  inline T value() const
10104  {
10105  if (rbvec_node_ptr_)
10106  {
10107  T& v = rbvec_node_ptr_->ref();
10109 
10110  return v;
10111  }
10112  else
10113  return std::numeric_limits<T>::quiet_NaN();
10114  }
10115 
10116  private:
10117 
10119  };
10120 
10121  template <typename T, typename Operation>
10123  {
10124  public:
10125 
10127 
10129  expression_ptr branch0,
10130  expression_ptr branch1)
10131  : binary_node<T>(opr, branch0, branch1),
10132  rbvec_node_ptr_(0)
10133  {
10135  {
10137  }
10138  }
10139 
10140  inline T value() const
10141  {
10142  if (rbvec_node_ptr_)
10143  {
10144  T& v = rbvec_node_ptr_->ref();
10146 
10147  return v;
10148  }
10149  else
10150  return std::numeric_limits<T>::quiet_NaN();
10151  }
10152 
10153  private:
10154 
10156  };
10157 
10158  template <typename T, typename Operation>
10160  public vector_interface<T>
10161  {
10162  public:
10163 
10167 
10169  expression_ptr branch0,
10170  expression_ptr branch1)
10171  : binary_node<T>(opr, branch0, branch1),
10172  vec_node_ptr_(0)
10173  {
10175  {
10176  vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10177  vds() = vec_node_ptr_->vds();
10178  }
10179  }
10180 
10181  inline T value() const
10182  {
10183  if (vec_node_ptr_)
10184  {
10185  const T v = binary_node<T>::branch_[1].first->value();
10186 
10187  T* vec = vds().data();
10188 
10189  loop_unroll::details lud(size());
10190  const T* upper_bound = vec + lud.upper_bound;
10191 
10192  while (vec < upper_bound)
10193  {
10194  #define exprtk_loop(N) \
10195  Operation::assign(vec[N],v); \
10196 
10197  exprtk_loop( 0) exprtk_loop( 1)
10198  exprtk_loop( 2) exprtk_loop( 3)
10199  #ifndef exprtk_disable_superscalar_unroll
10200  exprtk_loop( 4) exprtk_loop( 5)
10201  exprtk_loop( 6) exprtk_loop( 7)
10202  exprtk_loop( 8) exprtk_loop( 9)
10203  exprtk_loop(10) exprtk_loop(11)
10204  exprtk_loop(12) exprtk_loop(13)
10205  exprtk_loop(14) exprtk_loop(15)
10206  #endif
10207 
10208  vec += lud.batch_size;
10209  }
10210 
10212  switch (lud.remainder)
10213  {
10214  #define case_stmt(N) \
10215  case N : Operation::assign(*vec++,v); \
10216 
10217  #ifndef exprtk_disable_superscalar_unroll
10218  case_stmt(15) case_stmt(14)
10219  case_stmt(13) case_stmt(12)
10220  case_stmt(11) case_stmt(10)
10221  case_stmt( 9) case_stmt( 8)
10222  case_stmt( 7) case_stmt( 6)
10223  case_stmt( 5) case_stmt( 4)
10224  #endif
10225  case_stmt( 3) case_stmt( 2)
10226  case_stmt( 1)
10227  }
10229 
10230 
10231  #undef exprtk_loop
10232  #undef case_stmt
10233 
10234  return vec_node_ptr_->value();
10235  }
10236  else
10237  return std::numeric_limits<T>::quiet_NaN();
10238  }
10239 
10241  {
10242  return vec_node_ptr_;
10243  }
10244 
10246  {
10247  return vec_node_ptr_;
10248  }
10249 
10250  inline typename expression_node<T>::node_type type() const
10251  {
10253  }
10254 
10255  std::size_t size() const
10256  {
10257  return vds().size();
10258  }
10259 
10261  {
10262  return vds_;
10263  }
10264 
10265  const vds_t& vds() const
10266  {
10267  return vds_;
10268  }
10269 
10270  bool side_effect() const
10271  {
10272  return true;
10273  }
10274 
10275  private:
10276 
10279  };
10280 
10281  template <typename T, typename Operation>
10283  public vector_interface<T>
10284  {
10285  public:
10286 
10290 
10292  expression_ptr branch0,
10293  expression_ptr branch1)
10294  : binary_node<T>(opr, branch0, branch1),
10295  vec0_node_ptr_(0),
10296  vec1_node_ptr_(0),
10297  initialised_(false)
10298  {
10300  {
10301  vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
10302  vds() = vec0_node_ptr_->vds();
10303  }
10304 
10306  {
10307  vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
10308  vec1_node_ptr_->vds() = vds();
10309  }
10310  else if (is_ivector_node(binary_node<T>::branch_[1].first))
10311  {
10312  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10313 
10314  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10315  {
10316  vec1_node_ptr_ = vi->vec();
10317  vec1_node_ptr_->vds() = vds();
10318  }
10319  else
10321  }
10322 
10324  }
10325 
10326  inline T value() const
10327  {
10328  if (initialised_)
10329  {
10330  binary_node<T>::branch_[0].first->value();
10331  binary_node<T>::branch_[1].first->value();
10332 
10333  T* vec0 = vec0_node_ptr_->vds().data();
10334  const T* vec1 = vec1_node_ptr_->vds().data();
10335 
10336  loop_unroll::details lud(size());
10337  const T* upper_bound = vec0 + lud.upper_bound;
10338 
10339  while (vec0 < upper_bound)
10340  {
10341  #define exprtk_loop(N) \
10342  vec0[N] = Operation::process(vec0[N], vec1[N]); \
10343 
10344  exprtk_loop( 0) exprtk_loop( 1)
10345  exprtk_loop( 2) exprtk_loop( 3)
10346  #ifndef exprtk_disable_superscalar_unroll
10347  exprtk_loop( 4) exprtk_loop( 5)
10348  exprtk_loop( 6) exprtk_loop( 7)
10349  exprtk_loop( 8) exprtk_loop( 9)
10350  exprtk_loop(10) exprtk_loop(11)
10351  exprtk_loop(12) exprtk_loop(13)
10352  exprtk_loop(14) exprtk_loop(15)
10353  #endif
10354 
10355  vec0 += lud.batch_size;
10356  vec1 += lud.batch_size;
10357  }
10358 
10359  int i = 0;
10360 
10362  switch (lud.remainder)
10363  {
10364  #define case_stmt(N) \
10365  case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10366 
10367  #ifndef exprtk_disable_superscalar_unroll
10368  case_stmt(15) case_stmt(14)
10369  case_stmt(13) case_stmt(12)
10370  case_stmt(11) case_stmt(10)
10371  case_stmt( 9) case_stmt( 8)
10372  case_stmt( 7) case_stmt( 6)
10373  case_stmt( 5) case_stmt( 4)
10374  #endif
10375  case_stmt( 3) case_stmt( 2)
10376  case_stmt( 1)
10377  }
10379 
10380  #undef exprtk_loop
10381  #undef case_stmt
10382 
10383  return vec0_node_ptr_->value();
10384  }
10385  else
10386  return std::numeric_limits<T>::quiet_NaN();
10387  }
10388 
10390  {
10391  return vec0_node_ptr_;
10392  }
10393 
10395  {
10396  return vec0_node_ptr_;
10397  }
10398 
10399  inline typename expression_node<T>::node_type type() const
10400  {
10402  }
10403 
10404  std::size_t size() const
10405  {
10406  return vds().size();
10407  }
10408 
10410  {
10411  return vds_;
10412  }
10413 
10414  const vds_t& vds() const
10415  {
10416  return vds_;
10417  }
10418 
10419  bool side_effect() const
10420  {
10421  return true;
10422  }
10423 
10424  private:
10425 
10430  };
10431 
10432  template <typename T, typename Operation>
10434  public vector_interface<T>
10435  {
10436  public:
10437 
10442 
10444  expression_ptr branch0,
10445  expression_ptr branch1)
10446  : binary_node<T>(opr, branch0, branch1),
10447  vec0_node_ptr_(0),
10448  vec1_node_ptr_(0),
10449  temp_ (0),
10450  temp_vec_node_(0),
10451  initialised_(false)
10452  {
10453  bool v0_is_ivec = false;
10454  bool v1_is_ivec = false;
10455 
10457  {
10458  vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10459  }
10460  else if (is_ivector_node(binary_node<T>::branch_[0].first))
10461  {
10462  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10463 
10464  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10465  {
10466  vec0_node_ptr_ = vi->vec();
10467  v0_is_ivec = true;
10468  }
10469  }
10470 
10472  {
10473  vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10474  }
10475  else if (is_ivector_node(binary_node<T>::branch_[1].first))
10476  {
10477  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10478 
10479  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10480  {
10481  vec1_node_ptr_ = vi->vec();
10482  v1_is_ivec = true;
10483  }
10484  }
10485 
10487  {
10490 
10491  if (v0_is_ivec && (vec0.size() <= vec1.size()))
10492  vds_ = vds_t(vec0_node_ptr_->vds());
10493  else if (v1_is_ivec && (vec1.size() <= vec0.size()))
10494  vds_ = vds_t(vec1_node_ptr_->vds());
10495  else
10496  vds_ = vds_t(std::min(vec0.size(),vec1.size()));
10497 
10498  temp_ = new vector_holder<T>(vds().data(),vds().size());
10500 
10501  initialised_ = true;
10502  }
10503  }
10504 
10506  {
10507  delete temp_;
10508  delete temp_vec_node_;
10509  }
10510 
10511  inline T value() const
10512  {
10513  if (initialised_)
10514  {
10515  binary_node<T>::branch_[0].first->value();
10516  binary_node<T>::branch_[1].first->value();
10517 
10518  const T* vec0 = vec0_node_ptr_->vds().data();
10519  const T* vec1 = vec1_node_ptr_->vds().data();
10520  T* vec2 = vds().data();
10521 
10522  loop_unroll::details lud(size());
10523  const T* upper_bound = vec2 + lud.upper_bound;
10524 
10525  while (vec2 < upper_bound)
10526  {
10527  #define exprtk_loop(N) \
10528  vec2[N] = Operation::process(vec0[N], vec1[N]); \
10529 
10530  exprtk_loop( 0) exprtk_loop( 1)
10531  exprtk_loop( 2) exprtk_loop( 3)
10532  #ifndef exprtk_disable_superscalar_unroll
10533  exprtk_loop( 4) exprtk_loop( 5)
10534  exprtk_loop( 6) exprtk_loop( 7)
10535  exprtk_loop( 8) exprtk_loop( 9)
10536  exprtk_loop(10) exprtk_loop(11)
10537  exprtk_loop(12) exprtk_loop(13)
10538  exprtk_loop(14) exprtk_loop(15)
10539  #endif
10540 
10541  vec0 += lud.batch_size;
10542  vec1 += lud.batch_size;
10543  vec2 += lud.batch_size;
10544  }
10545 
10546  int i = 0;
10547 
10549  switch (lud.remainder)
10550  {
10551  #define case_stmt(N) \
10552  case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \
10553 
10554  #ifndef exprtk_disable_superscalar_unroll
10555  case_stmt(15) case_stmt(14)
10556  case_stmt(13) case_stmt(12)
10557  case_stmt(11) case_stmt(10)
10558  case_stmt( 9) case_stmt( 8)
10559  case_stmt( 7) case_stmt( 6)
10560  case_stmt( 5) case_stmt( 4)
10561  #endif
10562  case_stmt( 3) case_stmt( 2)
10563  case_stmt( 1)
10564  }
10566 
10567  #undef exprtk_loop
10568  #undef case_stmt
10569 
10570  return (vds().data())[0];
10571  }
10572  else
10573  return std::numeric_limits<T>::quiet_NaN();
10574  }
10575 
10577  {
10578  return temp_vec_node_;
10579  }
10580 
10582  {
10583  return temp_vec_node_;
10584  }
10585 
10586  inline typename expression_node<T>::node_type type() const
10587  {
10589  }
10590 
10591  std::size_t size() const
10592  {
10593  return vds_.size();
10594  }
10595 
10597  {
10598  return vds_;
10599  }
10600 
10601  const vds_t& vds() const
10602  {
10603  return vds_;
10604  }
10605 
10606  private:
10607 
10614  };
10615 
10616  template <typename T, typename Operation>
10618  public vector_interface<T>
10619  {
10620  public:
10621 
10626 
10628  expression_ptr branch0,
10629  expression_ptr branch1)
10630  : binary_node<T>(opr, branch0, branch1),
10631  vec0_node_ptr_(0),
10632  temp_ (0),
10633  temp_vec_node_(0)
10634  {
10635  bool v0_is_ivec = false;
10636 
10638  {
10639  vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
10640  }
10641  else if (is_ivector_node(binary_node<T>::branch_[0].first))
10642  {
10643  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10644 
10645  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
10646  {
10647  vec0_node_ptr_ = vi->vec();
10648  v0_is_ivec = true;
10649  }
10650  }
10651 
10652  if (vec0_node_ptr_)
10653  {
10654  if (v0_is_ivec)
10655  vds() = vec0_node_ptr_->vds();
10656  else
10657  vds() = vds_t(vec0_node_ptr_->size());
10658 
10659  temp_ = new vector_holder<T>(vds());
10661  }
10662  }
10663 
10665  {
10666  delete temp_;
10667  delete temp_vec_node_;
10668  }
10669 
10670  inline T value() const
10671  {
10672  if (vec0_node_ptr_)
10673  {
10674  binary_node<T>::branch_[0].first->value();
10675  const T v = binary_node<T>::branch_[1].first->value();
10676 
10677  const T* vec0 = vec0_node_ptr_->vds().data();
10678  T* vec1 = vds().data();
10679 
10680  loop_unroll::details lud(size());
10681  const T* upper_bound = vec0 + lud.upper_bound;
10682 
10683  while (vec0 < upper_bound)
10684  {
10685  #define exprtk_loop(N) \
10686  vec1[N] = Operation::process(vec0[N], v); \
10687 
10688  exprtk_loop( 0) exprtk_loop( 1)
10689  exprtk_loop( 2) exprtk_loop( 3)
10690  #ifndef exprtk_disable_superscalar_unroll
10691  exprtk_loop( 4) exprtk_loop( 5)
10692  exprtk_loop( 6) exprtk_loop( 7)
10693  exprtk_loop( 8) exprtk_loop( 9)
10694  exprtk_loop(10) exprtk_loop(11)
10695  exprtk_loop(12) exprtk_loop(13)
10696  exprtk_loop(14) exprtk_loop(15)
10697  #endif
10698 
10699  vec0 += lud.batch_size;
10700  vec1 += lud.batch_size;
10701  }
10702 
10703  int i = 0;
10704 
10706  switch (lud.remainder)
10707  {
10708  #define case_stmt(N) \
10709  case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \
10710 
10711  #ifndef exprtk_disable_superscalar_unroll
10712  case_stmt(15) case_stmt(14)
10713  case_stmt(13) case_stmt(12)
10714  case_stmt(11) case_stmt(10)
10715  case_stmt( 9) case_stmt( 8)
10716  case_stmt( 7) case_stmt( 6)
10717  case_stmt( 5) case_stmt( 4)
10718  #endif
10719  case_stmt( 3) case_stmt( 2)
10720  case_stmt( 1)
10721  }
10723 
10724  #undef exprtk_loop
10725  #undef case_stmt
10726 
10727  return (vds().data())[0];
10728  }
10729  else
10730  return std::numeric_limits<T>::quiet_NaN();
10731  }
10732 
10734  {
10735  return temp_vec_node_;
10736  }
10737 
10739  {
10740  return temp_vec_node_;
10741  }
10742 
10743  inline typename expression_node<T>::node_type type() const
10744  {
10746  }
10747 
10748  std::size_t size() const
10749  {
10750  return vds().size();
10751  }
10752 
10754  {
10755  return vds_;
10756  }
10757 
10758  const vds_t& vds() const
10759  {
10760  return vds_;
10761  }
10762 
10763  private:
10764 
10769  };
10770 
10771  template <typename T, typename Operation>
10773  public vector_interface<T>
10774  {
10775  public:
10776 
10781 
10783  expression_ptr branch0,
10784  expression_ptr branch1)
10785  : binary_node<T>(opr, branch0, branch1),
10786  vec1_node_ptr_(0),
10787  temp_ (0),
10788  temp_vec_node_(0)
10789  {
10790  bool v1_is_ivec = false;
10791 
10793  {
10794  vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
10795  }
10796  else if (is_ivector_node(binary_node<T>::branch_[1].first))
10797  {
10798  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10799 
10800  if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
10801  {
10802  vec1_node_ptr_ = vi->vec();
10803  v1_is_ivec = true;
10804  }
10805  }
10806 
10807  if (vec1_node_ptr_)
10808  {
10809  if (v1_is_ivec)
10810  vds() = vec1_node_ptr_->vds();
10811  else
10812  vds() = vds_t(vec1_node_ptr_->size());
10813 
10814  temp_ = new vector_holder<T>(vds());
10816  }
10817  }
10818 
10820  {
10821  delete temp_;
10822  delete temp_vec_node_;
10823  }
10824 
10825  inline T value() const
10826  {
10827  if (vec1_node_ptr_)
10828  {
10829  const T v = binary_node<T>::branch_[0].first->value();
10830  binary_node<T>::branch_[1].first->value();
10831 
10832  T* vec0 = vds().data();
10833  const T* vec1 = vec1_node_ptr_->vds().data();
10834 
10835  loop_unroll::details lud(size());
10836  const T* upper_bound = vec0 + lud.upper_bound;
10837 
10838  while (vec0 < upper_bound)
10839  {
10840  #define exprtk_loop(N) \
10841  vec0[N] = Operation::process(v, vec1[N]); \
10842 
10843  exprtk_loop( 0) exprtk_loop( 1)
10844  exprtk_loop( 2) exprtk_loop( 3)
10845  #ifndef exprtk_disable_superscalar_unroll
10846  exprtk_loop( 4) exprtk_loop( 5)
10847  exprtk_loop( 6) exprtk_loop( 7)
10848  exprtk_loop( 8) exprtk_loop( 9)
10849  exprtk_loop(10) exprtk_loop(11)
10850  exprtk_loop(12) exprtk_loop(13)
10851  exprtk_loop(14) exprtk_loop(15)
10852  #endif
10853 
10854  vec0 += lud.batch_size;
10855  vec1 += lud.batch_size;
10856  }
10857 
10858  int i = 0;
10859 
10861  switch (lud.remainder)
10862  {
10863  #define case_stmt(N) \
10864  case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \
10865 
10866  #ifndef exprtk_disable_superscalar_unroll
10867  case_stmt(15) case_stmt(14)
10868  case_stmt(13) case_stmt(12)
10869  case_stmt(11) case_stmt(10)
10870  case_stmt( 9) case_stmt( 8)
10871  case_stmt( 7) case_stmt( 6)
10872  case_stmt( 5) case_stmt( 4)
10873  #endif
10874  case_stmt( 3) case_stmt( 2)
10875  case_stmt( 1)
10876  }
10878 
10879  #undef exprtk_loop
10880  #undef case_stmt
10881 
10882  return (vds().data())[0];
10883  }
10884  else
10885  return std::numeric_limits<T>::quiet_NaN();
10886  }
10887 
10889  {
10890  return temp_vec_node_;
10891  }
10892 
10894  {
10895  return temp_vec_node_;
10896  }
10897 
10898  inline typename expression_node<T>::node_type type() const
10899  {
10901  }
10902 
10903  std::size_t size() const
10904  {
10905  return vds().size();
10906  }
10907 
10909  {
10910  return vds_;
10911  }
10912 
10913  const vds_t& vds() const
10914  {
10915  return vds_;
10916  }
10917 
10918  private:
10919 
10924  };
10925 
10926  template <typename T, typename Operation>
10927  class unary_vector_node : public unary_node <T>,
10928  public vector_interface<T>
10929  {
10930  public:
10931 
10936 
10938  : unary_node<T>(opr, branch0),
10939  vec0_node_ptr_(0),
10940  temp_ (0),
10941  temp_vec_node_(0)
10942  {
10943  bool vec0_is_ivec = false;
10944 
10946  {
10948  }
10950  {
10951  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
10952 
10953  if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
10954  {
10955  vec0_node_ptr_ = vi->vec();
10956  vec0_is_ivec = true;
10957  }
10958  }
10959 
10960  if (vec0_node_ptr_)
10961  {
10962  if (vec0_is_ivec)
10963  vds_ = vec0_node_ptr_->vds();
10964  else
10965  vds_ = vds_t(vec0_node_ptr_->size());
10966 
10967  temp_ = new vector_holder<T>(vds());
10969  }
10970  }
10971 
10973  {
10974  delete temp_;
10975  delete temp_vec_node_;
10976  }
10977 
10978  inline T value() const
10979  {
10981 
10982  if (vec0_node_ptr_)
10983  {
10984  const T* vec0 = vec0_node_ptr_->vds().data();
10985  T* vec1 = vds().data();
10986 
10987  loop_unroll::details lud(size());
10988  const T* upper_bound = vec0 + lud.upper_bound;
10989 
10990  while (vec0 < upper_bound)
10991  {
10992  #define exprtk_loop(N) \
10993  vec1[N] = Operation::process(vec0[N]); \
10994 
10995  exprtk_loop( 0) exprtk_loop( 1)
10996  exprtk_loop( 2) exprtk_loop( 3)
10997  #ifndef exprtk_disable_superscalar_unroll
10998  exprtk_loop( 4) exprtk_loop( 5)
10999  exprtk_loop( 6) exprtk_loop( 7)
11000  exprtk_loop( 8) exprtk_loop( 9)
11001  exprtk_loop(10) exprtk_loop(11)
11002  exprtk_loop(12) exprtk_loop(13)
11003  exprtk_loop(14) exprtk_loop(15)
11004  #endif
11005 
11006  vec0 += lud.batch_size;
11007  vec1 += lud.batch_size;
11008  }
11009 
11010  int i = 0;
11011 
11013  switch (lud.remainder)
11014  {
11015  #define case_stmt(N) \
11016  case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \
11017 
11018  #ifndef exprtk_disable_superscalar_unroll
11019  case_stmt(15) case_stmt(14)
11020  case_stmt(13) case_stmt(12)
11021  case_stmt(11) case_stmt(10)
11022  case_stmt( 9) case_stmt( 8)
11023  case_stmt( 7) case_stmt( 6)
11024  case_stmt( 5) case_stmt( 4)
11025  #endif
11026  case_stmt( 3) case_stmt( 2)
11027  case_stmt( 1)
11028  }
11030 
11031  #undef exprtk_loop
11032  #undef case_stmt
11033 
11034  return (vds().data())[0];
11035  }
11036  else
11037  return std::numeric_limits<T>::quiet_NaN();
11038  }
11039 
11041  {
11042  return temp_vec_node_;
11043  }
11044 
11046  {
11047  return temp_vec_node_;
11048  }
11049 
11050  inline typename expression_node<T>::node_type type() const
11051  {
11053  }
11054 
11055  std::size_t size() const
11056  {
11057  return vds().size();
11058  }
11059 
11061  {
11062  return vds_;
11063  }
11064 
11065  const vds_t& vds() const
11066  {
11067  return vds_;
11068  }
11069 
11070  private:
11071 
11076  };
11077 
11078  template <typename T>
11079  class scand_node : public binary_node<T>
11080  {
11081  public:
11082 
11084 
11086  expression_ptr branch0,
11087  expression_ptr branch1)
11088  : binary_node<T>(opr, branch0, branch1)
11089  {}
11090 
11091  inline T value() const
11092  {
11093  return (
11094  std::not_equal_to<T>()
11095  (T(0),binary_node<T>::branch_[0].first->value()) &&
11096  std::not_equal_to<T>()
11097  (T(0),binary_node<T>::branch_[1].first->value())
11098  ) ? T(1) : T(0);
11099  }
11100  };
11101 
11102  template <typename T>
11103  class scor_node : public binary_node<T>
11104  {
11105  public:
11106 
11108 
11110  expression_ptr branch0,
11111  expression_ptr branch1)
11112  : binary_node<T>(opr, branch0, branch1)
11113  {}
11114 
11115  inline T value() const
11116  {
11117  return (
11118  std::not_equal_to<T>()
11119  (T(0),binary_node<T>::branch_[0].first->value()) ||
11120  std::not_equal_to<T>()
11121  (T(0),binary_node<T>::branch_[1].first->value())
11122  ) ? T(1) : T(0);
11123  }
11124  };
11125 
11126  template <typename T, typename IFunction, std::size_t N>
11128  {
11129  public:
11130 
11131  // Function of N paramters.
11133  typedef std::pair<expression_ptr,bool> branch_t;
11134  typedef IFunction ifunction;
11135 
11136  explicit function_N_node(ifunction* func)
11137  : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
11138  parameter_count_(func->param_count)
11139  {}
11140 
11142  {
11143  cleanup_branches::execute<T,N>(branch_);
11144  }
11145 
11146  template <std::size_t NumBranches>
11147  bool init_branches(expression_ptr (&b)[NumBranches])
11148  {
11149  // Needed for incompetent and broken msvc compiler versions
11150  #ifdef _MSC_VER
11151  #pragma warning(push)
11152  #pragma warning(disable: 4127)
11153  #endif
11154  if (N != NumBranches)
11155  return false;
11156  else
11157  {
11158  for (std::size_t i = 0; i < NumBranches; ++i)
11159  {
11160  if (b[i])
11161  branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
11162  else
11163  return false;
11164  }
11165  return true;
11166  }
11167  #ifdef _MSC_VER
11168  #pragma warning(pop)
11169  #endif
11170  }
11171 
11172  inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
11173  {
11174  return this < (&fn);
11175  }
11176 
11177  inline T value() const
11178  {
11179  // Needed for incompetent and broken msvc compiler versions
11180  #ifdef _MSC_VER
11181  #pragma warning(push)
11182  #pragma warning(disable: 4127)
11183  #endif
11184  if ((0 == function_) || (0 == N))
11185  return std::numeric_limits<T>::quiet_NaN();
11186  else
11187  {
11188  T v[N];
11190  return invoke<T,N>::execute(*function_,v);
11191  }
11192  #ifdef _MSC_VER
11193  #pragma warning(pop)
11194  #endif
11195  }
11196 
11197  template <typename T_, std::size_t BranchCount>
11199  {
11200  static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
11201  {
11202  for (std::size_t i = 0; i < BranchCount; ++i)
11203  {
11204  v[i] = b[i].first->value();
11205  }
11206  }
11207  };
11208 
11209  template <typename T_>
11210  struct evaluate_branches <T_,5>
11211  {
11212  static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
11213  {
11214  v[0] = b[0].first->value();
11215  v[1] = b[1].first->value();
11216  v[2] = b[2].first->value();
11217  v[3] = b[3].first->value();
11218  v[4] = b[4].first->value();
11219  }
11220  };
11221 
11222  template <typename T_>
11223  struct evaluate_branches <T_,4>
11224  {
11225  static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
11226  {
11227  v[0] = b[0].first->value();
11228  v[1] = b[1].first->value();
11229  v[2] = b[2].first->value();
11230  v[3] = b[3].first->value();
11231  }
11232  };
11233 
11234  template <typename T_>
11235  struct evaluate_branches <T_,3>
11236  {
11237  static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
11238  {
11239  v[0] = b[0].first->value();
11240  v[1] = b[1].first->value();
11241  v[2] = b[2].first->value();
11242  }
11243  };
11244 
11245  template <typename T_>
11246  struct evaluate_branches <T_,2>
11247  {
11248  static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
11249  {
11250  v[0] = b[0].first->value();
11251  v[1] = b[1].first->value();
11252  }
11253  };
11254 
11255  template <typename T_>
11256  struct evaluate_branches <T_,1>
11257  {
11258  static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
11259  {
11260  v[0] = b[0].first->value();
11261  }
11262  };
11263 
11264  template <typename T_, std::size_t ParamCount>
11265  struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
11266 
11267  template <typename T_>
11268  struct invoke<T_,20>
11269  {
11270  static inline T_ execute(ifunction& f, T_ (&v)[20])
11271  { 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]); }
11272  };
11273 
11274  template <typename T_>
11275  struct invoke<T_,19>
11276  {
11277  static inline T_ execute(ifunction& f, T_ (&v)[19])
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]); }
11279  };
11280 
11281  template <typename T_>
11282  struct invoke<T_,18>
11283  {
11284  static inline T_ execute(ifunction& f, T_ (&v)[18])
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]); }
11286  };
11287 
11288  template <typename T_>
11289  struct invoke<T_,17>
11290  {
11291  static inline T_ execute(ifunction& f, T_ (&v)[17])
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]); }
11293  };
11294 
11295  template <typename T_>
11296  struct invoke<T_,16>
11297  {
11298  static inline T_ execute(ifunction& f, T_ (&v)[16])
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]); }
11300  };
11301 
11302  template <typename T_>
11303  struct invoke<T_,15>
11304  {
11305  static inline T_ execute(ifunction& f, T_ (&v)[15])
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]); }
11307  };
11308 
11309  template <typename T_>
11310  struct invoke<T_,14>
11311  {
11312  static inline T_ execute(ifunction& f, T_ (&v)[14])
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]); }
11314  };
11315 
11316  template <typename T_>
11317  struct invoke<T_,13>
11318  {
11319  static inline T_ execute(ifunction& f, T_ (&v)[13])
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]); }
11321  };
11322 
11323  template <typename T_>
11324  struct invoke<T_,12>
11325  {
11326  static inline T_ execute(ifunction& f, T_ (&v)[12])
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]); }
11328  };
11329 
11330  template <typename T_>
11331  struct invoke<T_,11>
11332  {
11333  static inline T_ execute(ifunction& f, T_ (&v)[11])
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]); }
11335  };
11336 
11337  template <typename T_>
11338  struct invoke<T_,10>
11339  {
11340  static inline T_ execute(ifunction& f, T_ (&v)[10])
11341  { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); }
11342  };
11343 
11344  template <typename T_>
11345  struct invoke<T_,9>
11346  {
11347  static inline T_ execute(ifunction& f, T_ (&v)[9])
11348  { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); }
11349  };
11350 
11351  template <typename T_>
11352  struct invoke<T_,8>
11353  {
11354  static inline T_ execute(ifunction& f, T_ (&v)[8])
11355  { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); }
11356  };
11357 
11358  template <typename T_>
11359  struct invoke<T_,7>
11360  {
11361  static inline T_ execute(ifunction& f, T_ (&v)[7])
11362  { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); }
11363  };
11364 
11365  template <typename T_>
11366  struct invoke<T_,6>
11367  {
11368  static inline T_ execute(ifunction& f, T_ (&v)[6])
11369  { return f(v[0],v[1],v[2],v[3],v[4],v[5]); }
11370  };
11371 
11372  template <typename T_>
11373  struct invoke<T_,5>
11374  {
11375  static inline T_ execute(ifunction& f, T_ (&v)[5])
11376  { return f(v[0],v[1],v[2],v[3],v[4]); }
11377  };
11378 
11379  template <typename T_>
11380  struct invoke<T_,4>
11381  {
11382  static inline T_ execute(ifunction& f, T_ (&v)[4])
11383  { return f(v[0],v[1],v[2],v[3]); }
11384  };
11385 
11386  template <typename T_>
11387  struct invoke<T_,3>
11388  {
11389  static inline T_ execute(ifunction& f, T_ (&v)[3])
11390  { return f(v[0],v[1],v[2]); }
11391  };
11392 
11393  template <typename T_>
11394  struct invoke<T_,2>
11395  {
11396  static inline T_ execute(ifunction& f, T_ (&v)[2])
11397  { return f(v[0],v[1]); }
11398  };
11399 
11400  template <typename T_>
11401  struct invoke<T_,1>
11402  {
11403  static inline T_ execute(ifunction& f, T_ (&v)[1])
11404  { return f(v[0]); }
11405  };
11406 
11407  inline typename expression_node<T>::node_type type() const
11408  {
11410  }
11411 
11412  private:
11413 
11415  std::size_t parameter_count_;
11417  };
11418 
11419  template <typename T, typename IFunction>
11420  class function_N_node<T,IFunction,0> : public expression_node<T>
11421  {
11422  public:
11423 
11425  typedef IFunction ifunction;
11426 
11427  explicit function_N_node(ifunction* func)
11428  : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
11429  {}
11430 
11431  inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
11432  {
11433  return this < (&fn);
11434  }
11435 
11436  inline T value() const
11437  {
11438  if (function_)
11439  return (*function_)();
11440  else
11441  return std::numeric_limits<T>::quiet_NaN();
11442  }
11443 
11444  inline typename expression_node<T>::node_type type() const
11445  {
11447  }
11448 
11449  private:
11450 
11452  };
11453 
11454  template <typename T, typename VarArgFunction>
11456  {
11457  public:
11458 
11460 
11461  vararg_function_node(VarArgFunction* func,
11462  const std::vector<expression_ptr>& arg_list)
11463  : function_(func),
11464  arg_list_(arg_list)
11465  {
11466  value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN());
11467  }
11468 
11470  {
11471  for (std::size_t i = 0; i < arg_list_.size(); ++i)
11472  {
11474  {
11475  destroy_node(arg_list_[i]);
11476  }
11477  }
11478  }
11479 
11480  inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const
11481  {
11482  return this < (&fn);
11483  }
11484 
11485  inline T value() const
11486  {
11487  if (function_)
11488  {
11490  return (*function_)(value_list_);
11491  }
11492  else
11493  return std::numeric_limits<T>::quiet_NaN();
11494  }
11495 
11496  inline typename expression_node<T>::node_type type() const
11497  {
11499  }
11500 
11501  private:
11502 
11503  inline void populate_value_list() const
11504  {
11505  for (std::size_t i = 0; i < arg_list_.size(); ++i)
11506  {
11507  value_list_[i] = arg_list_[i]->value();
11508  }
11509  }
11510 
11511  VarArgFunction* function_;
11512  std::vector<expression_ptr> arg_list_;
11513  mutable std::vector<T> value_list_;
11514  };
11515 
11516  template <typename T, typename GenericFunction>
11518  {
11519  public:
11520 
11530  typedef std::pair<expression_ptr,bool> branch_t;
11531  typedef std::pair<void*,std::size_t> void_t;
11532  typedef std::vector<T> tmp_vs_t;
11533  typedef std::vector<type_store_t> typestore_list_t;
11534  typedef std::vector<range_data_type_t> range_list_t;
11535 
11536  generic_function_node(const std::vector<expression_ptr>& arg_list,
11537  GenericFunction* func = (GenericFunction*)(0))
11538  : function_(func),
11539  arg_list_(arg_list)
11540  {}
11541 
11543  {
11545  }
11546 
11547  virtual bool init_branches()
11548  {
11549  expr_as_vec1_store_.resize(arg_list_.size(),T(0) );
11550  typestore_list_ .resize(arg_list_.size(),type_store_t() );
11551  range_list_ .resize(arg_list_.size(),range_data_type_t());
11552  branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false));
11553 
11554  for (std::size_t i = 0; i < arg_list_.size(); ++i)
11555  {
11556  type_store_t& ts = typestore_list_[i];
11557 
11558  if (0 == arg_list_[i])
11559  return false;
11560  else if (is_ivector_node(arg_list_[i]))
11561  {
11562  vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0);
11563 
11564  if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i])))
11565  return false;
11566 
11567  ts.size = vi->size();
11568  ts.data = vi->vds().data();
11570  vi->vec()->vec_holder().set_ref(&ts.vec_data);
11571  }
11572  #ifndef exprtk_disable_string_capabilities
11573  else if (is_generally_string_node(arg_list_[i]))
11574  {
11575  string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0);
11576 
11577  if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i])))
11578  return false;
11579 
11580  ts.size = sbn->size();
11581  ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base()));
11583 
11584  range_list_[i].data = ts.data;
11585  range_list_[i].size = ts.size;
11586  range_list_[i].type_size = sizeof(char);
11587  range_list_[i].str_node = sbn;
11588 
11589  range_interface_t* ri = reinterpret_cast<range_interface_t*>(0);
11590 
11591  if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i])))
11592  return false;
11593 
11594  range_t& rp = ri->range_ref();
11595 
11596  if (
11597  rp.const_range() &&
11599  )
11600  {
11601  ts.size = rp.const_size();
11602  ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second;
11603  range_list_[i].range = reinterpret_cast<range_t*>(0);
11604  }
11605  else
11606  range_list_[i].range = &(ri->range_ref());
11607  }
11608  #endif
11609  else if (is_variable_node(arg_list_[i]))
11610  {
11612 
11613  if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i])))
11614  return false;
11615 
11616  ts.size = 1;
11617  ts.data = &var->ref();
11619  }
11620  else
11621  {
11622  ts.size = 1;
11623  ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]);
11625  }
11626 
11627  branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i]));
11628  }
11629 
11630  return true;
11631  }
11632 
11633  inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const
11634  {
11635  return this < (&fn);
11636  }
11637 
11638  inline T value() const
11639  {
11640  if (function_)
11641  {
11642  if (populate_value_list())
11643  {
11644  typedef typename GenericFunction::parameter_list_t parameter_list_t;
11645 
11646  return (*function_)(parameter_list_t(typestore_list_));
11647  }
11648  }
11649 
11650  return std::numeric_limits<T>::quiet_NaN();
11651  }
11652 
11653  inline typename expression_node<T>::node_type type() const
11654  {
11656  }
11657 
11658  protected:
11659 
11660  inline virtual bool populate_value_list() const
11661  {
11662  for (std::size_t i = 0; i < branch_.size(); ++i)
11663  {
11664  expr_as_vec1_store_[i] = branch_[i].first->value();
11665  }
11666 
11667  for (std::size_t i = 0; i < branch_.size(); ++i)
11668  {
11669  range_data_type_t& rdt = range_list_[i];
11670 
11671  if (rdt.range)
11672  {
11673  range_t& rp = (*rdt.range);
11674  std::size_t r0 = 0;
11675  std::size_t r1 = 0;
11676 
11677  if (rp(r0,r1,rdt.size))
11678  {
11679  type_store_t& ts = typestore_list_[i];
11680 
11681  ts.size = rp.cache_size();
11682  #ifndef exprtk_disable_string_capabilities
11683  if (ts.type == type_store_t::e_string)
11684  ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first;
11685  else
11686  #endif
11687  ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size);
11688  }
11689  else
11690  return false;
11691  }
11692  }
11693 
11694  return true;
11695  }
11696 
11697  GenericFunction* function_;
11699 
11700  private:
11701 
11702  std::vector<expression_ptr> arg_list_;
11703  std::vector<branch_t> branch_;
11706  };
11707 
11708  #ifndef exprtk_disable_string_capabilities
11709  template <typename T, typename StringFunction>
11710  class string_function_node : public generic_function_node<T,StringFunction>,
11711  public string_base_node<T>,
11712  public range_interface <T>
11713  {
11714  public:
11715 
11718 
11719  string_function_node(StringFunction* func,
11720  const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11721  : gen_function_t(arg_list,func)
11722  {
11723  range_.n0_c = std::make_pair<bool,std::size_t>(true,0);
11724  range_.n1_c = std::make_pair<bool,std::size_t>(true,0);
11725  range_.cache.first = range_.n0_c.second;
11726  range_.cache.second = range_.n1_c.second;
11727  }
11728 
11729  inline bool operator <(const string_function_node<T,StringFunction>& fn) const
11730  {
11731  return this < (&fn);
11732  }
11733 
11734  inline T value() const
11735  {
11737  {
11739  {
11740  typedef typename StringFunction::parameter_list_t parameter_list_t;
11741 
11742  const T result = (*gen_function_t::function_)
11743  (ret_string_, parameter_list_t(gen_function_t::typestore_list_));
11744 
11745  range_.n1_c.second = ret_string_.size() - 1;
11746  range_.cache.second = range_.n1_c.second;
11747 
11748  return result;
11749  }
11750  }
11751 
11752  return std::numeric_limits<T>::quiet_NaN();
11753  }
11754 
11755  inline typename expression_node<T>::node_type type() const
11756  {
11758  }
11759 
11761  {
11762  return ret_string_;
11763  }
11764 
11765  char_cptr base() const
11766  {
11767  return &ret_string_[0];
11768  }
11769 
11770  std::size_t size() const
11771  {
11772  return ret_string_.size();
11773  }
11774 
11776  {
11777  return range_;
11778  }
11779 
11780  const range_t& range_ref() const
11781  {
11782  return range_;
11783  }
11784 
11785  protected:
11786 
11787  mutable range_t range_;
11789  };
11790  #endif
11791 
11792  template <typename T, typename GenericFunction>
11793  class multimode_genfunction_node : public generic_function_node<T,GenericFunction>
11794  {
11795  public:
11796 
11799 
11800  multimode_genfunction_node(GenericFunction* func,
11801  const std::size_t& param_seq_index,
11802  const std::vector<typename gen_function_t::expression_ptr>& arg_list)
11803  : gen_function_t(arg_list,func),
11804  param_seq_index_(param_seq_index)
11805  {}
11806 
11807  inline T value() const
11808  {
11810  {
11812  {
11813  typedef typename GenericFunction::parameter_list_t parameter_list_t;
11814 
11816  parameter_list_t(gen_function_t::typestore_list_));
11817  }
11818  }
11819 
11820  return std::numeric_limits<T>::quiet_NaN();
11821  }
11822 
11823  inline typename expression_node<T>::node_type type() const
11824  {
11826  }
11827 
11828  private:
11829 
11830  std::size_t param_seq_index_;
11831  };
11832 
11833  #ifndef exprtk_disable_string_capabilities
11834  template <typename T, typename StringFunction>
11835  class multimode_strfunction_node : public string_function_node<T,StringFunction>
11836  {
11837  public:
11838 
11841 
11842  multimode_strfunction_node(StringFunction* func,
11843  const std::size_t& param_seq_index,
11844  const std::vector<typename str_function_t::expression_ptr>& arg_list)
11845  : str_function_t(func,arg_list),
11846  param_seq_index_(param_seq_index)
11847  {}
11848 
11849  inline T value() const
11850  {
11852  {
11854  {
11855  typedef typename StringFunction::parameter_list_t parameter_list_t;
11856 
11857  const T result = (*str_function_t::function_)(param_seq_index_,
11859  parameter_list_t(str_function_t::typestore_list_));
11860 
11863 
11864  return result;
11865  }
11866  }
11867 
11868  return std::numeric_limits<T>::quiet_NaN();
11869  }
11870 
11871  inline typename expression_node<T>::node_type type() const
11872  {
11874  }
11875 
11876  private:
11877 
11878  const std::size_t param_seq_index_;
11879  };
11880  #endif
11881 
11883  {};
11884 
11885  template <typename T>
11887  {
11888  public:
11889 
11890  virtual ~null_igenfunc()
11891  {}
11892 
11895 
11896  inline virtual T operator() (parameter_list_t)
11897  {
11898  return std::numeric_limits<T>::quiet_NaN();
11899  }
11900  };
11901 
11902  #ifndef exprtk_disable_return_statement
11903  template <typename T>
11904  class return_node : public generic_function_node<T,null_igenfunc<T> >
11905  {
11906  public:
11907 
11912 
11913  return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list,
11914  results_context_t& rc)
11915  : gen_function_t (arg_list),
11916  results_context_(&rc)
11917  {}
11918 
11919  inline T value() const
11920  {
11921  if (
11922  (0 != results_context_) &&
11924  )
11925  {
11926  typedef typename type_store<T>::parameter_list parameter_list_t;
11927 
11929  assign(parameter_list_t(gen_function_t::typestore_list_));
11930 
11931  throw return_exception();
11932  }
11933 
11934  return std::numeric_limits<T>::quiet_NaN();
11935  }
11936 
11937  inline typename expression_node<T>::node_type type() const
11938  {
11940  }
11941 
11942  private:
11943 
11945  };
11946 
11947  template <typename T>
11948  class return_envelope_node : public expression_node<T>
11949  {
11950  public:
11951 
11954 
11956  : results_context_(&rc ),
11957  return_invoked_ (false),
11958  body_ (body ),
11960  {}
11961 
11963  {
11964  if (body_ && body_deletable_)
11965  {
11967  }
11968  }
11969 
11970  inline T value() const
11971  {
11972  try
11973  {
11974  return_invoked_ = false;
11976 
11977  return body_->value();
11978  }
11979  catch(const return_exception&)
11980  {
11981  return_invoked_ = true;
11982  return std::numeric_limits<T>::quiet_NaN();
11983  }
11984  }
11985 
11986  inline typename expression_node<T>::node_type type() const
11987  {
11989  }
11990 
11991  inline bool* retinvk_ptr()
11992  {
11993  return &return_invoked_;
11994  }
11995 
11996  private:
11997 
11999  mutable bool return_invoked_;
12001  const bool body_deletable_;
12002  };
12003  #endif
12004 
12005  #define exprtk_define_unary_op(OpName) \
12006  template <typename T> \
12007  struct OpName##_op \
12008  { \
12009  typedef typename functor_t<T>::Type Type; \
12010  typedef typename expression_node<T>::node_type node_t; \
12011  \
12012  static inline T process(Type v) \
12013  { \
12014  return numeric:: OpName (v); \
12015  } \
12016  \
12017  static inline node_t type() \
12018  { \
12019  return expression_node<T>::e_##OpName; \
12020  } \
12021  \
12022  static inline details::operator_type operation() \
12023  { \
12024  return details::e_##OpName; \
12025  } \
12026  }; \
12027 
12029  exprtk_define_unary_op(acos )
12030  exprtk_define_unary_op(acosh)
12031  exprtk_define_unary_op(asin )
12032  exprtk_define_unary_op(asinh)
12033  exprtk_define_unary_op(atan )
12034  exprtk_define_unary_op(atanh)
12035  exprtk_define_unary_op(ceil )
12037  exprtk_define_unary_op(cosh )
12043  exprtk_define_unary_op(erfc )
12045  exprtk_define_unary_op(expm1)
12046  exprtk_define_unary_op(floor)
12047  exprtk_define_unary_op(frac )
12050  exprtk_define_unary_op(log10)
12052  exprtk_define_unary_op(log1p)
12053  exprtk_define_unary_op(ncdf )
12055  exprtk_define_unary_op(notl )
12058  exprtk_define_unary_op(round)
12062  exprtk_define_unary_op(sinc )
12063  exprtk_define_unary_op(sinh )
12064  exprtk_define_unary_op(sqrt )
12066  exprtk_define_unary_op(tanh )
12067  exprtk_define_unary_op(trunc)
12068  #undef exprtk_define_unary_op
12069 
12070  template <typename T>
12071  struct opr_base
12072  {
12073  typedef typename details::functor_t<T>::Type Type;
12074  typedef typename details::functor_t<T>::RefType RefType;
12075  typedef typename details::functor_t<T> functor_t;
12076  typedef typename functor_t::qfunc_t quaternary_functor_t;
12077  typedef typename functor_t::tfunc_t trinary_functor_t;
12078  typedef typename functor_t::bfunc_t binary_functor_t;
12079  typedef typename functor_t::ufunc_t unary_functor_t;
12080  };
12081 
12082  template <typename T>
12083  struct add_op : public opr_base<T>
12084  {
12085  typedef typename opr_base<T>::Type Type;
12086  typedef typename opr_base<T>::RefType RefType;
12087 
12088  static inline T process(Type t1, Type t2) { return t1 + t2; }
12089  static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; }
12090  static inline void assign(RefType t1, Type t2) { t1 += t2; }
12091  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
12093  };
12094 
12095  template <typename T>
12096  struct mul_op : public opr_base<T>
12097  {
12098  typedef typename opr_base<T>::Type Type;
12099  typedef typename opr_base<T>::RefType RefType;
12100 
12101  static inline T process(Type t1, Type t2) { return t1 * t2; }
12102  static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; }
12103  static inline void assign(RefType t1, Type t2) { t1 *= t2; }
12104  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
12106  };
12107 
12108  template <typename T>
12109  struct sub_op : public opr_base<T>
12110  {
12111  typedef typename opr_base<T>::Type Type;
12112  typedef typename opr_base<T>::RefType RefType;
12113 
12114  static inline T process(Type t1, Type t2) { return t1 - t2; }
12115  static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; }
12116  static inline void assign(RefType t1, Type t2) { t1 -= t2; }
12117  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
12119  };
12120 
12121  template <typename T>
12122  struct div_op : public opr_base<T>
12123  {
12124  typedef typename opr_base<T>::Type Type;
12125  typedef typename opr_base<T>::RefType RefType;
12126 
12127  static inline T process(Type t1, Type t2) { return t1 / t2; }
12128  static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; }
12129  static inline void assign(RefType t1, Type t2) { t1 /= t2; }
12130  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
12132  };
12133 
12134  template <typename T>
12135  struct mod_op : public opr_base<T>
12136  {
12137  typedef typename opr_base<T>::Type Type;
12138  typedef typename opr_base<T>::RefType RefType;
12139 
12140  static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); }
12141  static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); }
12142  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
12144  };
12145 
12146  template <typename T>
12147  struct pow_op : public opr_base<T>
12148  {
12149  typedef typename opr_base<T>::Type Type;
12150  typedef typename opr_base<T>::RefType RefType;
12151 
12152  static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); }
12153  static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); }
12154  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
12156  };
12157 
12158  template <typename T>
12159  struct lt_op : public opr_base<T>
12160  {
12161  typedef typename opr_base<T>::Type Type;
12162 
12163  static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); }
12164  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
12165  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
12166  static inline details::operator_type operation() { return details::e_lt; }
12167  };
12168 
12169  template <typename T>
12170  struct lte_op : public opr_base<T>
12171  {
12172  typedef typename opr_base<T>::Type Type;
12173 
12174  static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12175  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
12176  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
12178  };
12179 
12180  template <typename T>
12181  struct gt_op : public opr_base<T>
12182  {
12183  typedef typename opr_base<T>::Type Type;
12184 
12185  static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); }
12186  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
12187  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
12188  static inline details::operator_type operation() { return details::e_gt; }
12189  };
12190 
12191  template <typename T>
12192  struct gte_op : public opr_base<T>
12193  {
12194  typedef typename opr_base<T>::Type Type;
12195 
12196  static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12197  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
12198  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
12200  };
12201 
12202  template <typename T>
12203  struct eq_op : public opr_base<T>
12204  {
12205  typedef typename opr_base<T>::Type Type;
12206  static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12207  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12208  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12209  static inline details::operator_type operation() { return details::e_eq; }
12210  };
12211 
12212  template <typename T>
12213  struct equal_op : public opr_base<T>
12214  {
12215  typedef typename opr_base<T>::Type Type;
12216 
12217  static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); }
12218  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
12219  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
12221  };
12222 
12223  template <typename T>
12224  struct ne_op : public opr_base<T>
12225  {
12226  typedef typename opr_base<T>::Type Type;
12227 
12228  static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); }
12229  static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
12230  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
12231  static inline details::operator_type operation() { return details::e_ne; }
12232  };
12233 
12234  template <typename T>
12235  struct and_op : public opr_base<T>
12236  {
12237  typedef typename opr_base<T>::Type Type;
12238 
12239  static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); }
12240  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
12242  };
12243 
12244  template <typename T>
12245  struct nand_op : public opr_base<T>
12246  {
12247  typedef typename opr_base<T>::Type Type;
12248 
12249  static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); }
12252  };
12253 
12254  template <typename T>
12255  struct or_op : public opr_base<T>
12256  {
12257  typedef typename opr_base<T>::Type Type;
12258 
12259  static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); }
12260  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
12261  static inline details::operator_type operation() { return details::e_or; }
12262  };
12263 
12264  template <typename T>
12265  struct nor_op : public opr_base<T>
12266  {
12267  typedef typename opr_base<T>::Type Type;
12268 
12269  static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); }
12270  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12272  };
12273 
12274  template <typename T>
12275  struct xor_op : public opr_base<T>
12276  {
12277  typedef typename opr_base<T>::Type Type;
12278 
12279  static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); }
12280  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12282  };
12283 
12284  template <typename T>
12285  struct xnor_op : public opr_base<T>
12286  {
12287  typedef typename opr_base<T>::Type Type;
12288 
12289  static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); }
12290  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
12292  };
12293 
12294  template <typename T>
12295  struct in_op : public opr_base<T>
12296  {
12297  typedef typename opr_base<T>::Type Type;
12298 
12299  static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12300  static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
12301  static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
12302  static inline details::operator_type operation() { return details::e_in; }
12303  };
12304 
12305  template <typename T>
12306  struct like_op : public opr_base<T>
12307  {
12308  typedef typename opr_base<T>::Type Type;
12309 
12310  static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12311  static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
12314  };
12315 
12316  template <typename T>
12317  struct ilike_op : public opr_base<T>
12318  {
12319  typedef typename opr_base<T>::Type Type;
12320 
12321  static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
12322  static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
12325  };
12326 
12327  template <typename T>
12328  struct inrange_op : public opr_base<T>
12329  {
12330  typedef typename opr_base<T>::Type Type;
12331 
12332  static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
12333  static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
12334  {
12335  return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
12336  }
12339  };
12340 
12341  template <typename T>
12343  {
12344  return n->value();
12345  }
12346 
12347  template <typename T>
12348  inline T value(T* t)
12349  {
12350  return (*t);
12351  }
12352 
12353  template <typename T>
12354  struct vararg_add_op : public opr_base<T>
12355  {
12356  typedef typename opr_base<T>::Type Type;
12357 
12358  template <typename Type,
12359  typename Allocator,
12360  template <typename, typename> class Sequence>
12361  static inline T process(const Sequence<Type,Allocator>& arg_list)
12362  {
12363  switch (arg_list.size())
12364  {
12365  case 0 : return T(0);
12366  case 1 : return process_1(arg_list);
12367  case 2 : return process_2(arg_list);
12368  case 3 : return process_3(arg_list);
12369  case 4 : return process_4(arg_list);
12370  case 5 : return process_5(arg_list);
12371  default :
12372  {
12373  T result = T(0);
12374 
12375  for (std::size_t i = 0; i < arg_list.size(); ++i)
12376  {
12377  result += value(arg_list[i]);
12378  }
12379 
12380  return result;
12381  }
12382  }
12383  }
12384 
12385  template <typename Sequence>
12386  static inline T process_1(const Sequence& arg_list)
12387  {
12388  return value(arg_list[0]);
12389  }
12390 
12391  template <typename Sequence>
12392  static inline T process_2(const Sequence& arg_list)
12393  {
12394  return value(arg_list[0]) + value(arg_list[1]);
12395  }
12396 
12397  template <typename Sequence>
12398  static inline T process_3(const Sequence& arg_list)
12399  {
12400  return value(arg_list[0]) + value(arg_list[1]) +
12401  value(arg_list[2]) ;
12402  }
12403 
12404  template <typename Sequence>
12405  static inline T process_4(const Sequence& arg_list)
12406  {
12407  return value(arg_list[0]) + value(arg_list[1]) +
12408  value(arg_list[2]) + value(arg_list[3]) ;
12409  }
12410 
12411  template <typename Sequence>
12412  static inline T process_5(const Sequence& arg_list)
12413  {
12414  return value(arg_list[0]) + value(arg_list[1]) +
12415  value(arg_list[2]) + value(arg_list[3]) +
12416  value(arg_list[4]) ;
12417  }
12418  };
12419 
12420  template <typename T>
12421  struct vararg_mul_op : public opr_base<T>
12422  {
12423  typedef typename opr_base<T>::Type Type;
12424 
12425  template <typename Type,
12426  typename Allocator,
12427  template <typename, typename> class Sequence>
12428  static inline T process(const Sequence<Type,Allocator>& arg_list)
12429  {
12430  switch (arg_list.size())
12431  {
12432  case 0 : return T(0);
12433  case 1 : return process_1(arg_list);
12434  case 2 : return process_2(arg_list);
12435  case 3 : return process_3(arg_list);
12436  case 4 : return process_4(arg_list);
12437  case 5 : return process_5(arg_list);
12438  default :
12439  {
12440  T result = T(value(arg_list[0]));
12441 
12442  for (std::size_t i = 1; i < arg_list.size(); ++i)
12443  {
12444  result *= value(arg_list[i]);
12445  }
12446 
12447  return result;
12448  }
12449  }
12450  }
12451 
12452  template <typename Sequence>
12453  static inline T process_1(const Sequence& arg_list)
12454  {
12455  return value(arg_list[0]);
12456  }
12457 
12458  template <typename Sequence>
12459  static inline T process_2(const Sequence& arg_list)
12460  {
12461  return value(arg_list[0]) * value(arg_list[1]);
12462  }
12463 
12464  template <typename Sequence>
12465  static inline T process_3(const Sequence& arg_list)
12466  {
12467  return value(arg_list[0]) * value(arg_list[1]) *
12468  value(arg_list[2]) ;
12469  }
12470 
12471  template <typename Sequence>
12472  static inline T process_4(const Sequence& arg_list)
12473  {
12474  return value(arg_list[0]) * value(arg_list[1]) *
12475  value(arg_list[2]) * value(arg_list[3]) ;
12476  }
12477 
12478  template <typename Sequence>
12479  static inline T process_5(const Sequence& arg_list)
12480  {
12481  return value(arg_list[0]) * value(arg_list[1]) *
12482  value(arg_list[2]) * value(arg_list[3]) *
12483  value(arg_list[4]) ;
12484  }
12485  };
12486 
12487  template <typename T>
12488  struct vararg_avg_op : public opr_base<T>
12489  {
12490  typedef typename opr_base<T>::Type Type;
12491 
12492  template <typename Type,
12493  typename Allocator,
12494  template <typename, typename> class Sequence>
12495  static inline T process(const Sequence<Type,Allocator>& arg_list)
12496  {
12497  switch (arg_list.size())
12498  {
12499  case 0 : return T(0);
12500  case 1 : return process_1(arg_list);
12501  case 2 : return process_2(arg_list);
12502  case 3 : return process_3(arg_list);
12503  case 4 : return process_4(arg_list);
12504  case 5 : return process_5(arg_list);
12505  default : return vararg_add_op<T>::process(arg_list) / arg_list.size();
12506  }
12507  }
12508 
12509  template <typename Sequence>
12510  static inline T process_1(const Sequence& arg_list)
12511  {
12512  return value(arg_list[0]);
12513  }
12514 
12515  template <typename Sequence>
12516  static inline T process_2(const Sequence& arg_list)
12517  {
12518  return (value(arg_list[0]) + value(arg_list[1])) / T(2);
12519  }
12520 
12521  template <typename Sequence>
12522  static inline T process_3(const Sequence& arg_list)
12523  {
12524  return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3);
12525  }
12526 
12527  template <typename Sequence>
12528  static inline T process_4(const Sequence& arg_list)
12529  {
12530  return (value(arg_list[0]) + value(arg_list[1]) +
12531  value(arg_list[2]) + value(arg_list[3])) / T(4);
12532  }
12533 
12534  template <typename Sequence>
12535  static inline T process_5(const Sequence& arg_list)
12536  {
12537  return (value(arg_list[0]) + value(arg_list[1]) +
12538  value(arg_list[2]) + value(arg_list[3]) +
12539  value(arg_list[4])) / T(5);
12540  }
12541  };
12542 
12543  template <typename T>
12544  struct vararg_min_op : public opr_base<T>
12545  {
12546  typedef typename opr_base<T>::Type Type;
12547 
12548  template <typename Type,
12549  typename Allocator,
12550  template <typename, typename> class Sequence>
12551  static inline T process(const Sequence<Type,Allocator>& arg_list)
12552  {
12553  switch (arg_list.size())
12554  {
12555  case 0 : return T(0);
12556  case 1 : return process_1(arg_list);
12557  case 2 : return process_2(arg_list);
12558  case 3 : return process_3(arg_list);
12559  case 4 : return process_4(arg_list);
12560  case 5 : return process_5(arg_list);
12561  default :
12562  {
12563  T result = T(value(arg_list[0]));
12564 
12565  for (std::size_t i = 1; i < arg_list.size(); ++i)
12566  {
12567  const T v = value(arg_list[i]);
12568 
12569  if (v < result)
12570  result = v;
12571  }
12572 
12573  return result;
12574  }
12575  }
12576  }
12577 
12578  template <typename Sequence>
12579  static inline T process_1(const Sequence& arg_list)
12580  {
12581  return value(arg_list[0]);
12582  }
12583 
12584  template <typename Sequence>
12585  static inline T process_2(const Sequence& arg_list)
12586  {
12587  return std::min<T>(value(arg_list[0]),value(arg_list[1]));
12588  }
12589 
12590  template <typename Sequence>
12591  static inline T process_3(const Sequence& arg_list)
12592  {
12593  return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12594  }
12595 
12596  template <typename Sequence>
12597  static inline T process_4(const Sequence& arg_list)
12598  {
12599  return std::min<T>(
12600  std::min<T>(value(arg_list[0]),value(arg_list[1])),
12601  std::min<T>(value(arg_list[2]),value(arg_list[3])));
12602  }
12603 
12604  template <typename Sequence>
12605  static inline T process_5(const Sequence& arg_list)
12606  {
12607  return std::min<T>(
12608  std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),
12609  std::min<T>(value(arg_list[2]),value(arg_list[3]))),
12610  value(arg_list[4]));
12611  }
12612  };
12613 
12614  template <typename T>
12615  struct vararg_max_op : public opr_base<T>
12616  {
12617  typedef typename opr_base<T>::Type Type;
12618 
12619  template <typename Type,
12620  typename Allocator,
12621  template <typename, typename> class Sequence>
12622  static inline T process(const Sequence<Type,Allocator>& arg_list)
12623  {
12624  switch (arg_list.size())
12625  {
12626  case 0 : return T(0);
12627  case 1 : return process_1(arg_list);
12628  case 2 : return process_2(arg_list);
12629  case 3 : return process_3(arg_list);
12630  case 4 : return process_4(arg_list);
12631  case 5 : return process_5(arg_list);
12632  default :
12633  {
12634  T result = T(value(arg_list[0]));
12635 
12636  for (std::size_t i = 1; i < arg_list.size(); ++i)
12637  {
12638  const T v = value(arg_list[i]);
12639 
12640  if (v > result)
12641  result = v;
12642  }
12643 
12644  return result;
12645  }
12646  }
12647  }
12648 
12649  template <typename Sequence>
12650  static inline T process_1(const Sequence& arg_list)
12651  {
12652  return value(arg_list[0]);
12653  }
12654 
12655  template <typename Sequence>
12656  static inline T process_2(const Sequence& arg_list)
12657  {
12658  return std::max<T>(value(arg_list[0]),value(arg_list[1]));
12659  }
12660 
12661  template <typename Sequence>
12662  static inline T process_3(const Sequence& arg_list)
12663  {
12664  return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2]));
12665  }
12666 
12667  template <typename Sequence>
12668  static inline T process_4(const Sequence& arg_list)
12669  {
12670  return std::max<T>(
12671  std::max<T>(value(arg_list[0]),value(arg_list[1])),
12672  std::max<T>(value(arg_list[2]),value(arg_list[3])));
12673  }
12674 
12675  template <typename Sequence>
12676  static inline T process_5(const Sequence& arg_list)
12677  {
12678  return std::max<T>(
12679  std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),
12680  std::max<T>(value(arg_list[2]),value(arg_list[3]))),
12681  value(arg_list[4]));
12682  }
12683  };
12684 
12685  template <typename T>
12686  struct vararg_mand_op : public opr_base<T>
12687  {
12688  typedef typename opr_base<T>::Type Type;
12689 
12690  template <typename Type,
12691  typename Allocator,
12692  template <typename, typename> class Sequence>
12693  static inline T process(const Sequence<Type,Allocator>& arg_list)
12694  {
12695  switch (arg_list.size())
12696  {
12697  case 1 : return process_1(arg_list);
12698  case 2 : return process_2(arg_list);
12699  case 3 : return process_3(arg_list);
12700  case 4 : return process_4(arg_list);
12701  case 5 : return process_5(arg_list);
12702  default :
12703  {
12704  for (std::size_t i = 0; i < arg_list.size(); ++i)
12705  {
12706  if (std::equal_to<T>()(T(0), value(arg_list[i])))
12707  return T(0);
12708  }
12709 
12710  return T(1);
12711  }
12712  }
12713  }
12714 
12715  template <typename Sequence>
12716  static inline T process_1(const Sequence& arg_list)
12717  {
12718  return std::not_equal_to<T>()
12719  (T(0), value(arg_list[0])) ? T(1) : T(0);
12720  }
12721 
12722  template <typename Sequence>
12723  static inline T process_2(const Sequence& arg_list)
12724  {
12725  return (
12726  std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12727  std::not_equal_to<T>()(T(0), value(arg_list[1]))
12728  ) ? T(1) : T(0);
12729  }
12730 
12731  template <typename Sequence>
12732  static inline T process_3(const Sequence& arg_list)
12733  {
12734  return (
12735  std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12736  std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12737  std::not_equal_to<T>()(T(0), value(arg_list[2]))
12738  ) ? T(1) : T(0);
12739  }
12740 
12741  template <typename Sequence>
12742  static inline T process_4(const Sequence& arg_list)
12743  {
12744  return (
12745  std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12746  std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12747  std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12748  std::not_equal_to<T>()(T(0), value(arg_list[3]))
12749  ) ? T(1) : T(0);
12750  }
12751 
12752  template <typename Sequence>
12753  static inline T process_5(const Sequence& arg_list)
12754  {
12755  return (
12756  std::not_equal_to<T>()(T(0), value(arg_list[0])) &&
12757  std::not_equal_to<T>()(T(0), value(arg_list[1])) &&
12758  std::not_equal_to<T>()(T(0), value(arg_list[2])) &&
12759  std::not_equal_to<T>()(T(0), value(arg_list[3])) &&
12760  std::not_equal_to<T>()(T(0), value(arg_list[4]))
12761  ) ? T(1) : T(0);
12762  }
12763  };
12764 
12765  template <typename T>
12766  struct vararg_mor_op : public opr_base<T>
12767  {
12768  typedef typename opr_base<T>::Type Type;
12769 
12770  template <typename Type,
12771  typename Allocator,
12772  template <typename, typename> class Sequence>
12773  static inline T process(const Sequence<Type,Allocator>& arg_list)
12774  {
12775  switch (arg_list.size())
12776  {
12777  case 1 : return process_1(arg_list);
12778  case 2 : return process_2(arg_list);
12779  case 3 : return process_3(arg_list);
12780  case 4 : return process_4(arg_list);
12781  case 5 : return process_5(arg_list);
12782  default :
12783  {
12784  for (std::size_t i = 0; i < arg_list.size(); ++i)
12785  {
12786  if (std::not_equal_to<T>()(T(0), value(arg_list[i])))
12787  return T(1);
12788  }
12789 
12790  return T(0);
12791  }
12792  }
12793  }
12794 
12795  template <typename Sequence>
12796  static inline T process_1(const Sequence& arg_list)
12797  {
12798  return std::not_equal_to<T>()
12799  (T(0), value(arg_list[0])) ? T(1) : T(0);
12800  }
12801 
12802  template <typename Sequence>
12803  static inline T process_2(const Sequence& arg_list)
12804  {
12805  return (
12806  std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12807  std::not_equal_to<T>()(T(0), value(arg_list[1]))
12808  ) ? T(1) : T(0);
12809  }
12810 
12811  template <typename Sequence>
12812  static inline T process_3(const Sequence& arg_list)
12813  {
12814  return (
12815  std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12816  std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12817  std::not_equal_to<T>()(T(0), value(arg_list[2]))
12818  ) ? T(1) : T(0);
12819  }
12820 
12821  template <typename Sequence>
12822  static inline T process_4(const Sequence& arg_list)
12823  {
12824  return (
12825  std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12826  std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12827  std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12828  std::not_equal_to<T>()(T(0), value(arg_list[3]))
12829  ) ? T(1) : T(0);
12830  }
12831 
12832  template <typename Sequence>
12833  static inline T process_5(const Sequence& arg_list)
12834  {
12835  return (
12836  std::not_equal_to<T>()(T(0), value(arg_list[0])) ||
12837  std::not_equal_to<T>()(T(0), value(arg_list[1])) ||
12838  std::not_equal_to<T>()(T(0), value(arg_list[2])) ||
12839  std::not_equal_to<T>()(T(0), value(arg_list[3])) ||
12840  std::not_equal_to<T>()(T(0), value(arg_list[4]))
12841  ) ? T(1) : T(0);
12842  }
12843  };
12844 
12845  template <typename T>
12846  struct vararg_multi_op : public opr_base<T>
12847  {
12848  typedef typename opr_base<T>::Type Type;
12849 
12850  template <typename Type,
12851  typename Allocator,
12852  template <typename, typename> class Sequence>
12853  static inline T process(const Sequence<Type,Allocator>& arg_list)
12854  {
12855  switch (arg_list.size())
12856  {
12857  case 0 : return std::numeric_limits<T>::quiet_NaN();
12858  case 1 : return process_1(arg_list);
12859  case 2 : return process_2(arg_list);
12860  case 3 : return process_3(arg_list);
12861  case 4 : return process_4(arg_list);
12862  case 5 : return process_5(arg_list);
12863  case 6 : return process_6(arg_list);
12864  case 7 : return process_7(arg_list);
12865  case 8 : return process_8(arg_list);
12866  default :
12867  {
12868  for (std::size_t i = 0; i < (arg_list.size() - 1); ++i)
12869  {
12870  value(arg_list[i]);
12871  }
12872 
12873  return value(arg_list.back());
12874  }
12875  }
12876  }
12877 
12878  template <typename Sequence>
12879  static inline T process_1(const Sequence& arg_list)
12880  {
12881  return value(arg_list[0]);
12882  }
12883 
12884  template <typename Sequence>
12885  static inline T process_2(const Sequence& arg_list)
12886  {
12887  value(arg_list[0]);
12888  return value(arg_list[1]);
12889  }
12890 
12891  template <typename Sequence>
12892  static inline T process_3(const Sequence& arg_list)
12893  {
12894  value(arg_list[0]);
12895  value(arg_list[1]);
12896  return value(arg_list[2]);
12897  }
12898 
12899  template <typename Sequence>
12900  static inline T process_4(const Sequence& arg_list)
12901  {
12902  value(arg_list[0]);
12903  value(arg_list[1]);
12904  value(arg_list[2]);
12905  return value(arg_list[3]);
12906  }
12907 
12908  template <typename Sequence>
12909  static inline T process_5(const Sequence& arg_list)
12910  {
12911  value(arg_list[0]);
12912  value(arg_list[1]);
12913  value(arg_list[2]);
12914  value(arg_list[3]);
12915  return value(arg_list[4]);
12916  }
12917 
12918  template <typename Sequence>
12919  static inline T process_6(const Sequence& arg_list)
12920  {
12921  value(arg_list[0]);
12922  value(arg_list[1]);
12923  value(arg_list[2]);
12924  value(arg_list[3]);
12925  value(arg_list[4]);
12926  return value(arg_list[5]);
12927  }
12928 
12929  template <typename Sequence>
12930  static inline T process_7(const Sequence& arg_list)
12931  {
12932  value(arg_list[0]);
12933  value(arg_list[1]);
12934  value(arg_list[2]);
12935  value(arg_list[3]);
12936  value(arg_list[4]);
12937  value(arg_list[5]);
12938  return value(arg_list[6]);
12939  }
12940 
12941  template <typename Sequence>
12942  static inline T process_8(const Sequence& arg_list)
12943  {
12944  value(arg_list[0]);
12945  value(arg_list[1]);
12946  value(arg_list[2]);
12947  value(arg_list[3]);
12948  value(arg_list[4]);
12949  value(arg_list[5]);
12950  value(arg_list[6]);
12951  return value(arg_list[7]);
12952  }
12953  };
12954 
12955  template <typename T>
12956  struct vec_add_op
12957  {
12959 
12960  static inline T process(const ivector_ptr v)
12961  {
12962  const T* vec = v->vec()->vds().data();
12963  const std::size_t vec_size = v->vec()->vds().size();
12964 
12965  loop_unroll::details lud(vec_size);
12966 
12967  if (vec_size <= static_cast<std::size_t>(lud.batch_size))
12968  {
12969  T result = T(0);
12970  int i = 0;
12971 
12973  switch (vec_size)
12974  {
12975  #define case_stmt(N) \
12976  case N : result += vec[i++]; \
12977 
12978  #ifndef exprtk_disable_superscalar_unroll
12979  case_stmt(16) case_stmt(15)
12980  case_stmt(14) case_stmt(13)
12981  case_stmt(12) case_stmt(11)
12982  case_stmt(10) case_stmt( 9)
12983  case_stmt( 8) case_stmt( 7)
12984  case_stmt( 6) case_stmt( 5)
12985  #endif
12986  case_stmt( 4) case_stmt( 3)
12987  case_stmt( 2) case_stmt( 1)
12988  }
12990 
12991  #undef case_stmt
12992 
12993  return result;
12994  }
12995 
12996  T r[] = {
12997  T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0),
12998  T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0)
12999  };
13000 
13001  const T* upper_bound = vec + lud.upper_bound;
13002 
13003  while (vec < upper_bound)
13004  {
13005  #define exprtk_loop(N) \
13006  r[N] += vec[N]; \
13007 
13008  exprtk_loop( 0) exprtk_loop( 1)
13009  exprtk_loop( 2) exprtk_loop( 3)
13010  #ifndef exprtk_disable_superscalar_unroll
13011  exprtk_loop( 4) exprtk_loop( 5)
13012  exprtk_loop( 6) exprtk_loop( 7)
13013  exprtk_loop( 8) exprtk_loop( 9)
13014  exprtk_loop(10) exprtk_loop(11)
13015  exprtk_loop(12) exprtk_loop(13)
13016  exprtk_loop(14) exprtk_loop(15)
13017  #endif
13018 
13019  vec += lud.batch_size;
13020  }
13021 
13022  int i = 0;
13023 
13025  switch (lud.remainder)
13026  {
13027  #define case_stmt(N) \
13028  case N : r[0] += vec[i++]; \
13029 
13030  #ifndef exprtk_disable_superscalar_unroll
13031  case_stmt(15) case_stmt(14)
13032  case_stmt(13) case_stmt(12)
13033  case_stmt(11) case_stmt(10)
13034  case_stmt( 9) case_stmt( 8)
13035  case_stmt( 7) case_stmt( 6)
13036  case_stmt( 5) case_stmt( 4)
13037  #endif
13038  case_stmt( 3) case_stmt( 2)
13039  case_stmt( 1)
13040  }
13042 
13043  #undef exprtk_loop
13044  #undef case_stmt
13045 
13046  return (r[ 0] + r[ 1] + r[ 2] + r[ 3])
13047  #ifndef exprtk_disable_superscalar_unroll
13048  + (r[ 4] + r[ 5] + r[ 6] + r[ 7])
13049  + (r[ 8] + r[ 9] + r[10] + r[11])
13050  + (r[12] + r[13] + r[14] + r[15])
13051  #endif
13052  ;
13053  }
13054  };
13055 
13056  template <typename T>
13057  struct vec_mul_op
13058  {
13060 
13061  static inline T process(const ivector_ptr v)
13062  {
13063  const T* vec = v->vec()->vds().data();
13064  const std::size_t vec_size = v->vec()->vds().size();
13065 
13066  loop_unroll::details lud(vec_size);
13067 
13068  if (vec_size <= static_cast<std::size_t>(lud.batch_size))
13069  {
13070  T result = T(1);
13071  int i = 0;
13072 
13074  switch (vec_size)
13075  {
13076  #define case_stmt(N) \
13077  case N : result *= vec[i++]; \
13078 
13079  #ifndef exprtk_disable_superscalar_unroll
13080  case_stmt(16) case_stmt(15)
13081  case_stmt(14) case_stmt(13)
13082  case_stmt(12) case_stmt(11)
13083  case_stmt(10) case_stmt( 9)
13084  case_stmt( 8) case_stmt( 7)
13085  case_stmt( 6) case_stmt( 5)
13086  #endif
13087  case_stmt( 4) case_stmt( 3)
13088  case_stmt( 2) case_stmt( 1)
13089  }
13091 
13092  #undef case_stmt
13093 
13094  return result;
13095  }
13096 
13097  T r[] = {
13098  T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1),
13099  T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1)
13100  };
13101 
13102  const T* upper_bound = vec + lud.upper_bound;
13103 
13104  while (vec < upper_bound)
13105  {
13106  #define exprtk_loop(N) \
13107  r[N] *= vec[N]; \
13108 
13109  exprtk_loop( 0) exprtk_loop( 1)
13110  exprtk_loop( 2) exprtk_loop( 3)
13111  #ifndef exprtk_disable_superscalar_unroll
13112  exprtk_loop( 4) exprtk_loop( 5)
13113  exprtk_loop( 6) exprtk_loop( 7)
13114  exprtk_loop( 8) exprtk_loop( 9)
13115  exprtk_loop(10) exprtk_loop(11)
13116  exprtk_loop(12) exprtk_loop(13)
13117  exprtk_loop(14) exprtk_loop(15)
13118  #endif
13119 
13120  vec += lud.batch_size;
13121  }
13122 
13123  int i = 0;
13124 
13126  switch (lud.remainder)
13127  {
13128  #define case_stmt(N) \
13129  case N : r[0] *= vec[i++]; \
13130 
13131  #ifndef exprtk_disable_superscalar_unroll
13132  case_stmt(15) case_stmt(14)
13133  case_stmt(13) case_stmt(12)
13134  case_stmt(11) case_stmt(10)
13135  case_stmt( 9) case_stmt( 8)
13136  case_stmt( 7) case_stmt( 6)
13137  case_stmt( 5) case_stmt( 4)
13138  #endif
13139  case_stmt( 3) case_stmt( 2)
13140  case_stmt( 1)
13141  }
13143 
13144  #undef exprtk_loop
13145  #undef case_stmt
13146 
13147  return (r[ 0] * r[ 1] * r[ 2] * r[ 3])
13148  #ifndef exprtk_disable_superscalar_unroll
13149  + (r[ 4] * r[ 5] * r[ 6] * r[ 7])
13150  + (r[ 8] * r[ 9] * r[10] * r[11])
13151  + (r[12] * r[13] * r[14] * r[15])
13152  #endif
13153  ;
13154  }
13155  };
13156 
13157  template <typename T>
13158  struct vec_avg_op
13159  {
13161 
13162  static inline T process(const ivector_ptr v)
13163  {
13164  const std::size_t vec_size = v->vec()->vds().size();
13165 
13166  return vec_add_op<T>::process(v) / vec_size;
13167  }
13168  };
13169 
13170  template <typename T>
13171  struct vec_min_op
13172  {
13174 
13175  static inline T process(const ivector_ptr v)
13176  {
13177  const T* vec = v->vec()->vds().data();
13178  const std::size_t vec_size = v->vec()->vds().size();
13179 
13180  T result = vec[0];
13181 
13182  for (std::size_t i = 1; i < vec_size; ++i)
13183  {
13184  T v_i = vec[i];
13185 
13186  if (v_i < result)
13187  result = v_i;
13188  }
13189 
13190  return result;
13191  }
13192  };
13193 
13194  template <typename T>
13195  struct vec_max_op
13196  {
13198 
13199  static inline T process(const ivector_ptr v)
13200  {
13201  const T* vec = v->vec()->vds().data();
13202  const std::size_t vec_size = v->vec()->vds().size();
13203 
13204  T result = vec[0];
13205 
13206  for (std::size_t i = 1; i < vec_size; ++i)
13207  {
13208  T v_i = vec[i];
13209 
13210  if (v_i > result)
13211  result = v_i;
13212  }
13213 
13214  return result;
13215  }
13216  };
13217 
13218  template <typename T>
13219  class vov_base_node : public expression_node<T>
13220  {
13221  public:
13222 
13223  virtual ~vov_base_node()
13224  {}
13225 
13226  inline virtual operator_type operation() const
13227  {
13228  return details::e_default;
13229  }
13230 
13231  virtual const T& v0() const = 0;
13232 
13233  virtual const T& v1() const = 0;
13234  };
13235 
13236  template <typename T>
13237  class cov_base_node : public expression_node<T>
13238  {
13239  public:
13240 
13241  virtual ~cov_base_node()
13242  {}
13243 
13244  inline virtual operator_type operation() const
13245  {
13246  return details::e_default;
13247  }
13248 
13249  virtual const T c() const = 0;
13250 
13251  virtual const T& v() const = 0;
13252  };
13253 
13254  template <typename T>
13255  class voc_base_node : public expression_node<T>
13256  {
13257  public:
13258 
13259  virtual ~voc_base_node()
13260  {}
13261 
13262  inline virtual operator_type operation() const
13263  {
13264  return details::e_default;
13265  }
13266 
13267  virtual const T c() const = 0;
13268 
13269  virtual const T& v() const = 0;
13270  };
13271 
13272  template <typename T>
13273  class vob_base_node : public expression_node<T>
13274  {
13275  public:
13276 
13277  virtual ~vob_base_node()
13278  {}
13279 
13280  virtual const T& v() const = 0;
13281  };
13282 
13283  template <typename T>
13284  class bov_base_node : public expression_node<T>
13285  {
13286  public:
13287 
13288  virtual ~bov_base_node()
13289  {}
13290 
13291  virtual const T& v() const = 0;
13292  };
13293 
13294  template <typename T>
13295  class cob_base_node : public expression_node<T>
13296  {
13297  public:
13298 
13299  virtual ~cob_base_node()
13300  {}
13301 
13302  inline virtual operator_type operation() const
13303  {
13304  return details::e_default;
13305  }
13306 
13307  virtual const T c() const = 0;
13308 
13309  virtual void set_c(const T) = 0;
13310 
13311  virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13312  };
13313 
13314  template <typename T>
13315  class boc_base_node : public expression_node<T>
13316  {
13317  public:
13318 
13319  virtual ~boc_base_node()
13320  {}
13321 
13322  inline virtual operator_type operation() const
13323  {
13324  return details::e_default;
13325  }
13326 
13327  virtual const T c() const = 0;
13328 
13329  virtual void set_c(const T) = 0;
13330 
13331  virtual expression_node<T>* move_branch(const std::size_t& index) = 0;
13332  };
13333 
13334  template <typename T>
13335  class uv_base_node : public expression_node<T>
13336  {
13337  public:
13338 
13339  virtual ~uv_base_node()
13340  {}
13341 
13342  inline virtual operator_type operation() const
13343  {
13344  return details::e_default;
13345  }
13346 
13347  virtual const T& v() const = 0;
13348  };
13349 
13350  template <typename T>
13351  class sos_base_node : public expression_node<T>
13352  {
13353  public:
13354 
13355  virtual ~sos_base_node()
13356  {}
13357 
13358  inline virtual operator_type operation() const
13359  {
13360  return details::e_default;
13361  }
13362  };
13363 
13364  template <typename T>
13366  {
13367  public:
13368 
13370  {}
13371 
13372  inline virtual operator_type operation() const
13373  {
13374  return details::e_default;
13375  }
13376  };
13377 
13378  template <typename T>
13380  {
13381  public:
13382 
13384  {}
13385 
13386  virtual std::string type_id() const = 0;
13387  };
13388 
13389  template <typename T>
13391  {
13392  public:
13393 
13395  {}
13396 
13397  virtual std::string type_id() const = 0;
13398  };
13399 
13400  template <typename T, typename Operation>
13402  {
13403  public:
13404 
13406  typedef Operation operation_t;
13407 
13408  explicit unary_variable_node(const T& var)
13409  : v_(var)
13410  {}
13411 
13412  inline T value() const
13413  {
13414  return Operation::process(v_);
13415  }
13416 
13417  inline typename expression_node<T>::node_type type() const
13418  {
13419  return Operation::type();
13420  }
13421 
13422  inline operator_type operation() const
13423  {
13424  return Operation::operation();
13425  }
13426 
13427  inline const T& v() const
13428  {
13429  return v_;
13430  }
13431 
13432  private:
13433 
13436 
13437  const T& v_;
13438  };
13439 
13440  template <typename T>
13441  class uvouv_node : public expression_node<T>
13442  {
13443  public:
13444 
13445  // UOpr1(v0) Op UOpr2(v1)
13446 
13449  typedef typename functor_t::bfunc_t bfunc_t;
13450  typedef typename functor_t::ufunc_t ufunc_t;
13451 
13452  explicit uvouv_node(const T& var0,const T& var1,
13453  ufunc_t uf0, ufunc_t uf1, bfunc_t bf)
13454  : v0_(var0),
13455  v1_(var1),
13456  u0_(uf0 ),
13457  u1_(uf1 ),
13458  f_ (bf )
13459  {}
13460 
13461  inline T value() const
13462  {
13463  return f_(u0_(v0_),u1_(v1_));
13464  }
13465 
13466  inline typename expression_node<T>::node_type type() const
13467  {
13469  }
13470 
13471  inline operator_type operation() const
13472  {
13473  return details::e_default;
13474  }
13475 
13476  inline const T& v0()
13477  {
13478  return v0_;
13479  }
13480 
13481  inline const T& v1()
13482  {
13483  return v1_;
13484  }
13485 
13486  inline ufunc_t u0()
13487  {
13488  return u0_;
13489  }
13490 
13491  inline ufunc_t u1()
13492  {
13493  return u1_;
13494  }
13495 
13496  inline ufunc_t f()
13497  {
13498  return f_;
13499  }
13500 
13501  private:
13502 
13505 
13506  const T& v0_;
13507  const T& v1_;
13508  const ufunc_t u0_;
13509  const ufunc_t u1_;
13510  const bfunc_t f_;
13511  };
13512 
13513  template <typename T, typename Operation>
13515  {
13516  public:
13517 
13519  typedef Operation operation_t;
13520 
13522  : branch_(brnch),
13524  {}
13525 
13527  {
13528  if (branch_ && branch_deletable_)
13529  {
13531  }
13532  }
13533 
13534  inline T value() const
13535  {
13536  return Operation::process(branch_->value());
13537  }
13538 
13539  inline typename expression_node<T>::node_type type() const
13540  {
13541  return Operation::type();
13542  }
13543 
13544  inline operator_type operation() const
13545  {
13546  return Operation::operation();
13547  }
13548 
13549  inline expression_node<T>* branch(const std::size_t&) const
13550  {
13551  return branch_;
13552  }
13553 
13554  inline void release()
13555  {
13556  branch_deletable_ = false;
13557  }
13558 
13559  private:
13560 
13563 
13566  };
13567 
13568  template <typename T> struct is_const { enum {result = 0}; };
13569  template <typename T> struct is_const <const T> { enum {result = 1}; };
13570  template <typename T> struct is_const_ref { enum {result = 0}; };
13571  template <typename T> struct is_const_ref <const T&> { enum {result = 1}; };
13572  template <typename T> struct is_ref { enum {result = 0}; };
13573  template <typename T> struct is_ref<T&> { enum {result = 1}; };
13574  template <typename T> struct is_ref<const T&> { enum {result = 0}; };
13575 
13576  template <std::size_t State>
13577  struct param_to_str { static std::string result() { static const std::string r("v"); return r; } };
13578 
13579  template <>
13580  struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } };
13581 
13582  #define exprtk_crtype(Type) \
13583  param_to_str<is_const_ref< Type >::result>::result() \
13584 
13585  template <typename T>
13587  {
13589  typedef typename functor_t::bfunc_t bfunc_t;
13590 
13591  struct mode0
13592  {
13593  static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13594  {
13595  // (T0 o0 T1) o1 T2
13596  return bf1(bf0(t0,t1),t2);
13597  }
13598 
13599  template <typename T0, typename T1, typename T2>
13600  static inline std::string id()
13601  {
13602  static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13603  exprtk_crtype(T1) + ")o(" +
13604  exprtk_crtype(T2) + ")" ;
13605  return result;
13606  }
13607  };
13608 
13609  struct mode1
13610  {
13611  static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1)
13612  {
13613  // T0 o0 (T1 o1 T2)
13614  return bf0(t0,bf1(t1,t2));
13615  }
13616 
13617  template <typename T0, typename T1, typename T2>
13618  static inline std::string id()
13619  {
13620  static const std::string result = "(" + exprtk_crtype(T0) + ")o(" +
13621  exprtk_crtype(T1) + "o" +
13622  exprtk_crtype(T2) + ")" ;
13623  return result;
13624  }
13625  };
13626  };
13627 
13628  template <typename T>
13630  {
13632  typedef typename functor_t::bfunc_t bfunc_t;
13633 
13634  struct mode0
13635  {
13636  static inline T process(const T& t0, const T& t1,
13637  const T& t2, const T& t3,
13638  const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13639  {
13640  // (T0 o0 T1) o1 (T2 o2 T3)
13641  return bf1(bf0(t0,t1),bf2(t2,t3));
13642  }
13643 
13644  template <typename T0, typename T1, typename T2, typename T3>
13645  static inline std::string id()
13646  {
13647  static const std::string result = "(" + exprtk_crtype(T0) + "o" +
13648  exprtk_crtype(T1) + ")o" +
13649  "(" + exprtk_crtype(T2) + "o" +
13650  exprtk_crtype(T3) + ")" ;
13651  return result;
13652  }
13653  };
13654 
13655  struct mode1
13656  {
13657  static inline T process(const T& t0, const T& t1,
13658  const T& t2, const T& t3,
13659  const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13660  {
13661  // (T0 o0 (T1 o1 (T2 o2 T3))
13662  return bf0(t0,bf1(t1,bf2(t2,t3)));
13663  }
13664  template <typename T0, typename T1, typename T2, typename T3>
13665  static inline std::string id()
13666  {
13667  static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13668  exprtk_crtype(T1) + ")o(" +
13669  exprtk_crtype(T2) + "o" +
13670  exprtk_crtype(T3) + "))" ;
13671  return result;
13672  }
13673  };
13674 
13675  struct mode2
13676  {
13677  static inline T process(const T& t0, const T& t1,
13678  const T& t2, const T& t3,
13679  const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13680  {
13681  // (T0 o0 ((T1 o1 T2) o2 T3)
13682  return bf0(t0,bf2(bf1(t1,t2),t3));
13683  }
13684 
13685  template <typename T0, typename T1, typename T2, typename T3>
13686  static inline std::string id()
13687  {
13688  static const std::string result = "(" + exprtk_crtype(T0) + ")o((" +
13689  exprtk_crtype(T1) + "o" +
13690  exprtk_crtype(T2) + ")o(" +
13691  exprtk_crtype(T3) + "))" ;
13692  return result;
13693  }
13694  };
13695 
13696  struct mode3
13697  {
13698  static inline T process(const T& t0, const T& t1,
13699  const T& t2, const T& t3,
13700  const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13701  {
13702  // (((T0 o0 T1) o1 T2) o2 T3)
13703  return bf2(bf1(bf0(t0,t1),t2),t3);
13704  }
13705 
13706  template <typename T0, typename T1, typename T2, typename T3>
13707  static inline std::string id()
13708  {
13709  static const std::string result = "((" + exprtk_crtype(T0) + "o" +
13710  exprtk_crtype(T1) + ")o(" +
13711  exprtk_crtype(T2) + "))o(" +
13712  exprtk_crtype(T3) + ")";
13713  return result;
13714  }
13715  };
13716 
13717  struct mode4
13718  {
13719  static inline T process(const T& t0, const T& t1,
13720  const T& t2, const T& t3,
13721  const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2)
13722  {
13723  // ((T0 o0 (T1 o1 T2)) o2 T3
13724  return bf2(bf0(t0,bf1(t1,t2)),t3);
13725  }
13726 
13727  template <typename T0, typename T1, typename T2, typename T3>
13728  static inline std::string id()
13729  {
13730  static const std::string result = "((" + exprtk_crtype(T0) + ")o(" +
13731  exprtk_crtype(T1) + "o" +
13732  exprtk_crtype(T2) + "))o(" +
13733  exprtk_crtype(T3) + ")" ;
13734  return result;
13735  }
13736  };
13737  };
13738 
13739  #undef exprtk_crtype
13740 
13741  template <typename T, typename T0, typename T1>
13742  struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; };
13743  template <typename T, typename T0, typename T1>
13745 
13746  #define synthesis_node_type_define(T0_,T1_,v_) \
13747  template <typename T, typename T0, typename T1> \
13748  struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \
13749  template <typename T, typename T0, typename T1> \
13750  const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \
13751 
13752  synthesis_node_type_define(const T0&, const T1&, e_vov)
13753  synthesis_node_type_define(const T0&, const T1 , e_voc)
13754  synthesis_node_type_define(const T0 , const T1&, e_cov)
13755  synthesis_node_type_define( T0&, T1&, e_none)
13756  synthesis_node_type_define(const T0 , const T1 , e_none)
13757  synthesis_node_type_define( T0&, const T1 , e_none)
13758  synthesis_node_type_define(const T0 , T1&, e_none)
13759  synthesis_node_type_define(const T0&, T1&, e_none)
13760  synthesis_node_type_define( T0&, const T1&, e_none)
13761  #undef synthesis_node_type_define
13762 
13763  template <typename T, typename T0, typename T1, typename T2>
13764  struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; };
13765  template <typename T, typename T0, typename T1, typename T2>
13767 
13768  #define synthesis_node_type_define(T0_,T1_,T2_,v_) \
13769  template <typename T, typename T0, typename T1, typename T2> \
13770  struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \
13771  template <typename T, typename T0, typename T1, typename T2> \
13772  const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \
13773 
13774  synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov)
13775  synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc)
13776  synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov)
13777  synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov)
13778  synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc)
13779  synthesis_node_type_define(const T0 , const T1 , const T2 , e_none )
13780  synthesis_node_type_define(const T0 , const T1 , const T2&, e_none )
13781  synthesis_node_type_define(const T0&, const T1 , const T2 , e_none )
13782  synthesis_node_type_define( T0&, T1&, T2&, e_none )
13783  #undef synthesis_node_type_define
13784 
13785  template <typename T, typename T0, typename T1, typename T2, typename T3>
13786  struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; };
13787  template <typename T, typename T0, typename T1, typename T2, typename T3>
13789 
13790  #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \
13791  template <typename T, typename T0, typename T1, typename T2, typename T3> \
13792  struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \
13793  template <typename T, typename T0, typename T1, typename T2, typename T3> \
13794  const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \
13795 
13796  synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov)
13797  synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc)
13798  synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov)
13799  synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov)
13800  synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov)
13801  synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov)
13802  synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc)
13803  synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc)
13804  synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov)
13805  synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none )
13806  synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none )
13807  synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none )
13808  synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none )
13809  synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none )
13810  synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none )
13811  synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none )
13812  #undef synthesis_node_type_define
13813 
13814  template <typename T, typename T0, typename T1>
13815  class T0oT1 : public expression_node<T>
13816  {
13817  public:
13818 
13820  typedef typename functor_t::bfunc_t bfunc_t;
13821  typedef T value_type;
13823 
13824  T0oT1(T0 p0, T1 p1, const bfunc_t p2)
13825  : t0_(p0),
13826  t1_(p1),
13827  f_ (p2)
13828  {}
13829 
13830  inline typename expression_node<T>::node_type type() const
13831  {
13832  static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result;
13833  return result;
13834  }
13835 
13836  inline operator_type operation() const
13837  {
13838  return e_default;
13839  }
13840 
13841  inline T value() const
13842  {
13843  return f_(t0_,t1_);
13844  }
13845 
13846  inline T0 t0() const
13847  {
13848  return t0_;
13849  }
13850 
13851  inline T1 t1() const
13852  {
13853  return t1_;
13854  }
13855 
13856  inline bfunc_t f() const
13857  {
13858  return f_;
13859  }
13860 
13861  template <typename Allocator>
13862  static inline expression_node<T>* allocate(Allocator& allocator,
13863  T0 p0, T1 p1,
13864  bfunc_t p2)
13865  {
13866  return allocator
13867  .template allocate_type<node_type, T0, T1, bfunc_t&>
13868  (p0, p1, p2);
13869  }
13870 
13871  private:
13872 
13874  T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); }
13875 
13878  const bfunc_t f_;
13879  };
13880 
13881  template <typename T, typename T0, typename T1, typename T2, typename ProcessMode>
13882  class T0oT1oT2 : public T0oT1oT2_base_node<T>
13883  {
13884  public:
13885 
13887  typedef typename functor_t::bfunc_t bfunc_t;
13888  typedef T value_type;
13890  typedef ProcessMode process_mode_t;
13891 
13892  T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4)
13893  : t0_(p0),
13894  t1_(p1),
13895  t2_(p2),
13896  f0_(p3),
13897  f1_(p4)
13898  {}
13899 
13900  inline typename expression_node<T>::node_type type() const
13901  {
13903  return result;
13904  }
13905 
13906  inline operator_type operation() const
13907  {
13908  return e_default;
13909  }
13910 
13911  inline T value() const
13912  {
13913  return ProcessMode::process(t0_, t1_, t2_, f0_, f1_);
13914  }
13915 
13916  inline T0 t0() const
13917  {
13918  return t0_;
13919  }
13920 
13921  inline T1 t1() const
13922  {
13923  return t1_;
13924  }
13925 
13926  inline T2 t2() const
13927  {
13928  return t2_;
13929  }
13930 
13931  bfunc_t f0() const
13932  {
13933  return f0_;
13934  }
13935 
13936  bfunc_t f1() const
13937  {
13938  return f1_;
13939  }
13940 
13942  {
13943  return id();
13944  }
13945 
13946  static inline std::string id()
13947  {
13948  return process_mode_t::template id<T0,T1,T2>();
13949  }
13950 
13951  template <typename Allocator>
13952  static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4)
13953  {
13954  return allocator
13955  .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t>
13956  (p0, p1, p2, p3, p4);
13957  }
13958 
13959  private:
13960 
13962  node_type& operator=(node_type&) { return (*this); }
13963 
13967  const bfunc_t f0_;
13968  const bfunc_t f1_;
13969  };
13970 
13971  template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode>
13973  {
13974  public:
13975 
13977  typedef typename functor_t::bfunc_t bfunc_t;
13978  typedef T value_type;
13979  typedef T0_ T0;
13980  typedef T1_ T1;
13981  typedef T2_ T2;
13982  typedef T3_ T3;
13984  typedef ProcessMode process_mode_t;
13985 
13986  T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6)
13987  : t0_(p0),
13988  t1_(p1),
13989  t2_(p2),
13990  t3_(p3),
13991  f0_(p4),
13992  f1_(p5),
13993  f2_(p6)
13994  {}
13995 
13996  inline T value() const
13997  {
13998  return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_);
13999  }
14000 
14001  inline T0 t0() const
14002  {
14003  return t0_;
14004  }
14005 
14006  inline T1 t1() const
14007  {
14008  return t1_;
14009  }
14010 
14011  inline T2 t2() const
14012  {
14013  return t2_;
14014  }
14015 
14016  inline T3 t3() const
14017  {
14018  return t3_;
14019  }
14020 
14021  inline bfunc_t f0() const
14022  {
14023  return f0_;
14024  }
14025 
14026  inline bfunc_t f1() const
14027  {
14028  return f1_;
14029  }
14030 
14031  inline bfunc_t f2() const
14032  {
14033  return f2_;
14034  }
14035 
14036  inline std::string type_id() const
14037  {
14038  return id();
14039  }
14040 
14041  static inline std::string id()
14042  {
14043  return process_mode_t::template id<T0, T1, T2, T3>();
14044  }
14045 
14046  template <typename Allocator>
14047  static inline expression_node<T>* allocate(Allocator& allocator,
14048  T0 p0, T1 p1, T2 p2, T3 p3,
14049  bfunc_t p4, bfunc_t p5, bfunc_t p6)
14050  {
14051  return allocator
14052  .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t>
14053  (p0, p1, p2, p3, p4, p5, p6);
14054  }
14055 
14056  private:
14057 
14059  node_type& operator=(node_type&) { return (*this); }
14060 
14065  const bfunc_t f0_;
14066  const bfunc_t f1_;
14067  const bfunc_t f2_;
14068  };
14069 
14070  template <typename T, typename T0, typename T1, typename T2>
14072  {
14073  public:
14074 
14076  typedef typename functor_t::tfunc_t tfunc_t;
14077  typedef T value_type;
14079 
14080  T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3)
14081  : t0_(p0),
14082  t1_(p1),
14083  t2_(p2),
14084  f_ (p3)
14085  {}
14086 
14087  inline typename expression_node<T>::node_type type() const
14088  {
14090  return result;
14091  }
14092 
14093  inline operator_type operation() const
14094  {
14095  return e_default;
14096  }
14097 
14098  inline T value() const
14099  {
14100  return f_(t0_, t1_, t2_);
14101  }
14102 
14103  inline T0 t0() const
14104  {
14105  return t0_;
14106  }
14107 
14108  inline T1 t1() const
14109  {
14110  return t1_;
14111  }
14112 
14113  inline T2 t2() const
14114  {
14115  return t2_;
14116  }
14117 
14118  tfunc_t f() const
14119  {
14120  return f_;
14121  }
14122 
14124  {
14125  return id();
14126  }
14127 
14128  static inline std::string id()
14129  {
14130  return "sf3";
14131  }
14132 
14133  template <typename Allocator>
14134  static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3)
14135  {
14136  return allocator
14137  .template allocate_type<node_type, T0, T1, T2, tfunc_t>
14138  (p0, p1, p2, p3);
14139  }
14140 
14141  private:
14142 
14144  node_type& operator=(node_type&) { return (*this); }
14145 
14149  const tfunc_t f_;
14150  };
14151 
14152  template <typename T, typename T0, typename T1, typename T2>
14154  {
14155  public:
14156 
14158  {}
14159 
14160  virtual T0 t0() const = 0;
14161 
14162  virtual T1 t1() const = 0;
14163 
14164  virtual T2 t2() const = 0;
14165  };
14166 
14167  template <typename T, typename T0, typename T1, typename T2, typename SF3Operation>
14168  class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2>
14169  {
14170  public:
14171 
14173  typedef typename functor_t::tfunc_t tfunc_t;
14174  typedef T value_type;
14176 
14177  T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2)
14178  : t0_(p0),
14179  t1_(p1),
14180  t2_(p2)
14181  {}
14182 
14183  inline typename expression_node<T>::node_type type() const
14184  {
14186  return result;
14187  }
14188 
14189  inline operator_type operation() const
14190  {
14191  return e_default;
14192  }
14193 
14194  inline T value() const
14195  {
14196  return SF3Operation::process(t0_, t1_, t2_);
14197  }
14198 
14199  T0 t0() const
14200  {
14201  return t0_;
14202  }
14203 
14204  T1 t1() const
14205  {
14206  return t1_;
14207  }
14208 
14209  T2 t2() const
14210  {
14211  return t2_;
14212  }
14213 
14215  {
14216  return id();
14217  }
14218 
14219  static inline std::string id()
14220  {
14221  return SF3Operation::id();
14222  }
14223 
14224  template <typename Allocator>
14225  static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2)
14226  {
14227  return allocator
14228  .template allocate_type<node_type, T0, T1, T2>
14229  (p0, p1, p2);
14230  }
14231 
14232  private:
14233 
14235  node_type& operator=(node_type&) { return (*this); }
14236 
14240  };
14241 
14242  template <typename T>
14243  inline bool is_sf3ext_node(const expression_node<T>* n)
14244  {
14245  switch (n->type())
14246  {
14247  case expression_node<T>::e_vovov : return true;
14248  case expression_node<T>::e_vovoc : return true;
14249  case expression_node<T>::e_vocov : return true;
14250  case expression_node<T>::e_covov : return true;
14251  case expression_node<T>::e_covoc : return true;
14252  default : return false;
14253  }
14254  }
14255 
14256  template <typename T, typename T0, typename T1, typename T2, typename T3>
14258  {
14259  public:
14260 
14262  typedef typename functor_t::qfunc_t qfunc_t;
14263  typedef T value_type;
14265 
14266  T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4)
14267  : t0_(p0),
14268  t1_(p1),
14269  t2_(p2),
14270  t3_(p3),
14271  f_ (p4)
14272  {}
14273 
14274  inline typename expression_node<T>::node_type type() const
14275  {
14277  return result;
14278  }
14279 
14280  inline operator_type operation() const
14281  {
14282  return e_default;
14283  }
14284 
14285  inline T value() const
14286  {
14287  return f_(t0_, t1_, t2_, t3_);
14288  }
14289 
14290  inline T0 t0() const
14291  {
14292  return t0_;
14293  }
14294 
14295  inline T1 t1() const
14296  {
14297  return t1_;
14298  }
14299 
14300  inline T2 t2() const
14301  {
14302  return t2_;
14303  }
14304 
14305  inline T3 t3() const
14306  {
14307  return t3_;
14308  }
14309 
14310  qfunc_t f() const
14311  {
14312  return f_;
14313  }
14314 
14316  {
14317  return id();
14318  }
14319 
14320  static inline std::string id()
14321  {
14322  return "sf4";
14323  }
14324 
14325  template <typename Allocator>
14326  static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4)
14327  {
14328  return allocator
14329  .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t>
14330  (p0, p1, p2, p3, p4);
14331  }
14332 
14333  private:
14334 
14336  node_type& operator=(node_type&) { return (*this); }
14337 
14342  const qfunc_t f_;
14343  };
14344 
14345  template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation>
14347  {
14348  public:
14349 
14351  typedef typename functor_t::tfunc_t tfunc_t;
14352  typedef T value_type;
14354 
14355  T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3)
14356  : t0_(p0),
14357  t1_(p1),
14358  t2_(p2),
14359  t3_(p3)
14360  {}
14361 
14362  inline typename expression_node<T>::node_type type() const
14363  {
14365  return result;
14366  }
14367 
14368  inline operator_type operation() const
14369  {
14370  return e_default;
14371  }
14372 
14373  inline T value() const
14374  {
14375  return SF4Operation::process(t0_, t1_, t2_, t3_);
14376  }
14377 
14378  inline T0 t0() const
14379  {
14380  return t0_;
14381  }
14382 
14383  inline T1 t1() const
14384  {
14385  return t1_;
14386  }
14387 
14388  inline T2 t2() const
14389  {
14390  return t2_;
14391  }
14392 
14393  inline T3 t3() const
14394  {
14395  return t2_;
14396  }
14397 
14399  {
14400  return id();
14401  }
14402 
14403  static inline std::string id()
14404  {
14405  return SF4Operation::id();
14406  }
14407 
14408  template <typename Allocator>
14409  static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3)
14410  {
14411  return allocator
14412  .template allocate_type<node_type, T0, T1, T2, T3>
14413  (p0, p1, p2, p3);
14414  }
14415 
14416  private:
14417 
14419  node_type& operator=(node_type&) { return (*this); }
14420 
14425  };
14426 
14427  template <typename T>
14428  inline bool is_sf4ext_node(const expression_node<T>* n)
14429  {
14430  switch (n->type())
14431  {
14432  case expression_node<T>::e_vovovov : return true;
14433  case expression_node<T>::e_vovovoc : return true;
14434  case expression_node<T>::e_vovocov : return true;
14435  case expression_node<T>::e_vocovov : return true;
14436  case expression_node<T>::e_covovov : return true;
14437  case expression_node<T>::e_covocov : return true;
14438  case expression_node<T>::e_vocovoc : return true;
14439  case expression_node<T>::e_covovoc : return true;
14440  case expression_node<T>::e_vococov : return true;
14441  default : return false;
14442  }
14443  }
14444 
14445  template <typename T, typename T0, typename T1>
14447  {
14449  };
14450 
14451  template <typename T, typename T0, typename T1, typename T2>
14453  {
14458  };
14459 
14460  template <typename T, typename T0, typename T1, typename T2, typename T3>
14462  {
14469  };
14470 
14471  template <typename T, typename Operation>
14472  class vov_node : public vov_base_node<T>
14473  {
14474  public:
14475 
14477  typedef Operation operation_t;
14478 
14479  // variable op variable node
14480  explicit vov_node(const T& var0, const T& var1)
14481  : v0_(var0),
14482  v1_(var1)
14483  {}
14484 
14485  inline T value() const
14486  {
14487  return Operation::process(v0_,v1_);
14488  }
14489 
14490  inline typename expression_node<T>::node_type type() const
14491  {
14492  return Operation::type();
14493  }
14494 
14495  inline operator_type operation() const
14496  {
14497  return Operation::operation();
14498  }
14499 
14500  inline const T& v0() const
14501  {
14502  return v0_;
14503  }
14504 
14505  inline const T& v1() const
14506  {
14507  return v1_;
14508  }
14509 
14510  protected:
14511 
14512  const T& v0_;
14513  const T& v1_;
14514 
14515  private:
14516 
14519  };
14520 
14521  template <typename T, typename Operation>
14522  class cov_node : public cov_base_node<T>
14523  {
14524  public:
14525 
14527  typedef Operation operation_t;
14528 
14529  // constant op variable node
14530  explicit cov_node(const T& const_var, const T& var)
14531  : c_(const_var),
14532  v_(var)
14533  {}
14534 
14535  inline T value() const
14536  {
14537  return Operation::process(c_,v_);
14538  }
14539 
14540  inline typename expression_node<T>::node_type type() const
14541  {
14542  return Operation::type();
14543  }
14544 
14545  inline operator_type operation() const
14546  {
14547  return Operation::operation();
14548  }
14549 
14550  inline const T c() const
14551  {
14552  return c_;
14553  }
14554 
14555  inline const T& v() const
14556  {
14557  return v_;
14558  }
14559 
14560  protected:
14561 
14562  const T c_;
14563  const T& v_;
14564 
14565  private:
14566 
14569  };
14570 
14571  template <typename T, typename Operation>
14572  class voc_node : public voc_base_node<T>
14573  {
14574  public:
14575 
14577  typedef Operation operation_t;
14578 
14579  // variable op constant node
14580  explicit voc_node(const T& var, const T& const_var)
14581  : v_(var),
14582  c_(const_var)
14583  {}
14584 
14585  inline T value() const
14586  {
14587  return Operation::process(v_,c_);
14588  }
14589 
14590  inline operator_type operation() const
14591  {
14592  return Operation::operation();
14593  }
14594 
14595  inline const T c() const
14596  {
14597  return c_;
14598  }
14599 
14600  inline const T& v() const
14601  {
14602  return v_;
14603  }
14604 
14605  protected:
14606 
14607  const T& v_;
14608  const T c_;
14609 
14610  private:
14611 
14614  };
14615 
14616  template <typename T, typename Operation>
14617  class vob_node : public vob_base_node<T>
14618  {
14619  public:
14620 
14622  typedef std::pair<expression_ptr,bool> branch_t;
14623  typedef Operation operation_t;
14624 
14625  // variable op constant node
14626  explicit vob_node(const T& var, const expression_ptr brnch)
14627  : v_(var)
14628  {
14629  init_branches<1>(branch_,brnch);
14630  }
14631 
14633  {
14634  cleanup_branches::execute<T,1>(branch_);
14635  }
14636 
14637  inline T value() const
14638  {
14639  return Operation::process(v_,branch_[0].first->value());
14640  }
14641 
14642  inline operator_type operation() const
14643  {
14644  return Operation::operation();
14645  }
14646 
14647  inline const T& v() const
14648  {
14649  return v_;
14650  }
14651 
14652  inline expression_node<T>* branch(const std::size_t&) const
14653  {
14654  return branch_[0].first;
14655  }
14656 
14657  private:
14658 
14661 
14662  const T& v_;
14664  };
14665 
14666  template <typename T, typename Operation>
14667  class bov_node : public bov_base_node<T>
14668  {
14669  public:
14670 
14672  typedef std::pair<expression_ptr,bool> branch_t;
14673  typedef Operation operation_t;
14674 
14675  // variable op constant node
14676  explicit bov_node(const expression_ptr brnch, const T& var)
14677  : v_(var)
14678  {
14679  init_branches<1>(branch_,brnch);
14680  }
14681 
14683  {
14684  cleanup_branches::execute<T,1>(branch_);
14685  }
14686 
14687  inline T value() const
14688  {
14689  return Operation::process(branch_[0].first->value(),v_);
14690  }
14691 
14692  inline operator_type operation() const
14693  {
14694  return Operation::operation();
14695  }
14696 
14697  inline const T& v() const
14698  {
14699  return v_;
14700  }
14701 
14702  inline expression_node<T>* branch(const std::size_t&) const
14703  {
14704  return branch_[0].first;
14705  }
14706 
14707  private:
14708 
14711 
14712  const T& v_;
14714  };
14715 
14716  template <typename T, typename Operation>
14717  class cob_node : public cob_base_node<T>
14718  {
14719  public:
14720 
14722  typedef std::pair<expression_ptr,bool> branch_t;
14723  typedef Operation operation_t;
14724 
14725  // variable op constant node
14726  explicit cob_node(const T const_var, const expression_ptr brnch)
14727  : c_(const_var)
14728  {
14729  init_branches<1>(branch_,brnch);
14730  }
14731 
14733  {
14734  cleanup_branches::execute<T,1>(branch_);
14735  }
14736 
14737  inline T value() const
14738  {
14739  return Operation::process(c_,branch_[0].first->value());
14740  }
14741 
14742  inline operator_type operation() const
14743  {
14744  return Operation::operation();
14745  }
14746 
14747  inline const T c() const
14748  {
14749  return c_;
14750  }
14751 
14752  inline void set_c(const T new_c)
14753  {
14754  (*const_cast<T*>(&c_)) = new_c;
14755  }
14756 
14757  inline expression_node<T>* branch(const std::size_t&) const
14758  {
14759  return branch_[0].first;
14760  }
14761 
14762  inline expression_node<T>* move_branch(const std::size_t&)
14763  {
14764  branch_[0].second = false;
14765  return branch_[0].first;
14766  }
14767 
14768  private:
14769 
14772 
14773  const T c_;
14775  };
14776 
14777  template <typename T, typename Operation>
14778  class boc_node : public boc_base_node<T>
14779  {
14780  public:
14781 
14783  typedef std::pair<expression_ptr,bool> branch_t;
14784  typedef Operation operation_t;
14785 
14786  // variable op constant node
14787  explicit boc_node(const expression_ptr brnch, const T const_var)
14788  : c_(const_var)
14789  {
14790  init_branches<1>(branch_,brnch);
14791  }
14792 
14794  {
14795  cleanup_branches::execute<T,1>(branch_);
14796  }
14797 
14798  inline T value() const
14799  {
14800  return Operation::process(branch_[0].first->value(),c_);
14801  }
14802 
14803  inline operator_type operation() const
14804  {
14805  return Operation::operation();
14806  }
14807 
14808  inline const T c() const
14809  {
14810  return c_;
14811  }
14812 
14813  inline void set_c(const T new_c)
14814  {
14815  (*const_cast<T*>(&c_)) = new_c;
14816  }
14817 
14818  inline expression_node<T>* branch(const std::size_t&) const
14819  {
14820  return branch_[0].first;
14821  }
14822 
14823  inline expression_node<T>* move_branch(const std::size_t&)
14824  {
14825  branch_[0].second = false;
14826  return branch_[0].first;
14827  }
14828 
14829  private:
14830 
14833 
14834  const T c_;
14836  };
14837 
14838  #ifndef exprtk_disable_string_capabilities
14839  template <typename T, typename SType0, typename SType1, typename Operation>
14840  class sos_node : public sos_base_node<T>
14841  {
14842  public:
14843 
14845  typedef Operation operation_t;
14846 
14847  // string op string node
14848  explicit sos_node(SType0 p0, SType1 p1)
14849  : s0_(p0),
14850  s1_(p1)
14851  {}
14852 
14853  inline T value() const
14854  {
14855  return Operation::process(s0_,s1_);
14856  }
14857 
14858  inline typename expression_node<T>::node_type type() const
14859  {
14860  return Operation::type();
14861  }
14862 
14863  inline operator_type operation() const
14864  {
14865  return Operation::operation();
14866  }
14867 
14868  inline std::string& s0()
14869  {
14870  return s0_;
14871  }
14872 
14873  inline std::string& s1()
14874  {
14875  return s1_;
14876  }
14877 
14878  protected:
14879 
14880  SType0 s0_;
14881  SType1 s1_;
14882 
14883  private:
14884 
14887  };
14888 
14889  template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14890  class str_xrox_node : public sos_base_node<T>
14891  {
14892  public:
14893 
14895  typedef Operation operation_t;
14896 
14897  // string-range op string node
14898  explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0)
14899  : s0_ (p0 ),
14900  s1_ (p1 ),
14901  rp0_(rp0)
14902  {}
14903 
14905  {
14906  rp0_.free();
14907  }
14908 
14909  inline T value() const
14910  {
14911  std::size_t r0 = 0;
14912  std::size_t r1 = 0;
14913 
14914  if (rp0_(r0, r1, s0_.size()))
14915  return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_);
14916  else
14917  return T(0);
14918  }
14919 
14920  inline typename expression_node<T>::node_type type() const
14921  {
14922  return Operation::type();
14923  }
14924 
14925  inline operator_type operation() const
14926  {
14927  return Operation::operation();
14928  }
14929 
14930  inline std::string& s0()
14931  {
14932  return s0_;
14933  }
14934 
14935  inline std::string& s1()
14936  {
14937  return s1_;
14938  }
14939 
14940  protected:
14941 
14942  SType0 s0_;
14943  SType1 s1_;
14944  RangePack rp0_;
14945 
14946  private:
14947 
14950  };
14951 
14952  template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
14953  class str_xoxr_node : public sos_base_node<T>
14954  {
14955  public:
14956 
14958  typedef Operation operation_t;
14959 
14960  // string op string range node
14961  explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1)
14962  : s0_ (p0 ),
14963  s1_ (p1 ),
14964  rp1_(rp1)
14965  {}
14966 
14968  {
14969  rp1_.free();
14970  }
14971 
14972  inline T value() const
14973  {
14974  std::size_t r0 = 0;
14975  std::size_t r1 = 0;
14976 
14977  if (rp1_(r0, r1, s1_.size()))
14978  return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1));
14979  else
14980  return T(0);
14981  }
14982 
14983  inline typename expression_node<T>::node_type type() const
14984  {
14985  return Operation::type();
14986  }
14987 
14988  inline operator_type operation() const
14989  {
14990  return Operation::operation();
14991  }
14992 
14993  inline std::string& s0()
14994  {
14995  return s0_;
14996  }
14997 
14998  inline std::string& s1()
14999  {
15000  return s1_;
15001  }
15002 
15003  protected:
15004 
15005  SType0 s0_;
15006  SType1 s1_;
15007  RangePack rp1_;
15008 
15009  private:
15010 
15013  };
15014 
15015  template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation>
15016  class str_xroxr_node : public sos_base_node<T>
15017  {
15018  public:
15019 
15021  typedef Operation operation_t;
15022 
15023  // string-range op string-range node
15024  explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1)
15025  : s0_ (p0 ),
15026  s1_ (p1 ),
15027  rp0_(rp0),
15028  rp1_(rp1)
15029  {}
15030 
15032  {
15033  rp0_.free();
15034  rp1_.free();
15035  }
15036 
15037  inline T value() const
15038  {
15039  std::size_t r0_0 = 0;
15040  std::size_t r0_1 = 0;
15041  std::size_t r1_0 = 0;
15042  std::size_t r1_1 = 0;
15043 
15044  if (
15045  rp0_(r0_0, r1_0, s0_.size()) &&
15046  rp1_(r0_1, r1_1, s1_.size())
15047  )
15048  {
15049  return Operation::process(
15050  s0_.substr(r0_0, (r1_0 - r0_0) + 1),
15051  s1_.substr(r0_1, (r1_1 - r0_1) + 1)
15052  );
15053  }
15054  else
15055  return T(0);
15056  }
15057 
15058  inline typename expression_node<T>::node_type type() const
15059  {
15060  return Operation::type();
15061  }
15062 
15063  inline operator_type operation() const
15064  {
15065  return Operation::operation();
15066  }
15067 
15068  inline std::string& s0()
15069  {
15070  return s0_;
15071  }
15072 
15073  inline std::string& s1()
15074  {
15075  return s1_;
15076  }
15077 
15078  protected:
15079 
15080  SType0 s0_;
15081  SType1 s1_;
15082  RangePack rp0_;
15083  RangePack rp1_;
15084 
15085  private:
15086 
15089  };
15090 
15091  template <typename T, typename Operation>
15092  class str_sogens_node : public binary_node<T>
15093  {
15094  public:
15095 
15099  typedef range_t* range_ptr;
15102 
15104  expression_ptr branch0,
15105  expression_ptr branch1)
15106  : binary_node<T>(opr, branch0, branch1),
15107  str0_base_ptr_ (0),
15108  str1_base_ptr_ (0),
15109  str0_range_ptr_(0),
15110  str1_range_ptr_(0)
15111  {
15113  {
15114  str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first);
15115 
15116  if (0 == str0_base_ptr_)
15117  return;
15118 
15119  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first);
15120 
15121  if (0 == range)
15122  return;
15123 
15124  str0_range_ptr_ = &(range->range_ref());
15125  }
15126 
15128  {
15129  str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first);
15130 
15131  if (0 == str1_base_ptr_)
15132  return;
15133 
15134  irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first);
15135 
15136  if (0 == range)
15137  return;
15138 
15139  str1_range_ptr_ = &(range->range_ref());
15140  }
15141  }
15142 
15143  inline T value() const
15144  {
15145  if (
15146  str0_base_ptr_ &&
15147  str1_base_ptr_ &&
15148  str0_range_ptr_ &&
15150  )
15151  {
15152  binary_node<T>::branch_[0].first->value();
15153  binary_node<T>::branch_[1].first->value();
15154 
15155  std::size_t str0_r0 = 0;
15156  std::size_t str0_r1 = 0;
15157 
15158  std::size_t str1_r0 = 0;
15159  std::size_t str1_r1 = 0;
15160 
15161  range_t& range0 = (*str0_range_ptr_);
15162  range_t& range1 = (*str1_range_ptr_);
15163 
15164  if (
15165  range0(str0_r0, str0_r1, str0_base_ptr_->size()) &&
15166  range1(str1_r0, str1_r1, str1_base_ptr_->size())
15167  )
15168  {
15169  return Operation::process(
15170  str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1),
15171  str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1)
15172  );
15173  }
15174  }
15175 
15176  return std::numeric_limits<T>::quiet_NaN();
15177  }
15178 
15179  inline typename expression_node<T>::node_type type() const
15180  {
15181  return Operation::type();
15182  }
15183 
15184  inline operator_type operation() const
15185  {
15186  return Operation::operation();
15187  }
15188 
15189  private:
15190 
15193 
15198  };
15199 
15200  template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
15201  class sosos_node : public sosos_base_node<T>
15202  {
15203  public:
15204 
15206  typedef Operation operation_t;
15207 
15208  // variable op variable node
15209  explicit sosos_node(SType0 p0, SType1 p1, SType2 p2)
15210  : s0_(p0),
15211  s1_(p1),
15212  s2_(p2)
15213  {}
15214 
15215  inline T value() const
15216  {
15217  return Operation::process(s0_,s1_,s2_);
15218  }
15219 
15220  inline typename expression_node<T>::node_type type() const
15221  {
15222  return Operation::type();
15223  }
15224 
15225  inline operator_type operation() const
15226  {
15227  return Operation::operation();
15228  }
15229 
15230  inline std::string& s0()
15231  {
15232  return s0_;
15233  }
15234 
15235  inline std::string& s1()
15236  {
15237  return s1_;
15238  }
15239 
15240  inline std::string& s2()
15241  {
15242  return s2_;
15243  }
15244 
15245  protected:
15246 
15247  SType0 s0_;
15248  SType1 s1_;
15249  SType2 s2_;
15250 
15251  private:
15252 
15255  };
15256  #endif
15257 
15258  template <typename T, typename PowOp>
15259  class ipow_node : public expression_node<T>
15260  {
15261  public:
15262 
15264  typedef PowOp operation_t;
15265 
15266  explicit ipow_node(const T& v)
15267  : v_(v)
15268  {}
15269 
15270  inline T value() const
15271  {
15272  return PowOp::result(v_);
15273  }
15274 
15275  inline typename expression_node<T>::node_type type() const
15276  {
15278  }
15279 
15280  private:
15281 
15282  ipow_node(const ipow_node<T,PowOp>&);
15284 
15285  const T& v_;
15286  };
15287 
15288  template <typename T, typename PowOp>
15289  class bipow_node : public expression_node<T>
15290  {
15291  public:
15292 
15294  typedef std::pair<expression_ptr, bool> branch_t;
15295  typedef PowOp operation_t;
15296 
15297  explicit bipow_node(expression_ptr brnch)
15298  {
15299  init_branches<1>(branch_, brnch);
15300  }
15301 
15303  {
15304  cleanup_branches::execute<T,1>(branch_);
15305  }
15306 
15307  inline T value() const
15308  {
15309  return PowOp::result(branch_[0].first->value());
15310  }
15311 
15312  inline typename expression_node<T>::node_type type() const
15313  {
15315  }
15316 
15317  private:
15318 
15321 
15323  };
15324 
15325  template <typename T, typename PowOp>
15326  class ipowinv_node : public expression_node<T>
15327  {
15328  public:
15329 
15331  typedef PowOp operation_t;
15332 
15333  explicit ipowinv_node(const T& v)
15334  : v_(v)
15335  {}
15336 
15337  inline T value() const
15338  {
15339  return (T(1) / PowOp::result(v_));
15340  }
15341 
15342  inline typename expression_node<T>::node_type type() const
15343  {
15345  }
15346 
15347  private:
15348 
15351 
15352  const T& v_;
15353  };
15354 
15355  template <typename T, typename PowOp>
15357  {
15358  public:
15359 
15361  typedef std::pair<expression_ptr, bool> branch_t;
15362  typedef PowOp operation_t;
15363 
15365  {
15366  init_branches<1>(branch_, brnch);
15367  }
15368 
15370  {
15371  cleanup_branches::execute<T,1>(branch_);
15372  }
15373 
15374  inline T value() const
15375  {
15376  return (T(1) / PowOp::result(branch_[0].first->value()));
15377  }
15378 
15379  inline typename expression_node<T>::node_type type() const
15380  {
15382  }
15383 
15384  private:
15385 
15388 
15390  };
15391 
15392  template <typename T>
15393  inline bool is_vov_node(const expression_node<T>* node)
15394  {
15395  return (0 != dynamic_cast<const vov_base_node<T>*>(node));
15396  }
15397 
15398  template <typename T>
15399  inline bool is_cov_node(const expression_node<T>* node)
15400  {
15401  return (0 != dynamic_cast<const cov_base_node<T>*>(node));
15402  }
15403 
15404  template <typename T>
15405  inline bool is_voc_node(const expression_node<T>* node)
15406  {
15407  return (0 != dynamic_cast<const voc_base_node<T>*>(node));
15408  }
15409 
15410  template <typename T>
15411  inline bool is_cob_node(const expression_node<T>* node)
15412  {
15413  return (0 != dynamic_cast<const cob_base_node<T>*>(node));
15414  }
15415 
15416  template <typename T>
15417  inline bool is_boc_node(const expression_node<T>* node)
15418  {
15419  return (0 != dynamic_cast<const boc_base_node<T>*>(node));
15420  }
15421 
15422  template <typename T>
15423  inline bool is_t0ot1ot2_node(const expression_node<T>* node)
15424  {
15425  return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node));
15426  }
15427 
15428  template <typename T>
15429  inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node)
15430  {
15431  return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node));
15432  }
15433 
15434  template <typename T>
15435  inline bool is_uv_node(const expression_node<T>* node)
15436  {
15437  return (0 != dynamic_cast<const uv_base_node<T>*>(node));
15438  }
15439 
15440  template <typename T>
15441  inline bool is_string_node(const expression_node<T>* node)
15442  {
15443  return node && (expression_node<T>::e_stringvar == node->type());
15444  }
15445 
15446  template <typename T>
15447  inline bool is_string_range_node(const expression_node<T>* node)
15448  {
15449  return node && (expression_node<T>::e_stringvarrng == node->type());
15450  }
15451 
15452  template <typename T>
15453  inline bool is_const_string_node(const expression_node<T>* node)
15454  {
15455  return node && (expression_node<T>::e_stringconst == node->type());
15456  }
15457 
15458  template <typename T>
15460  {
15461  return node && (expression_node<T>::e_cstringvarrng == node->type());
15462  }
15463 
15464  template <typename T>
15466  {
15467  return node && (expression_node<T>::e_strass == node->type());
15468  }
15469 
15470  template <typename T>
15472  {
15473  return node && (expression_node<T>::e_strconcat == node->type());
15474  }
15475 
15476  template <typename T>
15478  {
15479  return node && (expression_node<T>::e_strfunction == node->type());
15480  }
15481 
15482  template <typename T>
15484  {
15485  return node && (expression_node<T>::e_strcondition == node->type());
15486  }
15487 
15488  template <typename T>
15490  {
15491  return node && (expression_node<T>::e_strccondition == node->type());
15492  }
15493 
15494  template <typename T>
15496  {
15497  return node && (expression_node<T>::e_stringvararg == node->type());
15498  }
15499 
15500  template <typename T>
15502  {
15503  return node && (expression_node<T>::e_strgenrange == node->type());
15504  }
15505 
15506  template <typename T>
15508  {
15509  if (node)
15510  {
15511  switch (node->type())
15512  {
15523  case expression_node<T>::e_stringvararg : return true;
15524  default : return false;
15525  }
15526  }
15527 
15528  return false;
15529  }
15530 
15532  {
15533  public:
15534 
15535  template <typename ResultNode, typename OpType, typename ExprNode>
15536  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
15537  {
15538  return allocate<ResultNode>(operation, branch[0]);
15539  }
15540 
15541  template <typename ResultNode, typename OpType, typename ExprNode>
15542  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
15543  {
15544  return allocate<ResultNode>(operation, branch[0], branch[1]);
15545  }
15546 
15547  template <typename ResultNode, typename OpType, typename ExprNode>
15548  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
15549  {
15550  return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]);
15551  }
15552 
15553  template <typename ResultNode, typename OpType, typename ExprNode>
15554  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
15555  {
15556  return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]);
15557  }
15558 
15559  template <typename ResultNode, typename OpType, typename ExprNode>
15560  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
15561  {
15562  return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]);
15563  }
15564 
15565  template <typename ResultNode, typename OpType, typename ExprNode>
15566  inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
15567  {
15568  return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]);
15569  }
15570 
15571  template <typename node_type>
15573  {
15574  return (new node_type());
15575  }
15576 
15577  template <typename node_type,
15578  typename Type,
15579  typename Allocator,
15580  template <typename, typename> class Sequence>
15581  inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const
15582  {
15583  return (new node_type(seq));
15584  }
15585 
15586  template <typename node_type, typename T1>
15588  {
15589  return (new node_type(t1));
15590  }
15591 
15592  template <typename node_type, typename T1>
15594  {
15595  return (new node_type(t1));
15596  }
15597 
15598  template <typename node_type,
15599  typename T1, typename T2>
15601  {
15602  return (new node_type(t1, t2));
15603  }
15604 
15605  template <typename node_type,
15606  typename T1, typename T2>
15608  {
15609  return (new node_type(t1, t2));
15610  }
15611 
15612  template <typename node_type,
15613  typename T1, typename T2>
15615  {
15616  return (new node_type(t1, t2));
15617  }
15618 
15619  template <typename node_type,
15620  typename T1, typename T2>
15622  {
15623  return (new node_type(t1, t2));
15624  }
15625 
15626  template <typename node_type,
15627  typename T1, typename T2>
15629  {
15630  return (new node_type(t1, t2));
15631  }
15632 
15633  template <typename node_type,
15634  typename T1, typename T2, typename T3>
15636  {
15637  return (new node_type(t1, t2, t3));
15638  }
15639 
15640  template <typename node_type,
15641  typename T1, typename T2, typename T3, typename T4>
15643  {
15644  return (new node_type(t1, t2, t3, t4));
15645  }
15646 
15647  template <typename node_type,
15648  typename T1, typename T2, typename T3>
15650  {
15651  return (new node_type(t1, t2, t3));
15652  }
15653 
15654  template <typename node_type,
15655  typename T1, typename T2, typename T3, typename T4>
15657  {
15658  return (new node_type(t1, t2, t3, t4));
15659  }
15660 
15661  template <typename node_type,
15662  typename T1, typename T2, typename T3, typename T4, typename T5>
15663  inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const
15664  {
15665  return (new node_type(t1, t2, t3, t4, t5));
15666  }
15667 
15668  template <typename node_type,
15669  typename T1, typename T2, typename T3>
15671  const T3& t3) const
15672  {
15673  return (new node_type(t1, t2, t3));
15674  }
15675 
15676  template <typename node_type,
15677  typename T1, typename T2,
15678  typename T3, typename T4>
15680  const T3& t3, const T4& t4) const
15681  {
15682  return (new node_type(t1, t2, t3, t4));
15683  }
15684 
15685  template <typename node_type,
15686  typename T1, typename T2,
15687  typename T3, typename T4, typename T5>
15689  const T3& t3, const T4& t4,
15690  const T5& t5) const
15691  {
15692  return (new node_type(t1, t2, t3, t4, t5));
15693  }
15694 
15695  template <typename node_type,
15696  typename T1, typename T2,
15697  typename T3, typename T4, typename T5, typename T6>
15699  const T3& t3, const T4& t4,
15700  const T5& t5, const T6& t6) const
15701  {
15702  return (new node_type(t1, t2, t3, t4, t5, t6));
15703  }
15704 
15705  template <typename node_type,
15706  typename T1, typename T2,
15707  typename T3, typename T4,
15708  typename T5, typename T6, typename T7>
15710  const T3& t3, const T4& t4,
15711  const T5& t5, const T6& t6,
15712  const T7& t7) const
15713  {
15714  return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15715  }
15716 
15717  template <typename node_type,
15718  typename T1, typename T2,
15719  typename T3, typename T4,
15720  typename T5, typename T6,
15721  typename T7, typename T8>
15723  const T3& t3, const T4& t4,
15724  const T5& t5, const T6& t6,
15725  const T7& t7, const T8& t8) const
15726  {
15727  return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8));
15728  }
15729 
15730  template <typename node_type,
15731  typename T1, typename T2,
15732  typename T3, typename T4,
15733  typename T5, typename T6,
15734  typename T7, typename T8, typename T9>
15736  const T3& t3, const T4& t4,
15737  const T5& t5, const T6& t6,
15738  const T7& t7, const T8& t8,
15739  const T9& t9) const
15740  {
15741  return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9));
15742  }
15743 
15744  template <typename node_type,
15745  typename T1, typename T2,
15746  typename T3, typename T4,
15747  typename T5, typename T6,
15748  typename T7, typename T8,
15749  typename T9, typename T10>
15751  const T3& t3, const T4& t4,
15752  const T5& t5, const T6& t6,
15753  const T7& t7, const T8& t8,
15754  const T9& t9, const T10& t10) const
15755  {
15756  return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10));
15757  }
15758 
15759  template <typename node_type,
15760  typename T1, typename T2, typename T3>
15762  {
15763  return (new node_type(t1, t2, t3));
15764  }
15765 
15766  template <typename node_type,
15767  typename T1, typename T2,
15768  typename T3, typename T4>
15770  T3 t3, T4 t4) const
15771  {
15772  return (new node_type(t1, t2, t3, t4));
15773  }
15774 
15775  template <typename node_type,
15776  typename T1, typename T2,
15777  typename T3, typename T4,
15778  typename T5>
15780  T3 t3, T4 t4,
15781  T5 t5) const
15782  {
15783  return (new node_type(t1, t2, t3, t4, t5));
15784  }
15785 
15786  template <typename node_type,
15787  typename T1, typename T2,
15788  typename T3, typename T4,
15789  typename T5, typename T6>
15791  T3 t3, T4 t4,
15792  T5 t5, T6 t6) const
15793  {
15794  return (new node_type(t1, t2, t3, t4, t5, t6));
15795  }
15796 
15797  template <typename node_type,
15798  typename T1, typename T2,
15799  typename T3, typename T4,
15800  typename T5, typename T6, typename T7>
15802  T3 t3, T4 t4,
15803  T5 t5, T6 t6,
15804  T7 t7) const
15805  {
15806  return (new node_type(t1, t2, t3, t4, t5, t6, t7));
15807  }
15808 
15809  template <typename T>
15810  void inline free(expression_node<T>*& e) const
15811  {
15812  delete e;
15813  e = 0;
15814  }
15815  };
15816 
15817  inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m)
15818  {
15819  #define register_op(Symbol,Type,Args) \
15820  m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \
15821 
15822  register_op( "abs", e_abs , 1)
15823  register_op( "acos", e_acos , 1)
15824  register_op( "acosh", e_acosh , 1)
15825  register_op( "asin", e_asin , 1)
15826  register_op( "asinh", e_asinh , 1)
15827  register_op( "atan", e_atan , 1)
15828  register_op( "atanh", e_atanh , 1)
15829  register_op( "ceil", e_ceil , 1)
15830  register_op( "cos", e_cos , 1)
15831  register_op( "cosh", e_cosh , 1)
15832  register_op( "exp", e_exp , 1)
15833  register_op( "expm1", e_expm1 , 1)
15834  register_op( "floor", e_floor , 1)
15835  register_op( "log", e_log , 1)
15836  register_op( "log10", e_log10 , 1)
15837  register_op( "log2", e_log2 , 1)
15838  register_op( "log1p", e_log1p , 1)
15839  register_op( "round", e_round , 1)
15840  register_op( "sin", e_sin , 1)
15841  register_op( "sinc", e_sinc , 1)
15842  register_op( "sinh", e_sinh , 1)
15843  register_op( "sec", e_sec , 1)
15844  register_op( "csc", e_csc , 1)
15845  register_op( "sqrt", e_sqrt , 1)
15846  register_op( "tan", e_tan , 1)
15847  register_op( "tanh", e_tanh , 1)
15848  register_op( "cot", e_cot , 1)
15849  register_op( "rad2deg", e_r2d , 1)
15850  register_op( "deg2rad", e_d2r , 1)
15851  register_op( "deg2grad", e_d2g , 1)
15852  register_op( "grad2deg", e_g2d , 1)
15853  register_op( "sgn", e_sgn , 1)
15854  register_op( "not", e_notl , 1)
15855  register_op( "erf", e_erf , 1)
15856  register_op( "erfc", e_erfc , 1)
15857  register_op( "ncdf", e_ncdf , 1)
15858  register_op( "frac", e_frac , 1)
15859  register_op( "trunc", e_trunc , 1)
15860  register_op( "atan2", e_atan2 , 2)
15861  register_op( "mod", e_mod , 2)
15862  register_op( "logn", e_logn , 2)
15863  register_op( "pow", e_pow , 2)
15864  register_op( "root", e_root , 2)
15865  register_op( "roundn", e_roundn , 2)
15866  register_op( "equal", e_equal , 2)
15867  register_op("not_equal", e_nequal , 2)
15868  register_op( "hypot", e_hypot , 2)
15869  register_op( "shr", e_shr , 2)
15870  register_op( "shl", e_shl , 2)
15871  register_op( "clamp", e_clamp , 3)
15872  register_op( "iclamp", e_iclamp , 3)
15873  register_op( "inrange", e_inrange , 3)
15874  #undef register_op
15875  }
15876 
15877  } // namespace details
15878 
15880  {
15881  public:
15882 
15884  : allow_zero_parameters_(false),
15885  has_side_effects_(true),
15886  min_num_args_(0),
15887  max_num_args_(std::numeric_limits<std::size_t>::max())
15888  {}
15889 
15890  inline bool& allow_zero_parameters()
15891  {
15892  return allow_zero_parameters_;
15893  }
15894 
15895  inline bool& has_side_effects()
15896  {
15897  return has_side_effects_;
15898  }
15899 
15900  std::size_t& min_num_args()
15901  {
15902  return min_num_args_;
15903  }
15904 
15905  std::size_t& max_num_args()
15906  {
15907  return max_num_args_;
15908  }
15909 
15910  private:
15911 
15914  std::size_t min_num_args_;
15915  std::size_t max_num_args_;
15916  };
15917 
15918  template <typename FunctionType>
15919  void enable_zero_parameters(FunctionType& func)
15920  {
15921  func.allow_zero_parameters() = true;
15922 
15923  if (0 != func.min_num_args())
15924  {
15925  func.min_num_args() = 0;
15926  }
15927  }
15928 
15929  template <typename FunctionType>
15930  void disable_zero_parameters(FunctionType& func)
15931  {
15932  func.allow_zero_parameters() = false;
15933  }
15934 
15935  template <typename FunctionType>
15936  void enable_has_side_effects(FunctionType& func)
15937  {
15938  func.has_side_effects() = true;
15939  }
15940 
15941  template <typename FunctionType>
15942  void disable_has_side_effects(FunctionType& func)
15943  {
15944  func.has_side_effects() = false;
15945  }
15946 
15947  template <typename FunctionType>
15948  void set_min_num_args(FunctionType& func, const std::size_t& num_args)
15949  {
15950  func.min_num_args() = num_args;
15951 
15952  if ((0 != func.min_num_args()) && func.allow_zero_parameters())
15953  func.allow_zero_parameters() = false;
15954  }
15955 
15956  template <typename FunctionType>
15957  void set_max_num_args(FunctionType& func, const std::size_t& num_args)
15958  {
15959  func.max_num_args() = num_args;
15960  }
15961 
15962  template <typename T>
15964  {
15965  public:
15966 
15967  explicit ifunction(const std::size_t& pc)
15968  : param_count(pc)
15969  {}
15970 
15971  virtual ~ifunction()
15972  {}
15973 
15974  #define empty_method_body \
15975  { \
15976  return std::numeric_limits<T>::quiet_NaN(); \
15977  } \
15978 
15979  inline virtual T operator() ()
15981 
15982  inline virtual T operator() (const T&)
15984 
15985  inline virtual T operator() (const T&,const T&)
15987 
15988  inline virtual T operator() (const T&, const T&, const T&)
15990 
15991  inline virtual T operator() (const T&, const T&, const T&, const T&)
15993 
15994  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&)
15996 
15997  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&)
15999 
16000  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16002 
16003  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16005 
16006  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16008 
16009  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
16011 
16012  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16013  const T&)
16015 
16016  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16017  const T&, const T&)
16019 
16020  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16021  const T&, const T&, const T&)
16023 
16024  inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&,
16025  const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
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&, const T&, const T&, const T&, const T&)
16051 
16052  #undef empty_method_body
16053 
16054  std::size_t param_count;
16055  };
16056 
16057  template <typename T>
16059  {
16060  public:
16061 
16063  {}
16064 
16065  inline virtual T operator() (const std::vector<T>&)
16066  {
16067  exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n"));
16068  return std::numeric_limits<T>::quiet_NaN();
16069  }
16070  };
16071 
16072  template <typename T>
16074  {
16075  public:
16076 
16078  {
16082  };
16083 
16084  typedef T type;
16087 
16088  igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar)
16089  : parameter_sequence(param_seq),
16090  rtrn_type(rtr_type)
16091  {}
16092 
16094  {}
16095 
16096  #define igeneric_function_empty_body(N) \
16097  { \
16098  exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \
16099  return std::numeric_limits<T>::quiet_NaN(); \
16100  } \
16101 
16102  // f(i_0,i_1,....,i_N) --> Scalar
16103  inline virtual T operator() (parameter_list_t)
16105 
16106  // f(i_0,i_1,....,i_N) --> String
16107  inline virtual T operator() (std::string&, parameter_list_t)
16109 
16110  // f(psi,i_0,i_1,....,i_N) --> Scalar
16111  inline virtual T operator() (const std::size_t&, parameter_list_t)
16113 
16114  // f(psi,i_0,i_1,....,i_N) --> String
16115  inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t)
16117 
16118  std::string parameter_sequence;
16120  };
16121 
16122  template <typename T> class parser;
16123  template <typename T> class expression_helper;
16124 
16125  template <typename T>
16127  {
16128  public:
16129 
16130  typedef T (*ff00_functor)();
16131  typedef T (*ff01_functor)(T);
16132  typedef T (*ff02_functor)(T, T);
16133  typedef T (*ff03_functor)(T, T, T);
16134  typedef T (*ff04_functor)(T, T, T, T);
16135  typedef T (*ff05_functor)(T, T, T, T, T);
16136  typedef T (*ff06_functor)(T, T, T, T, T, T);
16137  typedef T (*ff07_functor)(T, T, T, T, T, T, T);
16138  typedef T (*ff08_functor)(T, T, T, T, T, T, T, T);
16139  typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T);
16140  typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T);
16141  typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T);
16142  typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T);
16143  typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T);
16144  typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16145  typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T);
16146 
16147  protected:
16148 
16149  struct freefunc00 : public exprtk::ifunction<T>
16150  {
16152 
16153  explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {}
16154  inline T operator() ()
16155  { return f(); }
16156  ff00_functor f;
16157  };
16158 
16159  struct freefunc01 : public exprtk::ifunction<T>
16160  {
16162 
16163  explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {}
16164  inline T operator() (const T& v0)
16165  { return f(v0); }
16166  ff01_functor f;
16167  };
16168 
16169  struct freefunc02 : public exprtk::ifunction<T>
16170  {
16172 
16173  explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {}
16174  inline T operator() (const T& v0, const T& v1)
16175  { return f(v0, v1); }
16176  ff02_functor f;
16177  };
16178 
16179  struct freefunc03 : public exprtk::ifunction<T>
16180  {
16182 
16183  explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {}
16184  inline T operator() (const T& v0, const T& v1, const T& v2)
16185  { return f(v0, v1, v2); }
16186  ff03_functor f;
16187  };
16188 
16189  struct freefunc04 : public exprtk::ifunction<T>
16190  {
16192 
16193  explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {}
16194  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3)
16195  { return f(v0, v1, v2, v3); }
16196  ff04_functor f;
16197  };
16198 
16199  struct freefunc05 : public exprtk::ifunction<T>
16200  {
16202 
16203  explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {}
16204  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
16205  { return f(v0, v1, v2, v3, v4); }
16206  ff05_functor f;
16207  };
16208 
16209  struct freefunc06 : public exprtk::ifunction<T>
16210  {
16212 
16213  explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {}
16214  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
16215  { return f(v0, v1, v2, v3, v4, v5); }
16216  ff06_functor f;
16217  };
16218 
16219  struct freefunc07 : public exprtk::ifunction<T>
16220  {
16222 
16223  explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {}
16224  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16225  const T& v5, const T& v6)
16226  { return f(v0, v1, v2, v3, v4, v5, v6); }
16227  ff07_functor f;
16228  };
16229 
16230  struct freefunc08 : public exprtk::ifunction<T>
16231  {
16233 
16234  explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {}
16235  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16236  const T& v5, const T& v6, const T& v7)
16237  { return f(v0, v1, v2, v3, v4, v5, v6, v7); }
16238  ff08_functor f;
16239  };
16240 
16241  struct freefunc09 : public exprtk::ifunction<T>
16242  {
16244 
16245  explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {}
16246  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16247  const T& v5, const T& v6, const T& v7, const T& v8)
16248  { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); }
16249  ff09_functor f;
16250  };
16251 
16252  struct freefunc10 : public exprtk::ifunction<T>
16253  {
16255 
16256  explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {}
16257  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16258  const T& v5, const T& v6, const T& v7, const T& v8, const T& v9)
16259  { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); }
16260  ff10_functor f;
16261  };
16262 
16263  struct freefunc11 : public exprtk::ifunction<T>
16264  {
16266 
16267  explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {}
16268  inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4,
16269  const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10)
16270  { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); }
16271  ff11_functor f;
16272  };
16273 
16274  struct freefunc12 : public exprtk::ifunction<T>
16275  {
16277 
16278  explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {}
16279  inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16280  const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16281  const T& v10, const T& v11)
16282  { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); }
16283  ff12_functor f;
16284  };
16285 
16286  struct freefunc13 : public exprtk::ifunction<T>
16287  {
16289 
16290  explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {}
16291  inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16292  const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16293  const T& v10, const T& v11, const T& v12)
16294  { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); }
16295  ff13_functor f;
16296  };
16297 
16298  struct freefunc14 : public exprtk::ifunction<T>
16299  {
16301 
16302  explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {}
16303  inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16304  const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16305  const T& v10, const T& v11, const T& v12, const T& v13)
16306  { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); }
16307  ff14_functor f;
16308  };
16309 
16310  struct freefunc15 : public exprtk::ifunction<T>
16311  {
16313 
16314  explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {}
16315  inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04,
16316  const T& v05, const T& v06, const T& v07, const T& v08, const T& v09,
16317  const T& v10, const T& v11, const T& v12, const T& v13, const T& v14)
16318  { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); }
16319  ff15_functor f;
16320  };
16321 
16322  template <typename Type, typename RawType>
16323  struct type_store
16324  {
16331  #ifndef exprtk_disable_string_capabilities
16333  #endif
16334 
16335  typedef Type type_t;
16336  typedef type_t* type_ptr;
16337  typedef std::pair<bool,type_ptr> type_pair_t;
16338  typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t;
16339  typedef typename type_map_t::iterator tm_itr_t;
16340  typedef typename type_map_t::const_iterator tm_const_itr_t;
16341 
16342  enum { lut_size = 256 };
16343 
16345  std::size_t size;
16346 
16348  : size(0)
16349  {}
16350 
16351  inline bool symbol_exists(const std::string& symbol_name) const
16352  {
16353  if (symbol_name.empty())
16354  return false;
16355  else if (map.end() != map.find(symbol_name))
16356  return true;
16357  else
16358  return false;
16359  }
16360 
16361  template <typename PtrType>
16362  inline std::string entity_name(const PtrType& ptr) const
16363  {
16364  if (map.empty())
16365  return std::string();
16366 
16367  tm_const_itr_t itr = map.begin();
16368 
16369  while (map.end() != itr)
16370  {
16371  if (itr->second.second == ptr)
16372  {
16373  return itr->first;
16374  }
16375  else
16376  ++itr;
16377  }
16378 
16379  return std::string();
16380  }
16381 
16382  inline bool is_constant(const std::string& symbol_name) const
16383  {
16384  if (symbol_name.empty())
16385  return false;
16386  else
16387  {
16388  const tm_const_itr_t itr = map.find(symbol_name);
16389 
16390  if (map.end() == itr)
16391  return false;
16392  else
16393  return (*itr).second.first;
16394  }
16395  }
16396 
16397  template <typename Tie, typename RType>
16398  inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const)
16399  {
16400  if (symbol_name.size() > 1)
16401  {
16402  for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16403  {
16404  if (details::imatch(symbol_name, details::reserved_symbols[i]))
16405  {
16406  return false;
16407  }
16408  }
16409  }
16410 
16411  const tm_itr_t itr = map.find(symbol_name);
16412 
16413  if (map.end() == itr)
16414  {
16415  map[symbol_name] = Tie::make(t,is_const);
16416  ++size;
16417  }
16418 
16419  return true;
16420  }
16421 
16422  struct tie_array
16423  {
16424  static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false)
16425  {
16426  return std::make_pair(is_const, new vector_t(v.first, v.second));
16427  }
16428  };
16429 
16430  struct tie_stdvec
16431  {
16432  template <typename Allocator>
16433  static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false)
16434  {
16435  return std::make_pair(is_const, new vector_t(v));
16436  }
16437  };
16438 
16440  {
16441  static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false)
16442  {
16443  return std::make_pair(is_const, new vector_t(v));
16444  }
16445  };
16446 
16447  struct tie_stddeq
16448  {
16449  template <typename Allocator>
16450  static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false)
16451  {
16452  return std::make_pair(is_const, new vector_t(v));
16453  }
16454  };
16455 
16456  template <std::size_t v_size>
16457  inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false)
16458  {
16459  return add_impl<tie_array,std::pair<T*,std::size_t> >
16460  (symbol_name, std::make_pair(v,v_size), is_const);
16461  }
16462 
16463  inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false)
16464  {
16465  return add_impl<tie_array,std::pair<T*,std::size_t> >
16466  (symbol_name, std::make_pair(v,v_size), is_const);
16467  }
16468 
16469  template <typename Allocator>
16470  inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false)
16471  {
16472  return add_impl<tie_stdvec,std::vector<T,Allocator>&>
16473  (symbol_name, v, is_const);
16474  }
16475 
16476  inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false)
16477  {
16478  return add_impl<tie_vecview,exprtk::vector_view<T>&>
16479  (symbol_name, v, is_const);
16480  }
16481 
16482  template <typename Allocator>
16483  inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false)
16484  {
16485  return add_impl<tie_stddeq,std::deque<T,Allocator>&>
16486  (symbol_name, v, is_const);
16487  }
16488 
16489  inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false)
16490  {
16491  struct tie
16492  {
16493  static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false)
16494  {
16495  return std::make_pair(is_const, new variable_node_t(t));
16496  }
16497 
16498  #ifndef exprtk_disable_string_capabilities
16499  static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false)
16500  {
16501  return std::make_pair(is_const, new stringvar_node_t(t));
16502  }
16503  #endif
16504 
16505  static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
16506  {
16507  return std::make_pair(is_constant,&t);
16508  }
16509 
16510  static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false)
16511  {
16512  return std::make_pair(is_const,&t);
16513  }
16514 
16515  static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false)
16516  {
16517  return std::make_pair(is_constant,&t);
16518  }
16519  };
16520 
16521  const tm_itr_t itr = map.find(symbol_name);
16522 
16523  if (map.end() == itr)
16524  {
16525  map[symbol_name] = tie::make(t,is_const);
16526  ++size;
16527  }
16528 
16529  return true;
16530  }
16531 
16532  inline type_ptr get(const std::string& symbol_name) const
16533  {
16534  const tm_const_itr_t itr = map.find(symbol_name);
16535 
16536  if (map.end() == itr)
16537  return reinterpret_cast<type_ptr>(0);
16538  else
16539  return itr->second.second;
16540  }
16541 
16542  template <typename TType, typename TRawType, typename PtrType>
16543  struct ptr_match
16544  {
16545  static inline bool test(const PtrType, const void*)
16546  {
16547  return false;
16548  }
16549  };
16550 
16551  template <typename TType, typename TRawType>
16552  struct ptr_match<TType,TRawType,variable_node_t*>
16553  {
16554  static inline bool test(const variable_node_t* p, const void* ptr)
16555  {
16556  exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr));
16557  return (&(p->ref()) == ptr);
16558  }
16559  };
16560 
16561  inline type_ptr get_from_varptr(const void* ptr) const
16562  {
16563  tm_const_itr_t itr = map.begin();
16564 
16565  while (map.end() != itr)
16566  {
16567  type_ptr ret_ptr = itr->second.second;
16568 
16569  if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr))
16570  {
16571  return ret_ptr;
16572  }
16573 
16574  ++itr;
16575  }
16576 
16577  return type_ptr(0);
16578  }
16579 
16580  inline bool remove(const std::string& symbol_name, const bool delete_node = true)
16581  {
16582  const tm_itr_t itr = map.find(symbol_name);
16583 
16584  if (map.end() != itr)
16585  {
16586  struct deleter
16587  {
16588  static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16589  static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16590  #ifndef exprtk_disable_string_capabilities
16591  static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16592  #endif
16593  static inline void process(std::pair<bool,function_t*>&) { }
16594  };
16595 
16596  if (delete_node)
16597  {
16598  deleter::process((*itr).second);
16599  }
16600 
16601  map.erase(itr);
16602  --size;
16603 
16604  return true;
16605  }
16606  else
16607  return false;
16608  }
16609 
16610  inline RawType& type_ref(const std::string& symbol_name)
16611  {
16612  struct init_type
16613  {
16614  static inline double set(double) { return (0.0); }
16615  static inline double set(long double) { return (0.0); }
16616  static inline float set(float) { return (0.0f); }
16617  static inline std::string set(std::string) { return std::string(""); }
16618  };
16619 
16620  static RawType null_type = init_type::set(RawType());
16621 
16622  const tm_const_itr_t itr = map.find(symbol_name);
16623 
16624  if (map.end() == itr)
16625  return null_type;
16626  else
16627  return itr->second.second->ref();
16628  }
16629 
16630  inline void clear(const bool delete_node = true)
16631  {
16632  struct deleter
16633  {
16634  static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
16635  static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; }
16636  static inline void process(std::pair<bool,function_t*>&) { }
16637  #ifndef exprtk_disable_string_capabilities
16638  static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
16639  #endif
16640  };
16641 
16642  if (!map.empty())
16643  {
16644  if (delete_node)
16645  {
16646  tm_itr_t itr = map.begin();
16647  tm_itr_t end = map.end ();
16648 
16649  while (end != itr)
16650  {
16651  deleter::process((*itr).second);
16652  ++itr;
16653  }
16654  }
16655 
16656  map.clear();
16657  }
16658 
16659  size = 0;
16660  }
16661 
16662  template <typename Allocator,
16663  template <typename, typename> class Sequence>
16664  inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
16665  {
16666  std::size_t count = 0;
16667 
16668  if (!map.empty())
16669  {
16670  tm_const_itr_t itr = map.begin();
16671  tm_const_itr_t end = map.end ();
16672 
16673  while (end != itr)
16674  {
16675  list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
16676  ++itr;
16677  ++count;
16678  }
16679  }
16680 
16681  return count;
16682  }
16683 
16684  template <typename Allocator,
16685  template <typename, typename> class Sequence>
16686  inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
16687  {
16688  std::size_t count = 0;
16689 
16690  if (!map.empty())
16691  {
16692  tm_const_itr_t itr = map.begin();
16693  tm_const_itr_t end = map.end ();
16694 
16695  while (end != itr)
16696  {
16697  vlist.push_back((*itr).first);
16698  ++itr;
16699  ++count;
16700  }
16701  }
16702 
16703  return count;
16704  }
16705  };
16706 
16711  #ifndef exprtk_disable_string_capabilities
16714  #endif
16721 
16722  static const std::size_t lut_size = 256;
16723 
16724  // Symbol Table Holder
16726  {
16727  struct st_data
16728  {
16730  #ifndef exprtk_disable_string_capabilities
16732  #endif
16739 
16741  {
16742  for (std::size_t i = 0; i < details::reserved_words_size; ++i)
16743  {
16744  reserved_symbol_table_.insert(details::reserved_words[i]);
16745  }
16746 
16747  for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
16748  {
16749  reserved_symbol_table_.insert(details::reserved_symbols[i]);
16750  }
16751  }
16752 
16754  {
16755  for (std::size_t i = 0; i < free_function_list_.size(); ++i)
16756  {
16757  delete free_function_list_[i];
16758  }
16759  }
16760 
16761  inline bool is_reserved_symbol(const std::string& symbol) const
16762  {
16763  return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
16764  }
16765 
16766  static inline st_data* create()
16767  {
16768  return (new st_data);
16769  }
16770 
16771  static inline void destroy(st_data*& sd)
16772  {
16773  delete sd;
16774  sd = reinterpret_cast<st_data*>(0);
16775  }
16776 
16777  std::list<T> local_symbol_list_;
16778  std::list<std::string> local_stringvar_list_;
16779  std::set<std::string> reserved_symbol_table_;
16780  std::vector<ifunction<T>*> free_function_list_;
16781  };
16782 
16784  : ref_count(1),
16785  data_(st_data::create())
16786  {}
16787 
16789  : ref_count(1),
16790  data_(data)
16791  {}
16792 
16794  {
16795  if (data_ && (0 == ref_count))
16796  {
16797  st_data::destroy(data_);
16798  }
16799  }
16800 
16801  static inline control_block* create()
16802  {
16803  return (new control_block);
16804  }
16805 
16806  template <typename SymTab>
16807  static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
16808  {
16809  if (cntrl_blck)
16810  {
16811  if (
16812  (0 != cntrl_blck->ref_count) &&
16813  (0 == --cntrl_blck->ref_count)
16814  )
16815  {
16816  if (sym_tab)
16817  sym_tab->clear();
16818 
16819  delete cntrl_blck;
16820  }
16821 
16822  cntrl_blck = 0;
16823  }
16824  }
16825 
16826  std::size_t ref_count;
16828  };
16829 
16830  public:
16831 
16833  : control_block_(control_block::create())
16834  {
16835  clear();
16836  }
16837 
16839  {
16840  control_block::destroy(control_block_,this);
16841  }
16842 
16844  {
16845  control_block_ = st.control_block_;
16846  control_block_->ref_count++;
16847  }
16848 
16850  {
16851  if (this != &st)
16852  {
16853  control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
16854 
16855  control_block_ = st.control_block_;
16856  control_block_->ref_count++;
16857  }
16858 
16859  return (*this);
16860  }
16861 
16862  inline bool operator==(const symbol_table<T>& st) const
16863  {
16864  return (this == &st) || (control_block_ == st.control_block_);
16865  }
16866 
16867  inline void clear_variables(const bool delete_node = true)
16868  {
16869  local_data().variable_store.clear(delete_node);
16870  }
16871 
16872  inline void clear_functions()
16873  {
16874  local_data().function_store.clear();
16875  }
16876 
16877  inline void clear_strings()
16878  {
16879  #ifndef exprtk_disable_string_capabilities
16880  local_data().stringvar_store.clear();
16881  #endif
16882  }
16883 
16884  inline void clear_vectors()
16885  {
16886  local_data().vector_store.clear();
16887  }
16888 
16890  {
16891  local_data().local_symbol_list_.clear();
16892  }
16893 
16894  inline void clear()
16895  {
16896  if (!valid()) return;
16897  clear_variables ();
16898  clear_functions ();
16899  clear_strings ();
16900  clear_vectors ();
16901  clear_local_constants();
16902  }
16903 
16904  inline std::size_t variable_count() const
16905  {
16906  if (valid())
16907  return local_data().variable_store.size;
16908  else
16909  return 0;
16910  }
16911 
16912  #ifndef exprtk_disable_string_capabilities
16913  inline std::size_t stringvar_count() const
16914  {
16915  if (valid())
16916  return local_data().stringvar_store.size;
16917  else
16918  return 0;
16919  }
16920  #endif
16921 
16922  inline std::size_t function_count() const
16923  {
16924  if (valid())
16925  return local_data().function_store.size;
16926  else
16927  return 0;
16928  }
16929 
16930  inline std::size_t vector_count() const
16931  {
16932  if (valid())
16933  return local_data().vector_store.size;
16934  else
16935  return 0;
16936  }
16937 
16938  inline variable_ptr get_variable(const std::string& variable_name) const
16939  {
16940  if (!valid())
16941  return reinterpret_cast<variable_ptr>(0);
16942  else if (!valid_symbol(variable_name))
16943  return reinterpret_cast<variable_ptr>(0);
16944  else
16945  return local_data().variable_store.get(variable_name);
16946  }
16947 
16948  inline variable_ptr get_variable(const T& var_ref) const
16949  {
16950  if (!valid())
16951  return reinterpret_cast<variable_ptr>(0);
16952  else
16953  return local_data().variable_store.get_from_varptr(
16954  reinterpret_cast<const void*>(&var_ref));
16955  }
16956 
16957  #ifndef exprtk_disable_string_capabilities
16958  inline stringvar_ptr get_stringvar(const std::string& string_name) const
16959  {
16960  if (!valid())
16961  return reinterpret_cast<stringvar_ptr>(0);
16962  else if (!valid_symbol(string_name))
16963  return reinterpret_cast<stringvar_ptr>(0);
16964  else
16965  return local_data().stringvar_store.get(string_name);
16966  }
16967  #endif
16968 
16969  inline function_ptr get_function(const std::string& function_name) const
16970  {
16971  if (!valid())
16972  return reinterpret_cast<function_ptr>(0);
16973  else if (!valid_symbol(function_name))
16974  return reinterpret_cast<function_ptr>(0);
16975  else
16976  return local_data().function_store.get(function_name);
16977  }
16978 
16979  inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
16980  {
16981  if (!valid())
16982  return reinterpret_cast<vararg_function_ptr>(0);
16983  else if (!valid_symbol(vararg_function_name))
16984  return reinterpret_cast<vararg_function_ptr>(0);
16985  else
16986  return local_data().vararg_function_store.get(vararg_function_name);
16987  }
16988 
16989  inline generic_function_ptr get_generic_function(const std::string& function_name) const
16990  {
16991  if (!valid())
16992  return reinterpret_cast<generic_function_ptr>(0);
16993  else if (!valid_symbol(function_name))
16994  return reinterpret_cast<generic_function_ptr>(0);
16995  else
16996  return local_data().generic_function_store.get(function_name);
16997  }
16998 
16999  inline generic_function_ptr get_string_function(const std::string& function_name) const
17000  {
17001  if (!valid())
17002  return reinterpret_cast<generic_function_ptr>(0);
17003  else if (!valid_symbol(function_name))
17004  return reinterpret_cast<generic_function_ptr>(0);
17005  else
17006  return local_data().string_function_store.get(function_name);
17007  }
17008 
17009  inline generic_function_ptr get_overload_function(const std::string& function_name) const
17010  {
17011  if (!valid())
17012  return reinterpret_cast<generic_function_ptr>(0);
17013  else if (!valid_symbol(function_name))
17014  return reinterpret_cast<generic_function_ptr>(0);
17015  else
17016  return local_data().overload_function_store.get(function_name);
17017  }
17018 
17020 
17021  inline vector_holder_ptr get_vector(const std::string& vector_name) const
17022  {
17023  if (!valid())
17024  return reinterpret_cast<vector_holder_ptr>(0);
17025  else if (!valid_symbol(vector_name))
17026  return reinterpret_cast<vector_holder_ptr>(0);
17027  else
17028  return local_data().vector_store.get(vector_name);
17029  }
17030 
17031  inline T& variable_ref(const std::string& symbol_name)
17032  {
17033  static T null_var = T(0);
17034  if (!valid())
17035  return null_var;
17036  else if (!valid_symbol(symbol_name))
17037  return null_var;
17038  else
17039  return local_data().variable_store.type_ref(symbol_name);
17040  }
17041 
17042  #ifndef exprtk_disable_string_capabilities
17043  inline std::string& stringvar_ref(const std::string& symbol_name)
17044  {
17045  static std::string null_stringvar;
17046  if (!valid())
17047  return null_stringvar;
17048  else if (!valid_symbol(symbol_name))
17049  return null_stringvar;
17050  else
17051  return local_data().stringvar_store.type_ref(symbol_name);
17052  }
17053  #endif
17054 
17055  inline bool is_constant_node(const std::string& symbol_name) const
17056  {
17057  if (!valid())
17058  return false;
17059  else if (!valid_symbol(symbol_name))
17060  return false;
17061  else
17062  return local_data().variable_store.is_constant(symbol_name);
17063  }
17064 
17065  #ifndef exprtk_disable_string_capabilities
17066  inline bool is_constant_string(const std::string& symbol_name) const
17067  {
17068  if (!valid())
17069  return false;
17070  else if (!valid_symbol(symbol_name))
17071  return false;
17072  else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17073  return false;
17074  else
17075  return local_data().stringvar_store.is_constant(symbol_name);
17076  }
17077  #endif
17078 
17079  inline bool create_variable(const std::string& variable_name, const T& value = T(0))
17080  {
17081  if (!valid())
17082  return false;
17083  else if (!valid_symbol(variable_name))
17084  return false;
17085  else if (symbol_exists(variable_name))
17086  return false;
17087 
17088  local_data().local_symbol_list_.push_back(value);
17089  T& t = local_data().local_symbol_list_.back();
17090 
17091  return add_variable(variable_name,t);
17092  }
17093 
17094  #ifndef exprtk_disable_string_capabilities
17095  inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
17096  {
17097  if (!valid())
17098  return false;
17099  else if (!valid_symbol(stringvar_name))
17100  return false;
17101  else if (symbol_exists(stringvar_name))
17102  return false;
17103 
17104  local_data().local_stringvar_list_.push_back(value);
17105  std::string& s = local_data().local_stringvar_list_.back();
17106 
17107  return add_stringvar(stringvar_name,s);
17108  }
17109  #endif
17110 
17111  inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
17112  {
17113  if (!valid())
17114  return false;
17115  else if (!valid_symbol(variable_name))
17116  return false;
17117  else if (symbol_exists(variable_name))
17118  return false;
17119  else
17120  return local_data().variable_store.add(variable_name,t,is_constant);
17121  }
17122 
17123  inline bool add_constant(const std::string& constant_name, const T& value)
17124  {
17125  if (!valid())
17126  return false;
17127  else if (!valid_symbol(constant_name))
17128  return false;
17129  else if (symbol_exists(constant_name))
17130  return false;
17131 
17132  local_data().local_symbol_list_.push_back(value);
17133  T& t = local_data().local_symbol_list_.back();
17134 
17135  return add_variable(constant_name,t,true);
17136  }
17137 
17138  #ifndef exprtk_disable_string_capabilities
17139  inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
17140  {
17141  if (!valid())
17142  return false;
17143  else if (!valid_symbol(stringvar_name))
17144  return false;
17145  else if (symbol_exists(stringvar_name))
17146  return false;
17147  else
17148  return local_data().stringvar_store.add(stringvar_name,s,is_constant);
17149  }
17150  #endif
17151 
17152  inline bool add_function(const std::string& function_name, function_t& function)
17153  {
17154  if (!valid())
17155  return false;
17156  else if (!valid_symbol(function_name))
17157  return false;
17158  else if (symbol_exists(function_name))
17159  return false;
17160  else
17161  return local_data().function_store.add(function_name,function);
17162  }
17163 
17164  inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17165  {
17166  if (!valid())
17167  return false;
17168  else if (!valid_symbol(vararg_function_name))
17169  return false;
17170  else if (symbol_exists(vararg_function_name))
17171  return false;
17172  else
17173  return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17174  }
17175 
17176  inline bool add_function(const std::string& function_name, generic_function_t& function)
17177  {
17178  if (!valid())
17179  return false;
17180  else if (!valid_symbol(function_name))
17181  return false;
17182  else if (symbol_exists(function_name))
17183  return false;
17184  else if (
17185  (
17186  (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17187  (generic_function_t::e_rtrn_string == function.rtrn_type)
17188  ) &&
17189  std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|")
17190  )
17191  return false;
17192  else if (
17193  (generic_function_t::e_rtrn_overload == function.rtrn_type) &&
17194  std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:")
17195  )
17196  return false;
17197 
17198  switch (function.rtrn_type)
17199  {
17200  case generic_function_t::e_rtrn_scalar :
17201  return local_data().generic_function_store.add(function_name,function);
17202 
17203  case generic_function_t::e_rtrn_string :
17204  return local_data().string_function_store.add(function_name,function);
17205 
17206  case generic_function_t::e_rtrn_overload :
17207  return local_data().overload_function_store.add(function_name,function);
17208  }
17209 
17210  return false;
17211  }
17212 
17213  #define exprtk_define_freefunction(NN) \
17214  inline bool add_function(const std::string& function_name, ff##NN##_functor function) \
17215  { \
17216  if (!valid()) \
17217  { return false; } \
17218  if (!valid_symbol(function_name)) \
17219  { return false; } \
17220  if (symbol_exists(function_name)) \
17221  { return false; } \
17222  \
17223  exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \
17224  \
17225  local_data().free_function_list_.push_back(ifunc); \
17226  \
17227  return add_function(function_name,(*local_data().free_function_list_.back())); \
17228  } \
17229 
17238 
17239  #undef exprtk_define_freefunction
17240 
17241  inline bool add_reserved_function(const std::string& function_name, function_t& function)
17242  {
17243  if (!valid())
17244  return false;
17245  else if (!valid_symbol(function_name,false))
17246  return false;
17247  else if (symbol_exists(function_name,false))
17248  return false;
17249  else
17250  return local_data().function_store.add(function_name,function);
17251  }
17252 
17253  inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function)
17254  {
17255  if (!valid())
17256  return false;
17257  else if (!valid_symbol(vararg_function_name,false))
17258  return false;
17259  else if (symbol_exists(vararg_function_name,false))
17260  return false;
17261  else
17262  return local_data().vararg_function_store.add(vararg_function_name,vararg_function);
17263  }
17264 
17265  inline bool add_reserved_function(const std::string& function_name, generic_function_t& function)
17266  {
17267  if (!valid())
17268  return false;
17269  else if (!valid_symbol(function_name,false))
17270  return false;
17271  else if (symbol_exists(function_name,false))
17272  return false;
17273  else if (
17274  (
17275  (generic_function_t::e_rtrn_scalar == function.rtrn_type) ||
17276  (generic_function_t::e_rtrn_string == function.rtrn_type)
17277  ) &&
17278  std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|")
17279  )
17280  return false;
17281  else if (
17282  generic_function_t::e_rtrn_overload &&
17283  std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:")
17284  )
17285  return false;
17286 
17287  switch (function.rtrn_type)
17288  {
17289  case generic_function_t::e_rtrn_scalar :
17290  return local_data().generic_function_store.add(function_name,function);
17291 
17292  case generic_function_t::e_rtrn_string :
17293  return local_data().string_function_store.add(function_name,function);
17294 
17295  case generic_function_t::e_rtrn_overload :
17296  return local_data().overload_function_store.add(function_name,function);
17297  }
17298 
17299  return false;
17300  }
17301 
17302  template <std::size_t N>
17303  inline bool add_vector(const std::string& vector_name, T (&v)[N])
17304  {
17305  if (!valid())
17306  return false;
17307  else if (!valid_symbol(vector_name))
17308  return false;
17309  else if (symbol_exists(vector_name))
17310  return false;
17311  else
17312  return local_data().vector_store.add(vector_name,v);
17313  }
17314 
17315  inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size)
17316  {
17317  if (!valid())
17318  return false;
17319  else if (!valid_symbol(vector_name))
17320  return false;
17321  else if (symbol_exists(vector_name))
17322  return false;
17323  else if (0 == v_size)
17324  return false;
17325  else
17326  return local_data().vector_store.add(vector_name,v,v_size);
17327  }
17328 
17329  template <typename Allocator>
17330  inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v)
17331  {
17332  if (!valid())
17333  return false;
17334  else if (!valid_symbol(vector_name))
17335  return false;
17336  else if (symbol_exists(vector_name))
17337  return false;
17338  else if (0 == v.size())
17339  return false;
17340  else
17341  return local_data().vector_store.add(vector_name,v);
17342  }
17343 
17344  inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v)
17345  {
17346  if (!valid())
17347  return false;
17348  else if (!valid_symbol(vector_name))
17349  return false;
17350  else if (symbol_exists(vector_name))
17351  return false;
17352  else if (0 == v.size())
17353  return false;
17354  else
17355  return local_data().vector_store.add(vector_name,v);
17356  }
17357 
17358  inline bool remove_variable(const std::string& variable_name, const bool delete_node = true)
17359  {
17360  if (!valid())
17361  return false;
17362  else
17363  return local_data().variable_store.remove(variable_name, delete_node);
17364  }
17365 
17366  #ifndef exprtk_disable_string_capabilities
17367  inline bool remove_stringvar(const std::string& string_name)
17368  {
17369  if (!valid())
17370  return false;
17371  else
17372  return local_data().stringvar_store.remove(string_name);
17373  }
17374  #endif
17375 
17376  inline bool remove_function(const std::string& function_name)
17377  {
17378  if (!valid())
17379  return false;
17380  else
17381  return local_data().function_store.remove(function_name);
17382  }
17383 
17384  inline bool remove_vararg_function(const std::string& vararg_function_name)
17385  {
17386  if (!valid())
17387  return false;
17388  else
17389  return local_data().vararg_function_store.remove(vararg_function_name);
17390  }
17391 
17392  inline bool remove_vector(const std::string& vector_name)
17393  {
17394  if (!valid())
17395  return false;
17396  else
17397  return local_data().vector_store.remove(vector_name);
17398  }
17399 
17400  inline bool add_constants()
17401  {
17402  return add_pi () &&
17403  add_epsilon () &&
17404  add_infinity() ;
17405  }
17406 
17407  inline bool add_pi()
17408  {
17409  const typename details::numeric::details::number_type<T>::type num_type;
17410  static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type);
17411  return add_constant("pi",local_pi);
17412  }
17413 
17414  inline bool add_epsilon()
17415  {
17416  static const T local_epsilon = details::numeric::details::epsilon_type<T>::value();
17417  return add_constant("epsilon",local_epsilon);
17418  }
17419 
17420  inline bool add_infinity()
17421  {
17422  static const T local_infinity = std::numeric_limits<T>::infinity();
17423  return add_constant("inf",local_infinity);
17424  }
17425 
17426  template <typename Package>
17427  inline bool add_package(Package& package)
17428  {
17429  return package.register_package(*this);
17430  }
17431 
17432  template <typename Allocator,
17433  template <typename, typename> class Sequence>
17434  inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
17435  {
17436  if (!valid())
17437  return 0;
17438  else
17439  return local_data().variable_store.get_list(vlist);
17440  }
17441 
17442  template <typename Allocator,
17443  template <typename, typename> class Sequence>
17444  inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
17445  {
17446  if (!valid())
17447  return 0;
17448  else
17449  return local_data().variable_store.get_list(vlist);
17450  }
17451 
17452  #ifndef exprtk_disable_string_capabilities
17453  template <typename Allocator,
17454  template <typename, typename> class Sequence>
17455  inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
17456  {
17457  if (!valid())
17458  return 0;
17459  else
17460  return local_data().stringvar_store.get_list(svlist);
17461  }
17462 
17463  template <typename Allocator,
17464  template <typename, typename> class Sequence>
17465  inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
17466  {
17467  if (!valid())
17468  return 0;
17469  else
17470  return local_data().stringvar_store.get_list(svlist);
17471  }
17472  #endif
17473 
17474  template <typename Allocator,
17475  template <typename, typename> class Sequence>
17476  inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const
17477  {
17478  if (!valid())
17479  return 0;
17480  else
17481  return local_data().vector_store.get_list(vlist);
17482  }
17483 
17484  inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const
17485  {
17486  /*
17487  Function will return true if symbol_name exists as either a
17488  reserved symbol, variable, stringvar, vector or function name
17489  in any of the type stores.
17490  */
17491  if (!valid())
17492  return false;
17493  else if (local_data().variable_store.symbol_exists(symbol_name))
17494  return true;
17495  #ifndef exprtk_disable_string_capabilities
17496  else if (local_data().stringvar_store.symbol_exists(symbol_name))
17497  return true;
17498  #endif
17499  else if (local_data().vector_store.symbol_exists(symbol_name))
17500  return true;
17501  else if (local_data().function_store.symbol_exists(symbol_name))
17502  return true;
17503  else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name))
17504  return true;
17505  else
17506  return false;
17507  }
17508 
17509  inline bool is_variable(const std::string& variable_name) const
17510  {
17511  if (!valid())
17512  return false;
17513  else
17514  return local_data().variable_store.symbol_exists(variable_name);
17515  }
17516 
17517  #ifndef exprtk_disable_string_capabilities
17518  inline bool is_stringvar(const std::string& stringvar_name) const
17519  {
17520  if (!valid())
17521  return false;
17522  else
17523  return local_data().stringvar_store.symbol_exists(stringvar_name);
17524  }
17525 
17526  inline bool is_conststr_stringvar(const std::string& symbol_name) const
17527  {
17528  if (!valid())
17529  return false;
17530  else if (!valid_symbol(symbol_name))
17531  return false;
17532  else if (!local_data().stringvar_store.symbol_exists(symbol_name))
17533  return false;
17534 
17535  return (
17536  local_data().stringvar_store.symbol_exists(symbol_name) ||
17537  local_data().stringvar_store.is_constant (symbol_name)
17538  );
17539  }
17540  #endif
17541 
17542  inline bool is_function(const std::string& function_name) const
17543  {
17544  if (!valid())
17545  return false;
17546  else
17547  return local_data().function_store.symbol_exists(function_name);
17548  }
17549 
17550  inline bool is_vararg_function(const std::string& vararg_function_name) const
17551  {
17552  if (!valid())
17553  return false;
17554  else
17555  return local_data().vararg_function_store.symbol_exists(vararg_function_name);
17556  }
17557 
17558  inline bool is_vector(const std::string& vector_name) const
17559  {
17560  if (!valid())
17561  return false;
17562  else
17563  return local_data().vector_store.symbol_exists(vector_name);
17564  }
17565 
17567  {
17568  return local_data().variable_store.entity_name(ptr);
17569  }
17570 
17572  {
17573  return local_data().vector_store.entity_name(ptr);
17574  }
17575 
17576  #ifndef exprtk_disable_string_capabilities
17578  {
17579  return local_data().stringvar_store.entity_name(ptr);
17580  }
17581 
17583  {
17584  return local_data().stringvar_store.entity_name(ptr);
17585  }
17586  #endif
17587 
17588  inline bool valid() const
17589  {
17590  // Symbol table sanity check.
17591  return control_block_ && control_block_->data_;
17592  }
17593 
17594  inline void load_from(const symbol_table<T>& st)
17595  {
17596  {
17597  std::vector<std::string> name_list;
17598 
17599  st.local_data().function_store.get_list(name_list);
17600 
17601  if (!name_list.empty())
17602  {
17603  for (std::size_t i = 0; i < name_list.size(); ++i)
17604  {
17605  exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]);
17606  add_function(name_list[i],ifunc);
17607  }
17608  }
17609  }
17610 
17611  {
17612  std::vector<std::string> name_list;
17613 
17614  st.local_data().vararg_function_store.get_list(name_list);
17615 
17616  if (!name_list.empty())
17617  {
17618  for (std::size_t i = 0; i < name_list.size(); ++i)
17619  {
17620  exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]);
17621  add_function(name_list[i],ivafunc);
17622  }
17623  }
17624  }
17625 
17626  {
17627  std::vector<std::string> name_list;
17628 
17629  st.local_data().generic_function_store.get_list(name_list);
17630 
17631  if (!name_list.empty())
17632  {
17633  for (std::size_t i = 0; i < name_list.size(); ++i)
17634  {
17635  exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]);
17636  add_function(name_list[i],ifunc);
17637  }
17638  }
17639  }
17640 
17641  {
17642  std::vector<std::string> name_list;
17643 
17644  st.local_data().string_function_store.get_list(name_list);
17645 
17646  if (!name_list.empty())
17647  {
17648  for (std::size_t i = 0; i < name_list.size(); ++i)
17649  {
17650  exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]);
17651  add_function(name_list[i],ifunc);
17652  }
17653  }
17654  }
17655 
17656  {
17657  std::vector<std::string> name_list;
17658 
17659  st.local_data().overload_function_store.get_list(name_list);
17660 
17661  if (!name_list.empty())
17662  {
17663  for (std::size_t i = 0; i < name_list.size(); ++i)
17664  {
17665  exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]);
17666  add_function(name_list[i],ifunc);
17667  }
17668  }
17669  }
17670  }
17671 
17672  private:
17673 
17674  inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const
17675  {
17676  if (symbol.empty())
17677  return false;
17678  else if (!details::is_letter(symbol[0]))
17679  return false;
17680  else if (symbol.size() > 1)
17681  {
17682  for (std::size_t i = 1; i < symbol.size(); ++i)
17683  {
17684  if (
17685  !details::is_letter_or_digit(symbol[i]) &&
17686  ('_' != symbol[i])
17687  )
17688  {
17689  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17690  continue;
17691  else
17692  return false;
17693  }
17694  }
17695  }
17696 
17697  return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true;
17698  }
17699 
17700  inline bool valid_function(const std::string& symbol) const
17701  {
17702  if (symbol.empty())
17703  return false;
17704  else if (!details::is_letter(symbol[0]))
17705  return false;
17706  else if (symbol.size() > 1)
17707  {
17708  for (std::size_t i = 1; i < symbol.size(); ++i)
17709  {
17710  if (
17711  !details::is_letter_or_digit(symbol[i]) &&
17712  ('_' != symbol[i])
17713  )
17714  {
17715  if (('.' == symbol[i]) && (i < (symbol.size() - 1)))
17716  continue;
17717  else
17718  return false;
17719  }
17720  }
17721  }
17722 
17723  return true;
17724  }
17725 
17726  typedef typename control_block::st_data local_data_t;
17727 
17729  {
17730  return *(control_block_->data_);
17731  }
17732 
17733  inline const local_data_t& local_data() const
17734  {
17735  return *(control_block_->data_);
17736  }
17737 
17738  control_block* control_block_;
17739 
17740  friend class parser<T>;
17741  };
17742 
17743  template <typename T>
17745 
17746  template <typename T>
17748  {
17749  private:
17750 
17753  typedef std::vector<symbol_table<T> > symtab_list_t;
17754 
17756  {
17758  {
17764  e_string
17765  };
17766 
17767  struct data_pack
17768  {
17770  : pointer(0),
17771  type(e_unknown),
17772  size(0)
17773  {}
17774 
17775  data_pack(void* ptr, const data_type dt, const std::size_t sz = 0)
17776  : pointer(ptr),
17777  type(dt),
17778  size(sz)
17779  {}
17780 
17781  void* pointer;
17783  std::size_t size;
17784  };
17785 
17786  typedef std::vector<data_pack> local_data_list_t;
17788 
17790  : ref_count(0),
17791  expr (0),
17792  results (0),
17793  retinv_null(false),
17794  return_invoked(&retinv_null)
17795  {}
17796 
17798  : ref_count(1),
17799  expr (e),
17800  results (0),
17801  retinv_null(false),
17802  return_invoked(&retinv_null)
17803  {}
17804 
17806  {
17807  if (expr && details::branch_deletable(expr))
17808  {
17809  destroy_node(expr);
17810  }
17811 
17812  if (!local_data_list.empty())
17813  {
17814  for (std::size_t i = 0; i < local_data_list.size(); ++i)
17815  {
17816  switch (local_data_list[i].type)
17817  {
17818  case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer);
17819  break;
17820 
17821  case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer);
17822  break;
17823 
17824  case e_data : delete (T*)(local_data_list[i].pointer);
17825  break;
17826 
17827  case e_vecdata : delete [] (T*)(local_data_list[i].pointer);
17828  break;
17829 
17830  case e_string : delete (std::string*)(local_data_list[i].pointer);
17831  break;
17832 
17833  default : break;
17834  }
17835  }
17836  }
17837 
17838  if (results)
17839  {
17840  delete results;
17841  }
17842  }
17843 
17845  {
17846  return new control_block(e);
17847  }
17848 
17849  static inline void destroy(control_block*& cntrl_blck)
17850  {
17851  if (cntrl_blck)
17852  {
17853  if (
17854  (0 != cntrl_blck->ref_count) &&
17855  (0 == --cntrl_blck->ref_count)
17856  )
17857  {
17858  delete cntrl_blck;
17859  }
17860 
17861  cntrl_blck = 0;
17862  }
17863  }
17864 
17865  std::size_t ref_count;
17871 
17872  friend class function_compositor<T>;
17873  };
17874 
17875  public:
17876 
17878  : control_block_(0)
17879  {
17880  set_expression(new details::null_node<T>());
17881  }
17882 
17884  : control_block_ (e.control_block_ ),
17885  symbol_table_list_(e.symbol_table_list_)
17886  {
17887  control_block_->ref_count++;
17888  }
17889 
17891  : control_block_(0)
17892  {
17893  set_expression(new details::null_node<T>());
17894  symbol_table_list_.push_back(symbol_table);
17895  }
17896 
17898  {
17899  if (this != &e)
17900  {
17901  if (control_block_)
17902  {
17903  if (
17904  (0 != control_block_->ref_count) &&
17905  (0 == --control_block_->ref_count)
17906  )
17907  {
17908  delete control_block_;
17909  }
17910 
17911  control_block_ = 0;
17912  }
17913 
17914  control_block_ = e.control_block_;
17915  control_block_->ref_count++;
17916  symbol_table_list_ = e.symbol_table_list_;
17917  }
17918 
17919  return *this;
17920  }
17921 
17922  inline bool operator==(const expression<T>& e) const
17923  {
17924  return (this == &e);
17925  }
17926 
17927  inline bool operator!() const
17928  {
17929  return (
17930  (0 == control_block_ ) ||
17931  (0 == control_block_->expr)
17932  );
17933  }
17934 
17936  {
17937  control_block::destroy(control_block_);
17938 
17939  return (*this);
17940  }
17941 
17943  {
17944  control_block::destroy(control_block_);
17945  }
17946 
17947  inline T value() const
17948  {
17949  return control_block_->expr->value();
17950  }
17951 
17952  inline T operator() () const
17953  {
17954  return value();
17955  }
17956 
17957  inline operator T() const
17958  {
17959  return value();
17960  }
17961 
17962  inline operator bool() const
17963  {
17964  return details::is_true(value());
17965  }
17966 
17968  {
17969  symbol_table_list_.push_back(st);
17970  }
17971 
17972  inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const
17973  {
17974  return symbol_table_list_[index];
17975  }
17976 
17977  inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0)
17978  {
17979  return symbol_table_list_[index];
17980  }
17981 
17983 
17984  inline const results_context_t& results() const
17985  {
17986  if (control_block_->results)
17987  return (*control_block_->results);
17988  else
17989  {
17990  static const results_context_t null_results;
17991  return null_results;
17992  }
17993  }
17994 
17995  inline bool return_invoked() const
17996  {
17997  return (*control_block_->return_invoked);
17998  }
17999 
18000  private:
18001 
18003  {
18004  return symbol_table_list_;
18005  }
18006 
18007  inline void set_expression(const expression_ptr expr)
18008  {
18009  if (expr)
18010  {
18011  if (control_block_)
18012  {
18013  if (0 == --control_block_->ref_count)
18014  {
18015  delete control_block_;
18016  }
18017  }
18018 
18019  control_block_ = control_block::create(expr);
18020  }
18021  }
18022 
18024  {
18025  if (expr)
18026  {
18027  if (control_block_)
18028  {
18029  control_block_->
18030  local_data_list.push_back(
18031  typename expression<T>::control_block::
18032  data_pack(reinterpret_cast<void*>(expr),
18033  control_block::e_expr));
18034  }
18035  }
18036  }
18037 
18038  inline void register_local_var(vector_holder_ptr vec_holder)
18039  {
18040  if (vec_holder)
18041  {
18042  if (control_block_)
18043  {
18044  control_block_->
18045  local_data_list.push_back(
18046  typename expression<T>::control_block::
18047  data_pack(reinterpret_cast<void*>(vec_holder),
18048  control_block::e_vecholder));
18049  }
18050  }
18051  }
18052 
18053  inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0)
18054  {
18055  if (data)
18056  {
18057  if (control_block_)
18058  {
18059  typename control_block::data_type dt = control_block::e_data;
18060 
18061  switch (data_mode)
18062  {
18063  case 0 : dt = control_block::e_data; break;
18064  case 1 : dt = control_block::e_vecdata; break;
18065  case 2 : dt = control_block::e_string; break;
18066  }
18067 
18068  control_block_->
18069  local_data_list.push_back(
18070  typename expression<T>::control_block::
18071  data_pack(reinterpret_cast<void*>(data), dt, size));
18072  }
18073  }
18074  }
18075 
18076  inline const typename control_block::local_data_list_t& local_data_list()
18077  {
18078  if (control_block_)
18079  {
18080  return control_block_->local_data_list;
18081  }
18082  else
18083  {
18084  static typename control_block::local_data_list_t null_local_data_list;
18085  return null_local_data_list;
18086  }
18087  }
18088 
18090  {
18091  if (control_block_ && rc)
18092  {
18093  control_block_->results = rc;
18094  }
18095  }
18096 
18097  inline void set_retinvk(bool* retinvk_ptr)
18098  {
18099  if (control_block_)
18100  {
18101  control_block_->return_invoked = retinvk_ptr;
18102  }
18103  }
18104 
18105  control_block* control_block_;
18107 
18108  friend class parser<T>;
18109  friend class expression_helper<T>;
18110  friend class function_compositor<T>;
18111  };
18112 
18113  template <typename T>
18114  class expression_helper
18115  {
18116  public:
18117 
18118  static inline bool is_constant(const expression<T>& expr)
18119  {
18120  return details::is_constant_node(expr.control_block_->expr);
18121  }
18122 
18123  static inline bool is_variable(const expression<T>& expr)
18124  {
18125  return details::is_variable_node(expr.control_block_->expr);
18126  }
18127 
18128  static inline bool is_unary(const expression<T>& expr)
18129  {
18130  return details::is_unary_node(expr.control_block_->expr);
18131  }
18132 
18133  static inline bool is_binary(const expression<T>& expr)
18134  {
18135  return details::is_binary_node(expr.control_block_->expr);
18136  }
18137 
18138  static inline bool is_function(const expression<T>& expr)
18139  {
18140  return details::is_function(expr.control_block_->expr);
18141  }
18142 
18143  static inline bool is_null(const expression<T>& expr)
18144  {
18145  return details::is_null_node(expr.control_block_->expr);
18146  }
18147  };
18148 
18149  template <typename T>
18150  inline bool is_valid(const expression<T>& expr)
18151  {
18152  return !expression_helper<T>::is_null(expr);
18153  }
18154 
18155  namespace parser_error
18156  {
18158  {
18161  e_token = 2,
18164  e_lexer = 6,
18166  };
18167 
18168  struct type
18169  {
18171  : mode(parser_error::e_unknown),
18172  line_no (0),
18173  column_no(0)
18174  {}
18175 
18181  std::size_t line_no;
18182  std::size_t column_no;
18183  };
18184 
18185  inline type make_error(const error_mode mode,
18186  const std::string& diagnostic = "",
18187  const std::string& src_location = "")
18188  {
18189  type t;
18190  t.mode = mode;
18191  t.token.type = lexer::token::e_error;
18192  t.diagnostic = diagnostic;
18193  t.src_location = src_location;
18194  exprtk_debug(("%s\n",diagnostic .c_str()));
18195  return t;
18196  }
18197 
18198  inline type make_error(const error_mode mode,
18199  const lexer::token& tk,
18200  const std::string& diagnostic = "",
18201  const std::string& src_location = "")
18202  {
18203  type t;
18204  t.mode = mode;
18205  t.token = tk;
18206  t.diagnostic = diagnostic;
18207  t.src_location = src_location;
18208  exprtk_debug(("%s\n",diagnostic .c_str()));
18209  return t;
18210  }
18211 
18213  {
18214  switch (mode)
18215  {
18216  case e_unknown : return std::string("Unknown Error");
18217  case e_syntax : return std::string("Syntax Error" );
18218  case e_token : return std::string("Token Error" );
18219  case e_numeric : return std::string("Numeric Error");
18220  case e_symtab : return std::string("Symbol Error" );
18221  case e_lexer : return std::string("Lexer Error" );
18222  case e_helper : return std::string("Helper Error" );
18223  default : return std::string("Unknown Error");
18224  }
18225  }
18226 
18228  {
18229  if (
18230  expression.empty() ||
18231  (error.token.position > expression.size()) ||
18232  (std::numeric_limits<std::size_t>::max() == error.token.position)
18233  )
18234  {
18235  return false;
18236  }
18237 
18238  std::size_t error_line_start = 0;
18239 
18240  for (std::size_t i = error.token.position; i > 0; --i)
18241  {
18242  const details::char_t c = expression[i];
18243 
18244  if (('\n' == c) || ('\r' == c))
18245  {
18246  error_line_start = i + 1;
18247  break;
18248  }
18249  }
18250 
18251  std::size_t next_nl_position = std::min(expression.size(),
18252  expression.find_first_of('\n',error.token.position + 1));
18253 
18254  error.column_no = error.token.position - error_line_start;
18255  error.error_line = expression.substr(error_line_start,
18256  next_nl_position - error_line_start);
18257 
18258  error.line_no = 0;
18259 
18260  for (std::size_t i = 0; i < next_nl_position; ++i)
18261  {
18262  if ('\n' == expression[i])
18263  ++error.line_no;
18264  }
18265 
18266  return true;
18267  }
18268 
18269  inline void dump_error(const type& error)
18270  {
18271  printf("Position: %02d Type: [%s] Msg: %s\n",
18272  static_cast<int>(error.token.position),
18273  exprtk::parser_error::to_str(error.mode).c_str(),
18274  error.diagnostic.c_str());
18275  }
18276  }
18277 
18278  namespace details
18279  {
18280  template <typename Parser>
18281  inline void disable_type_checking(Parser& p)
18282  {
18283  p.state_.type_check_enabled = false;
18284  }
18285  }
18286 
18287  template <typename T>
18288  class parser : public lexer::parser_helper
18289  {
18290  private:
18291 
18293  {
18308  e_level14
18309  };
18310 
18311  typedef const T& cref_t;
18312  typedef const T const_t;
18313  typedef ifunction <T> F;
18330  #ifndef exprtk_disable_break_continue
18334  #endif
18342  #ifndef exprtk_disable_string_capabilities
18353  #endif
18368 
18370  typedef typename functor_t::qfunc_t quaternary_functor_t;
18371  typedef typename functor_t::tfunc_t trinary_functor_t;
18372  typedef typename functor_t::bfunc_t binary_functor_t;
18373  typedef typename functor_t::ufunc_t unary_functor_t;
18374 
18376 
18377  typedef std::map<operator_t, unary_functor_t> unary_op_map_t;
18378  typedef std::map<operator_t, binary_functor_t> binary_op_map_t;
18379  typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t;
18380 
18381  typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t;
18382  typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t;
18383 
18384  typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t;
18385  typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t;
18386  typedef std::set<std::string,details::ilesscompare> disabled_func_set_t;
18387 
18391 
18399 
18405 
18410 
18412 
18413  typedef parser_helper prsrhlpr_t;
18414 
18416  {
18418  {
18423  e_string
18424  };
18425 
18430  #ifndef exprtk_disable_string_capabilities
18432  #endif
18433 
18435  : name("???"),
18436  size (std::numeric_limits<std::size_t>::max()),
18437  index(std::numeric_limits<std::size_t>::max()),
18438  depth(std::numeric_limits<std::size_t>::max()),
18439  ref_count(0),
18440  ip_index (0),
18441  type (e_none),
18442  active(false),
18443  data (0),
18444  var_node(0),
18445  vec_node(0)
18446  #ifndef exprtk_disable_string_capabilities
18447  ,str_node(0)
18448  #endif
18449  {}
18450 
18451  bool operator < (const scope_element& se) const
18452  {
18453  if (ip_index < se.ip_index)
18454  return true;
18455  else if (ip_index > se.ip_index)
18456  return false;
18457  else if (depth < se.depth)
18458  return true;
18459  else if (depth > se.depth)
18460  return false;
18461  else if (index < se.index)
18462  return true;
18463  else if (index > se.index)
18464  return false;
18465  else
18466  return (name < se.name);
18467  }
18468 
18469  void clear()
18470  {
18471  name = "???";
18475  type = e_none;
18476  active = false;
18477  ref_count = 0;
18478  ip_index = 0;
18479  data = 0;
18480  var_node = 0;
18481  vec_node = 0;
18482  #ifndef exprtk_disable_string_capabilities
18483  str_node = 0;
18484  #endif
18485  }
18486 
18488  std::size_t size;
18489  std::size_t index;
18490  std::size_t depth;
18491  std::size_t ref_count;
18492  std::size_t ip_index;
18494  bool active;
18495  void* data;
18498  #ifndef exprtk_disable_string_capabilities
18500  #endif
18501  };
18502 
18504  {
18505  public:
18506 
18510 
18512  : parser_(p),
18513  input_param_cnt_(0)
18514  {}
18515 
18516  inline std::size_t size() const
18517  {
18518  return element_.size();
18519  }
18520 
18521  inline bool empty() const
18522  {
18523  return element_.empty();
18524  }
18525 
18526  inline scope_element& get_element(const std::size_t& index)
18527  {
18528  if (index < element_.size())
18529  return element_[index];
18530  else
18531  return null_element_;
18532  }
18533 
18534  inline scope_element& get_element(const std::string& var_name,
18535  const std::size_t index = std::numeric_limits<std::size_t>::max())
18536  {
18537  const std::size_t current_depth = parser_.state_.scope_depth;
18538 
18539  for (std::size_t i = 0; i < element_.size(); ++i)
18540  {
18541  scope_element& se = element_[i];
18542 
18543  if (se.depth > current_depth)
18544  continue;
18545  else if (
18546  details::imatch(se.name, var_name) &&
18547  (se.index == index)
18548  )
18549  return se;
18550  }
18551 
18552  return null_element_;
18553  }
18554 
18556  const std::size_t index = std::numeric_limits<std::size_t>::max())
18557  {
18558  const std::size_t current_depth = parser_.state_.scope_depth;
18559 
18560  for (std::size_t i = 0; i < element_.size(); ++i)
18561  {
18562  scope_element& se = element_[i];
18563 
18564  if (se.depth > current_depth)
18565  continue;
18566  else if (
18567  details::imatch(se.name, var_name) &&
18568  (se.index == index) &&
18569  (se.active)
18570  )
18571  return se;
18572  }
18573 
18574  return null_element_;
18575  }
18576 
18577  inline bool add_element(const scope_element& se)
18578  {
18579  for (std::size_t i = 0; i < element_.size(); ++i)
18580  {
18581  scope_element& cse = element_[i];
18582 
18583  if (
18584  details::imatch(cse.name, se.name) &&
18585  (cse.depth <= se.depth) &&
18586  (cse.index == se.index) &&
18587  (cse.size == se.size ) &&
18588  (cse.type == se.type ) &&
18589  (cse.active)
18590  )
18591  return false;
18592  }
18593 
18594  element_.push_back(se);
18595  std::sort(element_.begin(),element_.end());
18596 
18597  return true;
18598  }
18599 
18600  inline void deactivate(const std::size_t& scope_depth)
18601  {
18602  exprtk_debug(("deactivate() - Scope depth: %d\n",
18603  static_cast<int>(parser_.state_.scope_depth)));
18604 
18605  for (std::size_t i = 0; i < element_.size(); ++i)
18606  {
18607  scope_element& se = element_[i];
18608 
18609  if (se.active && (se.depth >= scope_depth))
18610  {
18611  exprtk_debug(("deactivate() - element[%02d] '%s'\n",
18612  static_cast<int>(i),
18613  se.name.c_str()));
18614 
18615  se.active = false;
18616  }
18617  }
18618  }
18619 
18620  inline void free_element(scope_element& se)
18621  {
18622  #ifdef exprtk_enable_debugging
18623  exprtk_debug(("free_element() - se[%s]\n", se.name.c_str()));
18624  #endif
18625 
18626  switch (se.type)
18627  {
18628  case scope_element::e_variable : if (se.data ) delete (T*) se.data;
18629  if (se.var_node) delete se.var_node;
18630  break;
18631 
18632  case scope_element::e_vector : if (se.data ) delete[] (T*) se.data;
18633  if (se.vec_node) delete se.vec_node;
18634  break;
18635 
18636  case scope_element::e_vecelem : if (se.var_node) delete se.var_node;
18637  break;
18638 
18639  #ifndef exprtk_disable_string_capabilities
18640  case scope_element::e_string : if (se.data ) delete (std::string*) se.data;
18641  if (se.str_node) delete se.str_node;
18642  break;
18643  #endif
18644 
18645  default : return;
18646  }
18647 
18648  se.clear();
18649  }
18650 
18651  inline void cleanup()
18652  {
18653  for (std::size_t i = 0; i < element_.size(); ++i)
18654  {
18655  free_element(element_[i]);
18656  }
18657 
18658  element_.clear();
18659 
18660  input_param_cnt_ = 0;
18661  }
18662 
18663  inline std::size_t next_ip_index()
18664  {
18665  return ++input_param_cnt_;
18666  }
18667 
18669  {
18670  for (std::size_t i = 0; i < element_.size(); ++i)
18671  {
18672  scope_element& se = element_[i];
18673 
18674  if (
18675  se.active &&
18676  se.var_node &&
18678  )
18679  {
18680  variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node);
18681 
18682  if (&(vn->ref()) == (&v))
18683  {
18684  return se.var_node;
18685  }
18686  }
18687  }
18688 
18689  return expression_node_ptr(0);
18690  }
18691 
18692  private:
18693 
18694  scope_element_manager& operator=(const scope_element_manager&);
18695 
18697  std::vector<scope_element> element_;
18699  std::size_t input_param_cnt_;
18700  };
18701 
18703  {
18704  public:
18705 
18707 
18709  : parser_(p)
18710  {
18711  parser_.state_.scope_depth++;
18712  #ifdef exprtk_enable_debugging
18713  const std::string depth(2 * parser_.state_.scope_depth,'-');
18714  exprtk_debug(("%s> Scope Depth: %02d\n",
18715  depth.c_str(),
18716  static_cast<int>(parser_.state_.scope_depth)));
18717  #endif
18718  }
18719 
18721  {
18722  parser_.sem_.deactivate(parser_.state_.scope_depth);
18723  parser_.state_.scope_depth--;
18724  #ifdef exprtk_enable_debugging
18725  const std::string depth(2 * parser_.state_.scope_depth,'-');
18726  exprtk_debug(("<%s Scope Depth: %02d\n",
18727  depth.c_str(),
18728  static_cast<int>(parser_.state_.scope_depth)));
18729  #endif
18730  }
18731 
18732  private:
18733 
18734  scope_handler& operator=(const scope_handler&);
18735 
18737  };
18738 
18740  {
18742 
18746  #ifndef exprtk_disable_string_capabilities
18748  #endif
18752 
18753  inline bool empty() const
18754  {
18755  return symtab_list_.empty();
18756  }
18757 
18758  inline void clear()
18759  {
18760  symtab_list_.clear();
18761  }
18762 
18763  inline bool valid() const
18764  {
18765  if (!empty())
18766  {
18767  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18768  {
18769  if (symtab_list_[i].valid())
18770  return true;
18771  }
18772  }
18773 
18774  return false;
18775  }
18776 
18777  inline bool valid_symbol(const std::string& symbol) const
18778  {
18779  if (!symtab_list_.empty())
18780  return symtab_list_[0].valid_symbol(symbol);
18781  else
18782  return false;
18783  }
18784 
18785  inline bool valid_function_name(const std::string& symbol) const
18786  {
18787  if (!symtab_list_.empty())
18788  return symtab_list_[0].valid_function(symbol);
18789  else
18790  return false;
18791  }
18792 
18793  inline variable_ptr get_variable(const std::string& variable_name) const
18794  {
18795  if (!valid_symbol(variable_name))
18796  return reinterpret_cast<variable_ptr>(0);
18797 
18798  variable_ptr result = reinterpret_cast<variable_ptr>(0);
18799 
18800  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18801  {
18802  if (!symtab_list_[i].valid())
18803  continue;
18804  else
18805  result = local_data(i)
18806  .variable_store.get(variable_name);
18807 
18808  if (result) break;
18809  }
18810 
18811  return result;
18812  }
18813 
18814  inline variable_ptr get_variable(const T& var_ref) const
18815  {
18816  variable_ptr result = reinterpret_cast<variable_ptr>(0);
18817 
18818  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18819  {
18820  if (!symtab_list_[i].valid())
18821  continue;
18822  else
18823  result = local_data(i).variable_store
18824  .get_from_varptr(reinterpret_cast<const void*>(&var_ref));
18825 
18826  if (result) break;
18827  }
18828 
18829  return result;
18830  }
18831 
18832  #ifndef exprtk_disable_string_capabilities
18833  inline stringvar_ptr get_stringvar(const std::string& string_name) const
18834  {
18835  if (!valid_symbol(string_name))
18836  return reinterpret_cast<stringvar_ptr>(0);
18837 
18838  stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0);
18839 
18840  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18841  {
18842  if (!symtab_list_[i].valid())
18843  continue;
18844  else
18845  result = local_data(i)
18846  .stringvar_store.get(string_name);
18847 
18848  if (result) break;
18849  }
18850 
18851  return result;
18852  }
18853  #endif
18854 
18855  inline function_ptr get_function(const std::string& function_name) const
18856  {
18857  if (!valid_function_name(function_name))
18858  return reinterpret_cast<function_ptr>(0);
18859 
18860  function_ptr result = reinterpret_cast<function_ptr>(0);
18861 
18862  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18863  {
18864  if (!symtab_list_[i].valid())
18865  continue;
18866  else
18867  result = local_data(i)
18868  .function_store.get(function_name);
18869 
18870  if (result) break;
18871  }
18872 
18873  return result;
18874  }
18875 
18876  inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const
18877  {
18878  if (!valid_function_name(vararg_function_name))
18879  return reinterpret_cast<vararg_function_ptr>(0);
18880 
18881  vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0);
18882 
18883  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18884  {
18885  if (!symtab_list_[i].valid())
18886  continue;
18887  else
18888  result = local_data(i)
18889  .vararg_function_store.get(vararg_function_name);
18890 
18891  if (result) break;
18892  }
18893 
18894  return result;
18895  }
18896 
18897  inline generic_function_ptr get_generic_function(const std::string& function_name) const
18898  {
18899  if (!valid_function_name(function_name))
18900  return reinterpret_cast<generic_function_ptr>(0);
18901 
18902  generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18903 
18904  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18905  {
18906  if (!symtab_list_[i].valid())
18907  continue;
18908  else
18909  result = local_data(i)
18910  .generic_function_store.get(function_name);
18911 
18912  if (result) break;
18913  }
18914 
18915  return result;
18916  }
18917 
18918  inline generic_function_ptr get_string_function(const std::string& function_name) const
18919  {
18920  if (!valid_function_name(function_name))
18921  return reinterpret_cast<generic_function_ptr>(0);
18922 
18923  generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18924 
18925  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18926  {
18927  if (!symtab_list_[i].valid())
18928  continue;
18929  else
18930  result =
18931  local_data(i).string_function_store.get(function_name);
18932 
18933  if (result) break;
18934  }
18935 
18936  return result;
18937  }
18938 
18939  inline generic_function_ptr get_overload_function(const std::string& function_name) const
18940  {
18941  if (!valid_function_name(function_name))
18942  return reinterpret_cast<generic_function_ptr>(0);
18943 
18944  generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0);
18945 
18946  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18947  {
18948  if (!symtab_list_[i].valid())
18949  continue;
18950  else
18951  result =
18952  local_data(i).overload_function_store.get(function_name);
18953 
18954  if (result) break;
18955  }
18956 
18957  return result;
18958  }
18959 
18960  inline vector_holder_ptr get_vector(const std::string& vector_name) const
18961  {
18962  if (!valid_symbol(vector_name))
18963  return reinterpret_cast<vector_holder_ptr>(0);
18964 
18965  vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0);
18966 
18967  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18968  {
18969  if (!symtab_list_[i].valid())
18970  continue;
18971  else
18972  result =
18973  local_data(i).vector_store.get(vector_name);
18974 
18975  if (result) break;
18976  }
18977 
18978  return result;
18979  }
18980 
18981  inline bool is_constant_node(const std::string& symbol_name) const
18982  {
18983  if (!valid_symbol(symbol_name))
18984  return false;
18985 
18986  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
18987  {
18988  if (!symtab_list_[i].valid())
18989  continue;
18990  else if (local_data(i).variable_store.is_constant(symbol_name))
18991  return true;
18992  }
18993 
18994  return false;
18995  }
18996 
18997  #ifndef exprtk_disable_string_capabilities
18998  inline bool is_constant_string(const std::string& symbol_name) const
18999  {
19000  if (!valid_symbol(symbol_name))
19001  return false;
19002 
19003  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19004  {
19005  if (!symtab_list_[i].valid())
19006  continue;
19007  else if (!local_data(i).stringvar_store.symbol_exists(symbol_name))
19008  continue;
19009  else if ( local_data(i).stringvar_store.is_constant(symbol_name))
19010  return true;
19011  }
19012 
19013  return false;
19014  }
19015  #endif
19016 
19017  inline bool symbol_exists(const std::string& symbol) const
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 (symtab_list_[i].symbol_exists(symbol))
19024  return true;
19025  }
19026 
19027  return false;
19028  }
19029 
19030  inline bool is_variable(const std::string& variable_name) const
19031  {
19032  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19033  {
19034  if (!symtab_list_[i].valid())
19035  continue;
19036  else if (
19037  symtab_list_[i].local_data().variable_store
19038  .symbol_exists(variable_name)
19039  )
19040  return true;
19041  }
19042 
19043  return false;
19044  }
19045 
19046  #ifndef exprtk_disable_string_capabilities
19047  inline bool is_stringvar(const std::string& stringvar_name) const
19048  {
19049  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19050  {
19051  if (!symtab_list_[i].valid())
19052  continue;
19053  else if (
19054  symtab_list_[i].local_data().stringvar_store
19055  .symbol_exists(stringvar_name)
19056  )
19057  return true;
19058  }
19059 
19060  return false;
19061  }
19062 
19063  inline bool is_conststr_stringvar(const std::string& symbol_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(symbol_name)
19072  )
19073  {
19074  return (
19075  local_data(i).stringvar_store.symbol_exists(symbol_name) ||
19076  local_data(i).stringvar_store.is_constant (symbol_name)
19077  );
19078 
19079  }
19080  }
19081 
19082  return false;
19083  }
19084  #endif
19085 
19086  inline bool is_function(const std::string& function_name) const
19087  {
19088  for (std::size_t i = 0; i < symtab_list_.size(); ++i)
19089  {
19090  if (!symtab_list_[i].valid())
19091  continue;
19092  else if (
19093  local_data(i).vararg_function_store
19094  .symbol_exists(function_name)
19095  )
19096  return true;
19097  }
19098 
19099  return false;
19100  }
19101 
19102  inline bool is_vararg_function(const std::string& vararg_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(vararg_function_name)
19111  )
19112  return true;
19113  }
19114 
19115  return false;
19116  }
19117 
19118  inline bool is_vector(const std::string& vector_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).vector_store
19126  .symbol_exists(vector_name)
19127  )
19128  return true;
19129  }
19130 
19131  return false;
19132  }
19133 
19135  {
19136  return local_data().variable_store.entity_name(ptr);
19137  }
19138 
19140  {
19141  return local_data().vector_store.entity_name(ptr);
19142  }
19143 
19144  #ifndef exprtk_disable_string_capabilities
19146  {
19147  return local_data().stringvar_store.entity_name(ptr);
19148  }
19149 
19151  {
19152  return local_data().stringvar_store.entity_name(ptr);
19153  }
19154  #endif
19155 
19156  inline local_data_t& local_data(const std::size_t& index = 0)
19157  {
19158  return symtab_list_[index].local_data();
19159  }
19160 
19161  inline const local_data_t& local_data(const std::size_t& index = 0) const
19162  {
19163  return symtab_list_[index].local_data();
19164  }
19165 
19166  inline symbol_table_t& get_symbol_table(const std::size_t& index = 0)
19167  {
19168  return symtab_list_[index];
19169  }
19170  };
19171 
19173  {
19175  : type_check_enabled(true)
19176  {
19177  reset();
19178  }
19179 
19180  void reset()
19181  {
19182  parsing_return_stmt = false;
19183  parsing_break_stmt = false;
19184  return_stmt_present = false;
19185  side_effect_present = false;
19186  scope_depth = 0;
19187  }
19188 
19189  #ifndef exprtk_enable_debugging
19191  #else
19192  void activate_side_effect(const std::string& source)
19193  #endif
19194  {
19195  if (!side_effect_present)
19196  {
19197  side_effect_present = true;
19198 
19199  exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str()));
19200  }
19201  }
19202 
19208  std::size_t scope_depth;
19209  };
19210 
19211  public:
19212 
19214  {
19215 
19217  {
19218  e_usr_unknown_type = 0,
19219  e_usr_variable_type = 1,
19220  e_usr_constant_type = 2
19221  };
19222 
19224  {
19225  e_usrmode_default = 0,
19226  e_usrmode_extended = 1
19227  };
19228 
19230 
19231  unknown_symbol_resolver(const usr_mode m = e_usrmode_default)
19232  : mode(m)
19233  {}
19234 
19236  {}
19237 
19238  virtual bool process(const std::string& /*unknown_symbol*/,
19239  usr_symbol_type& st,
19240  T& default_value,
19241  std::string& error_message)
19242  {
19243  if (e_usrmode_default != mode)
19244  return false;
19245 
19246  st = e_usr_variable_type;
19247  default_value = T(0);
19248  error_message.clear();
19249 
19250  return true;
19251  }
19252 
19253  virtual bool process(const std::string& /* unknown_symbol */,
19254  symbol_table_t& /* symbol_table */,
19255  std::string& /* error_message */)
19256  {
19257  return false;
19258  }
19259  };
19260 
19262  {
19263  e_ct_none = 0,
19264  e_ct_variables = 1,
19265  e_ct_functions = 2,
19266  e_ct_assignments = 4
19267  };
19268 
19270  {
19271  e_st_unknown = 0,
19272  e_st_variable = 1,
19273  e_st_vector = 2,
19274  e_st_vecelem = 3,
19275  e_st_string = 4,
19276  e_st_function = 5,
19277  e_st_local_variable = 6,
19278  e_st_local_vector = 7,
19279  e_st_local_string = 8
19280  };
19281 
19283  {
19284  public:
19285 
19286  typedef std::pair<std::string,symbol_type> symbol_t;
19287  typedef std::vector<symbol_t> symbol_list_t;
19288 
19289  dependent_entity_collector(const std::size_t options = e_ct_none)
19290  : options_(options),
19291  collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ),
19292  collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ),
19293  collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments),
19294  return_present_ (false),
19295  final_stmt_return_(false)
19296  {}
19297 
19298  template <typename Allocator,
19299  template <typename, typename> class Sequence>
19300  inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list)
19301  {
19302  if (!collect_variables_ && !collect_functions_)
19303  return 0;
19304  else if (symbol_name_list_.empty())
19305  return 0;
19306 
19307  for (std::size_t i = 0; i < symbol_name_list_.size(); ++i)
19308  {
19309  details::case_normalise(symbol_name_list_[i].first);
19310  }
19311 
19312  std::sort(symbol_name_list_.begin(),symbol_name_list_.end());
19313 
19314  std::unique_copy(symbol_name_list_.begin(),
19315  symbol_name_list_.end (),
19316  std::back_inserter(symbols_list));
19317 
19318  return symbols_list.size();
19319  }
19320 
19321  template <typename Allocator,
19322  template <typename, typename> class Sequence>
19323  inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list)
19324  {
19325  if (!collect_assignments_)
19326  return 0;
19327  else if (assignment_name_list_.empty())
19328  return 0;
19329 
19330  for (std::size_t i = 0; i < assignment_name_list_.size(); ++i)
19331  {
19332  details::case_normalise(assignment_name_list_[i].first);
19333  }
19334 
19335  std::sort(assignment_name_list_.begin(),assignment_name_list_.end());
19336 
19337  std::unique_copy(assignment_name_list_.begin(),
19338  assignment_name_list_.end (),
19339  std::back_inserter(assignment_list));
19340 
19341  return assignment_list.size();
19342  }
19343 
19344  void clear()
19345  {
19346  symbol_name_list_ .clear();
19347  assignment_name_list_.clear();
19348  retparam_list_ .clear();
19349  return_present_ = false;
19350  final_stmt_return_ = false;
19351  }
19352 
19354  {
19355  return collect_variables_;
19356  }
19357 
19359  {
19360  return collect_functions_;
19361  }
19362 
19364  {
19365  return collect_assignments_;
19366  }
19367 
19368  bool return_present() const
19369  {
19370  return return_present_;
19371  }
19372 
19373  bool final_stmt_return() const
19374  {
19375  return final_stmt_return_;
19376  }
19377 
19378  typedef std::vector<std::string> retparam_list_t;
19379 
19381  {
19382  return retparam_list_;
19383  }
19384 
19385  private:
19386 
19387  inline void add_symbol(const std::string& symbol, const symbol_type st)
19388  {
19389  switch (st)
19390  {
19391  case e_st_variable :
19392  case e_st_vector :
19393  case e_st_string :
19394  case e_st_local_variable :
19395  case e_st_local_vector :
19396  case e_st_local_string : if (collect_variables_)
19397  symbol_name_list_
19398  .push_back(std::make_pair(symbol, st));
19399  break;
19400 
19401  case e_st_function : if (collect_functions_)
19402  symbol_name_list_
19403  .push_back(std::make_pair(symbol, st));
19404  break;
19405 
19406  default : return;
19407  }
19408  }
19409 
19410  inline void add_assignment(const std::string& symbol, const symbol_type st)
19411  {
19412  switch (st)
19413  {
19414  case e_st_variable :
19415  case e_st_vector :
19416  case e_st_string : if (collect_assignments_)
19417  assignment_name_list_
19418  .push_back(std::make_pair(symbol, st));
19419  break;
19420 
19421  default : return;
19422  }
19423  }
19424 
19425  std::size_t options_;
19434 
19435  friend class parser<T>;
19436  };
19437 
19439  {
19440  private:
19441 
19442  typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t;
19443  typedef disabled_entity_set_t::iterator des_itr_t;
19444 
19445  public:
19446 
19448  {
19450  e_replacer = 1,
19451  e_joiner = 2,
19452  e_numeric_check = 4,
19453  e_bracket_check = 8,
19454  e_sequence_check = 16,
19455  e_commutative_check = 32,
19456  e_strength_reduction = 64,
19457  e_disable_vardef = 128,
19458  e_collect_vars = 256,
19459  e_collect_funcs = 512,
19460  e_collect_assings = 1024,
19461  e_disable_usr_on_rsrvd = 2048,
19462  e_disable_zero_return = 4096
19463  };
19464 
19466  {
19467  e_bf_unknown = 0,
19468  e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin ,
19469  e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh ,
19470  e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos ,
19471  e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal ,
19472  e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 ,
19473  e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp ,
19474  e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p ,
19475  e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max ,
19476  e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul ,
19477  e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round ,
19478  e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin ,
19479  e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum ,
19480  e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc ,
19481  e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad,
19482  e_bf_rad2deg , e_bf_grad2deg
19483  };
19484 
19486  {
19487  e_ctrl_unknown = 0,
19493  e_ctrl_return
19494  };
19495 
19497  {
19498  e_logic_unknown = 0,
19499  e_logic_and, e_logic_nand, e_logic_nor,
19500  e_logic_not, e_logic_or, e_logic_xnor,
19501  e_logic_xor, e_logic_scand, e_logic_scor
19502  };
19503 
19505  {
19506  e_arith_unknown = 0,
19507  e_arith_add, e_arith_sub, e_arith_mul,
19508  e_arith_div, e_arith_mod, e_arith_pow
19509  };
19510 
19512  {
19513  e_assign_unknown = 0,
19514  e_assign_assign, e_assign_addass, e_assign_subass,
19515  e_assign_mulass, e_assign_divass, e_assign_modass
19516  };
19517 
19519  {
19520  e_ineq_unknown = 0,
19521  e_ineq_lt, e_ineq_lte, e_ineq_eq,
19522  e_ineq_equal, e_ineq_ne, e_ineq_nequal,
19523  e_ineq_gte, e_ineq_gt
19524  };
19525 
19526  static const std::size_t compile_all_opts = e_replacer +
19527  e_joiner +
19528  e_numeric_check +
19529  e_bracket_check +
19530  e_sequence_check +
19531  e_commutative_check +
19532  e_strength_reduction;
19533 
19534  settings_store(const std::size_t compile_options = compile_all_opts)
19535  {
19536  load_compile_options(compile_options);
19537  }
19538 
19540  {
19541  disabled_func_set_.clear();
19542  return (*this);
19543  }
19544 
19546  {
19547  disabled_ctrl_set_.clear();
19548  return (*this);
19549  }
19550 
19552  {
19553  disabled_logic_set_.clear();
19554  return (*this);
19555  }
19556 
19558  {
19559  disabled_arithmetic_set_.clear();
19560  return (*this);
19561  }
19562 
19564  {
19565  disabled_assignment_set_.clear();
19566  return (*this);
19567  }
19568 
19570  {
19571  disabled_inequality_set_.clear();
19572  return (*this);
19573  }
19574 
19576  {
19577  disable_vardef_ = false;
19578  return (*this);
19579  }
19580 
19582  {
19583  std::copy(details::base_function_list,
19585  std::insert_iterator<disabled_entity_set_t>
19586  (disabled_func_set_, disabled_func_set_.begin()));
19587  return (*this);
19588  }
19589 
19591  {
19592  std::copy(details::cntrl_struct_list,
19594  std::insert_iterator<disabled_entity_set_t>
19595  (disabled_ctrl_set_, disabled_ctrl_set_.begin()));
19596  return (*this);
19597  }
19598 
19600  {
19601  std::copy(details::logic_ops_list,
19603  std::insert_iterator<disabled_entity_set_t>
19604  (disabled_logic_set_, disabled_logic_set_.begin()));
19605  return (*this);
19606  }
19607 
19609  {
19610  std::copy(details::arithmetic_ops_list,
19612  std::insert_iterator<disabled_entity_set_t>
19613  (disabled_arithmetic_set_, disabled_arithmetic_set_.begin()));
19614  return (*this);
19615  }
19616 
19618  {
19619  std::copy(details::assignment_ops_list,
19621  std::insert_iterator<disabled_entity_set_t>
19622  (disabled_assignment_set_, disabled_assignment_set_.begin()));
19623  return (*this);
19624  }
19625 
19627  {
19628  std::copy(details::inequality_ops_list,
19630  std::insert_iterator<disabled_entity_set_t>
19631  (disabled_inequality_set_, disabled_inequality_set_.begin()));
19632  return (*this);
19633  }
19634 
19636  {
19637  disable_vardef_ = true;
19638  return (*this);
19639  }
19640 
19641  bool replacer_enabled () const { return enable_replacer_; }
19642  bool commutative_check_enabled () const { return enable_commutative_check_; }
19643  bool joiner_enabled () const { return enable_joiner_; }
19644  bool numeric_check_enabled () const { return enable_numeric_check_; }
19645  bool bracket_check_enabled () const { return enable_bracket_check_; }
19646  bool sequence_check_enabled () const { return enable_sequence_check_; }
19647  bool strength_reduction_enabled () const { return enable_strength_reduction_; }
19648  bool collect_variables_enabled () const { return enable_collect_vars_; }
19649  bool collect_functions_enabled () const { return enable_collect_funcs_; }
19650  bool collect_assignments_enabled() const { return enable_collect_assings_; }
19651  bool vardef_disabled () const { return disable_vardef_; }
19652  bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; }
19653  bool zero_return_disabled () const { return disable_zero_return_; }
19654 
19655  bool function_enabled(const std::string& function_name) const
19656  {
19657  if (disabled_func_set_.empty())
19658  return true;
19659  else
19660  return (disabled_func_set_.end() == disabled_func_set_.find(function_name));
19661  }
19662 
19663  bool control_struct_enabled(const std::string& control_struct) const
19664  {
19665  if (disabled_ctrl_set_.empty())
19666  return true;
19667  else
19668  return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct));
19669  }
19670 
19671  bool logic_enabled(const std::string& logic_operation) const
19672  {
19673  if (disabled_logic_set_.empty())
19674  return true;
19675  else
19676  return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation));
19677  }
19678 
19679  bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const
19680  {
19681  if (disabled_logic_set_.empty())
19682  return true;
19683  else
19684  return disabled_arithmetic_set_.end() == disabled_arithmetic_set_
19685  .find(arith_opr_to_string(arithmetic_operation));
19686  }
19687 
19688  bool assignment_enabled(const details::operator_type& assignment) const
19689  {
19690  if (disabled_assignment_set_.empty())
19691  return true;
19692  else
19693  return disabled_assignment_set_.end() == disabled_assignment_set_
19694  .find(assign_opr_to_string(assignment));
19695  }
19696 
19697  bool inequality_enabled(const details::operator_type& inequality) const
19698  {
19699  if (disabled_inequality_set_.empty())
19700  return true;
19701  else
19702  return disabled_inequality_set_.end() == disabled_inequality_set_
19703  .find(inequality_opr_to_string(inequality));
19704  }
19705 
19706  bool function_disabled(const std::string& function_name) const
19707  {
19708  if (disabled_func_set_.empty())
19709  return false;
19710  else
19711  return (disabled_func_set_.end() != disabled_func_set_.find(function_name));
19712  }
19713 
19714  bool control_struct_disabled(const std::string& control_struct) const
19715  {
19716  if (disabled_ctrl_set_.empty())
19717  return false;
19718  else
19719  return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct));
19720  }
19721 
19722  bool logic_disabled(const std::string& logic_operation) const
19723  {
19724  if (disabled_logic_set_.empty())
19725  return false;
19726  else
19727  return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation));
19728  }
19729 
19730  bool assignment_disabled(const details::operator_type assignment_operation) const
19731  {
19732  if (disabled_assignment_set_.empty())
19733  return false;
19734  else
19735  return disabled_assignment_set_.end() != disabled_assignment_set_
19736  .find(assign_opr_to_string(assignment_operation));
19737  }
19738 
19739  bool arithmetic_disabled(const details::operator_type arithmetic_operation) const
19740  {
19741  if (disabled_arithmetic_set_.empty())
19742  return false;
19743  else
19744  return disabled_arithmetic_set_.end() != disabled_arithmetic_set_
19745  .find(arith_opr_to_string(arithmetic_operation));
19746  }
19747 
19748  bool inequality_disabled(const details::operator_type& inequality) const
19749  {
19750  if (disabled_inequality_set_.empty())
19751  return false;
19752  else
19753  return disabled_inequality_set_.end() != disabled_inequality_set_
19754  .find(inequality_opr_to_string(inequality));
19755  }
19756 
19758  {
19759  if (
19760  (e_bf_unknown != bf) &&
19761  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19762  )
19763  {
19764  disabled_func_set_.insert(details::base_function_list[bf - 1]);
19765  }
19766 
19767  return (*this);
19768  }
19769 
19771  {
19772  if (
19773  (e_ctrl_unknown != ctrl_struct) &&
19774  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19775  )
19776  {
19777  disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]);
19778  }
19779 
19780  return (*this);
19781  }
19782 
19784  {
19785  if (
19786  (e_logic_unknown != logic) &&
19787  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19788  )
19789  {
19790  disabled_logic_set_.insert(details::logic_ops_list[logic - 1]);
19791  }
19792 
19793  return (*this);
19794  }
19795 
19797  {
19798  if (
19799  (e_arith_unknown != arithmetic) &&
19800  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19801  )
19802  {
19803  disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]);
19804  }
19805 
19806  return (*this);
19807  }
19808 
19810  {
19811  if (
19812  (e_assign_unknown != assignment) &&
19813  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19814  )
19815  {
19816  disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]);
19817  }
19818 
19819  return (*this);
19820  }
19821 
19823  {
19824  if (
19825  (e_ineq_unknown != inequality) &&
19826  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19827  )
19828  {
19829  disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]);
19830  }
19831 
19832  return (*this);
19833  }
19834 
19836  {
19837  if (
19838  (e_bf_unknown != bf) &&
19839  (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1))
19840  )
19841  {
19842  const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]);
19843 
19844  if (disabled_func_set_.end() != itr)
19845  {
19846  disabled_func_set_.erase(itr);
19847  }
19848  }
19849 
19850  return (*this);
19851  }
19852 
19854  {
19855  if (
19856  (e_ctrl_unknown != ctrl_struct) &&
19857  (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1))
19858  )
19859  {
19860  const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]);
19861 
19862  if (disabled_ctrl_set_.end() != itr)
19863  {
19864  disabled_ctrl_set_.erase(itr);
19865  }
19866  }
19867 
19868  return (*this);
19869  }
19870 
19872  {
19873  if (
19874  (e_logic_unknown != logic) &&
19875  (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1))
19876  )
19877  {
19878  const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]);
19879 
19880  if (disabled_logic_set_.end() != itr)
19881  {
19882  disabled_logic_set_.erase(itr);
19883  }
19884  }
19885 
19886  return (*this);
19887  }
19888 
19890  {
19891  if (
19892  (e_arith_unknown != arithmetic) &&
19893  (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1))
19894  )
19895  {
19896  const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]);
19897 
19898  if (disabled_arithmetic_set_.end() != itr)
19899  {
19900  disabled_arithmetic_set_.erase(itr);
19901  }
19902  }
19903 
19904  return (*this);
19905  }
19906 
19908  {
19909  if (
19910  (e_assign_unknown != assignment) &&
19911  (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1))
19912  )
19913  {
19914  const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]);
19915 
19916  if (disabled_assignment_set_.end() != itr)
19917  {
19918  disabled_assignment_set_.erase(itr);
19919  }
19920  }
19921 
19922  return (*this);
19923  }
19924 
19926  {
19927  if (
19928  (e_ineq_unknown != inequality) &&
19929  (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1))
19930  )
19931  {
19932  const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]);
19933 
19934  if (disabled_inequality_set_.end() != itr)
19935  {
19936  disabled_inequality_set_.erase(itr);
19937  }
19938  }
19939 
19940  return (*this);
19941  }
19942 
19943  private:
19944 
19945  void load_compile_options(const std::size_t compile_options)
19946  {
19947  enable_replacer_ = (compile_options & e_replacer ) == e_replacer;
19948  enable_joiner_ = (compile_options & e_joiner ) == e_joiner;
19949  enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check;
19950  enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check;
19951  enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check;
19952  enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check;
19953  enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction;
19954  enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars;
19955  enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs;
19956  enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings;
19957  disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef;
19958  disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd;
19959  disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return;
19960  }
19961 
19963  {
19964  switch (opr)
19965  {
19966  case details::e_assign : return ":=";
19967  case details::e_addass : return "+=";
19968  case details::e_subass : return "-=";
19969  case details::e_mulass : return "*=";
19970  case details::e_divass : return "/=";
19971  case details::e_modass : return "%=";
19972  default : return "";
19973  }
19974  }
19975 
19977  {
19978  switch (opr)
19979  {
19980  case details::e_add : return "+";
19981  case details::e_sub : return "-";
19982  case details::e_mul : return "*";
19983  case details::e_div : return "/";
19984  case details::e_mod : return "%";
19985  default : return "";
19986  }
19987  }
19988 
19990  {
19991  switch (opr)
19992  {
19993  case details::e_lt : return "<";
19994  case details::e_lte : return "<=";
19995  case details::e_eq : return "==";
19996  case details::e_equal : return "=";
19997  case details::e_ne : return "!=";
19998  case details::e_nequal: return "<>";
19999  case details::e_gte : return ">=";
20000  case details::e_gt : return ">";
20001  default : return "";
20002  }
20003  }
20004 
20018 
20025 
20026  friend class parser<T>;
20027  };
20028 
20029  typedef settings_store settings_t;
20030 
20031  parser(const settings_t& settings = settings_t())
20032  : settings_(settings),
20033  resolve_unknown_symbol_(false),
20034  results_context_(0),
20035  unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)),
20036  #ifdef _MSC_VER
20037  #pragma warning(push)
20038  #pragma warning (disable:4355)
20039  #endif
20040  sem_(*this),
20041  #ifdef _MSC_VER
20042  #pragma warning(pop)
20043  #endif
20044  operator_joiner_2_(2),
20045  operator_joiner_3_(3)
20046  {
20047  init_precompilation();
20048 
20049  load_operations_map (base_ops_map_ );
20050  load_unary_operations_map (unary_op_map_ );
20051  load_binary_operations_map (binary_op_map_ );
20052  load_inv_binary_operations_map(inv_binary_op_map_);
20053  load_sf3_map (sf3_map_ );
20054  load_sf4_map (sf4_map_ );
20055 
20056  expression_generator_.init_synthesize_map();
20057  expression_generator_.set_parser(*this);
20058  expression_generator_.set_uom(unary_op_map_);
20059  expression_generator_.set_bom(binary_op_map_);
20060  expression_generator_.set_ibom(inv_binary_op_map_);
20061  expression_generator_.set_sf3m(sf3_map_);
20062  expression_generator_.set_sf4m(sf4_map_);
20063  expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled());
20064  }
20065 
20067  {}
20068 
20069  inline void init_precompilation()
20070  {
20071  if (settings_.collect_variables_enabled())
20072  dec_.collect_variables() = true;
20073 
20074  if (settings_.collect_functions_enabled())
20075  dec_.collect_functions() = true;
20076 
20077  if (settings_.collect_assignments_enabled())
20078  dec_.collect_assignments() = true;
20079 
20080  if (settings_.replacer_enabled())
20081  {
20082  symbol_replacer_.clear();
20083  symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number);
20084  symbol_replacer_.add_replace("false","0",lexer::token::e_number);
20085  helper_assembly_.token_modifier_list.clear();
20086  helper_assembly_.register_modifier(&symbol_replacer_);
20087  }
20088 
20089  if (settings_.commutative_check_enabled())
20090  {
20091  for (std::size_t i = 0; i < details::reserved_words_size; ++i)
20092  {
20093  commutative_inserter_.ignore_symbol(details::reserved_words[i]);
20094  }
20095 
20096  helper_assembly_.token_inserter_list.clear();
20097  helper_assembly_.register_inserter(&commutative_inserter_);
20098  }
20099 
20100  if (settings_.joiner_enabled())
20101  {
20102  helper_assembly_.token_joiner_list.clear();
20103  helper_assembly_.register_joiner(&operator_joiner_2_);
20104  helper_assembly_.register_joiner(&operator_joiner_3_);
20105  }
20106 
20107  if (
20108  settings_.numeric_check_enabled () ||
20109  settings_.bracket_check_enabled () ||
20110  settings_.sequence_check_enabled()
20111  )
20112  {
20113  helper_assembly_.token_scanner_list.clear();
20114 
20115  if (settings_.numeric_check_enabled())
20116  {
20117  helper_assembly_.register_scanner(&numeric_checker_);
20118  }
20119 
20120  if (settings_.bracket_check_enabled())
20121  {
20122  helper_assembly_.register_scanner(&bracket_checker_);
20123  }
20124 
20125  if (settings_.sequence_check_enabled())
20126  {
20127  helper_assembly_.register_scanner(&sequence_validator_ );
20128  helper_assembly_.register_scanner(&sequence_validator_3tkns_);
20129  }
20130  }
20131  }
20132 
20133  inline bool compile(const std::string& expression_string, expression<T>& expr)
20134  {
20135  state_ .reset();
20136  error_list_ .clear();
20137  brkcnt_list_ .clear();
20138  synthesis_error_.clear();
20139  sem_ .cleanup();
20140 
20141  return_cleanup();
20142 
20143  expression_generator_.set_allocator(node_allocator_);
20144 
20145  if (expression_string.empty())
20146  {
20147  set_error(
20149  "ERR000 - Empty expression!",
20151 
20152  return false;
20153  }
20154 
20155  if (!init(expression_string))
20156  {
20157  process_lexer_errors();
20158  return false;
20159  }
20160 
20161  if (lexer().empty())
20162  {
20163  set_error(
20165  "ERR001 - Empty expression!",
20167 
20168  return false;
20169  }
20170 
20171  if (!run_assemblies())
20172  {
20173  return false;
20174  }
20175 
20176  symtab_store_.symtab_list_ = expr.get_symbol_table_list();
20177  dec_.clear();
20178 
20179  lexer().begin();
20180 
20181  next_token();
20182 
20183  expression_node_ptr e = parse_corpus();
20184 
20185  if ((0 != e) && (token_t::e_eof == current_token().type))
20186  {
20187  bool* retinvk_ptr = 0;
20188 
20189  if (state_.return_stmt_present)
20190  {
20191  dec_.return_present_ = true;
20192 
20193  e = expression_generator_
20194  .return_envelope(e,results_context_,retinvk_ptr);
20195  }
20196 
20197  expr.set_expression(e);
20198  expr.set_retinvk(retinvk_ptr);
20199 
20200  register_local_vars(expr);
20201  register_return_results(expr);
20202 
20203  return !(!expr);
20204  }
20205  else
20206  {
20207  if (error_list_.empty())
20208  {
20209  set_error(
20211  current_token(),
20212  "ERR002 - Invalid expression encountered",
20214  }
20215 
20216  if ((0 != e) && branch_deletable(e))
20217  {
20218  destroy_node(e);
20219  }
20220 
20221  dec_.clear ();
20222  sem_.cleanup ();
20223  return_cleanup();
20224 
20225  return false;
20226  }
20227  }
20228 
20229  inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab)
20230  {
20231  expression_t expr;
20232 
20233  expr.register_symbol_table(symtab);
20234 
20235  compile(expression_string,expr);
20236 
20237  return expr;
20238  }
20239 
20241  {
20242  for (std::size_t i = 0; i < lexer().size(); ++i)
20243  {
20244  if (lexer()[i].is_error())
20245  {
20246  std::string diagnostic = "ERR003 - ";
20247 
20248  switch (lexer()[i].type)
20249  {
20250  case lexer::token::e_error : diagnostic += "General token error";
20251  break;
20252 
20253  case lexer::token::e_err_symbol : diagnostic += "Symbol error";
20254  break;
20255 
20256  case lexer::token::e_err_number : diagnostic += "Invalid numeric token";
20257  break;
20258 
20259  case lexer::token::e_err_string : diagnostic += "Invalid string token";
20260  break;
20261 
20262  case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token";
20263  break;
20264 
20265  default : diagnostic += "Unknown compiler error";
20266  }
20267 
20268  set_error(
20270  lexer()[i],
20271  diagnostic + ": " + lexer()[i].value,
20273  }
20274  }
20275  }
20276 
20277  inline bool run_assemblies()
20278  {
20279  if (settings_.commutative_check_enabled())
20280  {
20281  helper_assembly_.run_inserters(lexer());
20282  }
20283 
20284  if (settings_.joiner_enabled())
20285  {
20286  helper_assembly_.run_joiners(lexer());
20287  }
20288 
20289  if (settings_.replacer_enabled())
20290  {
20291  helper_assembly_.run_modifiers(lexer());
20292  }
20293 
20294  if (
20295  settings_.numeric_check_enabled () ||
20296  settings_.bracket_check_enabled () ||
20297  settings_.sequence_check_enabled()
20298  )
20299  {
20300  if (!helper_assembly_.run_scanners(lexer()))
20301  {
20302  if (helper_assembly_.error_token_scanner)
20303  {
20304  lexer::helper::bracket_checker* bracket_checker_ptr = 0;
20305  lexer::helper::numeric_checker* numeric_checker_ptr = 0;
20306  lexer::helper::sequence_validator* sequence_validator_ptr = 0;
20307  lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0;
20308 
20309  if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner)))
20310  {
20311  set_error(
20313  bracket_checker_ptr->error_token(),
20314  "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'",
20316  }
20317  else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner)))
20318  {
20319  for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i)
20320  {
20321  lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)];
20322 
20323  set_error(
20325  error_token,
20326  "ERR005 - Invalid numeric token: '" + error_token.value + "'",
20328  }
20329 
20330  if (numeric_checker_ptr->error_count())
20331  {
20332  numeric_checker_ptr->clear_errors();
20333  }
20334  }
20335  else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner)))
20336  {
20337  for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i)
20338  {
20339  std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i);
20340 
20341  set_error(
20343  error_token.first,
20344  "ERR006 - Invalid token sequence: '" +
20345  error_token.first.value + "' and '" +
20346  error_token.second.value + "'",
20348  }
20349 
20350  if (sequence_validator_ptr->error_count())
20351  {
20352  sequence_validator_ptr->clear_errors();
20353  }
20354  }
20355  else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner)))
20356  {
20357  for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i)
20358  {
20359  std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i);
20360 
20361  set_error(
20363  error_token.first,
20364  "ERR007 - Invalid token sequence: '" +
20365  error_token.first.value + "' and '" +
20366  error_token.second.value + "'",
20368  }
20369 
20370  if (sequence_validator3_ptr->error_count())
20371  {
20372  sequence_validator3_ptr->clear_errors();
20373  }
20374  }
20375  }
20376 
20377  return false;
20378  }
20379  }
20380 
20381  return true;
20382  }
20383 
20384  inline settings_store& settings()
20385  {
20386  return settings_;
20387  }
20388 
20389  inline parser_error::type get_error(const std::size_t& index) const
20390  {
20391  if (index < error_list_.size())
20392  return error_list_[index];
20393  else
20394  throw std::invalid_argument("parser::get_error() - Invalid error index specificed");
20395  }
20396 
20397  inline std::string error() const
20398  {
20399  if (!error_list_.empty())
20400  {
20401  return error_list_[0].diagnostic;
20402  }
20403  else
20404  return std::string("No Error");
20405  }
20406 
20407  inline std::size_t error_count() const
20408  {
20409  return error_list_.size();
20410  }
20411 
20412  inline dependent_entity_collector& dec()
20413  {
20414  return dec_;
20415  }
20416 
20417  inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol)
20418  {
20419  if (!settings_.replacer_enabled())
20420  return false;
20421  else if (details::is_reserved_word(old_symbol))
20422  return false;
20423  else
20424  return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol);
20425  }
20426 
20427  inline bool remove_replace_symbol(const std::string& symbol)
20428  {
20429  if (!settings_.replacer_enabled())
20430  return false;
20431  else if (details::is_reserved_word(symbol))
20432  return false;
20433  else
20434  return symbol_replacer_.remove(symbol);
20435  }
20436 
20437  inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0))
20438  {
20439  resolve_unknown_symbol_ = true;
20440 
20441  if (usr)
20442  unknown_symbol_resolver_ = usr;
20443  else
20444  unknown_symbol_resolver_ = &default_usr_;
20445  }
20446 
20447  inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr)
20448  {
20449  enable_unknown_symbol_resolver(&usr);
20450  }
20451 
20453  {
20454  resolve_unknown_symbol_ = false;
20455  unknown_symbol_resolver_ = &default_usr_;
20456  }
20457 
20458  private:
20459 
20460  inline bool valid_base_operation(const std::string& symbol) const
20461  {
20462  const std::size_t length = symbol.size();
20463 
20464  if (
20465  (length < 3) || // Shortest base op symbol length
20466  (length > 9) // Longest base op symbol length
20467  )
20468  return false;
20469  else
20470  return settings_.function_enabled(symbol) &&
20471  (base_ops_map_.end() != base_ops_map_.find(symbol));
20472  }
20473 
20474  inline bool valid_vararg_operation(const std::string& symbol) const
20475  {
20476  static const std::string s_sum = "sum" ;
20477  static const std::string s_mul = "mul" ;
20478  static const std::string s_avg = "avg" ;
20479  static const std::string s_min = "min" ;
20480  static const std::string s_max = "max" ;
20481  static const std::string s_mand = "mand";
20482  static const std::string s_mor = "mor" ;
20483  static const std::string s_multi = "~" ;
20484  static const std::string s_mswitch = "[*]" ;
20485 
20486  return
20487  (
20488  details::imatch(symbol,s_sum ) ||
20489  details::imatch(symbol,s_mul ) ||
20490  details::imatch(symbol,s_avg ) ||
20491  details::imatch(symbol,s_min ) ||
20492  details::imatch(symbol,s_max ) ||
20493  details::imatch(symbol,s_mand ) ||
20494  details::imatch(symbol,s_mor ) ||
20495  details::imatch(symbol,s_multi ) ||
20496  details::imatch(symbol,s_mswitch)
20497  ) &&
20498  settings_.function_enabled(symbol);
20499  }
20500 
20502  {
20503  return settings_.arithmetic_disabled(operation);
20504  }
20505 
20507  {
20508  return settings_.assignment_disabled(operation);
20509  }
20510 
20512  {
20513  return settings_.inequality_disabled(operation);
20514  }
20515 
20516  #ifdef exprtk_enable_debugging
20517  inline void next_token()
20518  {
20519  const std::string ct_str = current_token().value;
20520  parser_helper::next_token();
20521  const std::string depth(2 * state_.scope_depth,' ');
20522  exprtk_debug(("%s"
20523  "prev[%s] --> curr[%s]\n",
20524  depth.c_str(),
20525  ct_str.c_str(),
20526  current_token().value.c_str()));
20527  }
20528  #endif
20529 
20531  {
20532  std::vector<expression_node_ptr> arg_list;
20533  std::vector<bool> side_effect_list;
20534 
20535  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
20536 
20537  lexer::token begin_token;
20538  lexer::token end_token;
20539 
20540  for ( ; ; )
20541  {
20542  state_.side_effect_present = false;
20543 
20544  begin_token = current_token();
20545 
20546  expression_node_ptr arg = parse_expression();
20547 
20548  if (0 == arg)
20549  {
20550  if (error_list_.empty())
20551  {
20552  set_error(
20554  current_token(),
20555  "ERR008 - Invalid expression encountered",
20557  }
20558 
20559  return error_node();
20560  }
20561  else
20562  {
20563  arg_list.push_back(arg);
20564 
20565  side_effect_list.push_back(state_.side_effect_present);
20566 
20567  end_token = current_token();
20568 
20569  const std::string sub_expr = construct_subexpr(begin_token, end_token);
20570 
20571  exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n",
20572  static_cast<int>(arg_list.size() - 1),
20573  sub_expr.c_str()));
20574 
20575  exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n",
20576  static_cast<int>(arg_list.size() - 1),
20577  state_.side_effect_present ? "true" : "false"));
20578 
20579  exprtk_debug(("-------------------------------------------------\n"));
20580  }
20581 
20582  if (lexer().finished())
20583  break;
20584  else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold))
20585  {
20586  if (lexer().finished())
20587  break;
20588  else
20589  next_token();
20590  }
20591  }
20592 
20593  if (
20594  !arg_list.empty() &&
20595  is_return_node(arg_list.back())
20596  )
20597  {
20598  dec_.final_stmt_return_ = true;
20599  }
20600 
20601  const expression_node_ptr result = simplify(arg_list,side_effect_list);
20602 
20603  sdd.delete_ptr = (0 == result);
20604 
20605  return result;
20606  }
20607 
20609  {
20610  std::string result = lexer().substr(begin_token.position,end_token.position);
20611 
20612  for (std::size_t i = 0; i < result.size(); ++i)
20613  {
20614  if (details::is_whitespace(result[i])) result[i] = ' ';
20615  }
20616 
20617  return result;
20618  }
20619 
20620  static const precedence_level default_precedence = e_level00;
20621 
20622  struct state_t
20623  {
20624  inline void set(const precedence_level& l,
20625  const precedence_level& r,
20626  const details::operator_type& o)
20627  {
20628  left = l;
20629  right = r;
20630  operation = o;
20631  }
20632 
20633  inline void reset()
20634  {
20635  left = e_level00;
20636  right = e_level00;
20637  operation = details::e_default;
20638  }
20639 
20643  };
20644 
20646  {
20647  expression_node_ptr expression = parse_branch(precedence);
20648 
20649  if (0 == expression)
20650  {
20651  return error_node();
20652  }
20653 
20654  bool break_loop = false;
20655 
20656  state_t current_state;
20657 
20658  for ( ; ; )
20659  {
20660  current_state.reset();
20661 
20662  switch (current_token().type)
20663  {
20664  case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break;
20665  case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break;
20666  case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break;
20667  case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break;
20668  case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break;
20669  case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break;
20670  case token_t::e_swap : current_state.set(e_level00,e_level00,details::e_swap ); break;
20671  case token_t::e_lt : current_state.set(e_level05,e_level06,details:: e_lt); break;
20672  case token_t::e_lte : current_state.set(e_level05,e_level06,details:: e_lte); break;
20673  case token_t::e_eq : current_state.set(e_level05,e_level06,details:: e_eq); break;
20674  case token_t::e_ne : current_state.set(e_level05,e_level06,details:: e_ne); break;
20675  case token_t::e_gte : current_state.set(e_level05,e_level06,details:: e_gte); break;
20676  case token_t::e_gt : current_state.set(e_level05,e_level06,details:: e_gt); break;
20677  case token_t::e_add : current_state.set(e_level07,e_level08,details:: e_add); break;
20678  case token_t::e_sub : current_state.set(e_level07,e_level08,details:: e_sub); break;
20679  case token_t::e_div : current_state.set(e_level10,e_level11,details:: e_div); break;
20680  case token_t::e_mul : current_state.set(e_level10,e_level11,details:: e_mul); break;
20681  case token_t::e_mod : current_state.set(e_level10,e_level11,details:: e_mod); break;
20682  case token_t::e_pow : current_state.set(e_level12,e_level12,details:: e_pow); break;
20683  default : if (token_t::e_symbol == current_token().type)
20684  {
20685  static const std::string s_and = "and";
20686  static const std::string s_nand = "nand";
20687  static const std::string s_or = "or";
20688  static const std::string s_nor = "nor";
20689  static const std::string s_xor = "xor";
20690  static const std::string s_xnor = "xnor";
20691  static const std::string s_in = "in";
20692  static const std::string s_like = "like";
20693  static const std::string s_ilike = "ilike";
20694  static const std::string s_and1 = "&";
20695  static const std::string s_or1 = "|";
20696  static const std::string s_not = "not";
20697 
20698  if (details::imatch(current_token().value,s_and))
20699  {
20700  current_state.set(e_level03, e_level04, details::e_and);
20701  break;
20702  }
20703  else if (details::imatch(current_token().value,s_and1))
20704  {
20705  #ifndef exprtk_disable_sc_andor
20706  current_state.set(e_level03, e_level04, details::e_scand);
20707  #else
20708  current_state.set(e_level03, e_level04, details::e_and);
20709  #endif
20710  break;
20711  }
20712  else if (details::imatch(current_token().value,s_nand))
20713  {
20714  current_state.set(e_level03, e_level04, details::e_nand);
20715  break;
20716  }
20717  else if (details::imatch(current_token().value,s_or))
20718  {
20719  current_state.set(e_level01, e_level02, details::e_or);
20720  break;
20721  }
20722  else if (details::imatch(current_token().value,s_or1))
20723  {
20724  #ifndef exprtk_disable_sc_andor
20725  current_state.set(e_level01, e_level02, details::e_scor);
20726  #else
20727  current_state.set(e_level01, e_level02, details::e_or);
20728  #endif
20729  break;
20730  }
20731  else if (details::imatch(current_token().value,s_nor))
20732  {
20733  current_state.set(e_level01, e_level02, details::e_nor);
20734  break;
20735  }
20736  else if (details::imatch(current_token().value,s_xor))
20737  {
20738  current_state.set(e_level01, e_level02, details::e_xor);
20739  break;
20740  }
20741  else if (details::imatch(current_token().value,s_xnor))
20742  {
20743  current_state.set(e_level01, e_level02, details::e_xnor);
20744  break;
20745  }
20746  else if (details::imatch(current_token().value,s_in))
20747  {
20748  current_state.set(e_level04, e_level04, details::e_in);
20749  break;
20750  }
20751  else if (details::imatch(current_token().value,s_like))
20752  {
20753  current_state.set(e_level04, e_level04, details::e_like);
20754  break;
20755  }
20756  else if (details::imatch(current_token().value,s_ilike))
20757  {
20758  current_state.set(e_level04, e_level04, details::e_ilike);
20759  break;
20760  }
20761  else if (details::imatch(current_token().value,s_not))
20762  {
20763  break;
20764  }
20765  }
20766 
20767  break_loop = true;
20768  }
20769 
20770  if (break_loop)
20771  {
20772  parse_pending_string_rangesize(expression);
20773  break;
20774  }
20775  else if (current_state.left < precedence)
20776  break;
20777 
20778  const lexer::token prev_token = current_token();
20779 
20780  next_token();
20781 
20782  expression_node_ptr right_branch = error_node();
20783  expression_node_ptr new_expression = error_node();
20784 
20785  if (is_invalid_arithmetic_operation(current_state.operation))
20786  {
20787  free_node(node_allocator_,expression);
20788 
20789  set_error(
20791  prev_token,
20792  "ERR009 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'",
20794 
20795  return error_node();
20796  }
20797  else if (is_invalid_inequality_operation(current_state.operation))
20798  {
20799  free_node(node_allocator_,expression);
20800 
20801  set_error(
20803  prev_token,
20804  "ERR010 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'",
20806 
20807  return error_node();
20808  }
20809  else if (is_invalid_assignment_operation(current_state.operation))
20810  {
20811  free_node(node_allocator_,expression);
20812 
20813  set_error(
20815  prev_token,
20816  "ERR011 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'",
20818 
20819  return error_node();
20820  }
20821 
20822  if (0 != (right_branch = parse_expression(current_state.right)))
20823  {
20824  if (
20826  details::is_return_node(right_branch)
20827  )
20828  {
20829  free_node(node_allocator_, expression);
20830  free_node(node_allocator_, right_branch);
20831 
20832  set_error(
20834  prev_token,
20835  "ERR012 - Return statements cannot be part of sub-expressions",
20837 
20838  return error_node();
20839  }
20840 
20841  new_expression = expression_generator_
20842  (
20843  current_state.operation,
20844  expression,
20845  right_branch
20846  );
20847  }
20848 
20849  if (0 == new_expression)
20850  {
20851  if (error_list_.empty())
20852  {
20853  set_error(
20855  prev_token,
20856  !synthesis_error_.empty() ?
20857  synthesis_error_ :
20858  "ERR013 - General parsing error at token: '" + prev_token.value + "'",
20860  }
20861 
20862  free_node(node_allocator_, expression);
20863  free_node(node_allocator_, right_branch);
20864 
20865  return error_node();
20866  }
20867  else
20868  {
20869  if (
20870  token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
20871  (precedence == e_level00)
20872  )
20873  {
20874  expression = parse_ternary_conditional_statement(new_expression);
20875  }
20876  else
20877  expression = new_expression;
20878 
20879  parse_pending_string_rangesize(expression);
20880  }
20881  }
20882 
20883  return expression;
20884  }
20885 
20887  {
20888  {
20890  ubn_t* n = dynamic_cast<ubn_t*>(node);
20891 
20892  if (n)
20893  {
20894  expression_node_ptr un_r = n->branch(0);
20895  n->release();
20896  free_node(node_allocator_,node);
20897  node = un_r;
20898 
20899  return true;
20900  }
20901  }
20902 
20903  {
20905 
20906  uvn_t* n = dynamic_cast<uvn_t*>(node);
20907 
20908  if (n)
20909  {
20910  const T& v = n->v();
20911  expression_node_ptr return_node = error_node();
20912 
20913  if (
20914  (0 != (return_node = symtab_store_.get_variable(v))) ||
20915  (0 != (return_node = sem_ .get_variable(v)))
20916  )
20917  {
20918  free_node(node_allocator_,node);
20919  node = return_node;
20920 
20921  return true;
20922  }
20923  else
20924  {
20925  set_error(
20927  current_token(),
20928  "ERR014 - Failed to find variable node in symbol table",
20930 
20931  free_node(node_allocator_,node);
20932 
20933  return false;
20934  }
20935  }
20936  }
20937 
20938  return false;
20939  }
20940 
20942  {
20943  return reinterpret_cast<expression_node_ptr>(0);
20944  }
20945 
20946  template <typename Type, std::size_t N>
20948  {
20949  typedef Type* ptr_t;
20950 
20952  : delete_ptr(true),
20953  parser_(pr),
20954  p_(&p)
20955  {}
20956 
20958  : delete_ptr(true),
20959  parser_(pr),
20960  p_(&p[0])
20961  {}
20962 
20964  {
20965  if (delete_ptr)
20966  {
20967  for (std::size_t i = 0; i < N; ++i)
20968  {
20969  free_node(parser_.node_allocator_,p_[i]);
20970  }
20971  }
20972  }
20973 
20977 
20978  private:
20979 
20980  scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
20981  };
20982 
20983  template <typename Type>
20985  {
20986  typedef Type* ptr_t;
20987 
20988  scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq)
20989  : delete_ptr(true),
20990  parser_(pr),
20991  deq_(deq)
20992  {}
20993 
20995  {
20996  if (delete_ptr && !deq_.empty())
20997  {
20998  for (std::size_t i = 0; i < deq_.size(); ++i)
20999  {
21000  free_node(parser_.node_allocator_,deq_[i]);
21001  }
21002 
21003  deq_.clear();
21004  }
21005  }
21006 
21009  std::deque<ptr_t>& deq_;
21010 
21011  private:
21012 
21014  };
21015 
21016  template <typename Type>
21018  {
21019  typedef Type* ptr_t;
21020 
21021  scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec)
21022  : delete_ptr(true),
21023  parser_(pr),
21024  vec_(vec)
21025  {}
21026 
21028  {
21029  if (delete_ptr && !vec_.empty())
21030  {
21031  for (std::size_t i = 0; i < vec_.size(); ++i)
21032  {
21033  free_node(parser_.node_allocator_,vec_[i]);
21034  }
21035 
21036  vec_.clear();
21037  }
21038  }
21039 
21042  std::vector<ptr_t>& vec_;
21043 
21044  private:
21045 
21047  };
21048 
21050  {
21051  explicit scoped_bool_negator(bool& bb)
21052  : b(bb)
21053  { b = !b; }
21054 
21056  { b = !b; }
21057 
21058  bool& b;
21059  };
21060 
21062  {
21063  explicit scoped_bool_or_restorer(bool& bb)
21064  : b(bb),
21065  original_value_(bb)
21066  {}
21067 
21069  {
21070  b = b || original_value_;
21071  }
21072 
21073  bool& b;
21075  };
21076 
21078  {
21079  expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
21080 
21081  switch (function->param_count)
21082  {
21083  case 0 : func_node = parse_function_call_0 (function,function_name); break;
21084  case 1 : func_node = parse_function_call< 1>(function,function_name); break;
21085  case 2 : func_node = parse_function_call< 2>(function,function_name); break;
21086  case 3 : func_node = parse_function_call< 3>(function,function_name); break;
21087  case 4 : func_node = parse_function_call< 4>(function,function_name); break;
21088  case 5 : func_node = parse_function_call< 5>(function,function_name); break;
21089  case 6 : func_node = parse_function_call< 6>(function,function_name); break;
21090  case 7 : func_node = parse_function_call< 7>(function,function_name); break;
21091  case 8 : func_node = parse_function_call< 8>(function,function_name); break;
21092  case 9 : func_node = parse_function_call< 9>(function,function_name); break;
21093  case 10 : func_node = parse_function_call<10>(function,function_name); break;
21094  case 11 : func_node = parse_function_call<11>(function,function_name); break;
21095  case 12 : func_node = parse_function_call<12>(function,function_name); break;
21096  case 13 : func_node = parse_function_call<13>(function,function_name); break;
21097  case 14 : func_node = parse_function_call<14>(function,function_name); break;
21098  case 15 : func_node = parse_function_call<15>(function,function_name); break;
21099  case 16 : func_node = parse_function_call<16>(function,function_name); break;
21100  case 17 : func_node = parse_function_call<17>(function,function_name); break;
21101  case 18 : func_node = parse_function_call<18>(function,function_name); break;
21102  case 19 : func_node = parse_function_call<19>(function,function_name); break;
21103  case 20 : func_node = parse_function_call<20>(function,function_name); break;
21104  default : {
21105  set_error(
21107  current_token(),
21108  "ERR015 - Invalid number of parameters for function: '" + function_name + "'",
21110 
21111  return error_node();
21112  }
21113  }
21114 
21115  if (func_node)
21116  return func_node;
21117  else
21118  {
21119  set_error(
21121  current_token(),
21122  "ERR016 - Failed to generate call to function: '" + function_name + "'",
21124 
21125  return error_node();
21126  }
21127  }
21128 
21129  template <std::size_t NumberofParameters>
21130  inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name)
21131  {
21132  #ifdef _MSC_VER
21133  #pragma warning(push)
21134  #pragma warning(disable: 4127)
21135  #endif
21136  if (0 == NumberofParameters)
21137  {
21138  set_error(
21140  current_token(),
21141  "ERR017 - Expecting ifunction '" + function_name + "' to have non-zero parameter count",
21143 
21144  return error_node();
21145  }
21146  #ifdef _MSC_VER
21147  #pragma warning(pop)
21148  #endif
21149 
21150  expression_node_ptr branch[NumberofParameters];
21151  expression_node_ptr result = error_node();
21152 
21153  std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21154 
21155  scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch);
21156 
21157  next_token();
21158 
21159  if (!token_is(token_t::e_lbracket))
21160  {
21161  set_error(
21163  current_token(),
21164  "ERR018 - Expecting argument list for function: '" + function_name + "'",
21166 
21167  return error_node();
21168  }
21169 
21170  for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
21171  {
21172  branch[i] = parse_expression();
21173 
21174  if (0 == branch[i])
21175  {
21176  set_error(
21178  current_token(),
21179  "ERR019 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'",
21181 
21182  return error_node();
21183  }
21184  else if (i < static_cast<int>(NumberofParameters - 1))
21185  {
21186  if (!token_is(token_t::e_comma))
21187  {
21188  set_error(
21190  current_token(),
21191  "ERR020 - Invalid number of arguments for function: '" + function_name + "'",
21193 
21194  return error_node();
21195  }
21196  }
21197  }
21198 
21199  if (!token_is(token_t::e_rbracket))
21200  {
21201  set_error(
21203  current_token(),
21204  "ERR021 - Invalid number of arguments for function: '" + function_name + "'",
21206 
21207  return error_node();
21208  }
21209  else
21210  result = expression_generator_.function(function,branch);
21211 
21212  sd.delete_ptr = false;
21213 
21214  return result;
21215  }
21216 
21217  inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name)
21218  {
21219  expression_node_ptr result = expression_generator_.function(function);
21220 
21221  state_.side_effect_present = function->has_side_effects();
21222 
21223  next_token();
21224 
21225  if (
21226  token_is(token_t::e_lbracket) &&
21227  !token_is(token_t::e_rbracket)
21228  )
21229  {
21230  set_error(
21232  current_token(),
21233  "ERR022 - Expecting '()' to proceed call to function: '" + function_name + "'",
21235 
21236  free_node(node_allocator_,result);
21237 
21238  return error_node();
21239  }
21240  else
21241  return result;
21242  }
21243 
21244  template <std::size_t MaxNumberofParameters>
21245  inline std::size_t parse_base_function_call(expression_node_ptr (&param_list)[MaxNumberofParameters], const std::string& function_name = "")
21246  {
21247  std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0));
21248 
21249  scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list);
21250 
21251  next_token();
21252 
21253  if (!token_is(token_t::e_lbracket))
21254  {
21255  set_error(
21257  current_token(),
21258  "ERR023 - Expected a '(' at start of function call to '" + function_name +
21259  "', instead got: '" + current_token().value + "'",
21261 
21262  return 0;
21263  }
21264 
21265  if (token_is(token_t::e_rbracket, e_hold))
21266  {
21267  set_error(
21269  current_token(),
21270  "ERR024 - Expected at least one input parameter for function call '" + function_name + "'",
21272 
21273  return 0;
21274  }
21275 
21276  std::size_t param_index = 0;
21277 
21278  for (; param_index < MaxNumberofParameters; ++param_index)
21279  {
21280  param_list[param_index] = parse_expression();
21281 
21282  if (0 == param_list[param_index])
21283  return 0;
21284  else if (token_is(token_t::e_rbracket))
21285  {
21286  sd.delete_ptr = false;
21287  break;
21288  }
21289  else if (token_is(token_t::e_comma))
21290  continue;
21291  else
21292  {
21293  set_error(
21295  current_token(),
21296  "ERR025 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'",
21298 
21299  return 0;
21300  }
21301  }
21302 
21303  if (sd.delete_ptr)
21304  {
21305  set_error(
21307  current_token(),
21308  "ERR026 - Invalid number of input parameters passed to function '" + function_name + "'",
21310 
21311  return 0;
21312  }
21313 
21314  return (param_index + 1);
21315  }
21316 
21318  {
21319  typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t;
21320 
21321  const std::string operation_name = current_token().value;
21322  const token_t diagnostic_token = current_token();
21323 
21324  map_range_t itr_range = base_ops_map_.equal_range(operation_name);
21325 
21326  if (0 == std::distance(itr_range.first,itr_range.second))
21327  {
21328  set_error(
21330  diagnostic_token,
21331  "ERR027 - No entry found for base operation: " + operation_name,
21333 
21334  return error_node();
21335  }
21336 
21337  static const std::size_t MaxNumberofParameters = 4;
21338  expression_node_ptr param_list[MaxNumberofParameters] = {0};
21339 
21340  const std::size_t parameter_count = parse_base_function_call(param_list, operation_name);
21341 
21342  if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters))
21343  {
21344  for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr)
21345  {
21346  const details::base_operation_t& operation = itr->second;
21347 
21348  if (operation.num_params == parameter_count)
21349  {
21350  switch (parameter_count)
21351  {
21352  #define base_opr_case(N) \
21353  case N : { \
21354  expression_node_ptr pl##N[N] = {0}; \
21355  std::copy(param_list, param_list + N, pl##N); \
21356  lodge_symbol(operation_name, e_st_function); \
21357  return expression_generator_(operation.type, pl##N); \
21358  } \
21359 
21360  base_opr_case(1)
21361  base_opr_case(2)
21362  base_opr_case(3)
21363  base_opr_case(4)
21364  #undef base_opr_case
21365  }
21366  }
21367  }
21368  }
21369 
21370  for (std::size_t i = 0; i < MaxNumberofParameters; ++i)
21371  {
21372  free_node(node_allocator_, param_list[i]);
21373  }
21374 
21375  set_error(
21377  diagnostic_token,
21378  "ERR028 - Invalid number of input parameters for call to function: '" + operation_name + "'",
21380 
21381  return error_node();
21382  }
21383 
21385  {
21386  // Parse: [if][(][condition][,][consequent][,][alternative][)]
21387 
21388  expression_node_ptr consequent = error_node();
21389  expression_node_ptr alternative = error_node();
21390 
21391  bool result = true;
21392 
21393  if (!token_is(token_t::e_comma))
21394  {
21395  set_error(
21397  current_token(),
21398  "ERR029 - Expected ',' between if-statement condition and consequent",
21400  result = false;
21401  }
21402  else if (0 == (consequent = parse_expression()))
21403  {
21404  set_error(
21406  current_token(),
21407  "ERR030 - Failed to parse consequent for if-statement",
21409  result = false;
21410  }
21411  else if (!token_is(token_t::e_comma))
21412  {
21413  set_error(
21415  current_token(),
21416  "ERR031 - Expected ',' between if-statement consequent and alternative",
21418  result = false;
21419  }
21420  else if (0 == (alternative = parse_expression()))
21421  {
21422  set_error(
21424  current_token(),
21425  "ERR032 - Failed to parse alternative for if-statement",
21427  result = false;
21428  }
21429  else if (!token_is(token_t::e_rbracket))
21430  {
21431  set_error(
21433  current_token(),
21434  "ERR033 - Expected ')' at the end of if-statement",
21436  result = false;
21437  }
21438 
21439  #ifndef exprtk_disable_string_capabilities
21440  if (result)
21441  {
21442  const bool consq_is_str = is_generally_string_node( consequent);
21443  const bool alter_is_str = is_generally_string_node(alternative);
21444 
21445  if (consq_is_str || alter_is_str)
21446  {
21447  if (consq_is_str && alter_is_str)
21448  {
21449  return expression_generator_
21450  .conditional_string(condition,consequent,alternative);
21451  }
21452 
21453  set_error(
21455  current_token(),
21456  "ERR034 - Return types of ternary if-statement differ",
21458 
21459  result = false;
21460  }
21461  }
21462  #endif
21463 
21464  if (!result)
21465  {
21466  free_node(node_allocator_, condition);
21467  free_node(node_allocator_, consequent);
21468  free_node(node_allocator_,alternative);
21469 
21470  return error_node();
21471  }
21472  else
21473  return expression_generator_
21474  .conditional(condition,consequent,alternative);
21475  }
21476 
21478  {
21479  expression_node_ptr consequent = error_node();
21480  expression_node_ptr alternative = error_node();
21481 
21482  bool result = true;
21483 
21484  if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21485  {
21486  if (0 == (consequent = parse_multi_sequence("if-statement-01")))
21487  {
21488  set_error(
21490  current_token(),
21491  "ERR035 - Failed to parse body of consequent for if-statement",
21493 
21494  result = false;
21495  }
21496  }
21497  else
21498  {
21499  if (
21500  settings_.commutative_check_enabled() &&
21501  token_is(token_t::e_mul,prsrhlpr_t::e_hold)
21502  )
21503  {
21504  next_token();
21505  }
21506 
21507  if (0 != (consequent = parse_expression()))
21508  {
21509  if (!token_is(token_t::e_eof))
21510  {
21511  set_error(
21513  current_token(),
21514  "ERR036 - Expected ';' at the end of the consequent for if-statement",
21516 
21517  result = false;
21518  }
21519  }
21520  else
21521  {
21522  set_error(
21524  current_token(),
21525  "ERR037 - Failed to parse body of consequent for if-statement",
21527 
21528  result = false;
21529  }
21530  }
21531 
21532  if (result)
21533  {
21534  if (details::imatch(current_token().value,"else"))
21535  {
21536  next_token();
21537 
21538  if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
21539  {
21540  if (0 == (alternative = parse_multi_sequence("else-statement-01")))
21541  {
21542  set_error(
21544  current_token(),
21545  "ERR038 - Failed to parse body of the 'else' for if-statement",
21547 
21548  result = false;
21549  }
21550  }
21551  else if (details::imatch(current_token().value,"if"))
21552  {
21553  if (0 == (alternative = parse_conditional_statement()))
21554  {
21555  set_error(
21557  current_token(),
21558  "ERR039 - Failed to parse body of if-else statement",
21560 
21561  result = false;
21562  }
21563  }
21564  else if (0 != (alternative = parse_expression()))
21565  {
21566  if (!token_is(token_t::e_eof))
21567  {
21568  set_error(
21570  current_token(),
21571  "ERR040 - Expected ';' at the end of the 'else-if' for the if-statement",
21573 
21574  result = false;
21575  }
21576  }
21577  else
21578  {
21579  set_error(
21581  current_token(),
21582  "ERR041 - Failed to parse body of the 'else' for if-statement",
21584 
21585  result = false;
21586  }
21587  }
21588  }
21589 
21590  #ifndef exprtk_disable_string_capabilities
21591  if (result)
21592  {
21593  const bool consq_is_str = is_generally_string_node( consequent);
21594  const bool alter_is_str = is_generally_string_node(alternative);
21595 
21596  if (consq_is_str || alter_is_str)
21597  {
21598  if (consq_is_str && alter_is_str)
21599  {
21600  return expression_generator_
21601  .conditional_string(condition, consequent, alternative);
21602  }
21603 
21604  set_error(
21606  current_token(),
21607  "ERR042 - Return types of ternary if-statement differ",
21609 
21610  result = false;
21611  }
21612  }
21613  #endif
21614 
21615  if (!result)
21616  {
21617  free_node(node_allocator_, condition);
21618  free_node(node_allocator_, consequent);
21619  free_node(node_allocator_, alternative);
21620 
21621  return error_node();
21622  }
21623  else
21624  return expression_generator_
21625  .conditional(condition, consequent, alternative);
21626  }
21627 
21629  {
21630  expression_node_ptr condition = error_node();
21631 
21632  next_token();
21633 
21634  if (!token_is(token_t::e_lbracket))
21635  {
21636  set_error(
21638  current_token(),
21639  "ERR043 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'",
21641 
21642  return error_node();
21643  }
21644  else if (0 == (condition = parse_expression()))
21645  {
21646  set_error(
21648  current_token(),
21649  "ERR044 - Failed to parse condition for if-statement",
21651 
21652  return error_node();
21653  }
21654  else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold))
21655  {
21656  // if (x,y,z)
21657  return parse_conditional_statement_01(condition);
21658  }
21659  else if (token_is(token_t::e_rbracket))
21660  {
21661  // 00. if (x) y;
21662  // 01. if (x) y; else z;
21663  // 02. if (x) y; else {z0; ... zn;}
21664  // 03. if (x) y; else if (z) w;
21665  // 04. if (x) y; else if (z) w; else u;
21666  // 05. if (x) y; else if (z) w; else {u0; ... un;}
21667  // 06. if (x) y; else if (z) {w0; ... wn;}
21668  // 07. if (x) {y0; ... yn;}
21669  // 08. if (x) {y0; ... yn;} else z;
21670  // 09. if (x) {y0; ... yn;} else {z0; ... zn;};
21671  // 10. if (x) {y0; ... yn;} else if (z) w;
21672  // 11. if (x) {y0; ... yn;} else if (z) w; else u;
21673  // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;}
21674  // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;}
21675  return parse_conditional_statement_02(condition);
21676  }
21677 
21678  set_error(
21680  current_token(),
21681  "ERR045 - Invalid if-statement",
21683 
21684  free_node(node_allocator_,condition);
21685 
21686  return error_node();
21687  }
21688 
21690  {
21691  // Parse: [condition][?][consequent][:][alternative]
21692  expression_node_ptr consequent = error_node();
21693  expression_node_ptr alternative = error_node();
21694 
21695  bool result = true;
21696 
21697  if (0 == condition)
21698  {
21699  set_error(
21701  current_token(),
21702  "ERR046 - Encountered invalid condition branch for ternary if-statement",
21704 
21705  return error_node();
21706  }
21707  else if (!token_is(token_t::e_ternary))
21708  {
21709  set_error(
21711  current_token(),
21712  "ERR047 - Expected '?' after condition of ternary if-statement",
21714 
21715  result = false;
21716  }
21717  else if (0 == (consequent = parse_expression()))
21718  {
21719  set_error(
21721  current_token(),
21722  "ERR048 - Failed to parse consequent for ternary if-statement",
21724 
21725  result = false;
21726  }
21727  else if (!token_is(token_t::e_colon))
21728  {
21729  set_error(
21731  current_token(),
21732  "ERR049 - Expected ':' between ternary if-statement consequent and alternative",
21734 
21735  result = false;
21736  }
21737  else if (0 == (alternative = parse_expression()))
21738  {
21739  set_error(
21741  current_token(),
21742  "ERR050 - Failed to parse alternative for ternary if-statement",
21744 
21745  result = false;
21746  }
21747 
21748  #ifndef exprtk_disable_string_capabilities
21749  if (result)
21750  {
21751  const bool consq_is_str = is_generally_string_node( consequent);
21752  const bool alter_is_str = is_generally_string_node(alternative);
21753 
21754  if (consq_is_str || alter_is_str)
21755  {
21756  if (consq_is_str && alter_is_str)
21757  {
21758  return expression_generator_
21759  .conditional_string(condition, consequent, alternative);
21760  }
21761 
21762  set_error(
21764  current_token(),
21765  "ERR051 - Return types of ternary if-statement differ",
21767 
21768  result = false;
21769  }
21770  }
21771  #endif
21772 
21773  if (!result)
21774  {
21775  free_node(node_allocator_, condition);
21776  free_node(node_allocator_, consequent);
21777  free_node(node_allocator_, alternative);
21778 
21779  return error_node();
21780  }
21781  else
21782  return expression_generator_
21783  .conditional(condition, consequent, alternative);
21784  }
21785 
21787  {
21788  // Parse: [while][(][test expr][)][{][expression][}]
21789  expression_node_ptr condition = error_node();
21790  expression_node_ptr branch = error_node();
21791  expression_node_ptr result_node = error_node();
21792 
21793  bool result = true;
21794 
21795  next_token();
21796 
21797  if (!token_is(token_t::e_lbracket))
21798  {
21799  set_error(
21801  current_token(),
21802  "ERR052 - Expected '(' at start of while-loop condition statement",
21804 
21805  return error_node();
21806  }
21807  else if (0 == (condition = parse_expression()))
21808  {
21809  set_error(
21811  current_token(),
21812  "ERR053 - Failed to parse condition for while-loop",
21814 
21815  return error_node();
21816  }
21817  else if (!token_is(token_t::e_rbracket))
21818  {
21819  set_error(
21821  current_token(),
21822  "ERR054 - Expected ')' at end of while-loop condition statement",
21824 
21825  result = false;
21826  }
21827 
21828  brkcnt_list_.push_front(false);
21829 
21830  if (result)
21831  {
21832  if (0 == (branch = parse_multi_sequence("while-loop")))
21833  {
21834  set_error(
21836  current_token(),
21837  "ERR055 - Failed to parse body of while-loop"));
21838  result = false;
21839  }
21840  else if (0 == (result_node = expression_generator_.while_loop(condition,
21841  branch,
21842  brkcnt_list_.front())))
21843  {
21844  set_error(
21846  current_token(),
21847  "ERR056 - Failed to synthesize while-loop",
21849 
21850  result = false;
21851  }
21852  }
21853 
21854  if (!result)
21855  {
21856  free_node(node_allocator_, branch);
21857  free_node(node_allocator_, condition);
21858  free_node(node_allocator_, result_node);
21859 
21860  brkcnt_list_.pop_front();
21861 
21862  return error_node();
21863  }
21864  else
21865  return result_node;
21866  }
21867 
21869  {
21870  // Parse: [repeat][{][expression][}][until][(][test expr][)]
21871  expression_node_ptr condition = error_node();
21872  expression_node_ptr branch = error_node();
21873  next_token();
21874 
21875  std::vector<expression_node_ptr> arg_list;
21876  std::vector<bool> side_effect_list;
21877 
21878  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
21879 
21880  brkcnt_list_.push_front(false);
21881 
21882  if (details::imatch(current_token().value,"until"))
21883  {
21884  next_token();
21885  branch = node_allocator_.allocate<details::null_node<T> >();
21886  }
21887  else
21888  {
21889  const token_t::token_type seperator = token_t::e_eof;
21890 
21891  scope_handler sh(*this);
21892 
21893  scoped_bool_or_restorer sbr(state_.side_effect_present);
21894 
21895  for ( ; ; )
21896  {
21897  state_.side_effect_present = false;
21898 
21899  expression_node_ptr arg = parse_expression();
21900 
21901  if (0 == arg)
21902  return error_node();
21903  else
21904  {
21905  arg_list.push_back(arg);
21906  side_effect_list.push_back(state_.side_effect_present);
21907  }
21908 
21909  if (details::imatch(current_token().value,"until"))
21910  {
21911  next_token();
21912  break;
21913  }
21914 
21915  const bool is_next_until = peek_token_is(token_t::e_symbol) &&
21916  peek_token_is("until");
21917 
21918  if (!token_is(seperator) && is_next_until)
21919  {
21920  set_error(
21922  current_token(),
21923  "ERR057 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop",
21925 
21926  return error_node();
21927  }
21928 
21929  if (details::imatch(current_token().value,"until"))
21930  {
21931  next_token();
21932  break;
21933  }
21934  }
21935 
21936  branch = simplify(arg_list,side_effect_list);
21937 
21938  sdd.delete_ptr = (0 == branch);
21939 
21940  if (sdd.delete_ptr)
21941  {
21942  brkcnt_list_.pop_front();
21943 
21944  set_error(
21946  current_token(),
21947  "ERR058 - Failed to parse body of repeat until loop",
21949 
21950  return error_node();
21951  }
21952  }
21953 
21954  if (!token_is(token_t::e_lbracket))
21955  {
21956  brkcnt_list_.pop_front();
21957 
21958  set_error(
21960  current_token(),
21961  "ERR059 - Expected '(' before condition statement of repeat until loop",
21963 
21964  free_node(node_allocator_,branch);
21965 
21966  return error_node();
21967  }
21968  else if (0 == (condition = parse_expression()))
21969  {
21970  brkcnt_list_.pop_front();
21971 
21972  set_error(
21974  current_token(),
21975  "ERR060 - Failed to parse condition for repeat until loop",
21977 
21978  free_node(node_allocator_,branch);
21979 
21980  return error_node();
21981  }
21982  else if (!token_is(token_t::e_rbracket))
21983  {
21984  set_error(
21986  current_token(),
21987  "ERR061 - Expected ')' after condition of repeat until loop",
21989 
21990  free_node(node_allocator_, branch);
21991  free_node(node_allocator_, condition);
21992 
21993  brkcnt_list_.pop_front();
21994 
21995  return error_node();
21996  }
21997 
21998  expression_node_ptr result;
21999 
22000  result = expression_generator_
22001  .repeat_until_loop(condition, branch, brkcnt_list_.front());
22002 
22003  if (0 == result)
22004  {
22005  set_error(
22007  current_token(),
22008  "ERR062 - Failed to synthesize repeat until loop",
22010 
22011  free_node(node_allocator_,condition);
22012 
22013  brkcnt_list_.pop_front();
22014 
22015  return error_node();
22016  }
22017  else
22018  {
22019  brkcnt_list_.pop_front();
22020  return result;
22021  }
22022  }
22023 
22025  {
22026  expression_node_ptr initialiser = error_node();
22027  expression_node_ptr condition = error_node();
22028  expression_node_ptr incrementor = error_node();
22029  expression_node_ptr loop_body = error_node();
22030 
22031  scope_element* se = 0;
22032  bool result = true;
22033 
22034  next_token();
22035 
22036  scope_handler sh(*this);
22037 
22038  if (!token_is(token_t::e_lbracket))
22039  {
22040  set_error(
22042  current_token(),
22043  "ERR063 - Expected '(' at start of for-loop",
22045 
22046  return error_node();
22047  }
22048 
22049  if (!token_is(token_t::e_eof))
22050  {
22051  if (
22052  !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) &&
22053  details::imatch(current_token().value,"var")
22054  )
22055  {
22056  next_token();
22057 
22058  if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
22059  {
22060  set_error(
22062  current_token(),
22063  "ERR064 - Expected a variable at the start of initialiser section of for-loop",
22065 
22066  return error_node();
22067  }
22068  else if (!peek_token_is(token_t::e_assign))
22069  {
22070  set_error(
22072  current_token(),
22073  "ERR065 - Expected variable assignment of initialiser section of for-loop",
22075 
22076  return error_node();
22077  }
22078 
22079  const std::string loop_counter_symbol = current_token().value;
22080 
22081  se = &sem_.get_element(loop_counter_symbol);
22082 
22083  if ((se->name == loop_counter_symbol) && se->active)
22084  {
22085  set_error(
22087  current_token(),
22088  "ERR066 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration",
22090 
22091  return error_node();
22092  }
22093  else if (!symtab_store_.is_variable(loop_counter_symbol))
22094  {
22095  if (
22096  !se->active &&
22097  (se->name == loop_counter_symbol) &&
22098  (se->type == scope_element::e_variable)
22099  )
22100  {
22101  se->active = true;
22102  se->ref_count++;
22103  }
22104  else
22105  {
22106  scope_element nse;
22107  nse.name = loop_counter_symbol;
22108  nse.active = true;
22109  nse.ref_count = 1;
22110  nse.type = scope_element::e_variable;
22111  nse.depth = state_.scope_depth;
22112  nse.data = new T(T(0));
22113  nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
22114 
22115  if (!sem_.add_element(nse))
22116  {
22117  set_error(
22119  current_token(),
22120  "ERR067 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM",
22122 
22123  sem_.free_element(nse);
22124 
22125  result = false;
22126  }
22127  else
22128  {
22129  exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str()));
22130 
22131  state_.activate_side_effect("parse_for_loop()");
22132  }
22133  }
22134  }
22135  }
22136 
22137  if (0 == (initialiser = parse_expression()))
22138  {
22139  set_error(
22141  current_token(),
22142  "ERR068 - Failed to parse initialiser of for-loop",
22144 
22145  result = false;
22146  }
22147  else if (!token_is(token_t::e_eof))
22148  {
22149  set_error(
22151  current_token(),
22152  "ERR069 - Expected ';' after initialiser of for-loop",
22154 
22155  result = false;
22156  }
22157  }
22158 
22159  if (!token_is(token_t::e_eof))
22160  {
22161  if (0 == (condition = parse_expression()))
22162  {
22163  set_error(
22165  current_token(),
22166  "ERR070 - Failed to parse condition of for-loop",
22168 
22169  result = false;
22170  }
22171  else if (!token_is(token_t::e_eof))
22172  {
22173  set_error(
22175  current_token(),
22176  "ERR071 - Expected ';' after condition section of for-loop",
22178 
22179  result = false;
22180  }
22181  }
22182 
22183  if (!token_is(token_t::e_rbracket))
22184  {
22185  if (0 == (incrementor = parse_expression()))
22186  {
22187  set_error(
22189  current_token(),
22190  "ERR072 - Failed to parse incrementor of for-loop",
22192 
22193  result = false;
22194  }
22195  else if (!token_is(token_t::e_rbracket))
22196  {
22197  set_error(
22199  current_token(),
22200  "ERR073 - Expected ')' after incrementor section of for-loop",
22202 
22203  result = false;
22204  }
22205  }
22206 
22207  if (result)
22208  {
22209  brkcnt_list_.push_front(false);
22210 
22211  if (0 == (loop_body = parse_multi_sequence("for-loop")))
22212  {
22213  set_error(
22215  current_token(),
22216  "ERR074 - Failed to parse body of for-loop",
22218 
22219  result = false;
22220  }
22221  }
22222 
22223  if (!result)
22224  {
22225  if (se)
22226  {
22227  se->ref_count--;
22228  }
22229 
22230  free_node(node_allocator_, initialiser);
22231  free_node(node_allocator_, condition);
22232  free_node(node_allocator_, incrementor);
22233  free_node(node_allocator_, loop_body);
22234 
22235  if (!brkcnt_list_.empty())
22236  {
22237  brkcnt_list_.pop_front();
22238  }
22239 
22240  return error_node();
22241  }
22242  else
22243  {
22244  expression_node_ptr result_node =
22245  expression_generator_.for_loop(initialiser,
22246  condition,
22247  incrementor,
22248  loop_body,
22249  brkcnt_list_.front());
22250  brkcnt_list_.pop_front();
22251 
22252  return result_node;
22253  }
22254  }
22255 
22257  {
22258  std::vector<expression_node_ptr> arg_list;
22259  expression_node_ptr result = error_node();
22260 
22261  if (!details::imatch(current_token().value,"switch"))
22262  {
22263  set_error(
22265  current_token(),
22266  "ERR075 - Expected keyword 'switch'",
22268 
22269  return error_node();
22270  }
22271 
22272  scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22273 
22274  next_token();
22275 
22276  if (!token_is(token_t::e_lcrlbracket))
22277  {
22278  set_error(
22280  current_token(),
22281  "ERR076 - Expected '{' for call to switch statement",
22283 
22284  return error_node();
22285  }
22286 
22287  for ( ; ; )
22288  {
22289  if (!details::imatch("case",current_token().value))
22290  {
22291  set_error(
22293  current_token(),
22294  "ERR077 - Expected either a 'case' or 'default' statement",
22296 
22297  return error_node();
22298  }
22299 
22300  next_token();
22301 
22302  expression_node_ptr condition = parse_expression();
22303 
22304  if (0 == condition)
22305  return error_node();
22306  else if (!token_is(token_t::e_colon))
22307  {
22308  set_error(
22310  current_token(),
22311  "ERR078 - Expected ':' for case of switch statement",
22313 
22314  return error_node();
22315  }
22316 
22317  expression_node_ptr consequent = parse_expression();
22318 
22319  if (0 == consequent)
22320  return error_node();
22321  else if (!token_is(token_t::e_eof))
22322  {
22323  set_error(
22325  current_token(),
22326  "ERR079 - Expected ';' at end of case for switch statement",
22328 
22329  return error_node();
22330  }
22331 
22332  // Can we optimise away the case statement?
22333  if (is_constant_node(condition) && is_false(condition))
22334  {
22335  free_node(node_allocator_, condition);
22336  free_node(node_allocator_, consequent);
22337  }
22338  else
22339  {
22340  arg_list.push_back( condition);
22341  arg_list.push_back(consequent);
22342  }
22343 
22344  if (details::imatch("default",current_token().value))
22345  {
22346  next_token();
22347  if (!token_is(token_t::e_colon))
22348  {
22349  set_error(
22351  current_token(),
22352  "ERR080 - Expected ':' for default of switch statement",
22354 
22355  return error_node();
22356  }
22357 
22358  expression_node_ptr default_statement = error_node();
22359 
22360  if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
22361  default_statement = parse_multi_sequence("switch-default");
22362  else
22363  default_statement = parse_expression();
22364 
22365  if (0 == default_statement)
22366  return error_node();
22367  else if (!token_is(token_t::e_eof))
22368  {
22369  free_node(node_allocator_,default_statement);
22370 
22371  set_error(
22373  current_token(),
22374  "ERR081 - Expected ';' at end of default for switch statement",
22376 
22377  return error_node();
22378  }
22379 
22380  arg_list.push_back(default_statement);
22381  break;
22382  }
22383  }
22384 
22385  if (!token_is(token_t::e_rcrlbracket))
22386  {
22387  set_error(
22389  current_token(),
22390  "ERR082 - Expected '}' at end of switch statement",
22392 
22393  return error_node();
22394  }
22395 
22396  result = expression_generator_.switch_statement(arg_list);
22397 
22398  svd.delete_ptr = (0 == result);
22399 
22400  return result;
22401  }
22402 
22404  {
22405  std::vector<expression_node_ptr> arg_list;
22406 
22407  if (!details::imatch(current_token().value,"[*]"))
22408  {
22409  set_error(
22411  current_token(),
22412  "ERR083 - Expected token '[*]'",
22414 
22415  return error_node();
22416  }
22417 
22418  scoped_vec_delete<expression_node_t> svd((*this),arg_list);
22419 
22420  next_token();
22421 
22422  if (!token_is(token_t::e_lcrlbracket))
22423  {
22424  set_error(
22426  current_token(),
22427  "ERR084 - Expected '{' for call to [*] statement",
22429 
22430  return error_node();
22431  }
22432 
22433  for ( ; ; )
22434  {
22435  if (!details::imatch("case",current_token().value))
22436  {
22437  set_error(
22439  current_token(),
22440  "ERR085 - Expected a 'case' statement for multi-switch",
22442 
22443  return error_node();
22444  }
22445 
22446  next_token();
22447 
22448  expression_node_ptr condition = parse_expression();
22449 
22450  if (0 == condition)
22451  return error_node();
22452 
22453  if (!token_is(token_t::e_colon))
22454  {
22455  set_error(
22457  current_token(),
22458  "ERR086 - Expected ':' for case of [*] statement",
22460 
22461  return error_node();
22462  }
22463 
22464  expression_node_ptr consequent = parse_expression();
22465 
22466  if (0 == consequent)
22467  return error_node();
22468 
22469  if (!token_is(token_t::e_eof))
22470  {
22471  set_error(
22473  current_token(),
22474  "ERR087 - Expected ';' at end of case for [*] statement",
22476 
22477  return error_node();
22478  }
22479 
22480  // Can we optimise away the case statement?
22481  if (is_constant_node(condition) && is_false(condition))
22482  {
22483  free_node(node_allocator_, condition);
22484  free_node(node_allocator_, consequent);
22485  }
22486  else
22487  {
22488  arg_list.push_back( condition);
22489  arg_list.push_back(consequent);
22490  }
22491 
22492  if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold))
22493  {
22494  break;
22495  }
22496  }
22497 
22498  if (!token_is(token_t::e_rcrlbracket))
22499  {
22500  set_error(
22502  current_token(),
22503  "ERR088 - Expected '}' at end of [*] statement",
22505 
22506  return error_node();
22507  }
22508 
22509  const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list);
22510 
22511  svd.delete_ptr = (0 == result);
22512 
22513  return result;
22514  }
22515 
22517  {
22518  std::vector<expression_node_ptr> arg_list;
22519 
22521  const std::string symbol = current_token().value;
22522 
22523  if (details::imatch(symbol,"~"))
22524  {
22525  next_token();
22526  return parse_multi_sequence();
22527  }
22528  else if (details::imatch(symbol,"[*]"))
22529  {
22530  return parse_multi_switch_statement();
22531  }
22532  else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ;
22533  else if (details::imatch(symbol, "mand")) opt_type = details::e_mand;
22534  else if (details::imatch(symbol, "max" )) opt_type = details::e_max ;
22535  else if (details::imatch(symbol, "min" )) opt_type = details::e_min ;
22536  else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ;
22537  else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod;
22538  else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ;
22539  else
22540  {
22541  set_error(
22543  current_token(),
22544  "ERR089 - Unsupported vararg function: " + symbol,
22546 
22547  return error_node();
22548  }
22549 
22550  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22551 
22552  lodge_symbol(symbol, e_st_function);
22553 
22554  next_token();
22555 
22556  if (!token_is(token_t::e_lbracket))
22557  {
22558  set_error(
22560  current_token(),
22561  "ERR090 - Expected '(' for call to vararg function: " + symbol,
22563 
22564  return error_node();
22565  }
22566 
22567  for ( ; ; )
22568  {
22569  expression_node_ptr arg = parse_expression();
22570 
22571  if (0 == arg)
22572  return error_node();
22573  else
22574  arg_list.push_back(arg);
22575 
22576  if (token_is(token_t::e_rbracket))
22577  break;
22578  else if (!token_is(token_t::e_comma))
22579  {
22580  set_error(
22582  current_token(),
22583  "ERR091 - Expected ',' for call to vararg function: " + symbol,
22585 
22586  return error_node();
22587  }
22588  }
22589 
22590  const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list);
22591 
22592  sdd.delete_ptr = (0 == result);
22593  return result;
22594  }
22595 
22596  #ifndef exprtk_disable_string_capabilities
22598  {
22599  if (!token_is(token_t::e_lsqrbracket))
22600  {
22601  set_error(
22603  current_token(),
22604  "ERR092 - Expected '[' as start of string range definition",
22606 
22607  free_node(node_allocator_,expression);
22608 
22609  return error_node();
22610  }
22611  else if (token_is(token_t::e_rsqrbracket))
22612  {
22613  return node_allocator_.allocate<details::string_size_node<T> >(expression);
22614  }
22615 
22616  range_t rp;
22617 
22618  if (!parse_range(rp,true))
22619  {
22620  free_node(node_allocator_,expression);
22621 
22622  return error_node();
22623  }
22624 
22625  expression_node_ptr result = expression_generator_(expression,rp);
22626 
22627  if (0 == result)
22628  {
22629  set_error(
22631  current_token(),
22632  "ERR093 - Failed to generate string range node",
22634 
22635  free_node(node_allocator_,expression);
22636  }
22637 
22638  rp.clear();
22639 
22640  return result;
22641  }
22642  #else
22643  inline expression_node_ptr parse_string_range_statement(expression_node_ptr&)
22644  {
22645  return error_node();
22646  }
22647  #endif
22648 
22650  {
22651  // Allow no more than 100 range calls, eg: s[][][]...[][]
22652  const std::size_t max_rangesize_parses = 100;
22653 
22654  std::size_t i = 0;
22655 
22656  while
22657  (
22658  (0 != expression) &&
22659  (i++ < max_rangesize_parses) &&
22660  error_list_.empty() &&
22662  token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)
22663  )
22664  {
22665  expression = parse_string_range_statement(expression);
22666  }
22667  }
22668 
22669  template <typename Allocator1,
22670  typename Allocator2,
22671  template <typename, typename> class Sequence>
22672  inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list,
22673  Sequence<bool,Allocator2>& side_effect_list,
22674  const bool specialise_on_final_type = false)
22675  {
22676  if (expression_list.empty())
22677  return error_node();
22678  else if (1 == expression_list.size())
22679  return expression_list[0];
22680 
22681  Sequence<expression_node_ptr,Allocator1> tmp_expression_list;
22682 
22683  bool return_node_present = false;
22684 
22685  for (std::size_t i = 0; i < (expression_list.size() - 1); ++i)
22686  {
22687  if (is_variable_node(expression_list[i]))
22688  continue;
22689  else if (
22690  is_return_node (expression_list[i]) ||
22691  is_break_node (expression_list[i]) ||
22692  is_continue_node(expression_list[i])
22693  )
22694  {
22695  tmp_expression_list.push_back(expression_list[i]);
22696 
22697  // Remove all subexpressions after first short-circuit
22698  // node has been encountered.
22699 
22700  for (std::size_t j = i + 1; j < expression_list.size(); ++j)
22701  {
22702  free_node(node_allocator_,expression_list[j]);
22703  }
22704 
22705  return_node_present = true;
22706 
22707  break;
22708  }
22709  else if (
22710  is_constant_node(expression_list[i]) ||
22711  is_null_node (expression_list[i]) ||
22712  !side_effect_list[i]
22713  )
22714  {
22715  free_node(node_allocator_,expression_list[i]);
22716  continue;
22717  }
22718  else
22719  tmp_expression_list.push_back(expression_list[i]);
22720  }
22721 
22722  if (!return_node_present)
22723  {
22724  tmp_expression_list.push_back(expression_list.back());
22725  }
22726 
22727  expression_list.swap(tmp_expression_list);
22728 
22729  if (tmp_expression_list.size() > expression_list.size())
22730  {
22731  exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n",
22732  static_cast<int>(tmp_expression_list.size()),
22733  static_cast<int>(expression_list .size())));
22734  }
22735 
22736  if (
22737  return_node_present ||
22738  side_effect_list.back() ||
22739  (expression_list.size() > 1)
22740  )
22741  state_.activate_side_effect("simplify()");
22742 
22743  if (1 == expression_list.size())
22744  return expression_list[0];
22745  else if (specialise_on_final_type && is_generally_string_node(expression_list.back()))
22746  return expression_generator_.vararg_function(details::e_smulti,expression_list);
22747  else
22748  return expression_generator_.vararg_function(details::e_multi,expression_list);
22749  }
22750 
22752  {
22753  token_t::token_type close_bracket = token_t::e_rcrlbracket;
22754  token_t::token_type seperator = token_t::e_eof;
22755 
22756  if (!token_is(token_t::e_lcrlbracket))
22757  {
22758  if (token_is(token_t::e_lbracket))
22759  {
22760  close_bracket = token_t::e_rbracket;
22761  seperator = token_t::e_comma;
22762  }
22763  else
22764  {
22765  set_error(
22767  current_token(),
22768  "ERR094 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" +
22769  ((!source.empty()) ? std::string(" section of " + source): ""),
22771 
22772  return error_node();
22773  }
22774  }
22775  else if (token_is(token_t::e_rcrlbracket))
22776  {
22777  return node_allocator_.allocate<details::null_node<T> >();
22778  }
22779 
22780  std::vector<expression_node_ptr> arg_list;
22781  std::vector<bool> side_effect_list;
22782 
22783  expression_node_ptr result = error_node();
22784 
22785  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
22786 
22787  scope_handler sh(*this);
22788 
22789  scoped_bool_or_restorer sbr(state_.side_effect_present);
22790 
22791  for ( ; ; )
22792  {
22793  state_.side_effect_present = false;
22794 
22795  expression_node_ptr arg = parse_expression();
22796 
22797  if (0 == arg)
22798  return error_node();
22799  else
22800  {
22801  arg_list.push_back(arg);
22802  side_effect_list.push_back(state_.side_effect_present);
22803  }
22804 
22805  if (token_is(close_bracket))
22806  break;
22807 
22808  const bool is_next_close = peek_token_is(close_bracket);
22809 
22810  if (!token_is(seperator) && is_next_close)
22811  {
22812  set_error(
22814  current_token(),
22815  "ERR095 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source,
22817 
22818  return error_node();
22819  }
22820 
22821  if (token_is(close_bracket))
22822  break;
22823  }
22824 
22825  result = simplify(arg_list,side_effect_list,source.empty());
22826 
22827  sdd.delete_ptr = (0 == result);
22828  return result;
22829  }
22830 
22831  inline bool parse_range(range_t& rp, const bool skip_lsqr = false)
22832  {
22833  // Examples of valid ranges:
22834  // 1. [1:5] -> 1..5
22835  // 2. [ :5] -> 0..5
22836  // 3. [1: ] -> 1..end
22837  // 4. [x:y] -> x..y where x <= y
22838  // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2
22839  // 6. [ :y] -> 0..y where 0 <= y
22840  // 7. [x: ] -> x..end where x <= end
22841 
22842  rp.clear();
22843 
22844  if (!skip_lsqr && !token_is(token_t::e_lsqrbracket))
22845  {
22846  set_error(
22848  current_token(),
22849  "ERR096 - Expected '[' for start of range",
22851 
22852  return false;
22853  }
22854 
22855  if (token_is(token_t::e_colon))
22856  {
22857  rp.n0_c.first = true;
22858  rp.n0_c.second = 0;
22859  rp.cache.first = 0;
22860  }
22861  else
22862  {
22863  expression_node_ptr r0 = parse_expression();
22864 
22865  if (0 == r0)
22866  {
22867  set_error(
22869  current_token(),
22870  "ERR097 - Failed parse begin section of range",
22872 
22873  return false;
22874  }
22875  else if (is_constant_node(r0))
22876  {
22877  const T r0_value = r0->value();
22878 
22879  if (r0_value >= T(0))
22880  {
22881  rp.n0_c.first = true;
22882  rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value));
22883  rp.cache.first = rp.n0_c.second;
22884  }
22885 
22886  free_node(node_allocator_,r0);
22887 
22888  if (r0_value < T(0))
22889  {
22890  set_error(
22892  current_token(),
22893  "ERR098 - Range lower bound less than zero! Constraint: r0 >= 0",
22895 
22896  return false;
22897  }
22898  }
22899  else
22900  {
22901  rp.n0_e.first = true;
22902  rp.n0_e.second = r0;
22903  }
22904 
22905  if (!token_is(token_t::e_colon))
22906  {
22907  set_error(
22909  current_token(),
22910  "ERR099 - Expected ':' for break in range",
22912 
22913  rp.free();
22914 
22915  return false;
22916  }
22917  }
22918 
22919  if (token_is(token_t::e_rsqrbracket))
22920  {
22921  rp.n1_c.first = true;
22923  }
22924  else
22925  {
22926  expression_node_ptr r1 = parse_expression();
22927 
22928  if (0 == r1)
22929  {
22930  set_error(
22932  current_token(),
22933  "ERR100 - Failed parse end section of range",
22935 
22936  rp.free();
22937 
22938  return false;
22939  }
22940  else if (is_constant_node(r1))
22941  {
22942  const T r1_value = r1->value();
22943 
22944  if (r1_value >= T(0))
22945  {
22946  rp.n1_c.first = true;
22947  rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value));
22948  rp.cache.second = rp.n1_c.second;
22949  }
22950 
22951  free_node(node_allocator_,r1);
22952 
22953  if (r1_value < T(0))
22954  {
22955  set_error(
22957  current_token(),
22958  "ERR101 - Range upper bound less than zero! Constraint: r1 >= 0",
22960 
22961  return false;
22962  }
22963  }
22964  else
22965  {
22966  rp.n1_e.first = true;
22967  rp.n1_e.second = r1;
22968  }
22969 
22970  if (!token_is(token_t::e_rsqrbracket))
22971  {
22972  set_error(
22974  current_token(),
22975  "ERR102 - Expected ']' for start of range",
22977 
22978  rp.free();
22979 
22980  return false;
22981  }
22982  }
22983 
22984  if (rp.const_range())
22985  {
22986  std::size_t r0 = 0;
22987  std::size_t r1 = 0;
22988 
22989  const bool rp_result = rp(r0,r1);
22990 
22991  if (!rp_result || (r0 > r1))
22992  {
22993  set_error(
22995  current_token(),
22996  "ERR103 - Invalid range, Constraint: r0 <= r1",
22998 
22999  return false;
23000  }
23001  }
23002 
23003  return true;
23004  }
23005 
23006  inline void lodge_symbol(const std::string& symbol,
23007  const symbol_type st)
23008  {
23009  dec_.add_symbol(symbol,st);
23010  }
23011 
23012  #ifndef exprtk_disable_string_capabilities
23014  {
23015  const std::string symbol = current_token().value;
23016 
23017  typedef details::stringvar_node<T>* strvar_node_t;
23018 
23019  expression_node_ptr result = error_node();
23020  strvar_node_t const_str_node = static_cast<strvar_node_t>(0);
23021 
23022  scope_element& se = sem_.get_active_element(symbol);
23023 
23024  if (scope_element::e_string == se.type)
23025  {
23026  se.active = true;
23027  result = se.str_node;
23028  lodge_symbol(symbol, e_st_local_string);
23029  }
23030  else
23031  {
23032  if (!symtab_store_.is_conststr_stringvar(symbol))
23033  {
23034  set_error(
23036  current_token(),
23037  "ERR104 - Unknown string symbol",
23039 
23040  return error_node();
23041  }
23042 
23043  result = symtab_store_.get_stringvar(symbol);
23044 
23045  if (symtab_store_.is_constant_string(symbol))
23046  {
23047  const_str_node = static_cast<strvar_node_t>(result);
23048  result = expression_generator_(const_str_node->str());
23049  }
23050 
23051  lodge_symbol(symbol, e_st_string);
23052  }
23053 
23054  if (peek_token_is(token_t::e_lsqrbracket))
23055  {
23056  next_token();
23057 
23058  if (peek_token_is(token_t::e_rsqrbracket))
23059  {
23060  next_token();
23061  next_token();
23062 
23063  if (const_str_node)
23064  {
23065  free_node(node_allocator_,result);
23066 
23067  return expression_generator_(T(const_str_node->size()));
23068  }
23069  else
23070  return node_allocator_.allocate<details::stringvar_size_node<T> >
23071  (static_cast<details::stringvar_node<T>*>(result)->ref());
23072  }
23073 
23074  range_t rp;
23075 
23076  if (!parse_range(rp))
23077  {
23078  free_node(node_allocator_,result);
23079 
23080  return error_node();
23081  }
23082  else if (const_str_node)
23083  {
23084  free_node(node_allocator_,result);
23085  result = expression_generator_(const_str_node->ref(),rp);
23086  }
23087  else
23088  result = expression_generator_(static_cast<details::stringvar_node<T>*>
23089  (result)->ref(), rp);
23090 
23091  if (result)
23092  rp.clear();
23093  }
23094  else
23095  next_token();
23096 
23097  return result;
23098  }
23099  #else
23100  inline expression_node_ptr parse_string()
23101  {
23102  return error_node();
23103  }
23104  #endif
23105 
23106  #ifndef exprtk_disable_string_capabilities
23108  {
23109  const std::string const_str = current_token().value;
23110  expression_node_ptr result = expression_generator_(const_str);
23111 
23112  if (peek_token_is(token_t::e_lsqrbracket))
23113  {
23114  next_token();
23115 
23116  if (peek_token_is(token_t::e_rsqrbracket))
23117  {
23118  next_token();
23119  next_token();
23120 
23121  free_node(node_allocator_,result);
23122 
23123  return expression_generator_(T(const_str.size()));
23124  }
23125 
23126  range_t rp;
23127 
23128  if (!parse_range(rp))
23129  {
23130  free_node(node_allocator_,result);
23131 
23132  return error_node();
23133  }
23134 
23135  free_node(node_allocator_,result);
23136 
23137  if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max()))
23138  {
23139  rp.n1_c.second = const_str.size() - 1;
23140  rp.cache.second = rp.n1_c.second;
23141  }
23142 
23143  if (
23144  (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) ||
23145  (rp.n1_c.first && (rp.n1_c.second >= const_str.size()))
23146  )
23147  {
23148  set_error(
23150  current_token(),
23151  "ERR105 - Overflow in range for string: '" + const_str + "'[" +
23152  (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" +
23153  (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]",
23155 
23156  return error_node();
23157  }
23158 
23159  result = expression_generator_(const_str,rp);
23160 
23161  if (result)
23162  rp.clear();
23163  }
23164  else
23165  next_token();
23166 
23167  return result;
23168  }
23169  #else
23170  inline expression_node_ptr parse_const_string()
23171  {
23172  return error_node();
23173  }
23174  #endif
23175 
23177  {
23178  const std::string symbol = current_token().value;
23179 
23181 
23182  const scope_element& se = sem_.get_active_element(symbol);
23183 
23184  if (
23185  !details::imatch(se.name, symbol) ||
23186  (se.depth > state_.scope_depth) ||
23187  (scope_element::e_vector != se.type)
23188  )
23189  {
23190  if (0 == (vec = symtab_store_.get_vector(symbol)))
23191  {
23192  set_error(
23194  current_token(),
23195  "ERR106 - Symbol '" + symbol+ " not a vector",
23197 
23198  return error_node();
23199  }
23200  }
23201  else
23202  vec = se.vec_node;
23203 
23204  expression_node_ptr index_expr = error_node();
23205 
23206  next_token();
23207 
23208  if (!token_is(token_t::e_lsqrbracket))
23209  {
23210  return node_allocator_.allocate<vector_node_t>(vec);
23211  }
23212  else if (token_is(token_t::e_rsqrbracket))
23213  {
23214  return expression_generator_(T(vec->size()));
23215  }
23216  else if (0 == (index_expr = parse_expression()))
23217  {
23218  set_error(
23220  current_token(),
23221  "ERR107 - Failed to parse index for vector: '" + symbol + "'",
23223 
23224  return error_node();
23225  }
23226  else if (!token_is(token_t::e_rsqrbracket))
23227  {
23228  set_error(
23230  current_token(),
23231  "ERR108 - Expected ']' for index of vector: '" + symbol + "'",
23233 
23234  free_node(node_allocator_,index_expr);
23235 
23236  return error_node();
23237  }
23238 
23239  // Perform compile-time range check
23240  if (details::is_constant_node(index_expr))
23241  {
23242  const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value()));
23243  const std::size_t vec_size = vec->size();
23244 
23245  if (index >= vec_size)
23246  {
23247  set_error(
23249  current_token(),
23250  "ERR109 - Index of " + details::to_str(index) + " out of range for "
23251  "vector '" + symbol + "' of size " + details::to_str(vec_size),
23253 
23254  free_node(node_allocator_,index_expr);
23255 
23256  return error_node();
23257  }
23258  }
23259 
23260  return expression_generator_.vector_element(symbol,vec,index_expr);
23261  }
23262 
23263  inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name)
23264  {
23265  std::vector<expression_node_ptr> arg_list;
23266 
23267  expression_node_ptr result = error_node();
23268 
23269  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23270 
23271  next_token();
23272 
23273  if (token_is(token_t::e_lbracket))
23274  {
23275  if (token_is(token_t::e_rbracket))
23276  {
23277  if (!vararg_function->allow_zero_parameters())
23278  {
23279  set_error(
23281  current_token(),
23282  "ERR110 - Zero parameter call to vararg function: "
23283  + vararg_function_name + " not allowed",
23285 
23286  return error_node();
23287  }
23288  }
23289  else
23290  {
23291  for ( ; ; )
23292  {
23293  expression_node_ptr arg = parse_expression();
23294 
23295  if (0 == arg)
23296  return error_node();
23297  else
23298  arg_list.push_back(arg);
23299 
23300  if (token_is(token_t::e_rbracket))
23301  break;
23302  else if (!token_is(token_t::e_comma))
23303  {
23304  set_error(
23306  current_token(),
23307  "ERR111 - Expected ',' for call to vararg function: "
23308  + vararg_function_name,
23310 
23311  return error_node();
23312  }
23313  }
23314  }
23315  }
23316  else if (!vararg_function->allow_zero_parameters())
23317  {
23318  set_error(
23320  current_token(),
23321  "ERR112 - Zero parameter call to vararg function: "
23322  + vararg_function_name + " not allowed",
23324 
23325  return error_node();
23326  }
23327 
23328  if (arg_list.size() < vararg_function->min_num_args())
23329  {
23330  set_error(
23332  current_token(),
23333  "ERR113 - Invalid number of parameters to call to vararg function: "
23334  + vararg_function_name + ", require at least "
23335  + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters",
23337 
23338  return error_node();
23339  }
23340  else if (arg_list.size() > vararg_function->max_num_args())
23341  {
23342  set_error(
23344  current_token(),
23345  "ERR114 - Invalid number of parameters to call to vararg function: "
23346  + vararg_function_name + ", require no more than "
23347  + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters",
23349 
23350  return error_node();
23351  }
23352 
23353  result = expression_generator_.vararg_function_call(vararg_function,arg_list);
23354 
23355  sdd.delete_ptr = (0 == result);
23356 
23357  return result;
23358  }
23359 
23361  {
23362  public:
23363 
23365  {
23366  e_overload = ' ',
23367  e_numeric = 'T',
23368  e_string = 'S'
23369  };
23370 
23372  {
23375  };
23376 
23378  typedef std::vector<function_prototype_t> function_definition_list_t;
23379 
23381  const std::string& func_name,
23382  const std::string& func_prototypes,
23383  const return_type_t default_return_type)
23384  : invalid_state_(true),
23385  parser_(p),
23386  function_name_(func_name),
23387  default_return_type_(default_return_type)
23388  {
23389  parse_function_prototypes(func_prototypes);
23390  }
23391 
23393  {
23394  default_return_type_ = return_type;
23395  }
23396 
23397  bool verify(const std::string& param_seq, std::size_t& pseq_index)
23398  {
23399  if (function_definition_list_.empty())
23400  return true;
23401 
23402  std::vector<std::pair<std::size_t,char> > error_list;
23403 
23404  for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23405  {
23406  details::char_t diff_value = 0;
23407  std::size_t diff_index = 0;
23408 
23409  const bool result = details::sequence_match(function_definition_list_[i].param_seq,
23410  param_seq,
23411  diff_index, diff_value);
23412 
23413  if (result)
23414  {
23415  pseq_index = i;
23416  return true;
23417  }
23418  else
23419  error_list.push_back(std::make_pair(diff_index, diff_value));
23420  }
23421 
23422  if (1 == error_list.size())
23423  {
23424  parser_.
23425  set_error(
23427  parser_.current_token(),
23428  "ERR115 - Failed parameter type check for function '" + function_name_ + "', "
23429  "Expected '" + function_definition_list_[0].param_seq +
23430  "' call set: '" + param_seq + "'",
23432  }
23433  else
23434  {
23435  // find first with largest diff_index;
23436  std::size_t max_diff_index = 0;
23437 
23438  for (std::size_t i = 1; i < error_list.size(); ++i)
23439  {
23440  if (error_list[i].first > error_list[max_diff_index].first)
23441  {
23442  max_diff_index = i;
23443  }
23444  }
23445 
23446  parser_.
23447  set_error(
23449  parser_.current_token(),
23450  "ERR116 - Failed parameter type check for function '" + function_name_ + "', "
23451  "Best match: '" + function_definition_list_[max_diff_index].param_seq +
23452  "' call set: '" + param_seq + "'",
23454  }
23455 
23456  return false;
23457  }
23458 
23459  std::size_t paramseq_count() const
23460  {
23461  return function_definition_list_.size();
23462  }
23463 
23464  std::string paramseq(const std::size_t& index) const
23465  {
23466  return function_definition_list_[index].param_seq;
23467  }
23468 
23469  return_type_t return_type(const std::size_t& index) const
23470  {
23471  return function_definition_list_[index].return_type;
23472  }
23473 
23474  bool invalid() const
23475  {
23476  return !invalid_state_;
23477  }
23478 
23480  {
23481 
23482  for (std::size_t i = 0; i < function_definition_list_.size(); ++i)
23483  {
23484  if (std::string::npos != function_definition_list_[i].param_seq.find("Z"))
23485  {
23486  return true;
23487  }
23488  }
23489 
23490  return false;
23491  }
23492 
23493  private:
23494 
23495  std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const
23496  {
23497  std::string::const_iterator current_begin = param_seq.begin();
23498  std::string::const_iterator iter = param_seq.begin();
23499 
23500  std::vector<std::string> result;
23501 
23502  while (iter != param_seq.end())
23503  {
23504  if (*iter == delimiter)
23505  {
23506  result.push_back(std::string(current_begin, iter));
23507  ++iter;
23508  current_begin = iter;
23509  }
23510  else
23511  ++iter;
23512  }
23513 
23514  if (current_begin != iter)
23515  {
23516  result.push_back(std::string(current_begin, iter));
23517  }
23518 
23519  return result;
23520  }
23521 
23522  inline bool is_valid_token(std::string param_seq,
23523  function_prototype_t& funcproto) const
23524  {
23525  // Determine return type
23526  funcproto.return_type = default_return_type_;
23527 
23528  if (param_seq.size() > 2)
23529  {
23530  if (':' == param_seq[1])
23531  {
23532  // Note: Only overloaded igeneric functions can have return
23533  // type definitions.
23534  if (type_checker::e_overload != default_return_type_)
23535  return false;
23536 
23537  switch (param_seq[0])
23538  {
23539  case 'T' : funcproto.return_type = type_checker::e_numeric;
23540  break;
23541 
23542  case 'S' : funcproto.return_type = type_checker::e_string;
23543  break;
23544 
23545  default : return false;
23546  }
23547 
23548  param_seq.erase(0,2);
23549  }
23550  }
23551 
23552  if (
23553  (std::string::npos != param_seq.find("?*")) ||
23554  (std::string::npos != param_seq.find("**"))
23555  )
23556  {
23557  return false;
23558  }
23559  else if (
23560  (std::string::npos == param_seq.find_first_not_of("STV*?|")) ||
23561  ("Z" == param_seq)
23562  )
23563  {
23564  funcproto.param_seq = param_seq;
23565  return true;
23566  }
23567 
23568  return false;
23569  }
23570 
23571  void parse_function_prototypes(const std::string& func_prototypes)
23572  {
23573  if (func_prototypes.empty())
23574  return;
23575 
23576  std::vector<std::string> param_seq_list = split_param_seq(func_prototypes);
23577 
23578  typedef std::map<std::string,std::size_t> param_seq_map_t;
23579  param_seq_map_t param_seq_map;
23580 
23581  for (std::size_t i = 0; i < param_seq_list.size(); ++i)
23582  {
23583  function_prototype_t func_proto;
23584 
23585  if (!is_valid_token(param_seq_list[i], func_proto))
23586  {
23587  invalid_state_ = false;
23588 
23589  parser_.
23590  set_error(
23592  parser_.current_token(),
23593  "ERR117 - Invalid parameter sequence of '" + param_seq_list[i] +
23594  "' for function: " + function_name_,
23596  return;
23597  }
23598 
23599  param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]);
23600 
23601  if (param_seq_map.end() != seq_itr)
23602  {
23603  invalid_state_ = false;
23604 
23605  parser_.
23606  set_error(
23608  parser_.current_token(),
23609  "ERR118 - Function '" + function_name_ + "' has a parameter sequence conflict between " +
23610  "pseq_idx[" + details::to_str(seq_itr->second) + "] and" +
23611  "pseq_idx[" + details::to_str(i) + "] " +
23612  "param seq: " + param_seq_list[i],
23614  return;
23615  }
23616 
23617  function_definition_list_.push_back(func_proto);
23618  }
23619  }
23620 
23621  type_checker(const type_checker&);
23622  type_checker& operator=(const type_checker&);
23623 
23629  };
23630 
23632  {
23633  std::vector<expression_node_ptr> arg_list;
23634 
23635  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23636 
23637  next_token();
23638 
23639  std::string param_type_list;
23640 
23641  type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23642 
23643  if (tc.invalid())
23644  {
23645  set_error(
23647  current_token(),
23648  "ERR119 - Type checker instantiation failure for generic function: " + function_name,
23650 
23651  return error_node();
23652  }
23653 
23654  if (token_is(token_t::e_lbracket))
23655  {
23656  if (token_is(token_t::e_rbracket))
23657  {
23658  if (
23659  !function->allow_zero_parameters() &&
23660  !tc .allow_zero_parameters()
23661  )
23662  {
23663  set_error(
23665  current_token(),
23666  "ERR120 - Zero parameter call to generic function: "
23667  + function_name + " not allowed",
23669 
23670  return error_node();
23671  }
23672  }
23673  else
23674  {
23675  for ( ; ; )
23676  {
23677  expression_node_ptr arg = parse_expression();
23678 
23679  if (0 == arg)
23680  return error_node();
23681 
23682  if (is_ivector_node(arg))
23683  param_type_list += 'V';
23684  else if (is_generally_string_node(arg))
23685  param_type_list += 'S';
23686  else // Everything else is assumed to be a scalar returning expression
23687  param_type_list += 'T';
23688 
23689  arg_list.push_back(arg);
23690 
23691  if (token_is(token_t::e_rbracket))
23692  break;
23693  else if (!token_is(token_t::e_comma))
23694  {
23695  set_error(
23697  current_token(),
23698  "ERR121 - Expected ',' for call to generic function: " + function_name,
23700 
23701  return error_node();
23702  }
23703  }
23704  }
23705  }
23706  else if (
23707  !function->parameter_sequence.empty() &&
23708  function->allow_zero_parameters () &&
23709  !tc .allow_zero_parameters ()
23710  )
23711  {
23712  set_error(
23714  current_token(),
23715  "ERR122 - Zero parameter call to generic function: "
23716  + function_name + " not allowed",
23718 
23719  return error_node();
23720  }
23721 
23722  std::size_t param_seq_index = 0;
23723 
23724  if (
23725  state_.type_check_enabled &&
23726  !tc.verify(param_type_list, param_seq_index)
23727  )
23728  {
23729  set_error(
23731  current_token(),
23732  "ERR123 - Invalid input parameter sequence for call to generic function: " + function_name,
23734 
23735  return error_node();
23736  }
23737 
23738  expression_node_ptr result = error_node();
23739 
23740  if (tc.paramseq_count() <= 1)
23741  result = expression_generator_
23742  .generic_function_call(function, arg_list);
23743  else
23744  result = expression_generator_
23745  .generic_function_call(function, arg_list, param_seq_index);
23746 
23747  sdd.delete_ptr = (0 == result);
23748 
23749  return result;
23750  }
23751 
23752  inline bool parse_igeneric_function_params(std::string& param_type_list,
23753  std::vector<expression_node_ptr>& arg_list,
23754  const std::string function_name,
23755  igeneric_function<T>* function,
23756  const type_checker& tc)
23757  {
23758  if (token_is(token_t::e_lbracket))
23759  {
23760  if (token_is(token_t::e_rbracket))
23761  {
23762  if (
23763  !function->allow_zero_parameters() &&
23764  !tc .allow_zero_parameters()
23765  )
23766  {
23767  set_error(
23769  current_token(),
23770  "ERR124 - Zero parameter call to generic function: "
23771  + function_name + " not allowed",
23773 
23774  return false;
23775  }
23776  }
23777  else
23778  {
23779  for ( ; ; )
23780  {
23781  expression_node_ptr arg = parse_expression();
23782 
23783  if (0 == arg)
23784  return false;
23785 
23786  if (is_ivector_node(arg))
23787  param_type_list += 'V';
23788  else if (is_generally_string_node(arg))
23789  param_type_list += 'S';
23790  else // Everything else is a scalar returning expression
23791  param_type_list += 'T';
23792 
23793  arg_list.push_back(arg);
23794 
23795  if (token_is(token_t::e_rbracket))
23796  break;
23797  else if (!token_is(token_t::e_comma))
23798  {
23799  set_error(
23801  current_token(),
23802  "ERR125 - Expected ',' for call to string function: " + function_name,
23804 
23805  return false;
23806  }
23807  }
23808  }
23809 
23810  return true;
23811  }
23812  else
23813  return false;
23814  }
23815 
23816  #ifndef exprtk_disable_string_capabilities
23818  {
23819  // Move pass the function name
23820  next_token();
23821 
23822  std::string param_type_list;
23823 
23824  type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string);
23825 
23826  if (
23827  (!function->parameter_sequence.empty()) &&
23828  (0 == tc.paramseq_count())
23829  )
23830  {
23831  return error_node();
23832  }
23833 
23834  std::vector<expression_node_ptr> arg_list;
23835  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23836 
23837  if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23838  {
23839  return error_node();
23840  }
23841 
23842  std::size_t param_seq_index = 0;
23843 
23844  if (!tc.verify(param_type_list, param_seq_index))
23845  {
23846  set_error(
23848  current_token(),
23849  "ERR126 - Invalid input parameter sequence for call to string function: " + function_name,
23851 
23852  return error_node();
23853  }
23854 
23855  expression_node_ptr result = error_node();
23856 
23857  if (tc.paramseq_count() <= 1)
23858  result = expression_generator_
23859  .string_function_call(function, arg_list);
23860  else
23861  result = expression_generator_
23862  .string_function_call(function, arg_list, param_seq_index);
23863 
23864  sdd.delete_ptr = (0 == result);
23865 
23866  return result;
23867  }
23868 
23870  {
23871  // Move pass the function name
23872  next_token();
23873 
23874  std::string param_type_list;
23875 
23876  type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload);
23877 
23878  if (
23879  (!function->parameter_sequence.empty()) &&
23880  (0 == tc.paramseq_count())
23881  )
23882  {
23883  return error_node();
23884  }
23885 
23886  std::vector<expression_node_ptr> arg_list;
23887  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
23888 
23889  if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc))
23890  {
23891  return error_node();
23892  }
23893 
23894  std::size_t param_seq_index = 0;
23895 
23896  if (!tc.verify(param_type_list, param_seq_index))
23897  {
23898  set_error(
23900  current_token(),
23901  "ERR127 - Invalid input parameter sequence for call to overloaded function: " + function_name,
23903 
23904  return error_node();
23905  }
23906 
23907  expression_node_ptr result = error_node();
23908 
23909  if (type_checker::e_numeric == tc.return_type(param_seq_index))
23910  {
23911  if (tc.paramseq_count() <= 1)
23912  result = expression_generator_
23913  .generic_function_call(function, arg_list);
23914  else
23915  result = expression_generator_
23916  .generic_function_call(function, arg_list, param_seq_index);
23917  }
23918  else if (type_checker::e_string == tc.return_type(param_seq_index))
23919  {
23920  if (tc.paramseq_count() <= 1)
23921  result = expression_generator_
23922  .string_function_call(function, arg_list);
23923  else
23924  result = expression_generator_
23925  .string_function_call(function, arg_list, param_seq_index);
23926  }
23927  else
23928  {
23929  set_error(
23931  current_token(),
23932  "ERR128 - Invalid return type for call to overloaded function: " + function_name,
23934  }
23935 
23936  sdd.delete_ptr = (0 == result);
23937  return result;
23938  }
23939  #endif
23940 
23941  template <typename Type, std::size_t NumberOfParameters>
23943  {
23944  static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type, const std::string& sf_name)
23945  {
23946  expression_node_ptr branch[NumberOfParameters];
23947  expression_node_ptr result = error_node();
23948 
23949  std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0));
23950 
23952 
23953  p.next_token();
23954 
23955  if (!p.token_is(token_t::e_lbracket))
23956  {
23957  p.set_error(
23959  p.current_token(),
23960  "ERR129 - Expected '(' for special function '" + sf_name + "'",
23962 
23963  return error_node();
23964  }
23965 
23966  for (std::size_t i = 0; i < NumberOfParameters; ++i)
23967  {
23968  branch[i] = p.parse_expression();
23969 
23970  if (0 == branch[i])
23971  {
23972  return p.error_node();
23973  }
23974  else if (i < (NumberOfParameters - 1))
23975  {
23976  if (!p.token_is(token_t::e_comma))
23977  {
23978  p.set_error(
23980  p.current_token(),
23981  "ERR130 - Expected ',' before next parameter of special function '" + sf_name + "'",
23983 
23984  return p.error_node();
23985  }
23986  }
23987  }
23988 
23989  if (!p.token_is(token_t::e_rbracket))
23990  {
23991  p.set_error(
23993  p.current_token(),
23994  "ERR131 - Invalid number of parameters for special function '" + sf_name + "'",
23996 
23997  return p.error_node();
23998  }
23999  else
24000  result = p.expression_generator_.special_function(opt_type,branch);
24001 
24002  sd.delete_ptr = (0 == result);
24003 
24004  return result;
24005  }
24006  };
24007 
24009  {
24010  const std::string sf_name = current_token().value;
24011 
24012  // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
24013  if (
24014  !details::is_digit(sf_name[2]) ||
24015  !details::is_digit(sf_name[3])
24016  )
24017  {
24018  set_error(
24020  current_token(),
24021  "ERR132 - Invalid special function[1]: " + sf_name,
24023 
24024  return error_node();
24025  }
24026 
24027  const int id = (sf_name[2] - '0') * 10 +
24028  (sf_name[3] - '0');
24029 
24030  if (id >= details::e_sffinal)
24031  {
24032  set_error(
24034  current_token(),
24035  "ERR133 - Invalid special function[2]: " + sf_name,
24037 
24038  return error_node();
24039  }
24040 
24041  const int sf_3_to_4 = details::e_sf48;
24042  const details::operator_type opt_type = details::operator_type(id + 1000);
24043  const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U;
24044 
24045  switch (NumberOfParameters)
24046  {
24047  case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name);
24048  case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name);
24049  default : return error_node();
24050  }
24051  }
24052 
24054  {
24055  next_token();
24056  return node_allocator_.allocate<details::null_node<T> >();
24057  }
24058 
24059  #ifndef exprtk_disable_break_continue
24061  {
24062  if (state_.parsing_break_stmt)
24063  {
24064  set_error(
24066  current_token(),
24067  "ERR134 - Break call within a break call is not allowed",
24069 
24070  return error_node();
24071  }
24072 
24073  scoped_bool_negator sbn(state_.parsing_break_stmt);
24074 
24075  if (!brkcnt_list_.empty())
24076  {
24077  next_token();
24078 
24079  brkcnt_list_.front() = true;
24080 
24081  expression_node_ptr return_expr = error_node();
24082 
24083  if (token_is(token_t::e_lsqrbracket))
24084  {
24085  if (0 == (return_expr = parse_expression()))
24086  {
24087  set_error(
24089  current_token(),
24090  "ERR135 - Failed to parse return expression for 'break' statement",
24092 
24093  return error_node();
24094  }
24095  else if (!token_is(token_t::e_rsqrbracket))
24096  {
24097  set_error(
24099  current_token(),
24100  "ERR136 - Expected ']' at the completion of break's return expression",
24102 
24103  free_node(node_allocator_,return_expr);
24104 
24105  return error_node();
24106  }
24107  }
24108 
24109  state_.activate_side_effect("parse_break_statement()");
24110 
24111  return node_allocator_.allocate<details::break_node<T> >(return_expr);
24112  }
24113  else
24114  {
24115  set_error(
24117  current_token(),
24118  "ERR137 - Invalid use of 'break', allowed only in the scope of a loop",
24120  }
24121 
24122  return error_node();
24123  }
24124 
24126  {
24127  if (!brkcnt_list_.empty())
24128  {
24129  next_token();
24130 
24131  brkcnt_list_.front() = true;
24132  state_.activate_side_effect("parse_continue_statement()");
24133 
24134  return node_allocator_.allocate<details::continue_node<T> >();
24135  }
24136  else
24137  {
24138  set_error(
24140  current_token(),
24141  "ERR138 - Invalid use of 'continue', allowed only in the scope of a loop",
24143 
24144  return error_node();
24145  }
24146  }
24147  #endif
24148 
24150  {
24151  expression_node_ptr size_expr = error_node();
24152 
24153  if (!token_is(token_t::e_lsqrbracket))
24154  {
24155  set_error(
24157  current_token(),
24158  "ERR139 - Expected '[' as part of vector size definition",
24160 
24161  return error_node();
24162  }
24163  else if (0 == (size_expr = parse_expression()))
24164  {
24165  set_error(
24167  current_token(),
24168  "ERR140 - Failed to determine size of vector '" + vec_name + "'",
24170 
24171  return error_node();
24172  }
24173  else if (!is_constant_node(size_expr))
24174  {
24175  free_node(node_allocator_,size_expr);
24176 
24177  set_error(
24179  current_token(),
24180  "ERR141 - Expected a literal number as size of vector '" + vec_name + "'",
24182 
24183  return error_node();
24184  }
24185 
24186  T vector_size = size_expr->value();
24187 
24188  free_node(node_allocator_,size_expr);
24189 
24190  const T max_vector_size = T(2000000000.0);
24191 
24192  if (
24193  (vector_size <= T(0)) ||
24194  std::not_equal_to<T>()
24195  (T(0),vector_size - details::numeric::trunc(vector_size)) ||
24196  (vector_size > max_vector_size)
24197  )
24198  {
24199  set_error(
24201  current_token(),
24202  "ERR142 - Invalid vector size. Must be an integer in the range [0,2e9], size: " +
24205 
24206  return error_node();
24207  }
24208 
24209  std::vector<expression_node_ptr> vec_initilizer_list;
24210 
24211  scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list);
24212 
24213  bool single_value_initialiser = false;
24214  bool vec_to_vec_initialiser = false;
24215  bool null_initialisation = false;
24216 
24217  if (!token_is(token_t::e_rsqrbracket))
24218  {
24219  set_error(
24221  current_token(),
24222  "ERR143 - Expected ']' as part of vector size definition",
24224 
24225  return error_node();
24226  }
24227  else if (!token_is(token_t::e_eof))
24228  {
24229  if (!token_is(token_t::e_assign))
24230  {
24231  set_error(
24233  current_token(),
24234  "ERR144 - Expected ':=' as part of vector definition",
24236 
24237  return error_node();
24238  }
24239  else if (token_is(token_t::e_lsqrbracket))
24240  {
24241  expression_node_ptr initialiser = parse_expression();
24242 
24243  if (0 == initialiser)
24244  {
24245  set_error(
24247  current_token(),
24248  "ERR145 - Failed to parse single vector initialiser",
24250 
24251  return error_node();
24252  }
24253 
24254  vec_initilizer_list.push_back(initialiser);
24255 
24256  if (!token_is(token_t::e_rsqrbracket))
24257  {
24258  set_error(
24260  current_token(),
24261  "ERR146 - Expected ']' to close single value vector initialiser",
24263 
24264  return error_node();
24265  }
24266 
24267  single_value_initialiser = true;
24268  }
24269  else if (!token_is(token_t::e_lcrlbracket))
24270  {
24271  expression_node_ptr initialiser = error_node();
24272 
24273  // Is this a vector to vector assignment and initialisation?
24274  if (token_t::e_symbol == current_token().type)
24275  {
24276  // Is it a locally defined vector?
24277  scope_element& se = sem_.get_active_element(current_token().value);
24278 
24279  if (scope_element::e_vector == se.type)
24280  {
24281  if (0 != (initialiser = parse_expression()))
24282  vec_initilizer_list.push_back(initialiser);
24283  else
24284  return error_node();
24285  }
24286  // Are we dealing with a user defined vector?
24287  else if (symtab_store_.is_vector(current_token().value))
24288  {
24289  lodge_symbol(current_token().value, e_st_vector);
24290 
24291  if (0 != (initialiser = parse_expression()))
24292  vec_initilizer_list.push_back(initialiser);
24293  else
24294  return error_node();
24295  }
24296  // Are we dealing with a null initialisation vector definition?
24297  else if (token_is(token_t::e_symbol,"null"))
24298  null_initialisation = true;
24299  }
24300 
24301  if (!null_initialisation)
24302  {
24303  if (0 == initialiser)
24304  {
24305  set_error(
24307  current_token(),
24308  "ERR147 - Expected '{' as part of vector initialiser list",
24310 
24311  return error_node();
24312  }
24313  else
24314  vec_to_vec_initialiser = true;
24315  }
24316  }
24317  else if (!token_is(token_t::e_rcrlbracket))
24318  {
24319  for ( ; ; )
24320  {
24321  expression_node_ptr initialiser = parse_expression();
24322 
24323  if (0 == initialiser)
24324  {
24325  set_error(
24327  current_token(),
24328  "ERR148 - Expected '{' as part of vector initialiser list",
24330 
24331  return error_node();
24332  }
24333  else
24334  vec_initilizer_list.push_back(initialiser);
24335 
24336  if (token_is(token_t::e_rcrlbracket))
24337  break;
24338 
24339  const bool is_next_close = peek_token_is(token_t::e_rcrlbracket);
24340 
24341  if (!token_is(token_t::e_comma) && is_next_close)
24342  {
24343  set_error(
24345  current_token(),
24346  "ERR149 - Expected ',' between vector initialisers",
24348 
24349  return error_node();
24350  }
24351 
24352  if (token_is(token_t::e_rcrlbracket))
24353  break;
24354  }
24355  }
24356 
24357  if (
24358  !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24359  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24360  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24361  )
24362  {
24363  if (!token_is(token_t::e_eof))
24364  {
24365  set_error(
24367  current_token(),
24368  "ERR150 - Expected ';' at end of vector definition",
24370 
24371  return error_node();
24372  }
24373  }
24374 
24375  if (vec_initilizer_list.size() > vector_size)
24376  {
24377  set_error(
24379  current_token(),
24380  "ERR151 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'",
24382 
24383  return error_node();
24384  }
24385  }
24386 
24387  typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0);
24388 
24389  const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size));
24390 
24391  scope_element& se = sem_.get_element(vec_name);
24392 
24393  if (se.name == vec_name)
24394  {
24395  if (se.active)
24396  {
24397  set_error(
24399  current_token(),
24400  "ERR152 - Illegal redefinition of local vector: '" + vec_name + "'",
24402 
24403  return error_node();
24404  }
24405  else if (
24406  (se.size == vec_size) &&
24407  (scope_element::e_vector == se.type)
24408  )
24409  {
24410  vec_holder = se.vec_node;
24411  se.active = true;
24412  se.depth = state_.scope_depth;
24413  se.ref_count++;
24414  }
24415  }
24416 
24417  if (0 == vec_holder)
24418  {
24419  scope_element nse;
24420  nse.name = vec_name;
24421  nse.active = true;
24422  nse.ref_count = 1;
24423  nse.type = scope_element::e_vector;
24424  nse.depth = state_.scope_depth;
24425  nse.size = vec_size;
24426  nse.data = new T[vec_size];
24427  nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size);
24428 
24429  if (!sem_.add_element(nse))
24430  {
24431  set_error(
24433  current_token(),
24434  "ERR153 - Failed to add new local vector '" + vec_name + "' to SEM",
24436 
24437  sem_.free_element(nse);
24438 
24439  return error_node();
24440  }
24441 
24442  vec_holder = nse.vec_node;
24443 
24444  exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n",
24445  nse.name.c_str(),
24446  static_cast<int>(nse.size)));
24447  }
24448 
24449  state_.activate_side_effect("parse_define_vector_statement()");
24450 
24451  lodge_symbol(vec_name, e_st_local_vector);
24452 
24453  expression_node_ptr result = error_node();
24454 
24455  if (null_initialisation)
24456  result = expression_generator_(T(0.0));
24457  else if (vec_to_vec_initialiser)
24458  {
24459  expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder);
24460 
24461  result = expression_generator_(
24463  vec_node,
24464  vec_initilizer_list[0]);
24465  }
24466  else
24467  result = node_allocator_
24469  (*vec_holder)[0],
24470  vec_size,
24471  vec_initilizer_list,
24472  single_value_initialiser);
24473 
24474  svd.delete_ptr = (0 == result);
24475 
24476  return result;
24477  }
24478 
24479  #ifndef exprtk_disable_string_capabilities
24480  inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression)
24481  {
24482  stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0);
24483 
24484  scope_element& se = sem_.get_element(str_name);
24485 
24486  if (se.name == str_name)
24487  {
24488  if (se.active)
24489  {
24490  set_error(
24492  current_token(),
24493  "ERR154 - Illegal redefinition of local variable: '" + str_name + "'",
24495 
24496  free_node(node_allocator_,initialisation_expression);
24497 
24498  return error_node();
24499  }
24500  else if (scope_element::e_string == se.type)
24501  {
24502  str_node = se.str_node;
24503  se.active = true;
24504  se.depth = state_.scope_depth;
24505  se.ref_count++;
24506  }
24507  }
24508 
24509  if (0 == str_node)
24510  {
24511  scope_element nse;
24512  nse.name = str_name;
24513  nse.active = true;
24514  nse.ref_count = 1;
24515  nse.type = scope_element::e_string;
24516  nse.depth = state_.scope_depth;
24517  nse.data = new std::string;
24518  nse.str_node = new stringvar_node_t(*(std::string*)(nse.data));
24519 
24520  if (!sem_.add_element(nse))
24521  {
24522  set_error(
24524  current_token(),
24525  "ERR155 - Failed to add new local string variable '" + str_name + "' to SEM",
24527 
24528  free_node(node_allocator_,initialisation_expression);
24529 
24530  sem_.free_element(nse);
24531 
24532  return error_node();
24533  }
24534 
24535  str_node = nse.str_node;
24536 
24537  exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str()));
24538  }
24539 
24540  lodge_symbol(str_name, e_st_local_string);
24541 
24542  state_.activate_side_effect("parse_define_string_statement()");
24543 
24544  expression_node_ptr branch[2] = {0};
24545 
24546  branch[0] = str_node;
24547  branch[1] = initialisation_expression;
24548 
24549  return expression_generator_(details::e_assign,branch);
24550  }
24551  #else
24552  inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr)
24553  {
24554  return error_node();
24555  }
24556  #endif
24557 
24558  inline bool local_variable_is_shadowed(const std::string& symbol)
24559  {
24560  const scope_element& se = sem_.get_element(symbol);
24561  return (se.name == symbol) && se.active;
24562  }
24563 
24565  {
24566  if (settings_.vardef_disabled())
24567  {
24568  set_error(
24570  current_token(),
24571  "ERR156 - Illegal variable definition",
24573 
24574  return error_node();
24575  }
24576  else if (!details::imatch(current_token().value,"var"))
24577  {
24578  return error_node();
24579  }
24580  else
24581  next_token();
24582 
24583  const std::string var_name = current_token().value;
24584 
24585  expression_node_ptr initialisation_expression = error_node();
24586 
24587  if (!token_is(token_t::e_symbol))
24588  {
24589  set_error(
24591  current_token(),
24592  "ERR157 - Expected a symbol for variable definition",
24594 
24595  return error_node();
24596  }
24597  else if (details::is_reserved_symbol(var_name))
24598  {
24599  set_error(
24601  current_token(),
24602  "ERR158 - Illegal redefinition of reserved keyword: '" + var_name + "'",
24604 
24605  return error_node();
24606  }
24607  else if (symtab_store_.symbol_exists(var_name))
24608  {
24609  set_error(
24611  current_token(),
24612  "ERR159 - Illegal redefinition of variable '" + var_name + "'",
24614 
24615  return error_node();
24616  }
24617  else if (local_variable_is_shadowed(var_name))
24618  {
24619  set_error(
24621  current_token(),
24622  "ERR160 - Illegal redefinition of local variable: '" + var_name + "'",
24624 
24625  return error_node();
24626  }
24627  else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold))
24628  {
24629  return parse_define_vector_statement(var_name);
24630  }
24631  else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold))
24632  {
24633  return parse_uninitialised_var_statement(var_name);
24634  }
24635  else if (token_is(token_t::e_assign))
24636  {
24637  if (0 == (initialisation_expression = parse_expression()))
24638  {
24639  set_error(
24641  current_token(),
24642  "ERR161 - Failed to parse initialisation expression",
24644 
24645  return error_node();
24646  }
24647  }
24648 
24649  if (
24650  !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) &&
24651  !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) &&
24652  !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold)
24653  )
24654  {
24655  if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24656  {
24657  set_error(
24659  current_token(),
24660  "ERR162 - Expected ';' after variable definition",
24662 
24663  free_node(node_allocator_,initialisation_expression);
24664 
24665  return error_node();
24666  }
24667  }
24668 
24669  if (
24670  (0 != initialisation_expression) &&
24671  details::is_generally_string_node(initialisation_expression)
24672  )
24673  {
24674  return parse_define_string_statement(var_name,initialisation_expression);
24675  }
24676 
24677  expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24678 
24679  scope_element& se = sem_.get_element(var_name);
24680 
24681  if (se.name == var_name)
24682  {
24683  if (se.active)
24684  {
24685  set_error(
24687  current_token(),
24688  "ERR163 - Illegal redefinition of local variable: '" + var_name + "'",
24690 
24691  free_node(node_allocator_, initialisation_expression);
24692 
24693  return error_node();
24694  }
24695  else if (scope_element::e_variable == se.type)
24696  {
24697  var_node = se.var_node;
24698  se.active = true;
24699  se.depth = state_.scope_depth;
24700  se.ref_count++;
24701  }
24702  }
24703 
24704  if (0 == var_node)
24705  {
24706  scope_element nse;
24707  nse.name = var_name;
24708  nse.active = true;
24709  nse.ref_count = 1;
24710  nse.type = scope_element::e_variable;
24711  nse.depth = state_.scope_depth;
24712  nse.data = new T(T(0));
24713  nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24714 
24715  if (!sem_.add_element(nse))
24716  {
24717  set_error(
24719  current_token(),
24720  "ERR164 - Failed to add new local variable '" + var_name + "' to SEM",
24722 
24723  free_node(node_allocator_, initialisation_expression);
24724 
24725  sem_.free_element(nse);
24726 
24727  return error_node();
24728  }
24729 
24730  var_node = nse.var_node;
24731 
24732  exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str()));
24733  }
24734 
24735  state_.activate_side_effect("parse_define_var_statement()");
24736 
24737  lodge_symbol(var_name, e_st_local_variable);
24738 
24739  expression_node_ptr branch[2] = {0};
24740 
24741  branch[0] = var_node;
24742  branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0));
24743 
24744  return expression_generator_(details::e_assign,branch);
24745  }
24746 
24748  {
24749  if (
24750  !token_is(token_t::e_lcrlbracket) ||
24751  !token_is(token_t::e_rcrlbracket)
24752  )
24753  {
24754  set_error(
24756  current_token(),
24757  "ERR165 - Expected a '{}' for uninitialised var definition",
24759 
24760  return error_node();
24761  }
24762  else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold))
24763  {
24764  set_error(
24766  current_token(),
24767  "ERR166 - Expected ';' after uninitialised variable definition",
24769 
24770  return error_node();
24771  }
24772 
24773  expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0);
24774 
24775  scope_element& se = sem_.get_element(var_name);
24776 
24777  if (se.name == var_name)
24778  {
24779  if (se.active)
24780  {
24781  set_error(
24783  current_token(),
24784  "ERR167 - Illegal redefinition of local variable: '" + var_name + "'",
24786 
24787  return error_node();
24788  }
24789  else if (scope_element::e_variable == se.type)
24790  {
24791  var_node = se.var_node;
24792  se.active = true;
24793  se.ref_count++;
24794  }
24795  }
24796 
24797  if (0 == var_node)
24798  {
24799  scope_element nse;
24800  nse.name = var_name;
24801  nse.active = true;
24802  nse.ref_count = 1;
24803  nse.type = scope_element::e_variable;
24804  nse.depth = state_.scope_depth;
24805  nse.ip_index = sem_.next_ip_index();
24806  nse.data = new T(T(0));
24807  nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data));
24808 
24809  if (!sem_.add_element(nse))
24810  {
24811  set_error(
24813  current_token(),
24814  "ERR168 - Failed to add new local variable '" + var_name + "' to SEM",
24816 
24817  sem_.free_element(nse);
24818 
24819  return error_node();
24820  }
24821 
24822  exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n",
24823  nse.name.c_str()));
24824  }
24825 
24826  lodge_symbol(var_name, e_st_local_variable);
24827 
24828  state_.activate_side_effect("parse_uninitialised_var_statement()");
24829 
24830  return expression_generator_(T(0));
24831  }
24832 
24834  {
24835  if (!details::imatch(current_token().value,"swap"))
24836  {
24837  return error_node();
24838  }
24839  else
24840  next_token();
24841 
24842  if (!token_is(token_t::e_lbracket))
24843  {
24844  set_error(
24846  current_token(),
24847  "ERR169 - Expected '(' at start of swap statement",
24849 
24850  return error_node();
24851  }
24852 
24853  expression_node_ptr variable0 = error_node();
24854  expression_node_ptr variable1 = error_node();
24855 
24856  bool variable0_generated = false;
24857  bool variable1_generated = false;
24858 
24859  const std::string var0_name = current_token().value;
24860 
24861  if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
24862  {
24863  set_error(
24865  current_token(),
24866  "ERR170 - Expected a symbol for variable or vector element definition",
24868 
24869  return error_node();
24870  }
24871  else if (peek_token_is(token_t::e_lsqrbracket))
24872  {
24873  if (0 == (variable0 = parse_vector()))
24874  {
24875  set_error(
24877  current_token(),
24878  "ERR171 - First parameter to swap is an invalid vector element: '" + var0_name + "'",
24880 
24881  return error_node();
24882  }
24883 
24884  variable0_generated = true;
24885  }
24886  else
24887  {
24888  if (symtab_store_.is_variable(var0_name))
24889  {
24890  variable0 = symtab_store_.get_variable(var0_name);
24891  }
24892 
24893  scope_element& se = sem_.get_element(var0_name);
24894 
24895  if (
24896  (se.active) &&
24897  (se.name == var0_name) &&
24898  (scope_element::e_variable == se.type)
24899  )
24900  {
24901  variable0 = se.var_node;
24902  }
24903 
24904  lodge_symbol(var0_name, e_st_variable);
24905 
24906  if (0 == variable0)
24907  {
24908  set_error(
24910  current_token(),
24911  "ERR172 - First parameter to swap is an invalid variable: '" + var0_name + "'",
24913 
24914  return error_node();
24915  }
24916  else
24917  next_token();
24918  }
24919 
24920  if (!token_is(token_t::e_comma))
24921  {
24922  set_error(
24924  current_token(),
24925  "ERR173 - Expected ',' between parameters to swap",
24927 
24928  if (variable0_generated)
24929  {
24930  free_node(node_allocator_,variable0);
24931  }
24932 
24933  return error_node();
24934  }
24935 
24936  const std::string var1_name = current_token().value;
24937 
24938  if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold))
24939  {
24940  set_error(
24942  current_token(),
24943  "ERR174 - Expected a symbol for variable or vector element definition",
24945 
24946  if (variable0_generated)
24947  {
24948  free_node(node_allocator_,variable0);
24949  }
24950 
24951  return error_node();
24952  }
24953  else if (peek_token_is(token_t::e_lsqrbracket))
24954  {
24955  if (0 == (variable1 = parse_vector()))
24956  {
24957  set_error(
24959  current_token(),
24960  "ERR175 - Second parameter to swap is an invalid vector element: '" + var1_name + "'",
24962 
24963  if (variable0_generated)
24964  {
24965  free_node(node_allocator_,variable0);
24966  }
24967 
24968  return error_node();
24969  }
24970 
24971  variable1_generated = true;
24972  }
24973  else
24974  {
24975  if (symtab_store_.is_variable(var1_name))
24976  {
24977  variable1 = symtab_store_.get_variable(var1_name);
24978  }
24979 
24980  scope_element& se = sem_.get_element(var1_name);
24981 
24982  if (
24983  (se.active) &&
24984  (se.name == var1_name) &&
24985  (scope_element::e_variable == se.type)
24986  )
24987  {
24988  variable1 = se.var_node;
24989  }
24990 
24991  lodge_symbol(var1_name, e_st_variable);
24992 
24993  if (0 == variable1)
24994  {
24995  set_error(
24997  current_token(),
24998  "ERR176 - Second parameter to swap is an invalid variable: '" + var1_name + "'",
25000 
25001  if (variable0_generated)
25002  {
25003  free_node(node_allocator_,variable0);
25004  }
25005 
25006  return error_node();
25007  }
25008  else
25009  next_token();
25010  }
25011 
25012  if (!token_is(token_t::e_rbracket))
25013  {
25014  set_error(
25016  current_token(),
25017  "ERR177 - Expected ')' at end of swap statement",
25019 
25020  if (variable0_generated)
25021  {
25022  free_node(node_allocator_,variable0);
25023  }
25024 
25025  if (variable1_generated)
25026  {
25027  free_node(node_allocator_,variable1);
25028  }
25029 
25030  return error_node();
25031  }
25032 
25033  typedef details::variable_node<T>* variable_node_ptr;
25034 
25035  variable_node_ptr v0 = variable_node_ptr(0);
25036  variable_node_ptr v1 = variable_node_ptr(0);
25037 
25038  expression_node_ptr result = error_node();
25039 
25040  if (
25041  (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) &&
25042  (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1)))
25043  )
25044  {
25045  result = node_allocator_.allocate<details::swap_node<T> >(v0, v1);
25046 
25047  if (variable0_generated)
25048  {
25049  free_node(node_allocator_,variable0);
25050  }
25051 
25052  if (variable1_generated)
25053  {
25054  free_node(node_allocator_,variable1);
25055  }
25056  }
25057  else
25058  result = node_allocator_.allocate<details::swap_generic_node<T> >
25059  (variable0, variable1);
25060 
25061  state_.activate_side_effect("parse_swap_statement()");
25062 
25063  return result;
25064  }
25065 
25066  #ifndef exprtk_disable_return_statement
25068  {
25069  if (state_.parsing_return_stmt)
25070  {
25071  set_error(
25073  current_token(),
25074  "ERR178 - Return call within a return call is not allowed",
25076 
25077  return error_node();
25078  }
25079 
25080  scoped_bool_negator sbn(state_.parsing_return_stmt);
25081 
25082  std::vector<expression_node_ptr> arg_list;
25083 
25084  scoped_vec_delete<expression_node_t> sdd((*this),arg_list);
25085 
25086  if (!details::imatch(current_token().value,"return"))
25087  {
25088  return error_node();
25089  }
25090  else
25091  next_token();
25092 
25093  if (!token_is(token_t::e_lsqrbracket))
25094  {
25095  set_error(
25097  current_token(),
25098  "ERR179 - Expected '[' at start of return statement",
25100 
25101  return error_node();
25102  }
25103  else if (!token_is(token_t::e_rsqrbracket))
25104  {
25105  for ( ; ; )
25106  {
25107  expression_node_ptr arg = parse_expression();
25108 
25109  if (0 == arg)
25110  return error_node();
25111 
25112  arg_list.push_back(arg);
25113 
25114  if (token_is(token_t::e_rsqrbracket))
25115  break;
25116  else if (!token_is(token_t::e_comma))
25117  {
25118  set_error(
25120  current_token(),
25121  "ERR180 - Expected ',' between values during call to return",
25123 
25124  return error_node();
25125  }
25126  }
25127  }
25128  else if (settings_.zero_return_disabled())
25129  {
25130  set_error(
25132  current_token(),
25133  "ERR181 - Zero parameter return statement not allowed",
25135 
25136  return error_node();
25137  }
25138 
25139  const lexer::token prev_token = current_token();
25140 
25141  if (token_is(token_t::e_rsqrbracket))
25142  {
25143  if (!arg_list.empty())
25144  {
25145  set_error(
25147  prev_token,
25148  "ERR182 - Invalid ']' found during return call",
25150 
25151  return error_node();
25152  }
25153  }
25154 
25155  std::string ret_param_type_list;
25156 
25157  for (std::size_t i = 0; i < arg_list.size(); ++i)
25158  {
25159  if (0 == arg_list[i])
25160  return error_node();
25161  else if (is_ivector_node(arg_list[i]))
25162  ret_param_type_list += 'V';
25163  else if (is_generally_string_node(arg_list[i]))
25164  ret_param_type_list += 'S';
25165  else
25166  ret_param_type_list += 'T';
25167  }
25168 
25169  dec_.retparam_list_.push_back(ret_param_type_list);
25170 
25171  expression_node_ptr result = expression_generator_.return_call(arg_list);
25172 
25173  sdd.delete_ptr = (0 == result);
25174 
25175  state_.return_stmt_present = true;
25176 
25177  state_.activate_side_effect("parse_return_statement()");
25178 
25179  return result;
25180  }
25181  #else
25182  inline expression_node_ptr parse_return_statement()
25183  {
25184  return error_node();
25185  }
25186  #endif
25187 
25188  inline bool post_variable_process(const std::string& symbol)
25189  {
25190  if (
25191  peek_token_is(token_t::e_lbracket ) ||
25192  peek_token_is(token_t::e_lcrlbracket) ||
25193  peek_token_is(token_t::e_lsqrbracket)
25194  )
25195  {
25196  if (!settings_.commutative_check_enabled())
25197  {
25198  set_error(
25200  current_token(),
25201  "ERR183 - Invalid sequence of variable '"+ symbol + "' and bracket",
25203 
25204  return false;
25205  }
25206 
25207  lexer().insert_front(token_t::e_mul);
25208  }
25209 
25210  return true;
25211  }
25212 
25214  {
25215  bool implied_mul = false;
25216 
25217  if (is_generally_string_node(branch))
25218  return true;
25219 
25220  const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold;
25221 
25222  switch (token)
25223  {
25224  case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25225  token_is(token_t::e_lcrlbracket,hold) ||
25226  token_is(token_t::e_lsqrbracket,hold) ;
25227  break;
25228 
25229  case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25230  token_is(token_t::e_lcrlbracket,hold) ||
25231  token_is(token_t::e_lsqrbracket,hold) ;
25232  break;
25233 
25234  case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) ||
25235  token_is(token_t::e_lcrlbracket,hold) ||
25236  token_is(token_t::e_lsqrbracket,hold) ;
25237  break;
25238 
25239  default : return true;
25240  }
25241 
25242  if (implied_mul)
25243  {
25244  if (!settings_.commutative_check_enabled())
25245  {
25246  set_error(
25248  current_token(),
25249  "ERR184 - Invalid sequence of brackets",
25251 
25252  return false;
25253  }
25254  else if (token_t::e_eof != current_token().type)
25255  {
25256  lexer().insert_front(current_token().type);
25257  lexer().insert_front(token_t::e_mul);
25258  next_token();
25259  }
25260  }
25261 
25262  return true;
25263  }
25264 
25266  {
25267  const std::string symbol = current_token().value;
25268 
25269  // Are we dealing with a variable or a special constant?
25270  expression_node_ptr variable = symtab_store_.get_variable(symbol);
25271 
25272  if (variable)
25273  {
25274  if (symtab_store_.is_constant_node(symbol))
25275  {
25276  variable = expression_generator_(variable->value());
25277  }
25278 
25279  if (!post_variable_process(symbol))
25280  return error_node();
25281 
25282  lodge_symbol(symbol, e_st_variable);
25283  next_token();
25284 
25285  return variable;
25286  }
25287 
25288  // Are we dealing with a locally defined variable, vector or string?
25289  if (!sem_.empty())
25290  {
25291  scope_element& se = sem_.get_active_element(symbol);
25292 
25293  if (se.active && details::imatch(se.name, symbol))
25294  {
25295  if (scope_element::e_variable == se.type)
25296  {
25297  se.active = true;
25298  lodge_symbol(symbol, e_st_local_variable);
25299 
25300  if (!post_variable_process(symbol))
25301  return error_node();
25302 
25303  next_token();
25304 
25305  return se.var_node;
25306  }
25307  else if (scope_element::e_vector == se.type)
25308  {
25309  return parse_vector();
25310  }
25311  #ifndef exprtk_disable_string_capabilities
25312  else if (scope_element::e_string == se.type)
25313  {
25314  return parse_string();
25315  }
25316  #endif
25317  }
25318  }
25319 
25320  #ifndef exprtk_disable_string_capabilities
25321  // Are we dealing with a string variable?
25322  if (symtab_store_.is_stringvar(symbol))
25323  {
25324  return parse_string();
25325  }
25326  #endif
25327 
25328  {
25329  // Are we dealing with a function?
25330  ifunction<T>* function = symtab_store_.get_function(symbol);
25331 
25332  if (function)
25333  {
25334  lodge_symbol(symbol, e_st_function);
25335 
25336  expression_node_ptr func_node =
25337  parse_function_invocation(function,symbol);
25338 
25339  if (func_node)
25340  return func_node;
25341  else
25342  {
25343  set_error(
25345  current_token(),
25346  "ERR185 - Failed to generate node for function: '" + symbol + "'",
25348 
25349  return error_node();
25350  }
25351  }
25352  }
25353 
25354  {
25355  // Are we dealing with a vararg function?
25356  ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol);
25357 
25358  if (vararg_function)
25359  {
25360  lodge_symbol(symbol, e_st_function);
25361 
25362  expression_node_ptr vararg_func_node =
25363  parse_vararg_function_call(vararg_function, symbol);
25364 
25365  if (vararg_func_node)
25366  return vararg_func_node;
25367  else
25368  {
25369  set_error(
25371  current_token(),
25372  "ERR186 - Failed to generate node for vararg function: '" + symbol + "'",
25374 
25375  return error_node();
25376  }
25377  }
25378  }
25379 
25380  {
25381  // Are we dealing with a vararg generic function?
25382  igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol);
25383 
25384  if (generic_function)
25385  {
25386  lodge_symbol(symbol, e_st_function);
25387 
25388  expression_node_ptr genericfunc_node =
25389  parse_generic_function_call(generic_function, symbol);
25390 
25391  if (genericfunc_node)
25392  return genericfunc_node;
25393  else
25394  {
25395  set_error(
25397  current_token(),
25398  "ERR187 - Failed to generate node for generic function: '" + symbol + "'",
25400 
25401  return error_node();
25402  }
25403  }
25404  }
25405 
25406  #ifndef exprtk_disable_string_capabilities
25407  {
25408  // Are we dealing with a vararg string returning function?
25409  igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol);
25410 
25411  if (string_function)
25412  {
25413  lodge_symbol(symbol, e_st_function);
25414 
25415  expression_node_ptr stringfunc_node =
25416  parse_string_function_call(string_function, symbol);
25417 
25418  if (stringfunc_node)
25419  return stringfunc_node;
25420  else
25421  {
25422  set_error(
25424  current_token(),
25425  "ERR188 - Failed to generate node for string function: '" + symbol + "'",
25427 
25428  return error_node();
25429  }
25430  }
25431  }
25432 
25433  {
25434  // Are we dealing with a vararg overloaded scalar/string returning function?
25435  igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol);
25436 
25437  if (overload_function)
25438  {
25439  lodge_symbol(symbol, e_st_function);
25440 
25441  expression_node_ptr overloadfunc_node =
25442  parse_overload_function_call(overload_function, symbol);
25443 
25444  if (overloadfunc_node)
25445  return overloadfunc_node;
25446  else
25447  {
25448  set_error(
25450  current_token(),
25451  "ERR189 - Failed to generate node for overload function: '" + symbol + "'",
25453 
25454  return error_node();
25455  }
25456  }
25457  }
25458  #endif
25459 
25460  // Are we dealing with a vector?
25461  if (symtab_store_.is_vector(symbol))
25462  {
25463  lodge_symbol(symbol, e_st_vector);
25464  return parse_vector();
25465  }
25466 
25467  if (details::is_reserved_symbol(symbol))
25468  {
25469  if (
25470  settings_.function_enabled(symbol) ||
25471  !details::is_base_function(symbol)
25472  )
25473  {
25474  set_error(
25476  current_token(),
25477  "ERR190 - Invalid use of reserved symbol '" + symbol + "'",
25479 
25480  return error_node();
25481  }
25482  }
25483 
25484  // Should we handle unknown symbols?
25485  if (resolve_unknown_symbol_ && unknown_symbol_resolver_)
25486  {
25487  if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol)))
25488  {
25489  symbol_table_t& symtab = symtab_store_.get_symbol_table();
25490 
25491  std::string error_message;
25492 
25493  if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode)
25494  {
25495  T default_value = T(0);
25496 
25497  typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type;
25498 
25499  if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message))
25500  {
25501  bool create_result = false;
25502 
25503  switch (usr_symbol_type)
25504  {
25505  case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value);
25506  break;
25507 
25508  case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value);
25509  break;
25510 
25511  default : create_result = false;
25512  }
25513 
25514  if (create_result)
25515  {
25516  expression_node_ptr var = symtab_store_.get_variable(symbol);
25517 
25518  if (var)
25519  {
25520  if (symtab_store_.is_constant_node(symbol))
25521  {
25522  var = expression_generator_(var->value());
25523  }
25524 
25525  lodge_symbol(symbol, e_st_variable);
25526 
25527  if (!post_variable_process(symbol))
25528  return error_node();
25529 
25530  next_token();
25531 
25532  return var;
25533  }
25534  }
25535  }
25536 
25537  set_error(
25539  current_token(),
25540  "ERR191 - Failed to create variable: '" + symbol + "'" +
25541  (error_message.empty() ? "" : " - " + error_message),
25543 
25544  }
25545  else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode)
25546  {
25547  if (unknown_symbol_resolver_->process(symbol, symtab, error_message))
25548  {
25549  expression_node_ptr result = parse_symtab_symbol();
25550 
25551  if (result)
25552  {
25553  return result;
25554  }
25555  }
25556 
25557  set_error(
25559  current_token(),
25560  "ERR192 - Failed to resolve symbol: '" + symbol + "'" +
25561  (error_message.empty() ? "" : " - " + error_message),
25563  }
25564 
25565  return error_node();
25566  }
25567  }
25568 
25569  set_error(
25571  current_token(),
25572  "ERR193 - Undefined symbol: '" + symbol + "'",
25574 
25575  return error_node();
25576  }
25577 
25579  {
25580  static const std::string symbol_if = "if" ;
25581  static const std::string symbol_while = "while" ;
25582  static const std::string symbol_repeat = "repeat" ;
25583  static const std::string symbol_for = "for" ;
25584  static const std::string symbol_switch = "switch" ;
25585  static const std::string symbol_null = "null" ;
25586  static const std::string symbol_break = "break" ;
25587  static const std::string symbol_continue = "continue";
25588  static const std::string symbol_var = "var" ;
25589  static const std::string symbol_swap = "swap" ;
25590  static const std::string symbol_return = "return" ;
25591 
25592  if (valid_vararg_operation(current_token().value))
25593  {
25594  return parse_vararg_function();
25595  }
25596  else if (valid_base_operation(current_token().value))
25597  {
25598  return parse_base_operation();
25599  }
25600  else if (
25601  details::imatch(current_token().value, symbol_if) &&
25602  settings_.control_struct_enabled(current_token().value)
25603  )
25604  {
25605  return parse_conditional_statement();
25606  }
25607  else if (
25608  details::imatch(current_token().value, symbol_while) &&
25609  settings_.control_struct_enabled(current_token().value)
25610  )
25611  {
25612  return parse_while_loop();
25613  }
25614  else if (
25615  details::imatch(current_token().value, symbol_repeat) &&
25616  settings_.control_struct_enabled(current_token().value)
25617  )
25618  {
25619  return parse_repeat_until_loop();
25620  }
25621  else if (
25622  details::imatch(current_token().value, symbol_for) &&
25623  settings_.control_struct_enabled(current_token().value)
25624  )
25625  {
25626  return parse_for_loop();
25627  }
25628  else if (
25629  details::imatch(current_token().value, symbol_switch) &&
25630  settings_.control_struct_enabled(current_token().value)
25631  )
25632  {
25633  return parse_switch_statement();
25634  }
25635  else if (details::is_valid_sf_symbol(current_token().value))
25636  {
25637  return parse_special_function();
25638  }
25639  else if (details::imatch(current_token().value, symbol_null))
25640  {
25641  return parse_null_statement();
25642  }
25643  #ifndef exprtk_disable_break_continue
25644  else if (details::imatch(current_token().value, symbol_break))
25645  {
25646  return parse_break_statement();
25647  }
25648  else if (details::imatch(current_token().value, symbol_continue))
25649  {
25650  return parse_continue_statement();
25651  }
25652  #endif
25653  else if (details::imatch(current_token().value, symbol_var))
25654  {
25655  return parse_define_var_statement();
25656  }
25657  else if (details::imatch(current_token().value, symbol_swap))
25658  {
25659  return parse_swap_statement();
25660  }
25661  #ifndef exprtk_disable_return_statement
25662  else if (
25663  details::imatch(current_token().value, symbol_return) &&
25664  settings_.control_struct_enabled(current_token().value)
25665  )
25666  {
25667  return parse_return_statement();
25668  }
25669  #endif
25670  else if (symtab_store_.valid() || !sem_.empty())
25671  {
25672  return parse_symtab_symbol();
25673  }
25674  else
25675  {
25676  set_error(
25678  current_token(),
25679  "ERR194 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value,
25681 
25682  return error_node();
25683  }
25684  }
25685 
25686  inline expression_node_ptr parse_branch(precedence_level precedence = e_level00)
25687  {
25688  expression_node_ptr branch = error_node();
25689 
25690  if (token_t::e_number == current_token().type)
25691  {
25692  T numeric_value = T(0);
25693 
25694  if (details::string_to_real(current_token().value, numeric_value))
25695  {
25696  expression_node_ptr literal_exp = expression_generator_(numeric_value);
25697 
25698  if (0 == literal_exp)
25699  {
25700  set_error(
25702  current_token(),
25703  "ERR195 - Failed generate node for scalar: '" + current_token().value + "'",
25705 
25706  return error_node();
25707  }
25708 
25709  next_token();
25710  branch = literal_exp;
25711  }
25712  else
25713  {
25714  set_error(
25716  current_token(),
25717  "ERR196 - Failed to convert '" + current_token().value + "' to a number",
25719 
25720  return error_node();
25721  }
25722  }
25723  else if (token_t::e_symbol == current_token().type)
25724  {
25725  branch = parse_symbol();
25726  }
25727  #ifndef exprtk_disable_string_capabilities
25728  else if (token_t::e_string == current_token().type)
25729  {
25730  branch = parse_const_string();
25731  }
25732  #endif
25733  else if (token_t::e_lbracket == current_token().type)
25734  {
25735  next_token();
25736 
25737  if (0 == (branch = parse_expression()))
25738  return error_node();
25739  else if (!token_is(token_t::e_rbracket))
25740  {
25741  set_error(
25743  current_token(),
25744  "ERR197 - Expected ')' instead of: '" + current_token().value + "'",
25746 
25747  free_node(node_allocator_,branch);
25748 
25749  return error_node();
25750  }
25751  else if (!post_bracket_process(token_t::e_lbracket,branch))
25752  {
25753  free_node(node_allocator_,branch);
25754 
25755  return error_node();
25756  }
25757  }
25758  else if (token_t::e_lsqrbracket == current_token().type)
25759  {
25760  next_token();
25761 
25762  if (0 == (branch = parse_expression()))
25763  return error_node();
25764  else if (!token_is(token_t::e_rsqrbracket))
25765  {
25766  set_error(
25768  current_token(),
25769  "ERR198 - Expected ']' instead of: '" + current_token().value + "'",
25771 
25772  free_node(node_allocator_,branch);
25773 
25774  return error_node();
25775  }
25776  else if (!post_bracket_process(token_t::e_lsqrbracket,branch))
25777  {
25778  free_node(node_allocator_,branch);
25779 
25780  return error_node();
25781  }
25782  }
25783  else if (token_t::e_lcrlbracket == current_token().type)
25784  {
25785  next_token();
25786 
25787  if (0 == (branch = parse_expression()))
25788  return error_node();
25789  else if (!token_is(token_t::e_rcrlbracket))
25790  {
25791  set_error(
25793  current_token(),
25794  "ERR199 - Expected '}' instead of: '" + current_token().value + "'",
25796 
25797  free_node(node_allocator_,branch);
25798 
25799  return error_node();
25800  }
25801  else if (!post_bracket_process(token_t::e_lcrlbracket,branch))
25802  {
25803  free_node(node_allocator_,branch);
25804 
25805  return error_node();
25806  }
25807  }
25808  else if (token_t::e_sub == current_token().type)
25809  {
25810  next_token();
25811  branch = parse_expression(e_level11);
25812 
25813  if (
25814  branch &&
25815  !(
25816  details::is_neg_unary_node (branch) &&
25817  simplify_unary_negation_branch(branch)
25818  )
25819  )
25820  {
25821  branch = expression_generator_(details::e_neg,branch);
25822  }
25823  }
25824  else if (token_t::e_add == current_token().type)
25825  {
25826  next_token();
25827  branch = parse_expression(e_level13);
25828  }
25829  else if (token_t::e_eof == current_token().type)
25830  {
25831  set_error(
25833  current_token(),
25834  "ERR200 - Premature end of expression[1]",
25836 
25837  return error_node();
25838  }
25839  else
25840  {
25841  set_error(
25843  current_token(),
25844  "ERR201 - Premature end of expression[2]",
25846 
25847  return error_node();
25848  }
25849 
25850  if (
25851  branch &&
25852  (e_level00 == precedence) &&
25853  token_is(token_t::e_ternary,prsrhlpr_t::e_hold)
25854  )
25855  {
25856  branch = parse_ternary_conditional_statement(branch);
25857  }
25858 
25859  parse_pending_string_rangesize(branch);
25860 
25861  return branch;
25862  }
25863 
25864  template <typename Type>
25866  {
25867  public:
25868 
25870  typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]);
25871  typedef std::map<std::string,synthesize_functor_t> synthesize_map_t;
25872  typedef typename exprtk::parser<Type> parser_t;
25873  typedef const Type& vtype;
25874  typedef const Type ctype;
25875 
25876  inline void init_synthesize_map()
25877  {
25878  #ifndef exprtk_disable_enhanced_features
25879  synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process;
25880  synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process;
25881  synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process;
25882 
25883  #define register_synthezier(S) \
25884  synthesize_map_[S ::node_type::id()] = S ::process; \
25885 
25886  register_synthezier(synthesize_vovov_expression0)
25887  register_synthezier(synthesize_vovov_expression1)
25888  register_synthezier(synthesize_vovoc_expression0)
25889  register_synthezier(synthesize_vovoc_expression1)
25890  register_synthezier(synthesize_vocov_expression0)
25891  register_synthezier(synthesize_vocov_expression1)
25892  register_synthezier(synthesize_covov_expression0)
25893  register_synthezier(synthesize_covov_expression1)
25894  register_synthezier(synthesize_covoc_expression0)
25895  register_synthezier(synthesize_covoc_expression1)
25896  register_synthezier(synthesize_cocov_expression1)
25897  register_synthezier(synthesize_vococ_expression0)
25898 
25899  register_synthezier(synthesize_vovovov_expression0)
25900  register_synthezier(synthesize_vovovoc_expression0)
25901  register_synthezier(synthesize_vovocov_expression0)
25902  register_synthezier(synthesize_vocovov_expression0)
25903  register_synthezier(synthesize_covovov_expression0)
25904  register_synthezier(synthesize_covocov_expression0)
25905  register_synthezier(synthesize_vocovoc_expression0)
25906  register_synthezier(synthesize_covovoc_expression0)
25907  register_synthezier(synthesize_vococov_expression0)
25908 
25909  register_synthezier(synthesize_vovovov_expression1)
25910  register_synthezier(synthesize_vovovoc_expression1)
25911  register_synthezier(synthesize_vovocov_expression1)
25912  register_synthezier(synthesize_vocovov_expression1)
25913  register_synthezier(synthesize_covovov_expression1)
25914  register_synthezier(synthesize_covocov_expression1)
25915  register_synthezier(synthesize_vocovoc_expression1)
25916  register_synthezier(synthesize_covovoc_expression1)
25917  register_synthezier(synthesize_vococov_expression1)
25918 
25919  register_synthezier(synthesize_vovovov_expression2)
25920  register_synthezier(synthesize_vovovoc_expression2)
25921  register_synthezier(synthesize_vovocov_expression2)
25922  register_synthezier(synthesize_vocovov_expression2)
25923  register_synthezier(synthesize_covovov_expression2)
25924  register_synthezier(synthesize_covocov_expression2)
25925  register_synthezier(synthesize_vocovoc_expression2)
25926  register_synthezier(synthesize_covovoc_expression2)
25927 
25928  register_synthezier(synthesize_vovovov_expression3)
25929  register_synthezier(synthesize_vovovoc_expression3)
25930  register_synthezier(synthesize_vovocov_expression3)
25931  register_synthezier(synthesize_vocovov_expression3)
25932  register_synthezier(synthesize_covovov_expression3)
25933  register_synthezier(synthesize_covocov_expression3)
25934  register_synthezier(synthesize_vocovoc_expression3)
25935  register_synthezier(synthesize_covovoc_expression3)
25936  register_synthezier(synthesize_vococov_expression3)
25937 
25938  register_synthezier(synthesize_vovovov_expression4)
25939  register_synthezier(synthesize_vovovoc_expression4)
25940  register_synthezier(synthesize_vovocov_expression4)
25941  register_synthezier(synthesize_vocovov_expression4)
25942  register_synthezier(synthesize_covovov_expression4)
25943  register_synthezier(synthesize_covocov_expression4)
25944  register_synthezier(synthesize_vocovoc_expression4)
25945  register_synthezier(synthesize_covovoc_expression4)
25946  #endif
25947  }
25948 
25949  inline void set_parser(parser_t& p)
25950  {
25951  parser_ = &p;
25952  }
25953 
25954  inline void set_uom(unary_op_map_t& unary_op_map)
25955  {
25956  unary_op_map_ = &unary_op_map;
25957  }
25958 
25959  inline void set_bom(binary_op_map_t& binary_op_map)
25960  {
25961  binary_op_map_ = &binary_op_map;
25962  }
25963 
25964  inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map)
25965  {
25966  inv_binary_op_map_ = &inv_binary_op_map;
25967  }
25968 
25969  inline void set_sf3m(sf3_map_t& sf3_map)
25970  {
25971  sf3_map_ = &sf3_map;
25972  }
25973 
25974  inline void set_sf4m(sf4_map_t& sf4_map)
25975  {
25976  sf4_map_ = &sf4_map;
25977  }
25978 
25980  {
25981  node_allocator_ = &na;
25982  }
25983 
25984  inline void set_strength_reduction_state(const bool enabled)
25985  {
25986  strength_reduction_enabled_ = enabled;
25987  }
25988 
25989  inline bool strength_reduction_enabled() const
25990  {
25991  return strength_reduction_enabled_;
25992  }
25993 
25994  inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop)
25995  {
25996  typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation);
25997 
25998  if ((*binary_op_map_).end() == bop_itr)
25999  return false;
26000 
26001  bop = bop_itr->second;
26002 
26003  return true;
26004  }
26005 
26006  inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop)
26007  {
26008  typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation);
26009 
26010  if ((*unary_op_map_).end() == uop_itr)
26011  return false;
26012 
26013  uop = uop_itr->second;
26014 
26015  return true;
26016  }
26017 
26019  {
26020  return (*inv_binary_op_map_).find(bop)->second;
26021  }
26022 
26023  inline expression_node_ptr operator() (const Type& v) const
26024  {
26025  return node_allocator_->allocate<literal_node_t>(v);
26026  }
26027 
26028  #ifndef exprtk_disable_string_capabilities
26029  inline expression_node_ptr operator() (const std::string& s) const
26030  {
26031  return node_allocator_->allocate<string_literal_node_t>(s);
26032  }
26033 
26034  inline expression_node_ptr operator() (std::string& s, range_t& rp) const
26035  {
26036  return node_allocator_->allocate_rr<string_range_node_t>(s,rp);
26037  }
26038 
26039  inline expression_node_ptr operator() (const std::string& s, range_t& rp) const
26040  {
26041  return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp);
26042  }
26043 
26044  inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const
26045  {
26046  if (is_generally_string_node(branch))
26047  return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp);
26048  else
26049  return error_node();
26050  }
26051  #endif
26052 
26053  inline bool unary_optimisable(const details::operator_type& operation) const
26054  {
26055  return (details::e_abs == operation) || (details::e_acos == operation) ||
26056  (details::e_acosh == operation) || (details::e_asin == operation) ||
26057  (details::e_asinh == operation) || (details::e_atan == operation) ||
26058  (details::e_atanh == operation) || (details::e_ceil == operation) ||
26059  (details::e_cos == operation) || (details::e_cosh == operation) ||
26060  (details::e_exp == operation) || (details::e_expm1 == operation) ||
26061  (details::e_floor == operation) || (details::e_log == operation) ||
26062  (details::e_log10 == operation) || (details::e_log2 == operation) ||
26063  (details::e_log1p == operation) || (details::e_neg == operation) ||
26064  (details::e_pos == operation) || (details::e_round == operation) ||
26065  (details::e_sin == operation) || (details::e_sinc == operation) ||
26066  (details::e_sinh == operation) || (details::e_sqrt == operation) ||
26067  (details::e_tan == operation) || (details::e_tanh == operation) ||
26068  (details::e_cot == operation) || (details::e_sec == operation) ||
26069  (details::e_csc == operation) || (details::e_r2d == operation) ||
26070  (details::e_d2r == operation) || (details::e_d2g == operation) ||
26071  (details::e_g2d == operation) || (details::e_notl == operation) ||
26072  (details::e_sgn == operation) || (details::e_erf == operation) ||
26073  (details::e_erfc == operation) || (details::e_ncdf == operation) ||
26074  (details::e_frac == operation) || (details::e_trunc == operation) ;
26075  }
26076 
26077  inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const
26078  {
26079  typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26080 
26081  if (sf3_map_->end() == itr)
26082  return false;
26083  else
26084  tfunc = itr->second.first;
26085 
26086  return true;
26087  }
26088 
26089  inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const
26090  {
26091  typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26092 
26093  if (sf4_map_->end() == itr)
26094  return false;
26095  else
26096  qfunc = itr->second.first;
26097 
26098  return true;
26099  }
26100 
26101  inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const
26102  {
26103  typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id);
26104 
26105  if (sf3_map_->end() == itr)
26106  return false;
26107  else
26108  operation = itr->second.second;
26109 
26110  return true;
26111  }
26112 
26113  inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const
26114  {
26115  typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id);
26116 
26117  if (sf4_map_->end() == itr)
26118  return false;
26119  else
26120  operation = itr->second.second;
26121 
26122  return true;
26123  }
26124 
26125  inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1])
26126  {
26127  if (0 == branch[0])
26128  {
26129  return error_node();
26130  }
26131  else if (details::is_null_node(branch[0]))
26132  {
26133  return branch[0];
26134  }
26135  else if (details::is_break_node(branch[0]))
26136  {
26137  return error_node();
26138  }
26139  else if (details::is_continue_node(branch[0]))
26140  {
26141  return error_node();
26142  }
26143  else if (details::is_constant_node(branch[0]))
26144  {
26145  return synthesize_expression<unary_node_t,1>(operation,branch);
26146  }
26147  else if (unary_optimisable(operation) && details::is_variable_node(branch[0]))
26148  {
26149  return synthesize_uv_expression(operation,branch);
26150  }
26151  else if (unary_optimisable(operation) && details::is_ivector_node(branch[0]))
26152  {
26153  return synthesize_uvec_expression(operation,branch);
26154  }
26155  else
26156  return synthesize_unary_expression(operation,branch);
26157  }
26158 
26159  inline bool is_assignment_operation(const details::operator_type& operation) const
26160  {
26161  return (
26162  (details::e_addass == operation) ||
26163  (details::e_subass == operation) ||
26164  (details::e_mulass == operation) ||
26165  (details::e_divass == operation) ||
26166  (details::e_modass == operation)
26167  ) &&
26168  parser_->settings_.assignment_enabled(operation);
26169  }
26170 
26171  #ifndef exprtk_disable_string_capabilities
26172  inline bool valid_string_operation(const details::operator_type& operation) const
26173  {
26174  return (details::e_add == operation) ||
26175  (details::e_lt == operation) ||
26176  (details::e_lte == operation) ||
26177  (details::e_gt == operation) ||
26178  (details::e_gte == operation) ||
26179  (details::e_eq == operation) ||
26180  (details::e_ne == operation) ||
26181  (details::e_in == operation) ||
26182  (details::e_like == operation) ||
26183  (details::e_ilike == operation) ||
26184  (details::e_assign == operation) ||
26185  (details::e_addass == operation) ||
26186  (details::e_swap == operation) ;
26187  }
26188  #else
26189  inline bool valid_string_operation(const details::operator_type&) const
26190  {
26191  return false;
26192  }
26193  #endif
26194 
26195  inline std::string to_str(const details::operator_type& operation) const
26196  {
26197  switch (operation)
26198  {
26199  case details::e_add : return "+" ;
26200  case details::e_sub : return "-" ;
26201  case details::e_mul : return "*" ;
26202  case details::e_div : return "/" ;
26203  case details::e_mod : return "%" ;
26204  case details::e_pow : return "^" ;
26205  case details::e_lt : return "<" ;
26206  case details::e_lte : return "<=" ;
26207  case details::e_gt : return ">" ;
26208  case details::e_gte : return ">=" ;
26209  case details::e_eq : return "==" ;
26210  case details::e_ne : return "!=" ;
26211  case details::e_and : return "and" ;
26212  case details::e_nand : return "nand" ;
26213  case details::e_or : return "or" ;
26214  case details::e_nor : return "nor" ;
26215  case details::e_xor : return "xor" ;
26216  case details::e_xnor : return "xnor" ;
26217  default : return "UNKNOWN";
26218  }
26219  }
26220 
26221  inline bool operation_optimisable(const details::operator_type& operation) const
26222  {
26223  return (details::e_add == operation) ||
26224  (details::e_sub == operation) ||
26225  (details::e_mul == operation) ||
26226  (details::e_div == operation) ||
26227  (details::e_mod == operation) ||
26228  (details::e_pow == operation) ||
26229  (details::e_lt == operation) ||
26230  (details::e_lte == operation) ||
26231  (details::e_gt == operation) ||
26232  (details::e_gte == operation) ||
26233  (details::e_eq == operation) ||
26234  (details::e_ne == operation) ||
26235  (details::e_and == operation) ||
26236  (details::e_nand == operation) ||
26237  (details::e_or == operation) ||
26238  (details::e_nor == operation) ||
26239  (details::e_xor == operation) ||
26240  (details::e_xnor == operation) ;
26241  }
26242 
26244  {
26245  static const std::string null_str ("(null)" );
26246  static const std::string const_str ("(c)" );
26247  static const std::string var_str ("(v)" );
26248  static const std::string vov_str ("(vov)" );
26249  static const std::string cov_str ("(cov)" );
26250  static const std::string voc_str ("(voc)" );
26251  static const std::string str_str ("(s)" );
26252  static const std::string strrng_str ("(rngs)" );
26253  static const std::string cs_str ("(cs)" );
26254  static const std::string cstrrng_str("(crngs)");
26255 
26256  if (details::is_null_node(branch))
26257  return null_str;
26258  else if (details::is_constant_node(branch))
26259  return const_str;
26260  else if (details::is_variable_node(branch))
26261  return var_str;
26262  else if (details::is_vov_node(branch))
26263  return vov_str;
26264  else if (details::is_cov_node(branch))
26265  return cov_str;
26266  else if (details::is_voc_node(branch))
26267  return voc_str;
26268  else if (details::is_string_node(branch))
26269  return str_str;
26270  else if (details::is_const_string_node(branch))
26271  return cs_str;
26272  else if (details::is_string_range_node(branch))
26273  return strrng_str;
26274  else if (details::is_const_string_range_node(branch))
26275  return cstrrng_str;
26276  else if (details::is_t0ot1ot2_node(branch))
26277  return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")";
26278  else if (details::is_t0ot1ot2ot3_node(branch))
26279  return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")";
26280  else
26281  return "ERROR";
26282  }
26283 
26284  inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const
26285  {
26286  return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]);
26287  }
26288 
26289  inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26290  {
26291  if (!operation_optimisable(operation))
26292  return false;
26293  else
26294  return details::is_constant_node(branch[0]) &&
26295  details::is_variable_node(branch[1]) ;
26296  }
26297 
26298  inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26299  {
26300  if (!operation_optimisable(operation))
26301  return false;
26302  else
26303  return details::is_variable_node(branch[0]) &&
26304  details::is_constant_node(branch[1]) ;
26305  }
26306 
26307  inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26308  {
26309  if (!operation_optimisable(operation))
26310  return false;
26311  else
26312  return details::is_variable_node(branch[0]) &&
26313  details::is_variable_node(branch[1]) ;
26314  }
26315 
26316  inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26317  {
26318  if (!operation_optimisable(operation))
26319  return false;
26320  else
26321  return details::is_constant_node(branch[0]) &&
26322  !details::is_constant_node(branch[1]) ;
26323  }
26324 
26325  inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26326  {
26327  if (!operation_optimisable(operation))
26328  return false;
26329  else
26330  return !details::is_constant_node(branch[0]) &&
26331  details::is_constant_node(branch[1]) ;
26332  }
26333 
26334  inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26335  {
26336  if (
26337  (details::e_add == operation) ||
26338  (details::e_sub == operation) ||
26339  (details::e_mul == operation) ||
26340  (details::e_div == operation)
26341  )
26342  {
26343  return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) ||
26344  (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ;
26345  }
26346  else
26347  return false;
26348  }
26349 
26350  inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26351  {
26352  if (
26353  (details::e_add == operation) ||
26354  (details::e_sub == operation) ||
26355  (details::e_mul == operation) ||
26356  (details::e_div == operation)
26357  )
26358  {
26359  return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) ||
26360  (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ;
26361  }
26362  else
26363  return false;
26364  }
26365 
26366  inline bool uvouv_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_uv_node(branch[0]) &&
26372  details::is_uv_node(branch[1]) ;
26373  }
26374 
26375  inline bool vob_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_variable_node(branch[1]) ;
26382  }
26383 
26384  inline bool bov_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 binext_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 is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26403  {
26404  if (is_assignment_operation(operation))
26405  {
26406  const bool b1_is_genstring = details::is_generally_string_node(branch[1]);
26407 
26408  if (details::is_string_node(branch[0]))
26409  return !b1_is_genstring;
26410  else
26411  return (
26412  !details::is_variable_node (branch[0]) &&
26413  !details::is_vector_elem_node (branch[0]) &&
26414  !details::is_rebasevector_elem_node (branch[0]) &&
26416  !details::is_vector_node (branch[0])
26417  )
26418  || b1_is_genstring;
26419  }
26420  else
26421  return false;
26422  }
26423 
26424  inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const
26425  {
26426  if (
26427  !details::is_constant_node(branch[1]) ||
26428  details::is_constant_node(branch[0]) ||
26429  details::is_variable_node(branch[0]) ||
26430  details::is_vector_node (branch[0]) ||
26432  )
26433  return false;
26434 
26435  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
26436 
26437  return cardinal_pow_optimisable(operation, c);
26438  }
26439 
26440  inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const
26441  {
26442  return (
26443  details::is_break_node (branch[0]) ||
26444  details::is_break_node (branch[1]) ||
26445  details::is_continue_node(branch[0]) ||
26446  details::is_continue_node(branch[1])
26447  );
26448  }
26449 
26450  inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26451  {
26452  const bool b0_string = is_generally_string_node(branch[0]);
26453  const bool b1_string = is_generally_string_node(branch[1]);
26454 
26455  bool result = false;
26456 
26457  if (b0_string != b1_string)
26458  result = true;
26459  else if (!valid_string_operation(operation) && b0_string && b1_string)
26460  result = true;
26461 
26462  if (result)
26463  {
26464  parser_->set_synthesis_error("Invalid string operation");
26465  }
26466 
26467  return result;
26468  }
26469 
26470  inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26471  {
26472  const bool b0_string = is_generally_string_node(branch[0]);
26473  const bool b1_string = is_generally_string_node(branch[1]);
26474  const bool b2_string = is_generally_string_node(branch[2]);
26475 
26476  bool result = false;
26477 
26478  if ((b0_string != b1_string) || (b1_string != b2_string))
26479  result = true;
26480  else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
26481  result = true;
26482 
26483  if (result)
26484  {
26485  parser_->set_synthesis_error("Invalid string operation");
26486  }
26487 
26488  return result;
26489  }
26490 
26491  inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26492  {
26493  const bool b0_string = is_generally_string_node(branch[0]);
26494  const bool b1_string = is_generally_string_node(branch[1]);
26495 
26496  return (b0_string && b1_string && valid_string_operation(operation));
26497  }
26498 
26499  inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const
26500  {
26501  const bool b0_string = is_generally_string_node(branch[0]);
26502  const bool b1_string = is_generally_string_node(branch[1]);
26503  const bool b2_string = is_generally_string_node(branch[2]);
26504 
26505  return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
26506  }
26507 
26508  #ifndef exprtk_disable_sc_andor
26509  inline bool is_shortcircuit_expression(const details::operator_type& operation) const
26510  {
26511  return (
26512  (details::e_scand == operation) ||
26513  (details::e_scor == operation)
26514  );
26515  }
26516  #else
26517  inline bool is_shortcircuit_expression(const details::operator_type&) const
26518  {
26519  return false;
26520  }
26521  #endif
26522 
26523  inline bool is_null_present(expression_node_ptr (&branch)[2]) const
26524  {
26525  return (
26526  details::is_null_node(branch[0]) ||
26527  details::is_null_node(branch[1])
26528  );
26529  }
26530 
26531  inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26532  {
26533  if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26534  return false;
26535  else
26536  return (
26537  (details::e_lt == operation) ||
26538  (details::e_lte == operation) ||
26539  (details::e_gt == operation) ||
26540  (details::e_gte == operation) ||
26541  (details::e_eq == operation) ||
26542  (details::e_ne == operation) ||
26543  (details::e_equal == operation) ||
26544  (details::e_and == operation) ||
26545  (details::e_nand == operation) ||
26546  (details:: e_or == operation) ||
26547  (details:: e_nor == operation) ||
26548  (details:: e_xor == operation) ||
26549  (details::e_xnor == operation)
26550  );
26551  }
26552 
26553  inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
26554  {
26555  if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1]))
26556  return false;
26557  else
26558  return (
26559  (details::e_add == operation) ||
26560  (details::e_sub == operation) ||
26561  (details::e_mul == operation) ||
26562  (details::e_div == operation) ||
26563  (details::e_pow == operation)
26564  );
26565  }
26566 
26567  inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2])
26568  {
26569  if ((0 == branch[0]) || (0 == branch[1]))
26570  {
26571  return error_node();
26572  }
26573  else if (is_invalid_string_op(operation,branch))
26574  {
26575  return error_node();
26576  }
26577  else if (is_invalid_assignment_op(operation,branch))
26578  {
26579  return error_node();
26580  }
26581  else if (is_invalid_break_continue_op(branch))
26582  {
26583  return error_node();
26584  }
26585  else if (details::e_assign == operation)
26586  {
26587  return synthesize_assignment_expression(operation, branch);
26588  }
26589  else if (details::e_swap == operation)
26590  {
26591  return synthesize_swap_expression(branch);
26592  }
26593  else if (is_assignment_operation(operation))
26594  {
26595  return synthesize_assignment_operation_expression(operation, branch);
26596  }
26597  else if (is_vector_eqineq_logic_operation(operation, branch))
26598  {
26599  return synthesize_veceqineqlogic_operation_expression(operation, branch);
26600  }
26601  else if (is_vector_arithmetic_operation(operation, branch))
26602  {
26603  return synthesize_vecarithmetic_operation_expression(operation, branch);
26604  }
26605  else if (is_shortcircuit_expression(operation))
26606  {
26607  return synthesize_shortcircuit_expression(operation, branch);
26608  }
26609  else if (is_string_operation(operation, branch))
26610  {
26611  return synthesize_string_expression(operation, branch);
26612  }
26613  else if (is_null_present(branch))
26614  {
26615  return synthesize_null_expression(operation, branch);
26616  }
26617  #ifndef exprtk_disable_cardinal_pow_optimisation
26618  else if (is_constpow_operation(operation, branch))
26619  {
26620  return cardinal_pow_optimisation(branch);
26621  }
26622  #endif
26623 
26624  expression_node_ptr result = error_node();
26625 
26626  #ifndef exprtk_disable_enhanced_features
26627  if (synthesize_expression(operation, branch, result))
26628  {
26629  return result;
26630  }
26631  else
26632  #endif
26633 
26634  {
26635  /*
26636  Possible reductions:
26637  1. c o cob -> cob
26638  2. cob o c -> cob
26639  3. c o boc -> boc
26640  4. boc o c -> boc
26641  */
26642  result = error_node();
26643 
26644  if (cocob_optimisable(operation, branch))
26645  {
26646  result = synthesize_cocob_expression::process((*this), operation, branch);
26647  }
26648  else if (coboc_optimisable(operation, branch) && (0 == result))
26649  {
26650  result = synthesize_coboc_expression::process((*this), operation, branch);
26651  }
26652 
26653  if (result)
26654  return result;
26655  }
26656 
26657  if (uvouv_optimisable(operation, branch))
26658  {
26659  return synthesize_uvouv_expression(operation, branch);
26660  }
26661  else if (vob_optimisable(operation, branch))
26662  {
26663  return synthesize_vob_expression::process((*this), operation, branch);
26664  }
26665  else if (bov_optimisable(operation, branch))
26666  {
26667  return synthesize_bov_expression::process((*this), operation, branch);
26668  }
26669  else if (cob_optimisable(operation, branch))
26670  {
26671  return synthesize_cob_expression::process((*this), operation, branch);
26672  }
26673  else if (boc_optimisable(operation, branch))
26674  {
26675  return synthesize_boc_expression::process((*this), operation, branch);
26676  }
26677  #ifndef exprtk_disable_enhanced_features
26678  else if (cov_optimisable(operation, branch))
26679  {
26680  return synthesize_cov_expression::process((*this), operation, branch);
26681  }
26682  #endif
26683  else if (binext_optimisable(operation, branch))
26684  {
26685  return synthesize_binary_ext_expression::process((*this), operation, branch);
26686  }
26687  else
26688  return synthesize_expression<binary_node_t,2>(operation, branch);
26689  }
26690 
26691  inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3])
26692  {
26693  if (
26694  (0 == branch[0]) ||
26695  (0 == branch[1]) ||
26696  (0 == branch[2])
26697  )
26698  {
26699  details::free_all_nodes(*node_allocator_,branch);
26700 
26701  return error_node();
26702  }
26703  else if (is_invalid_string_op(operation, branch))
26704  {
26705  return error_node();
26706  }
26707  else if (is_string_operation(operation, branch))
26708  {
26709  return synthesize_string_expression(operation, branch);
26710  }
26711  else
26712  return synthesize_expression<trinary_node_t,3>(operation, branch);
26713  }
26714 
26715  inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4])
26716  {
26717  return synthesize_expression<quaternary_node_t,4>(operation,branch);
26718  }
26719 
26720  inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0)
26721  {
26722  expression_node_ptr branch[1] = { b0 };
26723  return (*this)(operation,branch);
26724  }
26725 
26727  {
26728  expression_node_ptr result = error_node();
26729 
26730  if ((0 != b0) && (0 != b1))
26731  {
26732  expression_node_ptr branch[2] = { b0, b1 };
26733  result = expression_generator<Type>::operator()(operation, branch);
26734  b0 = branch[0];
26735  b1 = branch[1];
26736  }
26737 
26738  return result;
26739  }
26740 
26742  expression_node_ptr consequent,
26743  expression_node_ptr alternative) const
26744  {
26745  if ((0 == condition) || (0 == consequent))
26746  {
26747  free_node(*node_allocator_, condition);
26748  free_node(*node_allocator_, consequent);
26749  free_node(*node_allocator_, alternative);
26750 
26751  return error_node();
26752  }
26753  // Can the condition be immediately evaluated? if so optimise.
26754  else if (details::is_constant_node(condition))
26755  {
26756  // True branch
26757  if (details::is_true(condition))
26758  {
26759  free_node(*node_allocator_, condition);
26760  free_node(*node_allocator_, alternative);
26761 
26762  return consequent;
26763  }
26764  // False branch
26765  else
26766  {
26767  free_node(*node_allocator_, condition);
26768  free_node(*node_allocator_, consequent);
26769 
26770  if (alternative)
26771  return alternative;
26772  else
26773  return node_allocator_->allocate<details::null_node<T> >();
26774  }
26775  }
26776  else if ((0 != consequent) && (0 != alternative))
26777  {
26778  return node_allocator_->
26779  allocate<conditional_node_t>(condition, consequent, alternative);
26780  }
26781  else
26782  return node_allocator_->
26783  allocate<cons_conditional_node_t>(condition, consequent);
26784  }
26785 
26786  #ifndef exprtk_disable_string_capabilities
26788  expression_node_ptr consequent,
26789  expression_node_ptr alternative) const
26790  {
26791  if ((0 == condition) || (0 == consequent))
26792  {
26793  free_node(*node_allocator_, condition);
26794  free_node(*node_allocator_, consequent);
26795  free_node(*node_allocator_, alternative);
26796 
26797  return error_node();
26798  }
26799  // Can the condition be immediately evaluated? if so optimise.
26800  else if (details::is_constant_node(condition))
26801  {
26802  // True branch
26803  if (details::is_true(condition))
26804  {
26805  free_node(*node_allocator_, condition);
26806  free_node(*node_allocator_, alternative);
26807 
26808  return consequent;
26809  }
26810  // False branch
26811  else
26812  {
26813  free_node(*node_allocator_, condition);
26814  free_node(*node_allocator_, consequent);
26815 
26816  if (alternative)
26817  return alternative;
26818  else
26819  return node_allocator_->
26820  allocate_c<details::string_literal_node<Type> >("");
26821  }
26822  }
26823  else if ((0 != consequent) && (0 != alternative))
26824  return node_allocator_->
26825  allocate<conditional_string_node_t>(condition, consequent, alternative);
26826  else
26827  return error_node();
26828  }
26829  #else
26830  inline expression_node_ptr conditional_string(expression_node_ptr,
26832  expression_node_ptr) const
26833  {
26834  return error_node();
26835  }
26836  #endif
26837 
26839  expression_node_ptr& branch,
26840  const bool brkcont = false) const
26841  {
26842  if (!brkcont && details::is_constant_node(condition))
26843  {
26844  expression_node_ptr result = error_node();
26845  if (details::is_true(condition))
26846  // Infinite loops are not allowed.
26847  result = error_node();
26848  else
26849  result = node_allocator_->allocate<details::null_node<Type> >();
26850 
26851  free_node(*node_allocator_, condition);
26852  free_node(*node_allocator_, branch);
26853 
26854  return result;
26855  }
26856  else if (details::is_null_node(condition))
26857  {
26858  free_node(*node_allocator_,condition);
26859 
26860  return branch;
26861  }
26862  else if (!brkcont)
26863  return node_allocator_->allocate<while_loop_node_t>(condition,branch);
26864  #ifndef exprtk_disable_break_continue
26865  else
26866  return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch);
26867  #else
26868  return error_node();
26869  #endif
26870  }
26871 
26873  expression_node_ptr& branch,
26874  const bool brkcont = false) const
26875  {
26876  if (!brkcont && details::is_constant_node(condition))
26877  {
26878  if (
26879  details::is_true(condition) &&
26881  )
26882  {
26883  free_node(*node_allocator_,condition);
26884 
26885  return branch;
26886  }
26887 
26888  free_node(*node_allocator_, condition);
26889  free_node(*node_allocator_, branch);
26890 
26891  return error_node();
26892  }
26893  else if (details::is_null_node(condition))
26894  {
26895  free_node(*node_allocator_,condition);
26896 
26897  return branch;
26898  }
26899  else if (!brkcont)
26900  return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch);
26901  #ifndef exprtk_disable_break_continue
26902  else
26903  return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch);
26904  #else
26905  return error_node();
26906  #endif
26907  }
26908 
26910  expression_node_ptr& condition,
26911  expression_node_ptr& incrementor,
26912  expression_node_ptr& loop_body,
26913  bool brkcont = false) const
26914  {
26915  if (!brkcont && details::is_constant_node(condition))
26916  {
26917  expression_node_ptr result = error_node();
26918 
26919  if (details::is_true(condition))
26920  // Infinite loops are not allowed.
26921  result = error_node();
26922  else
26923  result = node_allocator_->allocate<details::null_node<Type> >();
26924 
26925  free_node(*node_allocator_, initialiser);
26926  free_node(*node_allocator_, condition);
26927  free_node(*node_allocator_, incrementor);
26928  free_node(*node_allocator_, loop_body);
26929 
26930  return result;
26931  }
26932  else if (details::is_null_node(condition) || (0 == condition))
26933  {
26934  free_node(*node_allocator_, initialiser);
26935  free_node(*node_allocator_, condition);
26936  free_node(*node_allocator_, incrementor);
26937 
26938  return loop_body;
26939  }
26940  else if (!brkcont)
26941  return node_allocator_->allocate<for_loop_node_t>
26942  (
26943  initialiser,
26944  condition,
26945  incrementor,
26946  loop_body
26947  );
26948 
26949  #ifndef exprtk_disable_break_continue
26950  else
26951  return node_allocator_->allocate<for_loop_bc_node_t>
26952  (
26953  initialiser,
26954  condition,
26955  incrementor,
26956  loop_body
26957  );
26958  #else
26959  return error_node();
26960  #endif
26961  }
26962 
26963  template <typename Allocator,
26964  template <typename, typename> class Sequence>
26965  inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list)
26966  {
26967  expression_node_ptr result = error_node();
26968 
26969  for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
26970  {
26971  expression_node_ptr condition = arg_list[(2 * i) ];
26972  expression_node_ptr consequent = arg_list[(2 * i) + 1];
26973 
26974  if ((0 == result) && details::is_true(condition))
26975  {
26976  result = consequent;
26977  break;
26978  }
26979  }
26980 
26981  if (0 == result)
26982  {
26983  result = arg_list.back();
26984  }
26985 
26986  for (std::size_t i = 0; i < arg_list.size(); ++i)
26987  {
26988  expression_node_ptr current_expr = arg_list[i];
26989 
26990  if (current_expr && (current_expr != result))
26991  {
26992  free_node(*node_allocator_,current_expr);
26993  }
26994  }
26995 
26996  return result;
26997  }
26998 
26999  template <typename Allocator,
27000  template <typename, typename> class Sequence>
27001  inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list)
27002  {
27003  expression_node_ptr result = error_node();
27004 
27005  for (std::size_t i = 0; i < (arg_list.size() / 2); ++i)
27006  {
27007  expression_node_ptr condition = arg_list[(2 * i) ];
27008  expression_node_ptr consequent = arg_list[(2 * i) + 1];
27009 
27010  if (details::is_true(condition))
27011  {
27012  result = consequent;
27013  }
27014  }
27015 
27016  if (0 == result)
27017  {
27018  T zero = T(0);
27019  result = node_allocator_->allocate<literal_node_t>(zero);
27020  }
27021 
27022  for (std::size_t i = 0; i < arg_list.size(); ++i)
27023  {
27024  expression_node_ptr& current_expr = arg_list[i];
27025 
27026  if (current_expr && (current_expr != result))
27027  {
27028  free_node(*node_allocator_,current_expr);
27029  }
27030  }
27031 
27032  return result;
27033  }
27034 
27036  {
27037  typedef std::vector<expression_node_ptr> arg_list_t;
27038 
27039  #define case_stmt(N) \
27040  if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \
27041 
27042  struct switch_1
27043  {
27044  static inline T process(const arg_list_t& arg)
27045  {
27046  case_stmt(0)
27047 
27048  return arg.back()->value();
27049  }
27050  };
27051 
27052  struct switch_2
27053  {
27054  static inline T process(const arg_list_t& arg)
27055  {
27056  case_stmt(0) case_stmt(1)
27057 
27058  return arg.back()->value();
27059  }
27060  };
27061 
27062  struct switch_3
27063  {
27064  static inline T process(const arg_list_t& arg)
27065  {
27066  case_stmt(0) case_stmt(1)
27067  case_stmt(2)
27068 
27069  return arg.back()->value();
27070  }
27071  };
27072 
27073  struct switch_4
27074  {
27075  static inline T process(const arg_list_t& arg)
27076  {
27077  case_stmt(0) case_stmt(1)
27078  case_stmt(2) case_stmt(3)
27079 
27080  return arg.back()->value();
27081  }
27082  };
27083 
27084  struct switch_5
27085  {
27086  static inline T process(const arg_list_t& arg)
27087  {
27088  case_stmt(0) case_stmt(1)
27089  case_stmt(2) case_stmt(3)
27090  case_stmt(4)
27091 
27092  return arg.back()->value();
27093  }
27094  };
27095 
27096  struct switch_6
27097  {
27098  static inline T process(const arg_list_t& arg)
27099  {
27100  case_stmt(0) case_stmt(1)
27101  case_stmt(2) case_stmt(3)
27102  case_stmt(4) case_stmt(5)
27103 
27104  return arg.back()->value();
27105  }
27106  };
27107 
27108  struct switch_7
27109  {
27110  static inline T process(const arg_list_t& arg)
27111  {
27112  case_stmt(0) case_stmt(1)
27113  case_stmt(2) case_stmt(3)
27114  case_stmt(4) case_stmt(5)
27115  case_stmt(6)
27116 
27117  return arg.back()->value();
27118  }
27119  };
27120 
27121  #undef case_stmt
27122  };
27123 
27124  template <typename Allocator,
27125  template <typename, typename> class Sequence>
27126  inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27127  {
27128  if (arg_list.empty())
27129  return error_node();
27130  else if (
27131  !all_nodes_valid(arg_list) ||
27132  (arg_list.size() < 3) ||
27133  ((arg_list.size() % 2) != 1)
27134  )
27135  {
27136  details::free_all_nodes(*node_allocator_,arg_list);
27137 
27138  return error_node();
27139  }
27140  else if (is_constant_foldable(arg_list))
27141  return const_optimise_switch(arg_list);
27142 
27143  switch ((arg_list.size() - 1) / 2)
27144  {
27145  #define case_stmt(N) \
27146  case N : \
27147  return node_allocator_-> \
27148  allocate<details::switch_n_node \
27149  <Type,typename switch_nodes::switch_##N> >(arg_list); \
27150 
27151  case_stmt(1)
27152  case_stmt(2)
27153  case_stmt(3)
27154  case_stmt(4)
27155  case_stmt(5)
27156  case_stmt(6)
27157  case_stmt(7)
27158  #undef case_stmt
27159 
27160  default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list);
27161  }
27162  }
27163 
27164  template <typename Allocator,
27165  template <typename, typename> class Sequence>
27166  inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list)
27167  {
27168  if (!all_nodes_valid(arg_list))
27169  {
27170  details::free_all_nodes(*node_allocator_,arg_list);
27171 
27172  return error_node();
27173  }
27174  else if (is_constant_foldable(arg_list))
27175  return const_optimise_mswitch(arg_list);
27176  else
27177  return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list);
27178  }
27179 
27180  #define unary_opr_switch_statements \
27181  case_stmt(details:: e_abs, details:: abs_op) \
27182  case_stmt(details:: e_acos, details:: acos_op) \
27183  case_stmt(details::e_acosh, details::acosh_op) \
27184  case_stmt(details:: e_asin, details:: asin_op) \
27185  case_stmt(details::e_asinh, details::asinh_op) \
27186  case_stmt(details:: e_atan, details:: atan_op) \
27187  case_stmt(details::e_atanh, details::atanh_op) \
27188  case_stmt(details:: e_ceil, details:: ceil_op) \
27189  case_stmt(details:: e_cos, details:: cos_op) \
27190  case_stmt(details:: e_cosh, details:: cosh_op) \
27191  case_stmt(details:: e_exp, details:: exp_op) \
27192  case_stmt(details::e_expm1, details::expm1_op) \
27193  case_stmt(details::e_floor, details::floor_op) \
27194  case_stmt(details:: e_log, details:: log_op) \
27195  case_stmt(details::e_log10, details::log10_op) \
27196  case_stmt(details:: e_log2, details:: log2_op) \
27197  case_stmt(details::e_log1p, details::log1p_op) \
27198  case_stmt(details:: e_neg, details:: neg_op) \
27199  case_stmt(details:: e_pos, details:: pos_op) \
27200  case_stmt(details::e_round, details::round_op) \
27201  case_stmt(details:: e_sin, details:: sin_op) \
27202  case_stmt(details:: e_sinc, details:: sinc_op) \
27203  case_stmt(details:: e_sinh, details:: sinh_op) \
27204  case_stmt(details:: e_sqrt, details:: sqrt_op) \
27205  case_stmt(details:: e_tan, details:: tan_op) \
27206  case_stmt(details:: e_tanh, details:: tanh_op) \
27207  case_stmt(details:: e_cot, details:: cot_op) \
27208  case_stmt(details:: e_sec, details:: sec_op) \
27209  case_stmt(details:: e_csc, details:: csc_op) \
27210  case_stmt(details:: e_r2d, details:: r2d_op) \
27211  case_stmt(details:: e_d2r, details:: d2r_op) \
27212  case_stmt(details:: e_d2g, details:: d2g_op) \
27213  case_stmt(details:: e_g2d, details:: g2d_op) \
27214  case_stmt(details:: e_notl, details:: notl_op) \
27215  case_stmt(details:: e_sgn, details:: sgn_op) \
27216  case_stmt(details:: e_erf, details:: erf_op) \
27217  case_stmt(details:: e_erfc, details:: erfc_op) \
27218  case_stmt(details:: e_ncdf, details:: ncdf_op) \
27219  case_stmt(details:: e_frac, details:: frac_op) \
27220  case_stmt(details::e_trunc, details::trunc_op) \
27221 
27223  expression_node_ptr (&branch)[1])
27224  {
27225  T& v = static_cast<details::variable_node<T>*>(branch[0])->ref();
27226 
27227  switch (operation)
27228  {
27229  #define case_stmt(op0,op1) \
27230  case op0 : return node_allocator_-> \
27231  allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \
27232 
27234  #undef case_stmt
27235  default : return error_node();
27236  }
27237  }
27238 
27240  expression_node_ptr (&branch)[1])
27241  {
27242  switch (operation)
27243  {
27244  #define case_stmt(op0,op1) \
27245  case op0 : return node_allocator_-> \
27246  allocate<typename details::unary_vector_node<Type,op1<Type> > > \
27247  (operation, branch[0]); \
27248 
27250  #undef case_stmt
27251  default : return error_node();
27252  }
27253  }
27254 
27256  expression_node_ptr (&branch)[1])
27257  {
27258  switch (operation)
27259  {
27260  #define case_stmt(op0,op1) \
27261  case op0 : return node_allocator_-> \
27262  allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \
27263 
27265  #undef case_stmt
27266  default : return error_node();
27267  }
27268  }
27269 
27271  expression_node_ptr (&branch)[3])
27272  {
27273  expression_node_ptr temp_node = error_node();
27274 
27275  switch (operation)
27276  {
27277  #define case_stmt(op) \
27278  case details::e_sf##op : temp_node = node_allocator_-> \
27279  allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27280  (operation, branch); \
27281  break; \
27282 
27283  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27284  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27285  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27286  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27287  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27288  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27289  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27290  case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27291  case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27292  case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27293  case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27294  case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27295  #undef case_stmt
27296  default : return error_node();
27297  }
27298 
27299  const T v = temp_node->value();
27300 
27301  details::free_node(*node_allocator_,temp_node);
27302 
27303  return node_allocator_->allocate<literal_node_t>(v);
27304  }
27305 
27307  {
27308  typedef details::variable_node<Type>* variable_ptr;
27309 
27310  const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27311  const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27312  const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27313 
27314  switch (operation)
27315  {
27316  #define case_stmt(op) \
27317  case details::e_sf##op : return node_allocator_-> \
27318  allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \
27319  (v0, v1, v2); \
27320 
27321  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27322  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27323  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27324  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27325  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27326  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27327  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27328  case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27329  case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27330  case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27331  case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27332  case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27333  #undef case_stmt
27334  default : return error_node();
27335  }
27336  }
27337 
27339  {
27340  if (!all_nodes_valid(branch))
27341  return error_node();
27342  else if (is_constant_foldable(branch))
27343  return const_optimise_sf3(operation,branch);
27344  else if (all_nodes_variables(branch))
27345  return varnode_optimise_sf3(operation,branch);
27346  else
27347  {
27348  switch (operation)
27349  {
27350  #define case_stmt(op) \
27351  case details::e_sf##op : return node_allocator_-> \
27352  allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \
27353  (operation, branch); \
27354 
27355  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
27356  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
27357  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
27358  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
27359  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
27360  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
27361  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
27362  case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31)
27363  case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35)
27364  case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39)
27365  case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43)
27366  case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47)
27367  #undef case_stmt
27368  default : return error_node();
27369  }
27370  }
27371  }
27372 
27374  {
27375  expression_node_ptr temp_node = error_node();
27376 
27377  switch (operation)
27378  {
27379  #define case_stmt(op) \
27380  case details::e_sf##op : temp_node = node_allocator_-> \
27381  allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27382  (operation, branch); \
27383  break; \
27384 
27385  case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27386  case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27387  case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27388  case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27389  case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27390  case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27391  case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27392  case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27393  case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27394  case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27395  case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27396  case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27397  case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27398  #undef case_stmt
27399  default : return error_node();
27400  }
27401 
27402  const T v = temp_node->value();
27403 
27404  details::free_node(*node_allocator_,temp_node);
27405 
27406  return node_allocator_->allocate<literal_node_t>(v);
27407  }
27408 
27410  {
27411  typedef details::variable_node<Type>* variable_ptr;
27412 
27413  const Type& v0 = static_cast<variable_ptr>(branch[0])->ref();
27414  const Type& v1 = static_cast<variable_ptr>(branch[1])->ref();
27415  const Type& v2 = static_cast<variable_ptr>(branch[2])->ref();
27416  const Type& v3 = static_cast<variable_ptr>(branch[3])->ref();
27417 
27418  switch (operation)
27419  {
27420  #define case_stmt(op) \
27421  case details::e_sf##op : return node_allocator_-> \
27422  allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \
27423  (v0, v1, v2, v3); \
27424 
27425  case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27426  case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27427  case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27428  case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27429  case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27430  case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27431  case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27432  case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27433  case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27434  case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27435  case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27436  case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27437  case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27438  #undef case_stmt
27439  default : return error_node();
27440  }
27441  }
27442 
27444  {
27445  if (!all_nodes_valid(branch))
27446  return error_node();
27447  else if (is_constant_foldable(branch))
27448  return const_optimise_sf4(operation,branch);
27449  else if (all_nodes_variables(branch))
27450  return varnode_optimise_sf4(operation,branch);
27451  switch (operation)
27452  {
27453  #define case_stmt(op) \
27454  case details::e_sf##op : return node_allocator_-> \
27455  allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \
27456  (operation, branch); \
27457 
27458  case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51)
27459  case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55)
27460  case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59)
27461  case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63)
27462  case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67)
27463  case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71)
27464  case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75)
27465  case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79)
27466  case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83)
27467  case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87)
27468  case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91)
27469  case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95)
27470  case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99)
27471  #undef case_stmt
27472  default : return error_node();
27473  }
27474  }
27475 
27476  template <typename Allocator,
27477  template <typename, typename> class Sequence>
27478  inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27479  {
27480  expression_node_ptr temp_node = error_node();
27481 
27482  switch (operation)
27483  {
27484  #define case_stmt(op0,op1) \
27485  case op0 : temp_node = node_allocator_-> \
27486  allocate<details::vararg_node<Type,op1<Type> > > \
27487  (arg_list); \
27488  break; \
27489 
27498  #undef case_stmt
27499  default : return error_node();
27500  }
27501 
27502  const T v = temp_node->value();
27503 
27504  details::free_node(*node_allocator_,temp_node);
27505 
27506  return node_allocator_->allocate<literal_node_t>(v);
27507  }
27508 
27509  inline bool special_one_parameter_vararg(const details::operator_type& operation) const
27510  {
27511  return (
27512  (details::e_sum == operation) ||
27513  (details::e_prod == operation) ||
27514  (details::e_avg == operation) ||
27515  (details::e_min == operation) ||
27516  (details::e_max == operation)
27517  );
27518  }
27519 
27520  template <typename Allocator,
27521  template <typename, typename> class Sequence>
27522  inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27523  {
27524  switch (operation)
27525  {
27526  #define case_stmt(op0,op1) \
27527  case op0 : return node_allocator_-> \
27528  allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \
27529 
27538  #undef case_stmt
27539  default : return error_node();
27540  }
27541  }
27542 
27543  template <typename Allocator,
27544  template <typename, typename> class Sequence>
27545  inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27546  {
27547  if (1 == arg_list.size())
27548  {
27549  switch (operation)
27550  {
27551  #define case_stmt(op0,op1) \
27552  case op0 : return node_allocator_-> \
27553  allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \
27554 
27560  #undef case_stmt
27561  default : return error_node();
27562  }
27563  }
27564  else
27565  return error_node();
27566  }
27567 
27568  template <typename Allocator,
27569  template <typename, typename> class Sequence>
27570  inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list)
27571  {
27572  if (!all_nodes_valid(arg_list))
27573  {
27574  details::free_all_nodes(*node_allocator_,arg_list);
27575 
27576  return error_node();
27577  }
27578  else if (is_constant_foldable(arg_list))
27579  return const_optimise_varargfunc(operation,arg_list);
27580  else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0]))
27581  return vectorize_func(operation,arg_list);
27582  else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation))
27583  return arg_list[0];
27584  else if (all_nodes_variables(arg_list))
27585  return varnode_optimise_varargfunc(operation,arg_list);
27586 
27587  #ifndef exprtk_disable_string_capabilities
27588  if (details::e_smulti == operation)
27589  {
27590  return node_allocator_->
27591  allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list);
27592  }
27593  else
27594  #endif
27595  {
27596  switch (operation)
27597  {
27598  #define case_stmt(op0,op1) \
27599  case op0 : return node_allocator_-> \
27600  allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \
27601 
27610  #undef case_stmt
27611  default : return error_node();
27612  }
27613  }
27614  }
27615 
27616  template <std::size_t N>
27618  {
27619  typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
27620  expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
27621 
27622  if (0 == result)
27623  return error_node();
27624  else
27625  {
27626  // Can the function call be completely optimised?
27627  if (details::is_constant_node(result))
27628  return result;
27629  else if (!all_nodes_valid(b))
27630  return error_node();
27631  else if (N != f->param_count)
27632  {
27633  details::free_all_nodes(*node_allocator_,b);
27634 
27635  return error_node();
27636  }
27637 
27638  function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result);
27639 
27640  if (func_node_ptr->init_branches(b))
27641  return result;
27642  else
27643  {
27644  details::free_all_nodes(*node_allocator_,b);
27645 
27646  return error_node();
27647  }
27648  }
27649  }
27650 
27652  {
27653  typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t;
27654  return node_allocator_->allocate<function_N_node_t>(f);
27655  }
27656 
27658  std::vector<expression_node_ptr>& arg_list)
27659  {
27660  if (!all_nodes_valid(arg_list))
27661  {
27662  details::free_all_nodes(*node_allocator_,arg_list);
27663 
27664  return error_node();
27665  }
27666 
27668 
27669  expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list);
27670 
27671  if (
27672  !arg_list.empty() &&
27673  !vaf->has_side_effects() &&
27674  is_constant_foldable(arg_list)
27675  )
27676  {
27677  const Type v = result->value();
27678  details::free_node(*node_allocator_,result);
27679  result = node_allocator_->allocate<literal_node_t>(v);
27680  }
27681 
27682  parser_->state_.activate_side_effect("vararg_function_call()");
27683 
27684  return result;
27685  }
27686 
27688  std::vector<expression_node_ptr>& arg_list,
27689  const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27690  {
27691  if (!all_nodes_valid(arg_list))
27692  {
27693  details::free_all_nodes(*node_allocator_,arg_list);
27694  return error_node();
27695  }
27696 
27699 
27700  const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27701 
27702  expression_node_ptr result = error_node();
27703 
27704  if (no_psi == param_seq_index)
27705  result = node_allocator_->allocate<alloc_type1>(arg_list,gf);
27706  else
27707  result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27708 
27709  alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result);
27710 
27711  if (
27712  !arg_list.empty() &&
27713  !gf->has_side_effects() &&
27714  parser_->state_.type_check_enabled &&
27715  is_constant_foldable(arg_list)
27716  )
27717  {
27718  genfunc_node_ptr->init_branches();
27719 
27720  const Type v = result->value();
27721 
27722  details::free_node(*node_allocator_,result);
27723 
27724  return node_allocator_->allocate<literal_node_t>(v);
27725  }
27726  else if (genfunc_node_ptr->init_branches())
27727  {
27728  parser_->state_.activate_side_effect("generic_function_call()");
27729 
27730  return result;
27731  }
27732  else
27733  {
27734  details::free_node(*node_allocator_, result);
27735  details::free_all_nodes(*node_allocator_, arg_list);
27736 
27737  return error_node();
27738  }
27739  }
27740 
27741  #ifndef exprtk_disable_string_capabilities
27743  std::vector<expression_node_ptr>& arg_list,
27744  const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max())
27745  {
27746  if (!all_nodes_valid(arg_list))
27747  {
27748  details::free_all_nodes(*node_allocator_,arg_list);
27749  return error_node();
27750  }
27751 
27754 
27755  const std::size_t no_psi = std::numeric_limits<std::size_t>::max();
27756 
27757  expression_node_ptr result = error_node();
27758 
27759  if (no_psi == param_seq_index)
27760  result = node_allocator_->allocate<alloc_type1>(gf,arg_list);
27761  else
27762  result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list);
27763 
27764  alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result);
27765 
27766  if (
27767  !arg_list.empty() &&
27768  !gf->has_side_effects() &&
27769  is_constant_foldable(arg_list)
27770  )
27771  {
27772  strfunc_node_ptr->init_branches();
27773 
27774  const Type v = result->value();
27775 
27776  details::free_node(*node_allocator_,result);
27777 
27778  return node_allocator_->allocate<literal_node_t>(v);
27779  }
27780  else if (strfunc_node_ptr->init_branches())
27781  {
27782  parser_->state_.activate_side_effect("string_function_call()");
27783 
27784  return result;
27785  }
27786  else
27787  {
27788  details::free_node (*node_allocator_,result );
27789  details::free_all_nodes(*node_allocator_,arg_list);
27790 
27791  return error_node();
27792  }
27793  }
27794  #endif
27795 
27796  #ifndef exprtk_disable_return_statement
27797  inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list)
27798  {
27799  if (!all_nodes_valid(arg_list))
27800  {
27801  details::free_all_nodes(*node_allocator_,arg_list);
27802  return error_node();
27803  }
27804 
27805  typedef details::return_node<Type> alloc_type;
27806 
27807  expression_node_ptr result = node_allocator_->
27808  allocate_rr<alloc_type>(arg_list,parser_->results_ctx());
27809 
27810  alloc_type* return_node_ptr = static_cast<alloc_type*>(result);
27811 
27812  if (return_node_ptr->init_branches())
27813  {
27814  parser_->state_.activate_side_effect("return_call()");
27815 
27816  return result;
27817  }
27818  else
27819  {
27820  details::free_node (*node_allocator_,result );
27821  details::free_all_nodes(*node_allocator_,arg_list);
27822 
27823  return error_node();
27824  }
27825  }
27826 
27828  results_context_t* rc,
27829  bool*& return_invoked)
27830  {
27831  typedef details::return_envelope_node<Type> alloc_type;
27832 
27833  expression_node_ptr result = node_allocator_->
27834  allocate_cr<alloc_type>(body,(*rc));
27835 
27836  return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr();
27837 
27838  return result;
27839  }
27840  #else
27841  inline expression_node_ptr return_call(std::vector<expression_node_ptr>&)
27842  {
27843  return error_node();
27844  }
27845 
27846  inline expression_node_ptr return_envelope(expression_node_ptr,
27847  results_context_t*,
27848  bool*&)
27849  {
27850  return error_node();
27851  }
27852  #endif
27853 
27855  vector_holder_ptr vector_base,
27856  expression_node_ptr index)
27857  {
27858  expression_node_ptr result = error_node();
27859 
27860  if (details::is_constant_node(index))
27861  {
27862  std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value()));
27863 
27864  details::free_node(*node_allocator_,index);
27865 
27866  if (vector_base->rebaseable())
27867  {
27868  return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base);
27869  }
27870 
27871  scope_element& se = parser_->sem_.get_element(symbol,i);
27872 
27873  if (se.index == i)
27874  {
27875  result = se.var_node;
27876  }
27877  else
27878  {
27879  scope_element nse;
27880  nse.name = symbol;
27881  nse.active = true;
27882  nse.ref_count = 1;
27883  nse.type = scope_element::e_vecelem;
27884  nse.index = i;
27885  nse.depth = parser_->state_.scope_depth;
27886  nse.data = 0;
27887  nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i]));
27888 
27889  if (!parser_->sem_.add_element(nse))
27890  {
27891  parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]");
27892 
27893  parser_->sem_.free_element(nse);
27894 
27895  result = error_node();
27896  }
27897 
27898  exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str()));
27899 
27900  parser_->state_.activate_side_effect("vector_element()");
27901 
27902  result = nse.var_node;
27903  }
27904  }
27905  else if (vector_base->rebaseable())
27906  result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base);
27907  else
27908  result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base);
27909 
27910  return result;
27911  }
27912 
27913  private:
27914 
27915  template <std::size_t N, typename NodePtr>
27916  inline bool is_constant_foldable(NodePtr (&b)[N]) const
27917  {
27918  for (std::size_t i = 0; i < N; ++i)
27919  {
27920  if (0 == b[i])
27921  return false;
27922  else if (!details::is_constant_node(b[i]))
27923  return false;
27924  }
27925 
27926  return true;
27927  }
27928 
27929  template <typename NodePtr,
27930  typename Allocator,
27931  template <typename, typename> class Sequence>
27932  inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const
27933  {
27934  for (std::size_t i = 0; i < b.size(); ++i)
27935  {
27936  if (0 == b[i])
27937  return false;
27938  else if (!details::is_constant_node(b[i]))
27939  return false;
27940  }
27941 
27942  return true;
27943  }
27944 
27946  {
27947  parser_->state_.activate_side_effect("lodge_assignment()");
27948 
27949  if (!parser_->dec_.collect_assignments())
27950  return;
27951 
27952  std::string symbol_name;
27953 
27954  switch (cst)
27955  {
27956  case e_st_variable : symbol_name = parser_->symtab_store_
27957  .get_variable_name(node);
27958  break;
27959 
27960  #ifndef exprtk_disable_string_capabilities
27961  case e_st_string : symbol_name = parser_->symtab_store_
27962  .get_stringvar_name(node);
27963  break;
27964  #endif
27965 
27966  case e_st_vector : {
27967  typedef details::vector_holder<T> vector_holder_t;
27968 
27969  vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder();
27970 
27971  symbol_name = parser_->symtab_store_.get_vector_name(&vh);
27972  }
27973  break;
27974 
27975  case e_st_vecelem : {
27976  typedef details::vector_holder<T> vector_holder_t;
27977 
27978  vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder();
27979 
27980  symbol_name = parser_->symtab_store_.get_vector_name(&vh);
27981 
27982  cst = e_st_vector;
27983  }
27984  break;
27985 
27986  default : return;
27987  }
27988 
27989  if (!symbol_name.empty())
27990  {
27991  parser_->dec_.add_assignment(symbol_name,cst);
27992  }
27993  }
27994 
27996  {
27997  if (details::is_variable_node(branch[0]))
27998  {
27999  lodge_assignment(e_st_variable,branch[0]);
28000 
28001  return synthesize_expression<assignment_node_t,2>(operation,branch);
28002  }
28003  else if (details::is_vector_elem_node(branch[0]))
28004  {
28005  lodge_assignment(e_st_vecelem,branch[0]);
28006 
28007  return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch);
28008  }
28009  else if (details::is_rebasevector_elem_node(branch[0]))
28010  {
28011  lodge_assignment(e_st_vecelem,branch[0]);
28012 
28013  return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch);
28014  }
28015  else if (details::is_rebasevector_celem_node(branch[0]))
28016  {
28017  lodge_assignment(e_st_vecelem,branch[0]);
28018 
28019  return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch);
28020  }
28021  #ifndef exprtk_disable_string_capabilities
28022  else if (details::is_string_node(branch[0]))
28023  {
28024  lodge_assignment(e_st_string,branch[0]);
28025 
28026  return synthesize_expression<assignment_string_node_t,2>(operation, branch);
28027  }
28028  else if (details::is_string_range_node(branch[0]))
28029  {
28030  lodge_assignment(e_st_string,branch[0]);
28031 
28032  return synthesize_expression<assignment_string_range_node_t,2>(operation, branch);
28033  }
28034  #endif
28035  else if (details::is_vector_node(branch[0]))
28036  {
28037  lodge_assignment(e_st_vector,branch[0]);
28038 
28039  if (details::is_ivector_node(branch[1]))
28040  return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch);
28041  else
28042  return synthesize_expression<assignment_vec_node_t,2>(operation, branch);
28043  }
28044  else
28045  {
28046  parser_->set_synthesis_error("Invalid assignment operation.[1]");
28047 
28048  return error_node();
28049  }
28050  }
28051 
28053  expression_node_ptr (&branch)[2])
28054  {
28055  if (details::is_variable_node(branch[0]))
28056  {
28057  lodge_assignment(e_st_variable,branch[0]);
28058 
28059  switch (operation)
28060  {
28061  #define case_stmt(op0,op1) \
28062  case op0 : return node_allocator_-> \
28063  template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \
28064  (operation, branch[0], branch[1]); \
28065 
28071  #undef case_stmt
28072  default : return error_node();
28073  }
28074  }
28075  else if (details::is_vector_elem_node(branch[0]))
28076  {
28077  lodge_assignment(e_st_vecelem,branch[0]);
28078 
28079  switch (operation)
28080  {
28081  #define case_stmt(op0,op1) \
28082  case op0 : return node_allocator_-> \
28083  template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \
28084  (operation, branch[0], branch[1]); \
28085 
28091  #undef case_stmt
28092  default : return error_node();
28093  }
28094  }
28095  else if (details::is_rebasevector_elem_node(branch[0]))
28096  {
28097  lodge_assignment(e_st_vecelem,branch[0]);
28098 
28099  switch (operation)
28100  {
28101  #define case_stmt(op0,op1) \
28102  case op0 : return node_allocator_-> \
28103  template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \
28104  (operation, branch[0], branch[1]); \
28105 
28111  #undef case_stmt
28112  default : return error_node();
28113  }
28114  }
28115  else if (details::is_rebasevector_celem_node(branch[0]))
28116  {
28117  lodge_assignment(e_st_vecelem,branch[0]);
28118 
28119  switch (operation)
28120  {
28121  #define case_stmt(op0,op1) \
28122  case op0 : return node_allocator_-> \
28123  template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \
28124  (operation, branch[0], branch[1]); \
28125 
28131  #undef case_stmt
28132  default : return error_node();
28133  }
28134  }
28135  else if (details::is_vector_node(branch[0]))
28136  {
28137  lodge_assignment(e_st_vector,branch[0]);
28138 
28139  if (details::is_ivector_node(branch[1]))
28140  {
28141  switch (operation)
28142  {
28143  #define case_stmt(op0,op1) \
28144  case op0 : return node_allocator_-> \
28145  template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \
28146  (operation, branch[0], branch[1]); \
28147 
28153  #undef case_stmt
28154  default : return error_node();
28155  }
28156  }
28157  else
28158  {
28159  switch (operation)
28160  {
28161  #define case_stmt(op0,op1) \
28162  case op0 : return node_allocator_-> \
28163  template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \
28164  (operation, branch[0], branch[1]); \
28165 
28171  #undef case_stmt
28172  default : return error_node();
28173  }
28174  }
28175  }
28176  #ifndef exprtk_disable_string_capabilities
28177  else if (
28178  (details::e_addass == operation) &&
28179  details::is_string_node(branch[0])
28180  )
28181  {
28183 
28184  lodge_assignment(e_st_string,branch[0]);
28185 
28186  return synthesize_expression<addass_t,2>(operation,branch);
28187  }
28188  #endif
28189  else
28190  {
28191  parser_->set_synthesis_error("Invalid assignment operation[2]");
28192 
28193  return error_node();
28194  }
28195  }
28196 
28198  expression_node_ptr (&branch)[2])
28199  {
28200  const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28201  const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28202 
28203  #define batch_eqineq_logic_case \
28204  case_stmt(details:: e_lt, details:: lt_op) \
28205  case_stmt(details:: e_lte, details:: lte_op) \
28206  case_stmt(details:: e_gt, details:: gt_op) \
28207  case_stmt(details:: e_gte, details:: gte_op) \
28208  case_stmt(details:: e_eq, details:: eq_op) \
28209  case_stmt(details:: e_ne, details:: ne_op) \
28210  case_stmt(details::e_equal, details::equal_op) \
28211  case_stmt(details:: e_and, details:: and_op) \
28212  case_stmt(details:: e_nand, details:: nand_op) \
28213  case_stmt(details:: e_or, details:: or_op) \
28214  case_stmt(details:: e_nor, details:: nor_op) \
28215  case_stmt(details:: e_xor, details:: xor_op) \
28216  case_stmt(details:: e_xnor, details:: xnor_op) \
28217 
28218  if (is_b0_ivec && is_b1_ivec)
28219  {
28220  switch (operation)
28221  {
28222  #define case_stmt(op0,op1) \
28223  case op0 : return node_allocator_-> \
28224  template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28225  (operation, branch[0], branch[1]); \
28226 
28228  #undef case_stmt
28229  default : return error_node();
28230  }
28231  }
28232  else if (is_b0_ivec && !is_b1_ivec)
28233  {
28234  switch (operation)
28235  {
28236  #define case_stmt(op0,op1) \
28237  case op0 : return node_allocator_-> \
28238  template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28239  (operation, branch[0], branch[1]); \
28240 
28242  #undef case_stmt
28243  default : return error_node();
28244  }
28245  }
28246  else if (!is_b0_ivec && is_b1_ivec)
28247  {
28248  switch (operation)
28249  {
28250  #define case_stmt(op0,op1) \
28251  case op0 : return node_allocator_-> \
28252  template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \
28253  (operation, branch[0], branch[1]); \
28254 
28256  #undef case_stmt
28257  default : return error_node();
28258  }
28259  }
28260  else
28261  return error_node();
28262 
28263  #undef batch_eqineq_logic_case
28264  }
28265 
28267  expression_node_ptr (&branch)[2])
28268  {
28269  const bool is_b0_ivec = details::is_ivector_node(branch[0]);
28270  const bool is_b1_ivec = details::is_ivector_node(branch[1]);
28271 
28272  #define vector_ops \
28273  case_stmt(details::e_add,details::add_op) \
28274  case_stmt(details::e_sub,details::sub_op) \
28275  case_stmt(details::e_mul,details::mul_op) \
28276  case_stmt(details::e_div,details::div_op) \
28277  case_stmt(details::e_mod,details::mod_op) \
28278 
28279  if (is_b0_ivec && is_b1_ivec)
28280  {
28281  switch (operation)
28282  {
28283  #define case_stmt(op0,op1) \
28284  case op0 : return node_allocator_-> \
28285  template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \
28286  (operation, branch[0], branch[1]); \
28287 
28288  vector_ops
28290  #undef case_stmt
28291  default : return error_node();
28292  }
28293  }
28294  else if (is_b0_ivec && !is_b1_ivec)
28295  {
28296  switch (operation)
28297  {
28298  #define case_stmt(op0,op1) \
28299  case op0 : return node_allocator_-> \
28300  template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \
28301  (operation, branch[0], branch[1]); \
28302 
28303  vector_ops
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_valvec_node<Type,op1<Type> > > \
28316  (operation, branch[0], branch[1]); \
28317 
28318  vector_ops
28319  #undef case_stmt
28320  default : return error_node();
28321  }
28322  }
28323  else
28324  return error_node();
28325 
28326  #undef vector_ops
28327  }
28328 
28330  {
28331  const bool v0_is_ivar = details::is_ivariable_node(branch[0]);
28332  const bool v1_is_ivar = details::is_ivariable_node(branch[1]);
28333 
28334  const bool v0_is_ivec = details::is_ivector_node (branch[0]);
28335  const bool v1_is_ivec = details::is_ivector_node (branch[1]);
28336 
28337  #ifndef exprtk_disable_string_capabilities
28338  const bool v0_is_str = details::is_generally_string_node(branch[0]);
28339  const bool v1_is_str = details::is_generally_string_node(branch[1]);
28340  #endif
28341 
28342  expression_node_ptr result = error_node();
28343 
28344  if (v0_is_ivar && v1_is_ivar)
28345  {
28346  typedef details::variable_node<T>* variable_node_ptr;
28347 
28348  variable_node_ptr v0 = variable_node_ptr(0);
28349  variable_node_ptr v1 = variable_node_ptr(0);
28350 
28351  if (
28352  (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) &&
28353  (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1])))
28354  )
28355  {
28356  result = node_allocator_->allocate<details::swap_node<T> >(v0,v1);
28357  }
28358  else
28359  result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]);
28360  }
28361  else if (v0_is_ivec && v1_is_ivec)
28362  {
28363  result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]);
28364  }
28365  #ifndef exprtk_disable_string_capabilities
28366  else if (v0_is_str && v1_is_str)
28367  {
28368  if (is_string_node(branch[0]) && is_string_node(branch[1]))
28369  result = node_allocator_->allocate<details::swap_string_node<T> >
28370  (branch[0], branch[1]);
28371  else
28372  result = node_allocator_->allocate<details::swap_genstrings_node<T> >
28373  (branch[0], branch[1]);
28374  }
28375  #endif
28376  else
28377  {
28378  parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped");
28379 
28380  return error_node();
28381  }
28382 
28383  parser_->state_.activate_side_effect("synthesize_swap_expression()");
28384 
28385  return result;
28386  }
28387 
28388  #ifndef exprtk_disable_sc_andor
28390  {
28391  expression_node_ptr result = error_node();
28392 
28393  if (details::is_constant_node(branch[0]))
28394  {
28395  if (
28396  (details::e_scand == operation) &&
28397  std::equal_to<T>()(T(0),branch[0]->value())
28398  )
28399  result = node_allocator_->allocate_c<literal_node_t>(T(0));
28400  else if (
28401  (details::e_scor == operation) &&
28402  std::not_equal_to<T>()(T(0),branch[0]->value())
28403  )
28404  result = node_allocator_->allocate_c<literal_node_t>(T(1));
28405  }
28406 
28407  if (details::is_constant_node(branch[1]) && (0 == result))
28408  {
28409  if (
28410  (details::e_scand == operation) &&
28411  std::equal_to<T>()(T(0),branch[1]->value())
28412  )
28413  result = node_allocator_->allocate_c<literal_node_t>(T(0));
28414  else if (
28415  (details::e_scor == operation) &&
28416  std::not_equal_to<T>()(T(0),branch[1]->value())
28417  )
28418  result = node_allocator_->allocate_c<literal_node_t>(T(1));
28419  }
28420 
28421  if (result)
28422  {
28423  free_node(*node_allocator_, branch[0]);
28424  free_node(*node_allocator_, branch[1]);
28425 
28426  return result;
28427  }
28428  else if (details::e_scand == operation)
28429  {
28430  return synthesize_expression<scand_node_t,2>(operation, branch);
28431  }
28432  else if (details::e_scor == operation)
28433  {
28434  return synthesize_expression<scor_node_t,2>(operation, branch);
28435  }
28436  else
28437  return error_node();
28438  }
28439  #else
28440  inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2])
28441  {
28442  return error_node();
28443  }
28444  #endif
28445 
28446  #define basic_opr_switch_statements \
28447  case_stmt(details::e_add, details::add_op) \
28448  case_stmt(details::e_sub, details::sub_op) \
28449  case_stmt(details::e_mul, details::mul_op) \
28450  case_stmt(details::e_div, details::div_op) \
28451  case_stmt(details::e_mod, details::mod_op) \
28452  case_stmt(details::e_pow, details::pow_op) \
28453 
28454  #define extended_opr_switch_statements \
28455  case_stmt(details:: e_lt, details:: lt_op) \
28456  case_stmt(details:: e_lte, details:: lte_op) \
28457  case_stmt(details:: e_gt, details:: gt_op) \
28458  case_stmt(details:: e_gte, details:: gte_op) \
28459  case_stmt(details:: e_eq, details:: eq_op) \
28460  case_stmt(details:: e_ne, details:: ne_op) \
28461  case_stmt(details:: e_and, details:: and_op) \
28462  case_stmt(details::e_nand, details::nand_op) \
28463  case_stmt(details:: e_or, details:: or_op) \
28464  case_stmt(details:: e_nor, details:: nor_op) \
28465  case_stmt(details:: e_xor, details:: xor_op) \
28466  case_stmt(details::e_xnor, details::xnor_op) \
28467 
28468  #ifndef exprtk_disable_cardinal_pow_optimisation
28469  template <typename TType, template <typename, typename> class IPowNode>
28470  inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p)
28471  {
28472  switch (p)
28473  {
28474  #define case_stmt(cp) \
28475  case cp : return node_allocator_-> \
28476  allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \
28477 
28478  case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
28479  case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
28480  case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
28481  case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
28482  case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
28483  case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
28484  case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
28485  case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
28486  case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
28487  case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
28488  case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
28489  case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
28490  case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
28491  case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
28492  case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
28493  #undef case_stmt
28494  default : return error_node();
28495  }
28496  }
28497 
28498  inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c)
28499  {
28500  const bool not_recipricol = (c >= T(0));
28501  const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28502 
28503  if (0 == p)
28504  return node_allocator_->allocate_c<literal_node_t>(T(1));
28505  else if (std::equal_to<T>()(T(2),c))
28506  {
28507  return node_allocator_->
28508  template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v);
28509  }
28510  else
28511  {
28512  if (not_recipricol)
28513  return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p);
28514  else
28515  return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p);
28516  }
28517  }
28518 
28519  inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const
28520  {
28521  return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c);
28522  }
28523 
28525  {
28526  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
28527  const bool not_recipricol = (c >= T(0));
28528  const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c)));
28529 
28530  node_allocator_->free(branch[1]);
28531 
28532  if (0 == p)
28533  {
28534  details::free_all_nodes(*node_allocator_, branch);
28535 
28536  return node_allocator_->allocate_c<literal_node_t>(T(1));
28537  }
28538  else if (not_recipricol)
28539  return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p);
28540  else
28541  return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p);
28542  }
28543  #else
28544  inline expression_node_ptr cardinal_pow_optimisation(T&, const T&)
28545  {
28546  return error_node();
28547  }
28548 
28549  inline bool cardinal_pow_optimisable(const details::operator_type&, const T&)
28550  {
28551  return false;
28552  }
28553 
28554  inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2])
28555  {
28556  return error_node();
28557  }
28558  #endif
28559 
28561  {
28563  const details::operator_type& operation,
28564  expression_node_ptr (&branch)[2])
28565  {
28566  const bool left_neg = is_neg_unary_node(branch[0]);
28567  const bool right_neg = is_neg_unary_node(branch[1]);
28568 
28569  if (left_neg && right_neg)
28570  {
28571  if (
28572  (details::e_add == operation) ||
28573  (details::e_sub == operation) ||
28574  (details::e_mul == operation) ||
28575  (details::e_div == operation)
28576  )
28577  {
28578  if (
28579  !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) ||
28580  !expr_gen.parser_->simplify_unary_negation_branch(branch[1])
28581  )
28582  {
28583  details::free_all_nodes(*expr_gen.node_allocator_,branch);
28584 
28585  return error_node();
28586  }
28587  }
28588 
28589  switch (operation)
28590  {
28591  // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1))
28592  case details::e_add : return expr_gen(details::e_neg,
28593  expr_gen.node_allocator_->
28594  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28595  (branch[0],branch[1]));
28596 
28597  // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1)
28598  case details::e_sub : return expr_gen.node_allocator_->
28599  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28600  (branch[1],branch[0]);
28601 
28602  default : break;
28603  }
28604  }
28605  else if (left_neg && !right_neg)
28606  {
28607  if (
28608  (details::e_add == operation) ||
28609  (details::e_sub == operation) ||
28610  (details::e_mul == operation) ||
28611  (details::e_div == operation)
28612  )
28613  {
28614  if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0]))
28615  {
28616  details::free_all_nodes(*expr_gen.node_allocator_,branch);
28617 
28618  return error_node();
28619  }
28620 
28621  switch (operation)
28622  {
28623  // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1)
28624  case details::e_add : return expr_gen.node_allocator_->
28625  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28626  (branch[1], branch[0]);
28627 
28628  // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1))
28629  case details::e_sub : return expr_gen(details::e_neg,
28630  expr_gen.node_allocator_->
28631  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28632  (branch[0], branch[1]));
28633 
28634  // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1))
28635  case details::e_mul : return expr_gen(details::e_neg,
28636  expr_gen.node_allocator_->
28637  template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28638  (branch[0], branch[1]));
28639 
28640  // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1))
28641  case details::e_div : return expr_gen(details::e_neg,
28642  expr_gen.node_allocator_->
28643  template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28644  (branch[0], branch[1]));
28645 
28646  default : return error_node();
28647  }
28648  }
28649  }
28650  else if (!left_neg && right_neg)
28651  {
28652  if (
28653  (details::e_add == operation) ||
28654  (details::e_sub == operation) ||
28655  (details::e_mul == operation) ||
28656  (details::e_div == operation)
28657  )
28658  {
28659  if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1]))
28660  {
28661  details::free_all_nodes(*expr_gen.node_allocator_,branch);
28662 
28663  return error_node();
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.node_allocator_->
28670  template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > >
28671  (branch[0], branch[1]);
28672 
28673  // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1)
28674  case details::e_sub : return expr_gen.node_allocator_->
28675  template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > >
28676  (branch[0], branch[1]);
28677 
28678  // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1))
28679  case details::e_mul : return expr_gen(details::e_neg,
28680  expr_gen.node_allocator_->
28681  template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > >
28682  (branch[0], branch[1]));
28683 
28684  // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1))
28685  case details::e_div : return expr_gen(details::e_neg,
28686  expr_gen.node_allocator_->
28687  template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > >
28688  (branch[0], branch[1]));
28689 
28690  default : return error_node();
28691  }
28692  }
28693  }
28694 
28695  switch (operation)
28696  {
28697  #define case_stmt(op0,op1) \
28698  case op0 : return expr_gen.node_allocator_-> \
28699  template allocate<typename details::binary_ext_node<Type,op1<Type> > > \
28700  (branch[0], branch[1]); \
28701 
28704  #undef case_stmt
28705  default : return error_node();
28706  }
28707  }
28708  };
28709 
28711  {
28713  const details::operator_type& operation,
28714  expression_node_ptr (&branch)[2])
28715  {
28716  const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref();
28717 
28718  #ifndef exprtk_disable_enhanced_features
28719  if (details::is_sf3ext_node(branch[1]))
28720  {
28721  expression_node_ptr result = error_node();
28722 
28723  const bool synthesis_result = synthesize_sf4ext_expression::template compile_right<vtype>
28724  (expr_gen, v, operation, branch[1], result);
28725 
28726  if (synthesis_result)
28727  {
28728  free_node(*expr_gen.node_allocator_,branch[1]);
28729  return result;
28730  }
28731  }
28732  #endif
28733 
28734  if (
28735  (details::e_mul == operation) ||
28736  (details::e_div == operation)
28737  )
28738  {
28739  if (details::is_uv_node(branch[1]))
28740  {
28741  typedef details::uv_base_node<Type>* uvbn_ptr_t;
28742 
28743  details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation();
28744 
28745  if (details::e_neg == o)
28746  {
28747  const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v();
28748 
28749  free_node(*expr_gen.node_allocator_,branch[1]);
28750 
28751  switch (operation)
28752  {
28753  case details::e_mul : return expr_gen(details::e_neg,
28754  expr_gen.node_allocator_->
28755  template allocate_rr<typename details::
28756  vov_node<Type,details::mul_op<Type> > >(v,v1));
28757 
28758  case details::e_div : return expr_gen(details::e_neg,
28759  expr_gen.node_allocator_->
28760  template allocate_rr<typename details::
28761  vov_node<Type,details::div_op<Type> > >(v,v1));
28762 
28763  default : break;
28764  }
28765  }
28766  }
28767  }
28768 
28769  switch (operation)
28770  {
28771  #define case_stmt(op0,op1) \
28772  case op0 : return expr_gen.node_allocator_-> \
28773  template allocate_rc<typename details::vob_node<Type,op1<Type> > > \
28774  (v, branch[1]); \
28775 
28778  #undef case_stmt
28779  default : return error_node();
28780  }
28781  }
28782  };
28783 
28785  {
28787  const details::operator_type& operation,
28788  expression_node_ptr (&branch)[2])
28789  {
28790  const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref();
28791 
28792  #ifndef exprtk_disable_enhanced_features
28793  if (details::is_sf3ext_node(branch[0]))
28794  {
28795  expression_node_ptr result = error_node();
28796 
28797  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<vtype>
28798  (expr_gen, v, operation, branch[0], result);
28799 
28800  if (synthesis_result)
28801  {
28802  free_node(*expr_gen.node_allocator_, branch[0]);
28803 
28804  return result;
28805  }
28806  }
28807  #endif
28808 
28809  if (
28810  (details::e_add == operation) ||
28811  (details::e_sub == operation) ||
28812  (details::e_mul == operation) ||
28813  (details::e_div == operation)
28814  )
28815  {
28816  if (details::is_uv_node(branch[0]))
28817  {
28818  typedef details::uv_base_node<Type>* uvbn_ptr_t;
28819 
28820  details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation();
28821 
28822  if (details::e_neg == o)
28823  {
28824  const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v();
28825 
28826  free_node(*expr_gen.node_allocator_,branch[0]);
28827 
28828  switch (operation)
28829  {
28830  case details::e_add : return expr_gen.node_allocator_->
28831  template allocate_rr<typename details::
28832  vov_node<Type,details::sub_op<Type> > >(v,v0);
28833 
28834  case details::e_sub : return expr_gen(details::e_neg,
28835  expr_gen.node_allocator_->
28836  template allocate_rr<typename details::
28837  vov_node<Type,details::add_op<Type> > >(v0,v));
28838 
28839  case details::e_mul : return expr_gen(details::e_neg,
28840  expr_gen.node_allocator_->
28841  template allocate_rr<typename details::
28842  vov_node<Type,details::mul_op<Type> > >(v0,v));
28843 
28844  case details::e_div : return expr_gen(details::e_neg,
28845  expr_gen.node_allocator_->
28846  template allocate_rr<typename details::
28847  vov_node<Type,details::div_op<Type> > >(v0,v));
28848  default : break;
28849  }
28850  }
28851  }
28852  }
28853 
28854  switch (operation)
28855  {
28856  #define case_stmt(op0,op1) \
28857  case op0 : return expr_gen.node_allocator_-> \
28858  template allocate_cr<typename details::bov_node<Type,op1<Type> > > \
28859  (branch[0], v); \
28860 
28863  #undef case_stmt
28864  default : return error_node();
28865  }
28866  }
28867  };
28868 
28870  {
28872  const details::operator_type& operation,
28873  expression_node_ptr (&branch)[2])
28874  {
28875  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
28876 
28877  free_node(*expr_gen.node_allocator_,branch[0]);
28878 
28879  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
28880  {
28881  free_node(*expr_gen.node_allocator_,branch[1]);
28882 
28883  return expr_gen(T(0));
28884  }
28885  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
28886  {
28887  free_node(*expr_gen.node_allocator_, branch[1]);
28888 
28889  return expr_gen(T(0));
28890  }
28891  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
28892  return branch[1];
28893  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
28894  return branch[1];
28895 
28896  if (details::is_cob_node(branch[1]))
28897  {
28898  // Simplify expressions of the form:
28899  // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x)
28900  // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x
28901  if (
28902  (operation == details::e_mul) ||
28903  (operation == details::e_add)
28904  )
28905  {
28906  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28907 
28908  if (operation == cobnode->operation())
28909  {
28910  switch (operation)
28911  {
28912  case details::e_add : cobnode->set_c(c + cobnode->c()); break;
28913  case details::e_mul : cobnode->set_c(c * cobnode->c()); break;
28914  default : return error_node();
28915  }
28916 
28917  return cobnode;
28918  }
28919  }
28920 
28921  if (operation == details::e_mul)
28922  {
28923  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28924  details::operator_type cob_opr = cobnode->operation();
28925 
28926  if (
28927  (details::e_div == cob_opr) ||
28928  (details::e_mul == cob_opr)
28929  )
28930  {
28931  switch (cob_opr)
28932  {
28933  case details::e_div : cobnode->set_c(c * cobnode->c()); break;
28934  case details::e_mul : cobnode->set_c(cobnode->c() / c); break;
28935  default : return error_node();
28936  }
28937 
28938  return cobnode;
28939  }
28940  }
28941  else if (operation == details::e_div)
28942  {
28943  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
28944  details::operator_type cob_opr = cobnode->operation();
28945 
28946  if (
28947  (details::e_div == cob_opr) ||
28948  (details::e_mul == cob_opr)
28949  )
28950  {
28951  details::expression_node<Type>* new_cobnode = error_node();
28952 
28953  switch (cob_opr)
28954  {
28955  case details::e_div : new_cobnode = expr_gen.node_allocator_->
28956  template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
28957  (c / cobnode->c(), cobnode->move_branch(0));
28958  break;
28959 
28960  case details::e_mul : new_cobnode = expr_gen.node_allocator_->
28961  template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
28962  (c / cobnode->c(), cobnode->move_branch(0));
28963  break;
28964 
28965  default : return error_node();
28966  }
28967 
28968  free_node(*expr_gen.node_allocator_,branch[1]);
28969 
28970  return new_cobnode;
28971  }
28972  }
28973  }
28974  #ifndef exprtk_disable_enhanced_features
28975  else if (details::is_sf3ext_node(branch[1]))
28976  {
28977  expression_node_ptr result = error_node();
28978 
28979  if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result))
28980  {
28981  free_node(*expr_gen.node_allocator_,branch[1]);
28982 
28983  return result;
28984  }
28985  }
28986  #endif
28987 
28988  switch (operation)
28989  {
28990  #define case_stmt(op0,op1) \
28991  case op0 : return expr_gen.node_allocator_-> \
28992  template allocate_tt<typename details::cob_node<Type,op1<Type> > > \
28993  (c, branch[1]); \
28994 
28997  #undef case_stmt
28998  default : return error_node();
28999  }
29000  }
29001  };
29002 
29004  {
29006  const details::operator_type& operation,
29007  expression_node_ptr (&branch)[2])
29008  {
29009  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29010 
29011  details::free_node(*(expr_gen.node_allocator_), branch[1]);
29012 
29013  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29014  {
29015  free_node(*expr_gen.node_allocator_, branch[0]);
29016 
29017  return expr_gen(T(0));
29018  }
29019  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29020  {
29021  free_node(*expr_gen.node_allocator_, branch[0]);
29022 
29023  return expr_gen(std::numeric_limits<T>::quiet_NaN());
29024  }
29025  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29026  return branch[0];
29027  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29028  return branch[0];
29029 
29030  if (details::is_boc_node(branch[0]))
29031  {
29032  // Simplify expressions of the form:
29033  // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320
29034  // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45
29035  if (
29036  (operation == details::e_mul) ||
29037  (operation == details::e_add)
29038  )
29039  {
29040  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29041 
29042  if (operation == bocnode->operation())
29043  {
29044  switch (operation)
29045  {
29046  case details::e_add : bocnode->set_c(c + bocnode->c()); break;
29047  case details::e_mul : bocnode->set_c(c * bocnode->c()); break;
29048  default : return error_node();
29049  }
29050 
29051  return bocnode;
29052  }
29053  }
29054  else if (operation == details::e_div)
29055  {
29056  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29057  details::operator_type boc_opr = bocnode->operation();
29058 
29059  if (
29060  (details::e_div == boc_opr) ||
29061  (details::e_mul == boc_opr)
29062  )
29063  {
29064  switch (boc_opr)
29065  {
29066  case details::e_div : bocnode->set_c(c * bocnode->c()); break;
29067  case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29068  default : return error_node();
29069  }
29070 
29071  return bocnode;
29072  }
29073  }
29074  else if (operation == details::e_pow)
29075  {
29076  // (v ^ c0) ^ c1 --> v ^(c0 * c1)
29077  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29078  details::operator_type boc_opr = bocnode->operation();
29079 
29080  if (details::e_pow == boc_opr)
29081  {
29082  bocnode->set_c(bocnode->c() * c);
29083 
29084  return bocnode;
29085  }
29086  }
29087  }
29088 
29089  #ifndef exprtk_disable_enhanced_features
29090  if (details::is_sf3ext_node(branch[0]))
29091  {
29092  expression_node_ptr result = error_node();
29093 
29094  const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<ctype>
29095  (expr_gen, c, operation, branch[0], result);
29096 
29097  if (synthesis_result)
29098  {
29099  free_node(*expr_gen.node_allocator_, branch[0]);
29100 
29101  return result;
29102  }
29103  }
29104  #endif
29105 
29106  switch (operation)
29107  {
29108  #define case_stmt(op0,op1) \
29109  case op0 : return expr_gen.node_allocator_-> \
29110  template allocate_cr<typename details::boc_node<Type,op1<Type> > > \
29111  (branch[0], c); \
29112 
29115  #undef case_stmt
29116  default : return error_node();
29117  }
29118  }
29119  };
29120 
29122  {
29124  const details::operator_type& operation,
29125  expression_node_ptr (&branch)[2])
29126  {
29127  expression_node_ptr result = error_node();
29128 
29129  // (cob) o c --> cob
29130  if (details::is_cob_node(branch[0]))
29131  {
29132  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]);
29133 
29134  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29135 
29136  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29137  {
29138  free_node(*expr_gen.node_allocator_, branch[0]);
29139  free_node(*expr_gen.node_allocator_, branch[1]);
29140 
29141  return expr_gen(T(0));
29142  }
29143  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29144  {
29145  free_node(*expr_gen.node_allocator_, branch[0]);
29146  free_node(*expr_gen.node_allocator_, branch[1]);
29147 
29148  return expr_gen(T(std::numeric_limits<T>::quiet_NaN()));
29149  }
29150  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29151  {
29152  free_node(*expr_gen.node_allocator_, branch[1]);
29153 
29154  return branch[0];
29155  }
29156  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29157  {
29158  free_node(*expr_gen.node_allocator_, branch[1]);
29159 
29160  return branch[0];
29161  }
29162  else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29163  {
29164  free_node(*expr_gen.node_allocator_, branch[1]);
29165 
29166  return branch[0];
29167  }
29168 
29169  const bool op_addsub = (details::e_add == cobnode->operation()) ||
29170  (details::e_sub == cobnode->operation()) ;
29171 
29172  if (op_addsub)
29173  {
29174  switch (operation)
29175  {
29176  case details::e_add : cobnode->set_c(cobnode->c() + c); break;
29177  case details::e_sub : cobnode->set_c(cobnode->c() - c); break;
29178  default : return error_node();
29179  }
29180 
29181  result = cobnode;
29182  }
29183  else if (details::e_mul == cobnode->operation())
29184  {
29185  switch (operation)
29186  {
29187  case details::e_mul : cobnode->set_c(cobnode->c() * c); break;
29188  case details::e_div : cobnode->set_c(cobnode->c() / c); break;
29189  default : return error_node();
29190  }
29191 
29192  result = cobnode;
29193  }
29194  else if (details::e_div == cobnode->operation())
29195  {
29196  if (details::e_mul == operation)
29197  {
29198  cobnode->set_c(cobnode->c() * c);
29199  result = cobnode;
29200  }
29201  else if (details::e_div == operation)
29202  {
29203  result = expr_gen.node_allocator_->
29204  template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29205  (cobnode->c() / c, cobnode->move_branch(0));
29206 
29207  free_node(*expr_gen.node_allocator_, branch[0]);
29208  }
29209  }
29210 
29211  if (result)
29212  {
29213  free_node(*expr_gen.node_allocator_,branch[1]);
29214  }
29215  }
29216 
29217  // c o (cob) --> cob
29218  else if (details::is_cob_node(branch[1]))
29219  {
29220  details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]);
29221 
29222  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29223 
29224  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29225  {
29226  free_node(*expr_gen.node_allocator_, branch[0]);
29227  free_node(*expr_gen.node_allocator_, branch[1]);
29228 
29229  return expr_gen(T(0));
29230  }
29231  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29232  {
29233  free_node(*expr_gen.node_allocator_, branch[0]);
29234  free_node(*expr_gen.node_allocator_, branch[1]);
29235 
29236  return expr_gen(T(0));
29237  }
29238  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29239  {
29240  free_node(*expr_gen.node_allocator_, branch[0]);
29241 
29242  return branch[1];
29243  }
29244  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29245  {
29246  free_node(*expr_gen.node_allocator_, branch[0]);
29247 
29248  return branch[1];
29249  }
29250 
29251  if (details::e_add == cobnode->operation())
29252  {
29253  if (details::e_add == operation)
29254  {
29255  cobnode->set_c(c + cobnode->c());
29256  result = cobnode;
29257  }
29258  else if (details::e_sub == operation)
29259  {
29260  result = expr_gen.node_allocator_->
29261  template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29262  (c - cobnode->c(), cobnode->move_branch(0));
29263 
29264  free_node(*expr_gen.node_allocator_,branch[1]);
29265  }
29266  }
29267  else if (details::e_sub == cobnode->operation())
29268  {
29269  if (details::e_add == operation)
29270  {
29271  cobnode->set_c(c + cobnode->c());
29272  result = cobnode;
29273  }
29274  else if (details::e_sub == operation)
29275  {
29276  result = expr_gen.node_allocator_->
29277  template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > >
29278  (c - cobnode->c(), cobnode->move_branch(0));
29279 
29280  free_node(*expr_gen.node_allocator_,branch[1]);
29281  }
29282  }
29283  else if (details::e_mul == cobnode->operation())
29284  {
29285  if (details::e_mul == operation)
29286  {
29287  cobnode->set_c(c * cobnode->c());
29288  result = cobnode;
29289  }
29290  else if (details::e_div == operation)
29291  {
29292  result = expr_gen.node_allocator_->
29293  template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29294  (c / cobnode->c(), cobnode->move_branch(0));
29295 
29296  free_node(*expr_gen.node_allocator_,branch[1]);
29297  }
29298  }
29299  else if (details::e_div == cobnode->operation())
29300  {
29301  if (details::e_mul == operation)
29302  {
29303  cobnode->set_c(c * cobnode->c());
29304  result = cobnode;
29305  }
29306  else if (details::e_div == operation)
29307  {
29308  result = expr_gen.node_allocator_->
29309  template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > >
29310  (c / cobnode->c(), cobnode->move_branch(0));
29311 
29312  free_node(*expr_gen.node_allocator_,branch[1]);
29313  }
29314  }
29315 
29316  if (result)
29317  {
29318  free_node(*expr_gen.node_allocator_,branch[0]);
29319  }
29320  }
29321 
29322  return result;
29323  }
29324  };
29325 
29327  {
29329  const details::operator_type& operation,
29330  expression_node_ptr (&branch)[2])
29331  {
29332  expression_node_ptr result = error_node();
29333 
29334  // (boc) o c --> boc
29335  if (details::is_boc_node(branch[0]))
29336  {
29337  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]);
29338 
29339  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29340 
29341  if (details::e_add == bocnode->operation())
29342  {
29343  switch (operation)
29344  {
29345  case details::e_add : bocnode->set_c(bocnode->c() + c); break;
29346  case details::e_sub : bocnode->set_c(bocnode->c() - c); break;
29347  default : return error_node();
29348  }
29349 
29350  result = bocnode;
29351  }
29352  else if (details::e_mul == bocnode->operation())
29353  {
29354  switch (operation)
29355  {
29356  case details::e_mul : bocnode->set_c(bocnode->c() * c); break;
29357  case details::e_div : bocnode->set_c(bocnode->c() / c); break;
29358  default : return error_node();
29359  }
29360 
29361  result = bocnode;
29362  }
29363  else if (details::e_sub == bocnode->operation())
29364  {
29365  if (details::e_add == operation)
29366  {
29367  result = expr_gen.node_allocator_->
29368  template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29369  (bocnode->move_branch(0), c - bocnode->c());
29370 
29371  free_node(*expr_gen.node_allocator_,branch[0]);
29372  }
29373  else if (details::e_sub == operation)
29374  {
29375  bocnode->set_c(bocnode->c() + c);
29376  result = bocnode;
29377  }
29378  }
29379  else if (details::e_div == bocnode->operation())
29380  {
29381  switch (operation)
29382  {
29383  case details::e_div : bocnode->set_c(bocnode->c() * c); break;
29384  case details::e_mul : bocnode->set_c(bocnode->c() / c); break;
29385  default : return error_node();
29386  }
29387 
29388  result = bocnode;
29389  }
29390 
29391  if (result)
29392  {
29393  free_node(*expr_gen.node_allocator_, branch[1]);
29394  }
29395  }
29396 
29397  // c o (boc) --> boc
29398  else if (details::is_boc_node(branch[1]))
29399  {
29400  details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]);
29401 
29402  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
29403 
29404  if (details::e_add == bocnode->operation())
29405  {
29406  if (details::e_add == operation)
29407  {
29408  bocnode->set_c(c + bocnode->c());
29409  result = bocnode;
29410  }
29411  else if (details::e_sub == operation)
29412  {
29413  result = expr_gen.node_allocator_->
29414  template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29415  (c - bocnode->c(), bocnode->move_branch(0));
29416 
29417  free_node(*expr_gen.node_allocator_,branch[1]);
29418  }
29419  }
29420  else if (details::e_sub == bocnode->operation())
29421  {
29422  if (details::e_add == operation)
29423  {
29424  result = expr_gen.node_allocator_->
29425  template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > >
29426  (bocnode->move_branch(0), c - bocnode->c());
29427 
29428  free_node(*expr_gen.node_allocator_,branch[1]);
29429  }
29430  else if (details::e_sub == operation)
29431  {
29432  result = expr_gen.node_allocator_->
29433  template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > >
29434  (c + bocnode->c(), bocnode->move_branch(0));
29435 
29436  free_node(*expr_gen.node_allocator_,branch[1]);
29437  }
29438  }
29439  else if (details::e_mul == bocnode->operation())
29440  {
29441  if (details::e_mul == operation)
29442  {
29443  bocnode->set_c(c * bocnode->c());
29444  result = bocnode;
29445  }
29446  else if (details::e_div == operation)
29447  {
29448  result = expr_gen.node_allocator_->
29449  template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29450  (c / bocnode->c(), bocnode->move_branch(0));
29451 
29452  free_node(*expr_gen.node_allocator_,branch[1]);
29453  }
29454  }
29455  else if (details::e_div == bocnode->operation())
29456  {
29457  if (details::e_mul == operation)
29458  {
29459  bocnode->set_c(bocnode->c() / c);
29460  result = bocnode;
29461  }
29462  else if (details::e_div == operation)
29463  {
29464  result = expr_gen.node_allocator_->
29465  template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > >
29466  (c * bocnode->c(), bocnode->move_branch(0));
29467 
29468  free_node(*expr_gen.node_allocator_,branch[1]);
29469  }
29470  }
29471 
29472  if (result)
29473  {
29474  free_node(*expr_gen.node_allocator_,branch[0]);
29475  }
29476  }
29477 
29478  return result;
29479  }
29480  };
29481 
29482  #ifndef exprtk_disable_enhanced_features
29483  inline bool synthesize_expression(const details::operator_type& operation,
29484  expression_node_ptr (&branch)[2],
29485  expression_node_ptr& result)
29486  {
29487  result = error_node();
29488 
29489  if (!operation_optimisable(operation))
29490  return false;
29491 
29492  const std::string node_id = branch_to_id(branch);
29493 
29494  const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id);
29495 
29496  if (synthesize_map_.end() != itr)
29497  {
29498  result = itr->second((*this), operation, branch);
29499 
29500  return true;
29501  }
29502  else
29503  return false;
29504  }
29505 
29507  {
29509  const details::operator_type& operation,
29510  expression_node_ptr (&branch)[2])
29511  {
29512  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29513  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29514 
29515  switch (operation)
29516  {
29517  #define case_stmt(op0,op1) \
29518  case op0 : return expr_gen.node_allocator_-> \
29519  template allocate_rr<typename details::vov_node<Type,op1<Type> > > \
29520  (v1, v2); \
29521 
29524  #undef case_stmt
29525  default : return error_node();
29526  }
29527  }
29528  };
29529 
29531  {
29533  const details::operator_type& operation,
29534  expression_node_ptr (&branch)[2])
29535  {
29536  const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value();
29537  const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref ();
29538 
29539  details::free_node(*(expr_gen.node_allocator_),branch[0]);
29540 
29541  if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29542  return expr_gen(T(0));
29543  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29544  return expr_gen(T(0));
29545  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29546  return static_cast<details::variable_node<Type>*>(branch[1]);
29547  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29548  return static_cast<details::variable_node<Type>*>(branch[1]);
29549 
29550  switch (operation)
29551  {
29552  #define case_stmt(op0,op1) \
29553  case op0 : return expr_gen.node_allocator_-> \
29554  template allocate_cr<typename details::cov_node<Type,op1<Type> > > \
29555  (c, v); \
29556 
29559  #undef case_stmt
29560  default : return error_node();
29561  }
29562  }
29563  };
29564 
29566  {
29568  const details::operator_type& operation,
29569  expression_node_ptr (&branch)[2])
29570  {
29571  const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref ();
29572  const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value();
29573 
29574  details::free_node(*(expr_gen.node_allocator_), branch[1]);
29575 
29576  if (expr_gen.cardinal_pow_optimisable(operation,c))
29577  {
29578  if (std::equal_to<T>()(T(1),c))
29579  return branch[0];
29580  else
29581  return expr_gen.cardinal_pow_optimisation(v,c);
29582  }
29583  else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation))
29584  return expr_gen(T(0));
29585  else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation))
29586  return expr_gen(std::numeric_limits<T>::quiet_NaN());
29587  else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation))
29588  return static_cast<details::variable_node<Type>*>(branch[0]);
29589  else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation))
29590  return static_cast<details::variable_node<Type>*>(branch[0]);
29591  else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation))
29592  return static_cast<details::variable_node<Type>*>(branch[0]);
29593 
29594  switch (operation)
29595  {
29596  #define case_stmt(op0,op1) \
29597  case op0 : return expr_gen.node_allocator_-> \
29598  template allocate_rc<typename details::voc_node<Type,op1<Type> > > \
29599  (v, c); \
29600 
29603  #undef case_stmt
29604  default : return error_node();
29605  }
29606  }
29607  };
29608 
29610  {
29611  template <typename T0, typename T1, typename T2>
29613  const details::operator_type& sf3opr,
29614  T0 t0, T1 t1, T2 t2)
29615  {
29616  switch (sf3opr)
29617  {
29618  #define case_stmt(op) \
29619  case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \
29620  allocate(*(expr_gen.node_allocator_), t0, t1, t2); \
29621 
29622  case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03)
29623  case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07)
29624  case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11)
29625  case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15)
29626  case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19)
29627  case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23)
29628  case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27)
29629  case_stmt(28) case_stmt(29) case_stmt(30)
29630  #undef case_stmt
29631  default : return error_node();
29632  }
29633  }
29634 
29635  template <typename T0, typename T1, typename T2>
29636  static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29637  T0 t0, T1 t1, T2 t2,
29638  expression_node_ptr& result)
29639  {
29640  details::operator_type sf3opr;
29641 
29642  if (!expr_gen.sf3_optimisable(id,sf3opr))
29643  return false;
29644  else
29645  result = synthesize_sf3ext_expression::template process<T0, T1, T2>
29646  (expr_gen, sf3opr, t0, t1, t2);
29647 
29648  return true;
29649  }
29650  };
29651 
29653  {
29654  template <typename T0, typename T1, typename T2, typename T3>
29656  const details::operator_type& sf4opr,
29657  T0 t0, T1 t1, T2 t2, T3 t3)
29658  {
29659  switch (sf4opr)
29660  {
29661  #define case_stmt0(op) \
29662  case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \
29663  allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29664 
29665 
29666  #define case_stmt1(op) \
29667  case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \
29668  allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \
29669 
29670  case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51)
29671  case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55)
29672  case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59)
29673  case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63)
29674  case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67)
29675  case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71)
29676  case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75)
29677  case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79)
29678  case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83)
29679 
29680  case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03)
29681  case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07)
29682  case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11)
29683  case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15)
29684  case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19)
29685  case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23)
29686  case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27)
29687  case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31)
29688  case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35)
29689  case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39)
29690  case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43)
29691  case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47)
29692  case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51)
29693  case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55)
29694  case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59)
29695  case_stmt1(60) case_stmt1(61)
29696 
29697  #undef case_stmt0
29698  #undef case_stmt1
29699  default : return error_node();
29700  }
29701  }
29702 
29703  template <typename T0, typename T1, typename T2, typename T3>
29704  static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id,
29705  T0 t0, T1 t1, T2 t2, T3 t3,
29706  expression_node_ptr& result)
29707  {
29708  details::operator_type sf4opr;
29709 
29710  if (!expr_gen.sf4_optimisable(id,sf4opr))
29711  return false;
29712  else
29713  result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3>
29714  (expr_gen, sf4opr, t0, t1, t2, t3);
29715 
29716  return true;
29717  }
29718 
29719  // T o (sf3ext)
29720  template <typename ExternalType>
29721  static inline bool compile_right(expression_generator<Type>& expr_gen,
29722  ExternalType t,
29723  const details::operator_type& operation,
29724  expression_node_ptr& sf3node,
29725  expression_node_ptr& result)
29726  {
29727  if (!details::is_sf3ext_node(sf3node))
29728  return false;
29729 
29730  typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29731 
29732  sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29733  const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")";
29734 
29735  switch (n->type())
29736  {
29737  case details::expression_node<Type>::e_covoc : return compile_right_impl
29738  <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29739  (expr_gen, id, t, sf3node, result);
29740 
29741  case details::expression_node<Type>::e_covov : return compile_right_impl
29742  <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29743  (expr_gen, id, t, sf3node, result);
29744 
29745  case details::expression_node<Type>::e_vocov : return compile_right_impl
29746  <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29747  (expr_gen, id, t, sf3node, result);
29748 
29749  case details::expression_node<Type>::e_vovoc : return compile_right_impl
29750  <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29751  (expr_gen, id, t, sf3node, result);
29752 
29753  case details::expression_node<Type>::e_vovov : return compile_right_impl
29754  <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29755  (expr_gen, id, t, sf3node, result);
29756 
29757  default : return false;
29758  }
29759  }
29760 
29761  // (sf3ext) o T
29762  template <typename ExternalType>
29763  static inline bool compile_left(expression_generator<Type>& expr_gen,
29764  ExternalType t,
29765  const details::operator_type& operation,
29766  expression_node_ptr& sf3node,
29767  expression_node_ptr& result)
29768  {
29769  if (!details::is_sf3ext_node(sf3node))
29770  return false;
29771 
29772  typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr;
29773 
29774  sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node);
29775 
29776  const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t";
29777 
29778  switch (n->type())
29779  {
29780  case details::expression_node<Type>::e_covoc : return compile_left_impl
29781  <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype>
29782  (expr_gen, id, t, sf3node, result);
29783 
29784  case details::expression_node<Type>::e_covov : return compile_left_impl
29785  <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype>
29786  (expr_gen, id, t, sf3node, result);
29787 
29788  case details::expression_node<Type>::e_vocov : return compile_left_impl
29789  <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype>
29790  (expr_gen, id, t, sf3node, result);
29791 
29792  case details::expression_node<Type>::e_vovoc : return compile_left_impl
29793  <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype>
29794  (expr_gen, id, t, sf3node, result);
29795 
29796  case details::expression_node<Type>::e_vovov : return compile_left_impl
29797  <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype>
29798  (expr_gen, id, t, sf3node, result);
29799 
29800  default : return false;
29801  }
29802  }
29803 
29804  template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29805  static inline bool compile_right_impl(expression_generator<Type>& expr_gen,
29806  const std::string& id,
29807  ExternalType t,
29808  expression_node_ptr& node,
29809  expression_node_ptr& result)
29810  {
29811  SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29812 
29813  if (n)
29814  {
29815  T0 t0 = n->t0();
29816  T1 t1 = n->t1();
29817  T2 t2 = n->t2();
29818 
29819  return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2>
29820  (expr_gen, id, t, t0, t1, t2, result);
29821  }
29822  else
29823  return false;
29824  }
29825 
29826  template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2>
29827  static inline bool compile_left_impl(expression_generator<Type>& expr_gen,
29828  const std::string& id,
29829  ExternalType t,
29830  expression_node_ptr& node,
29831  expression_node_ptr& result)
29832  {
29833  SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node);
29834 
29835  if (n)
29836  {
29837  T0 t0 = n->t0();
29838  T1 t1 = n->t1();
29839  T2 t2 = n->t2();
29840 
29841  return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType>
29842  (expr_gen, id, t0, t1, t2, t, result);
29843  }
29844  else
29845  return false;
29846  }
29847  };
29848 
29850  {
29851  typedef typename vovov_t::type0 node_type;
29852  typedef typename vovov_t::sf3_type sf3_type;
29853 
29855  const details::operator_type& operation,
29856  expression_node_ptr (&branch)[2])
29857  {
29858  // (v0 o0 v1) o1 (v2)
29859  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
29860  const Type& v0 = vov->v0();
29861  const Type& v1 = vov->v1();
29862  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
29863  const details::operator_type o0 = vov->operation();
29864  const details::operator_type o1 = operation;
29865 
29866  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29867  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29868 
29869  details::free_node(*(expr_gen.node_allocator_),branch[0]);
29870 
29871  expression_node_ptr result = error_node();
29872 
29874  {
29875  // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)
29876  if ((details::e_div == o0) && (details::e_div == o1))
29877  {
29878  const bool synthesis_result =
29879  synthesize_sf3ext_expression::
29880  template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result);
29881 
29882  exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n"));
29883 
29884  return (synthesis_result) ? result : error_node();
29885  }
29886  }
29887 
29888  const bool synthesis_result =
29889  synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
29890  (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
29891 
29892  if (synthesis_result)
29893  return result;
29894  else if (!expr_gen.valid_operator(o0,f0))
29895  return error_node();
29896  else if (!expr_gen.valid_operator(o1,f1))
29897  return error_node();
29898  else
29899  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
29900  }
29901 
29902  static inline std::string id(expression_generator<Type>& expr_gen,
29904  {
29905  return details::build_string()
29906  << "(t" << expr_gen.to_str(o0)
29907  << "t)" << expr_gen.to_str(o1)
29908  << "t";
29909  }
29910  };
29911 
29913  {
29914  typedef typename vovov_t::type1 node_type;
29915  typedef typename vovov_t::sf3_type sf3_type;
29916 
29918  const details::operator_type& operation,
29919  expression_node_ptr (&branch)[2])
29920  {
29921  // (v0) o0 (v1 o1 v2)
29922  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
29923  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
29924  const Type& v1 = vov->v0();
29925  const Type& v2 = vov->v1();
29926  const details::operator_type o0 = operation;
29927  const details::operator_type o1 = vov->operation();
29928 
29929  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29930  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29931 
29932  details::free_node(*(expr_gen.node_allocator_),branch[1]);
29933 
29934  expression_node_ptr result = error_node();
29935 
29937  {
29938  // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1
29939  if ((details::e_div == o0) && (details::e_div == o1))
29940  {
29941  const bool synthesis_result =
29942  synthesize_sf3ext_expression::
29943  template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result);
29944 
29945  exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n"));
29946 
29947  return (synthesis_result) ? result : error_node();
29948  }
29949  }
29950 
29951  const bool synthesis_result =
29952  synthesize_sf3ext_expression::template compile<vtype, vtype, vtype>
29953  (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result);
29954 
29955  if (synthesis_result)
29956  return result;
29957  else if (!expr_gen.valid_operator(o0,f0))
29958  return error_node();
29959  else if (!expr_gen.valid_operator(o1,f1))
29960  return error_node();
29961  else
29962  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1);
29963  }
29964 
29965  static inline std::string id(expression_generator<Type>& expr_gen,
29967  {
29968  return details::build_string()
29969  << "t" << expr_gen.to_str(o0)
29970  << "(t" << expr_gen.to_str(o1)
29971  << "t)";
29972  }
29973  };
29974 
29976  {
29977  typedef typename vovoc_t::type0 node_type;
29978  typedef typename vovoc_t::sf3_type sf3_type;
29979 
29981  const details::operator_type& operation,
29982  expression_node_ptr (&branch)[2])
29983  {
29984  // (v0 o0 v1) o1 (c)
29985  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
29986  const Type& v0 = vov->v0();
29987  const Type& v1 = vov->v1();
29988  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
29989  const details::operator_type o0 = vov->operation();
29990  const details::operator_type o1 = operation;
29991 
29992  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
29993  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
29994 
29995  details::free_node(*(expr_gen.node_allocator_),branch[0]);
29996  details::free_node(*(expr_gen.node_allocator_),branch[1]);
29997 
29998  expression_node_ptr result = error_node();
29999 
30001  {
30002  // (v0 / v1) / c --> (vovoc) v0 / (v1 * c)
30003  if ((details::e_div == o0) && (details::e_div == o1))
30004  {
30005  const bool synthesis_result =
30006  synthesize_sf3ext_expression::
30007  template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30008 
30009  exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n"));
30010 
30011  return (synthesis_result) ? result : error_node();
30012  }
30013  }
30014 
30015  const bool synthesis_result =
30016  synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30017  (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30018 
30019  if (synthesis_result)
30020  return result;
30021  else if (!expr_gen.valid_operator(o0,f0))
30022  return error_node();
30023  else if (!expr_gen.valid_operator(o1,f1))
30024  return error_node();
30025  else
30026  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30027  }
30028 
30029  static inline std::string id(expression_generator<Type>& expr_gen,
30031  {
30032  return details::build_string()
30033  << "(t" << expr_gen.to_str(o0)
30034  << "t)" << expr_gen.to_str(o1)
30035  << "t";
30036  }
30037  };
30038 
30040  {
30041  typedef typename vovoc_t::type1 node_type;
30042  typedef typename vovoc_t::sf3_type sf3_type;
30043 
30045  const details::operator_type& operation,
30046  expression_node_ptr (&branch)[2])
30047  {
30048  // (v0) o0 (v1 o1 c)
30049  const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]);
30050  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30051  const Type& v1 = voc->v();
30052  const Type c = voc->c();
30053  const details::operator_type o0 = operation;
30054  const details::operator_type o1 = voc->operation();
30055 
30056  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30057  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30058 
30059  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30060 
30061  expression_node_ptr result = error_node();
30062 
30064  {
30065  // v0 / (v1 / c) --> (vocov) (v0 * c) / v1
30066  if ((details::e_div == o0) && (details::e_div == o1))
30067  {
30068  const bool synthesis_result =
30069  synthesize_sf3ext_expression::
30070  template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result);
30071 
30072  exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n"));
30073 
30074  return (synthesis_result) ? result : error_node();
30075  }
30076  }
30077 
30078  const bool synthesis_result =
30079  synthesize_sf3ext_expression::template compile<vtype, vtype, ctype>
30080  (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result);
30081 
30082  if (synthesis_result)
30083  return result;
30084  else if (!expr_gen.valid_operator(o0,f0))
30085  return error_node();
30086  else if (!expr_gen.valid_operator(o1,f1))
30087  return error_node();
30088  else
30089  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1);
30090  }
30091 
30092  static inline std::string id(expression_generator<Type>& expr_gen,
30094  {
30095  return details::build_string()
30096  << "t" << expr_gen.to_str(o0)
30097  << "(t" << expr_gen.to_str(o1)
30098  << "t)";
30099  }
30100  };
30101 
30103  {
30104  typedef typename vocov_t::type0 node_type;
30105  typedef typename vocov_t::sf3_type sf3_type;
30106 
30108  const details::operator_type& operation,
30109  expression_node_ptr (&branch)[2])
30110  {
30111  // (v0 o0 c) o1 (v1)
30112  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30113  const Type& v0 = voc->v();
30114  const Type c = voc->c();
30115  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30116  const details::operator_type o0 = voc->operation();
30117  const details::operator_type o1 = operation;
30118 
30119  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30120  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30121 
30122  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30123 
30124  expression_node_ptr result = error_node();
30125 
30127  {
30128  // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c)
30129  if ((details::e_div == o0) && (details::e_div == o1))
30130  {
30131  const bool synthesis_result =
30132  synthesize_sf3ext_expression::
30133  template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result);
30134 
30135  exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n"));
30136 
30137  return (synthesis_result) ? result : error_node();
30138  }
30139  }
30140 
30141  const bool synthesis_result =
30142  synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30143  (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30144 
30145  if (synthesis_result)
30146  return result;
30147  else if (!expr_gen.valid_operator(o0,f0))
30148  return error_node();
30149  else if (!expr_gen.valid_operator(o1,f1))
30150  return error_node();
30151  else
30152  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30153  }
30154 
30155  static inline std::string id(expression_generator<Type>& expr_gen,
30157  {
30158  return details::build_string()
30159  << "(t" << expr_gen.to_str(o0)
30160  << "t)" << expr_gen.to_str(o1)
30161  << "t";
30162  }
30163  };
30164 
30166  {
30167  typedef typename vocov_t::type1 node_type;
30168  typedef typename vocov_t::sf3_type sf3_type;
30169 
30171  const details::operator_type& operation,
30172  expression_node_ptr (&branch)[2])
30173  {
30174  // (v0) o0 (c o1 v1)
30175  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30176  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
30177  const Type c = cov->c();
30178  const Type& v1 = cov->v();
30179  const details::operator_type o0 = operation;
30180  const details::operator_type o1 = cov->operation();
30181 
30182  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30183  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30184 
30185  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30186 
30187  expression_node_ptr result = error_node();
30188 
30190  {
30191  // v0 / (c / v1) --> (vovoc) (v0 * v1) / c
30192  if ((details::e_div == o0) && (details::e_div == o1))
30193  {
30194  const bool synthesis_result =
30195  synthesize_sf3ext_expression::
30196  template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result);
30197 
30198  exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n"));
30199 
30200  return (synthesis_result) ? result : error_node();
30201  }
30202  }
30203 
30204  const bool synthesis_result =
30205  synthesize_sf3ext_expression::template compile<vtype, ctype, vtype>
30206  (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result);
30207 
30208  if (synthesis_result)
30209  return result;
30210  else if (!expr_gen.valid_operator(o0,f0))
30211  return error_node();
30212  else if (!expr_gen.valid_operator(o1,f1))
30213  return error_node();
30214  else
30215  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1);
30216  }
30217 
30218  static inline std::string id(expression_generator<Type>& expr_gen,
30220  {
30221  return details::build_string()
30222  << "t" << expr_gen.to_str(o0)
30223  << "(t" << expr_gen.to_str(o1)
30224  << "t)";
30225  }
30226  };
30227 
30229  {
30230  typedef typename covov_t::type0 node_type;
30231  typedef typename covov_t::sf3_type sf3_type;
30232 
30234  const details::operator_type& operation,
30235  expression_node_ptr (&branch)[2])
30236  {
30237  // (c o0 v0) o1 (v1)
30238  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30239  const Type c = cov->c();
30240  const Type& v0 = cov->v();
30241  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
30242  const details::operator_type o0 = cov->operation();
30243  const details::operator_type o1 = operation;
30244 
30245  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30246  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30247 
30248  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30249 
30250  expression_node_ptr result = error_node();
30251 
30253  {
30254  // (c / v0) / v1 --> (covov) c / (v0 * v1)
30255  if ((details::e_div == o0) && (details::e_div == o1))
30256  {
30257  const bool synthesis_result =
30258  synthesize_sf3ext_expression::
30259  template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result);
30260 
30261  exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n"));
30262 
30263  return (synthesis_result) ? result : error_node();
30264  }
30265  }
30266 
30267  const bool synthesis_result =
30268  synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30269  (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30270 
30271  if (synthesis_result)
30272  return result;
30273  else if (!expr_gen.valid_operator(o0,f0))
30274  return error_node();
30275  else if (!expr_gen.valid_operator(o1,f1))
30276  return error_node();
30277  else
30278  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30279  }
30280 
30281  static inline std::string id(expression_generator<Type>& expr_gen,
30283  {
30284  return details::build_string()
30285  << "(t" << expr_gen.to_str(o0)
30286  << "t)" << expr_gen.to_str(o1)
30287  << "t";
30288  }
30289  };
30290 
30292  {
30293  typedef typename covov_t::type1 node_type;
30294  typedef typename covov_t::sf3_type sf3_type;
30295 
30297  const details::operator_type& operation,
30298  expression_node_ptr (&branch)[2])
30299  {
30300  // (c) o0 (v0 o1 v1)
30301  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
30302  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
30303  const Type& v0 = vov->v0();
30304  const Type& v1 = vov->v1();
30305  const details::operator_type o0 = operation;
30306  const details::operator_type o1 = vov->operation();
30307 
30308  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30309  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30310 
30311  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30312  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30313 
30314  expression_node_ptr result = error_node();
30315 
30317  {
30318  // c / (v0 / v1) --> (covov) (c * v1) / v0
30319  if ((details::e_div == o0) && (details::e_div == o1))
30320  {
30321  const bool synthesis_result =
30322  synthesize_sf3ext_expression::
30323  template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result);
30324 
30325  exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n"));
30326 
30327  return (synthesis_result) ? result : error_node();
30328  }
30329  }
30330 
30331  const bool synthesis_result =
30332  synthesize_sf3ext_expression::template compile<ctype, vtype, vtype>
30333  (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result);
30334 
30335  if (synthesis_result)
30336  return result;
30337  else if (!expr_gen.valid_operator(o0,f0))
30338  return error_node();
30339  else if (!expr_gen.valid_operator(o1,f1))
30340  return error_node();
30341  else
30342  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1);
30343  }
30344 
30346  {
30347  return details::build_string()
30348  << "t" << expr_gen.to_str(o0)
30349  << "(t" << expr_gen.to_str(o1)
30350  << "t)";
30351  }
30352  };
30353 
30355  {
30356  typedef typename covoc_t::type0 node_type;
30357  typedef typename covoc_t::sf3_type sf3_type;
30358 
30360  const details::operator_type& operation,
30361  expression_node_ptr (&branch)[2])
30362  {
30363  // (c0 o0 v) o1 (c1)
30364  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
30365  const Type c0 = cov->c();
30366  const Type& v = cov->v();
30367  const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30368  const details::operator_type o0 = cov->operation();
30369  const details::operator_type o1 = operation;
30370 
30371  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30372  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30373 
30374  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30375  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30376 
30377  expression_node_ptr result = error_node();
30378 
30380  {
30381  // (c0 + v) + c1 --> (cov) (c0 + c1) + v
30382  if ((details::e_add == o0) && (details::e_add == o1))
30383  {
30384  exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n"));
30385 
30386  return expr_gen.node_allocator_->
30387  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30388  }
30389  // (c0 + v) - c1 --> (cov) (c0 - c1) + v
30390  else if ((details::e_add == o0) && (details::e_sub == o1))
30391  {
30392  exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n"));
30393 
30394  return expr_gen.node_allocator_->
30395  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30396  }
30397  // (c0 - v) + c1 --> (cov) (c0 + c1) - v
30398  else if ((details::e_sub == o0) && (details::e_add == o1))
30399  {
30400  exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n"));
30401 
30402  return expr_gen.node_allocator_->
30403  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30404  }
30405  // (c0 - v) - c1 --> (cov) (c0 - c1) - v
30406  else if ((details::e_sub == o0) && (details::e_sub == o1))
30407  {
30408  exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n"));
30409 
30410  return expr_gen.node_allocator_->
30411  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30412  }
30413  // (c0 * v) * c1 --> (cov) (c0 * c1) * v
30414  else if ((details::e_mul == o0) && (details::e_mul == o1))
30415  {
30416  exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n"));
30417 
30418  return expr_gen.node_allocator_->
30419  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30420  }
30421  // (c0 * v) / c1 --> (cov) (c0 / c1) * v
30422  else if ((details::e_mul == o0) && (details::e_div == o1))
30423  {
30424  exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n"));
30425 
30426  return expr_gen.node_allocator_->
30427  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30428  }
30429  // (c0 / v) * c1 --> (cov) (c0 * c1) / v
30430  else if ((details::e_div == o0) && (details::e_mul == o1))
30431  {
30432  exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n"));
30433 
30434  return expr_gen.node_allocator_->
30435  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30436  }
30437  // (c0 / v) / c1 --> (cov) (c0 / c1) / v
30438  else if ((details::e_div == o0) && (details::e_div == o1))
30439  {
30440  exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n"));
30441 
30442  return expr_gen.node_allocator_->
30443  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30444  }
30445  }
30446 
30447  const bool synthesis_result =
30448  synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30449  (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30450 
30451  if (synthesis_result)
30452  return result;
30453  else if (!expr_gen.valid_operator(o0,f0))
30454  return error_node();
30455  else if (!expr_gen.valid_operator(o1,f1))
30456  return error_node();
30457  else
30458  return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30459  }
30460 
30461  static inline std::string id(expression_generator<Type>& expr_gen,
30463  {
30464  return details::build_string()
30465  << "(t" << expr_gen.to_str(o0)
30466  << "t)" << expr_gen.to_str(o1)
30467  << "t";
30468  }
30469  };
30470 
30472  {
30473  typedef typename covoc_t::type1 node_type;
30474  typedef typename covoc_t::sf3_type sf3_type;
30475 
30477  const details::operator_type& operation,
30478  expression_node_ptr (&branch)[2])
30479  {
30480  // (c0) o0 (v o1 c1)
30481  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
30482  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30483  const Type& v = voc->v();
30484  const Type c1 = voc->c();
30485  const details::operator_type o0 = operation;
30486  const details::operator_type o1 = voc->operation();
30487 
30488  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30489  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30490 
30491  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30492  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30493 
30494  expression_node_ptr result = error_node();
30495 
30497  {
30498  // (c0) + (v + c1) --> (cov) (c0 + c1) + v
30499  if ((details::e_add == o0) && (details::e_add == o1))
30500  {
30501  exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n"));
30502 
30503  return expr_gen.node_allocator_->
30504  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30505  }
30506  // (c0) + (v - c1) --> (cov) (c0 - c1) + v
30507  else if ((details::e_add == o0) && (details::e_sub == o1))
30508  {
30509  exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n"));
30510 
30511  return expr_gen.node_allocator_->
30512  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30513  }
30514  // (c0) - (v + c1) --> (cov) (c0 - c1) - v
30515  else if ((details::e_sub == o0) && (details::e_add == o1))
30516  {
30517  exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n"));
30518 
30519  return expr_gen.node_allocator_->
30520  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30521  }
30522  // (c0) - (v - c1) --> (cov) (c0 + c1) - v
30523  else if ((details::e_sub == o0) && (details::e_sub == o1))
30524  {
30525  exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n"));
30526 
30527  return expr_gen.node_allocator_->
30528  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30529  }
30530  // (c0) * (v * c1) --> (voc) v * (c0 * c1)
30531  else if ((details::e_mul == o0) && (details::e_mul == o1))
30532  {
30533  exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n"));
30534 
30535  return expr_gen.node_allocator_->
30536  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30537  }
30538  // (c0) * (v / c1) --> (cov) (c0 / c1) * v
30539  else if ((details::e_mul == o0) && (details::e_div == o1))
30540  {
30541  exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n"));
30542 
30543  return expr_gen.node_allocator_->
30544  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30545  }
30546  // (c0) / (v * c1) --> (cov) (c0 / c1) / v
30547  else if ((details::e_div == o0) && (details::e_mul == o1))
30548  {
30549  exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n"));
30550 
30551  return expr_gen.node_allocator_->
30552  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30553  }
30554  // (c0) / (v / c1) --> (cov) (c0 * c1) / v
30555  else if ((details::e_div == o0) && (details::e_div == o1))
30556  {
30557  exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n"));
30558 
30559  return expr_gen.node_allocator_->
30560  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30561  }
30562  }
30563 
30564  const bool synthesis_result =
30565  synthesize_sf3ext_expression::template compile<ctype, vtype, ctype>
30566  (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result);
30567 
30568  if (synthesis_result)
30569  return result;
30570  else if (!expr_gen.valid_operator(o0,f0))
30571  return error_node();
30572  else if (!expr_gen.valid_operator(o1,f1))
30573  return error_node();
30574  else
30575  return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1);
30576  }
30577 
30578  static inline std::string id(expression_generator<Type>& expr_gen,
30580  {
30581  return details::build_string()
30582  << "t" << expr_gen.to_str(o0)
30583  << "(t" << expr_gen.to_str(o1)
30584  << "t)";
30585  }
30586  };
30587 
30589  {
30590  typedef typename cocov_t::type0 node_type;
30592  {
30593  // (c0 o0 c1) o1 (v) - Not possible.
30594  return error_node();
30595  }
30596  };
30597 
30599  {
30600  typedef typename cocov_t::type1 node_type;
30601  typedef typename cocov_t::sf3_type sf3_type;
30602 
30604  const details::operator_type& operation,
30605  expression_node_ptr (&branch)[2])
30606  {
30607  // (c0) o0 (c1 o1 v)
30608  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
30609  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
30610  const Type c1 = cov->c();
30611  const Type& v = cov->v();
30612  const details::operator_type o0 = operation;
30613  const details::operator_type o1 = cov->operation();
30614 
30615  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30616  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30617 
30618  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30619  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30620 
30621  expression_node_ptr result = error_node();
30622 
30624  {
30625  // (c0) + (c1 + v) --> (cov) (c0 + c1) + v
30626  if ((details::e_add == o0) && (details::e_add == o1))
30627  {
30628  exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n"));
30629 
30630  return expr_gen.node_allocator_->
30631  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v);
30632  }
30633  // (c0) + (c1 - v) --> (cov) (c0 + c1) - v
30634  else if ((details::e_add == o0) && (details::e_sub == o1))
30635  {
30636  exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n"));
30637 
30638  return expr_gen.node_allocator_->
30639  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v);
30640  }
30641  // (c0) - (c1 + v) --> (cov) (c0 - c1) - v
30642  else if ((details::e_sub == o0) && (details::e_add == o1))
30643  {
30644  exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n"));
30645 
30646  return expr_gen.node_allocator_->
30647  template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v);
30648  }
30649  // (c0) - (c1 - v) --> (cov) (c0 - c1) + v
30650  else if ((details::e_sub == o0) && (details::e_sub == o1))
30651  {
30652  exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n"));
30653 
30654  return expr_gen.node_allocator_->
30655  template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v);
30656  }
30657  // (c0) * (c1 * v) --> (cov) (c0 * c1) * v
30658  else if ((details::e_mul == o0) && (details::e_mul == o1))
30659  {
30660  exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n"));
30661 
30662  return expr_gen.node_allocator_->
30663  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v);
30664  }
30665  // (c0) * (c1 / v) --> (cov) (c0 * c1) / v
30666  else if ((details::e_mul == o0) && (details::e_div == o1))
30667  {
30668  exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n"));
30669 
30670  return expr_gen.node_allocator_->
30671  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v);
30672  }
30673  // (c0) / (c1 * v) --> (cov) (c0 / c1) / v
30674  else if ((details::e_div == o0) && (details::e_mul == o1))
30675  {
30676  exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n"));
30677 
30678  return expr_gen.node_allocator_->
30679  template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v);
30680  }
30681  // (c0) / (c1 / v) --> (cov) (c0 / c1) * v
30682  else if ((details::e_div == o0) && (details::e_div == o1))
30683  {
30684  exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n"));
30685 
30686  return expr_gen.node_allocator_->
30687  template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v);
30688  }
30689  }
30690 
30691  const bool synthesis_result =
30692  synthesize_sf3ext_expression::template compile<ctype, ctype, vtype>
30693  (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result);
30694 
30695  if (synthesis_result)
30696  return result;
30697  else if (!expr_gen.valid_operator(o0,f0))
30698  return error_node();
30699  else if (!expr_gen.valid_operator(o1,f1))
30700  return error_node();
30701  else
30702  return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1);
30703  }
30704 
30706  {
30707  return details::build_string()
30708  << "t" << expr_gen.to_str(o0)
30709  << "(t" << expr_gen.to_str(o1)
30710  << "t)";
30711  }
30712  };
30713 
30715  {
30716  typedef typename vococ_t::type0 node_type;
30717  typedef typename vococ_t::sf3_type sf3_type;
30718 
30720  const details::operator_type& operation,
30721  expression_node_ptr (&branch)[2])
30722  {
30723  // (v o0 c0) o1 (c1)
30724  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
30725  const Type& v = voc->v();
30726  const Type& c0 = voc->c();
30727  const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
30728  const details::operator_type o0 = voc->operation();
30729  const details::operator_type o1 = operation;
30730 
30731  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30732  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30733 
30734  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30735  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30736 
30737  expression_node_ptr result = error_node();
30738 
30740  {
30741  // (v + c0) + c1 --> (voc) v + (c0 + c1)
30742  if ((details::e_add == o0) && (details::e_add == o1))
30743  {
30744  exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n"));
30745 
30746  return expr_gen.node_allocator_->
30747  template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1);
30748  }
30749  // (v + c0) - c1 --> (voc) v + (c0 - c1)
30750  else if ((details::e_add == o0) && (details::e_sub == o1))
30751  {
30752  exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n"));
30753 
30754  return expr_gen.node_allocator_->
30755  template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1);
30756  }
30757  // (v - c0) + c1 --> (voc) v - (c0 + c1)
30758  else if ((details::e_sub == o0) && (details::e_add == o1))
30759  {
30760  exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n"));
30761 
30762  return expr_gen.node_allocator_->
30763  template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0);
30764  }
30765  // (v - c0) - c1 --> (voc) v - (c0 + c1)
30766  else if ((details::e_sub == o0) && (details::e_sub == o1))
30767  {
30768  exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n"));
30769 
30770  return expr_gen.node_allocator_->
30771  template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1);
30772  }
30773  // (v * c0) * c1 --> (voc) v * (c0 * c1)
30774  else if ((details::e_mul == o0) && (details::e_mul == o1))
30775  {
30776  exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n"));
30777 
30778  return expr_gen.node_allocator_->
30779  template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1);
30780  }
30781  // (v * c0) / c1 --> (voc) v * (c0 / c1)
30782  else if ((details::e_mul == o0) && (details::e_div == o1))
30783  {
30784  exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n"));
30785 
30786  return expr_gen.node_allocator_->
30787  template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1);
30788  }
30789  // (v / c0) * c1 --> (voc) v * (c1 / c0)
30790  else if ((details::e_div == o0) && (details::e_mul == o1))
30791  {
30792  exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n"));
30793 
30794  return expr_gen.node_allocator_->
30795  template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0);
30796  }
30797  // (v / c0) / c1 --> (voc) v / (c0 * c1)
30798  else if ((details::e_div == o0) && (details::e_div == o1))
30799  {
30800  exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n"));
30801 
30802  return expr_gen.node_allocator_->
30803  template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1);
30804  }
30805  // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)
30806  else if ((details::e_pow == o0) && (details::e_pow == o1))
30807  {
30808  exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n"));
30809 
30810  return expr_gen.node_allocator_->
30811  template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1);
30812  }
30813  }
30814 
30815  const bool synthesis_result =
30816  synthesize_sf3ext_expression::template compile<vtype, ctype, ctype>
30817  (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result);
30818 
30819  if (synthesis_result)
30820  return result;
30821  else if (!expr_gen.valid_operator(o0,f0))
30822  return error_node();
30823  else if (!expr_gen.valid_operator(o1,f1))
30824  return error_node();
30825  else
30826  return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1);
30827  }
30828 
30829  static inline std::string id(expression_generator<Type>& expr_gen,
30831  {
30832  return details::build_string()
30833  << "(t" << expr_gen.to_str(o0)
30834  << "t)" << expr_gen.to_str(o1)
30835  << "t";
30836  }
30837  };
30838 
30840  {
30841  typedef typename vococ_t::type0 node_type;
30842 
30844  {
30845  // (v) o0 (c0 o1 c1) - Not possible.
30846  exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n"));
30847  return error_node();
30848  }
30849  };
30850 
30852  {
30853  typedef typename vovovov_t::type0 node_type;
30854  typedef typename vovovov_t::sf4_type sf4_type;
30855  typedef typename node_type::T0 T0;
30856  typedef typename node_type::T1 T1;
30857  typedef typename node_type::T2 T2;
30858  typedef typename node_type::T3 T3;
30859 
30861  const details::operator_type& operation,
30862  expression_node_ptr (&branch)[2])
30863  {
30864  // (v0 o0 v1) o1 (v2 o2 v3)
30865  const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]);
30866  const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]);
30867  const Type& v0 = vov0->v0();
30868  const Type& v1 = vov0->v1();
30869  const Type& v2 = vov1->v0();
30870  const Type& v3 = vov1->v1();
30871  const details::operator_type o0 = vov0->operation();
30872  const details::operator_type o1 = operation;
30873  const details::operator_type o2 = vov1->operation();
30874 
30875  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30876  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30877  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
30878 
30879  details::free_node(*(expr_gen.node_allocator_),branch[0]);
30880  details::free_node(*(expr_gen.node_allocator_),branch[1]);
30881 
30882  expression_node_ptr result = error_node();
30883 
30885  {
30886  // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)
30887  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
30888  {
30889  const bool synthesis_result =
30890  synthesize_sf4ext_expression::
30891  template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result);
30892 
30893  exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n"));
30894 
30895  return (synthesis_result) ? result : error_node();
30896  }
30897  // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)
30898  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
30899  {
30900  const bool synthesis_result =
30901  synthesize_sf4ext_expression::
30902  template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result);
30903 
30904  exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n"));
30905 
30906  return (synthesis_result) ? result : error_node();
30907  }
30908  // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
30909  else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2))
30910  {
30911  const bool synthesis_result =
30912  synthesize_sf4ext_expression::
30913  template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result);
30914 
30915  exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n"));
30916 
30917  return (synthesis_result) ? result : error_node();
30918  }
30919  // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)
30920  else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2))
30921  {
30922  const bool synthesis_result =
30923  synthesize_sf4ext_expression::
30924  template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result);
30925 
30926  exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n"));
30927 
30928  return (synthesis_result) ? result : error_node();
30929  }
30930  // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2
30931  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
30932  {
30933  const bool synthesis_result =
30934  synthesize_sf4ext_expression::
30935  template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result);
30936 
30937  exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n"));
30938 
30939  return (synthesis_result) ? result : error_node();
30940  }
30941  }
30942 
30943  const bool synthesis_result =
30944  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
30945  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
30946 
30947  if (synthesis_result)
30948  return result;
30949  else if (!expr_gen.valid_operator(o0,f0))
30950  return error_node();
30951  else if (!expr_gen.valid_operator(o1,f1))
30952  return error_node();
30953  else if (!expr_gen.valid_operator(o2,f2))
30954  return error_node();
30955  else
30956  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
30957  }
30958 
30959  static inline std::string id(expression_generator<Type>& expr_gen,
30960  const details::operator_type o0,
30961  const details::operator_type o1,
30962  const details::operator_type o2)
30963  {
30964  return details::build_string()
30965  << "(t" << expr_gen.to_str(o0)
30966  << "t)" << expr_gen.to_str(o1)
30967  << "(t" << expr_gen.to_str(o2)
30968  << "t)";
30969  }
30970  };
30971 
30973  {
30974  typedef typename vovovoc_t::type0 node_type;
30975  typedef typename vovovoc_t::sf4_type sf4_type;
30976  typedef typename node_type::T0 T0;
30977  typedef typename node_type::T1 T1;
30978  typedef typename node_type::T2 T2;
30979  typedef typename node_type::T3 T3;
30980 
30982  const details::operator_type& operation,
30983  expression_node_ptr (&branch)[2])
30984  {
30985  // (v0 o0 v1) o1 (v2 o2 c)
30986  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
30987  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
30988  const Type& v0 = vov->v0();
30989  const Type& v1 = vov->v1();
30990  const Type& v2 = voc->v ();
30991  const Type c = voc->c ();
30992  const details::operator_type o0 = vov->operation();
30993  const details::operator_type o1 = operation;
30994  const details::operator_type o2 = voc->operation();
30995 
30996  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
30997  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
30998  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
30999 
31000  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31001  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31002 
31003  expression_node_ptr result = error_node();
31004 
31006  {
31007  // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)
31008  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31009  {
31010  const bool synthesis_result =
31011  synthesize_sf4ext_expression::
31012  template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31013 
31014  exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31015 
31016  return (synthesis_result) ? result : error_node();
31017  }
31018  // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)
31019  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31020  {
31021  const bool synthesis_result =
31022  synthesize_sf4ext_expression::
31023  template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31024 
31025  exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31026 
31027  return (synthesis_result) ? result : error_node();
31028  }
31029  }
31030 
31031  const bool synthesis_result =
31032  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31033  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
31034 
31035  if (synthesis_result)
31036  return result;
31037  else if (!expr_gen.valid_operator(o0,f0))
31038  return error_node();
31039  else if (!expr_gen.valid_operator(o1,f1))
31040  return error_node();
31041  else if (!expr_gen.valid_operator(o2,f2))
31042  return error_node();
31043  else
31044  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
31045  }
31046 
31047  static inline std::string id(expression_generator<Type>& expr_gen,
31048  const details::operator_type o0,
31049  const details::operator_type o1,
31050  const details::operator_type o2)
31051  {
31052  return details::build_string()
31053  << "(t" << expr_gen.to_str(o0)
31054  << "t)" << expr_gen.to_str(o1)
31055  << "(t" << expr_gen.to_str(o2)
31056  << "t)";
31057  }
31058  };
31059 
31061  {
31062  typedef typename vovocov_t::type0 node_type;
31063  typedef typename vovocov_t::sf4_type sf4_type;
31064  typedef typename node_type::T0 T0;
31065  typedef typename node_type::T1 T1;
31066  typedef typename node_type::T2 T2;
31067  typedef typename node_type::T3 T3;
31068 
31070  const details::operator_type& operation,
31071  expression_node_ptr (&branch)[2])
31072  {
31073  // (v0 o0 v1) o1 (c o2 v2)
31074  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]);
31075  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31076  const Type& v0 = vov->v0();
31077  const Type& v1 = vov->v1();
31078  const Type& v2 = cov->v ();
31079  const Type c = cov->c ();
31080  const details::operator_type o0 = vov->operation();
31081  const details::operator_type o1 = operation;
31082  const details::operator_type o2 = cov->operation();
31083 
31084  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31085  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31086  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31087 
31088  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31089  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31090 
31091  expression_node_ptr result = error_node();
31092 
31094  {
31095  // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)
31096  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31097  {
31098  const bool synthesis_result =
31099  synthesize_sf4ext_expression::
31100  template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result);
31101 
31102  exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n"));
31103 
31104  return (synthesis_result) ? result : error_node();
31105  }
31106  // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)
31107  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31108  {
31109  const bool synthesis_result =
31110  synthesize_sf4ext_expression::
31111  template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result);
31112 
31113  exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n"));
31114 
31115  return (synthesis_result) ? result : error_node();
31116  }
31117  }
31118 
31119  const bool synthesis_result =
31120  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31121  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
31122 
31123  if (synthesis_result)
31124  return result;
31125  else if (!expr_gen.valid_operator(o0,f0))
31126  return error_node();
31127  else if (!expr_gen.valid_operator(o1,f1))
31128  return error_node();
31129  else if (!expr_gen.valid_operator(o2,f2))
31130  return error_node();
31131  else
31132  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
31133  }
31134 
31135  static inline std::string id(expression_generator<Type>& expr_gen,
31136  const details::operator_type o0,
31137  const details::operator_type o1,
31138  const details::operator_type o2)
31139  {
31140  return details::build_string()
31141  << "(t" << expr_gen.to_str(o0)
31142  << "t)" << expr_gen.to_str(o1)
31143  << "(t" << expr_gen.to_str(o2)
31144  << "t)";
31145  }
31146  };
31147 
31149  {
31150  typedef typename vocovov_t::type0 node_type;
31151  typedef typename vocovov_t::sf4_type sf4_type;
31152  typedef typename node_type::T0 T0;
31153  typedef typename node_type::T1 T1;
31154  typedef typename node_type::T2 T2;
31155  typedef typename node_type::T3 T3;
31156 
31158  const details::operator_type& operation,
31159  expression_node_ptr (&branch)[2])
31160  {
31161  // (v0 o0 c) o1 (v1 o2 v2)
31162  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31163  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31164  const Type c = voc->c ();
31165  const Type& v0 = voc->v ();
31166  const Type& v1 = vov->v0();
31167  const Type& v2 = vov->v1();
31168  const details::operator_type o0 = voc->operation();
31169  const details::operator_type o1 = operation;
31170  const details::operator_type o2 = vov->operation();
31171 
31172  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31173  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31174  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31175 
31176  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31177  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31178 
31179  expression_node_ptr result = error_node();
31180 
31182  {
31183  // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)
31184  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31185  {
31186  const bool synthesis_result =
31187  synthesize_sf4ext_expression::
31188  template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result);
31189 
31190  exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n"));
31191 
31192  return (synthesis_result) ? result : error_node();
31193  }
31194  // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)
31195  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31196  {
31197  const bool synthesis_result =
31198  synthesize_sf4ext_expression::
31199  template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result);
31200 
31201  exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n"));
31202 
31203  return (synthesis_result) ? result : error_node();
31204  }
31205  }
31206 
31207  const bool synthesis_result =
31208  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31209  (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
31210 
31211  if (synthesis_result)
31212  return result;
31213  else if (!expr_gen.valid_operator(o0,f0))
31214  return error_node();
31215  else if (!expr_gen.valid_operator(o1,f1))
31216  return error_node();
31217  else if (!expr_gen.valid_operator(o2,f2))
31218  return error_node();
31219  else
31220  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
31221  }
31222 
31223  static inline std::string id(expression_generator<Type>& expr_gen,
31224  const details::operator_type o0,
31225  const details::operator_type o1,
31226  const details::operator_type o2)
31227  {
31228  return details::build_string()
31229  << "(t" << expr_gen.to_str(o0)
31230  << "t)" << expr_gen.to_str(o1)
31231  << "(t" << expr_gen.to_str(o2)
31232  << "t)";
31233  }
31234  };
31235 
31237  {
31238  typedef typename covovov_t::type0 node_type;
31239  typedef typename covovov_t::sf4_type sf4_type;
31240  typedef typename node_type::T0 T0;
31241  typedef typename node_type::T1 T1;
31242  typedef typename node_type::T2 T2;
31243  typedef typename node_type::T3 T3;
31244 
31246  const details::operator_type& operation,
31247  expression_node_ptr (&branch)[2])
31248  {
31249  // (c o0 v0) o1 (v1 o2 v2)
31250  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31251  const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]);
31252  const Type c = cov->c ();
31253  const Type& v0 = cov->v ();
31254  const Type& v1 = vov->v0();
31255  const Type& v2 = vov->v1();
31256  const details::operator_type o0 = cov->operation();
31257  const details::operator_type o1 = operation;
31258  const details::operator_type o2 = vov->operation();
31259 
31260  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31261  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31262  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31263 
31264  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31265  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31266 
31267  expression_node_ptr result = error_node();
31268 
31270  {
31271  // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)
31272  if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31273  {
31274  const bool synthesis_result =
31275  synthesize_sf4ext_expression::
31276  template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result);
31277 
31278  exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n"));
31279 
31280  return (synthesis_result) ? result : error_node();
31281  }
31282  // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)
31283  if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31284  {
31285  const bool synthesis_result =
31286  synthesize_sf4ext_expression::
31287  template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result);
31288 
31289  exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n"));
31290 
31291  return (synthesis_result) ? result : error_node();
31292  }
31293  }
31294 
31295  const bool synthesis_result =
31296  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31297  (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
31298 
31299  if (synthesis_result)
31300  return result;
31301  else if (!expr_gen.valid_operator(o0,f0))
31302  return error_node();
31303  else if (!expr_gen.valid_operator(o1,f1))
31304  return error_node();
31305  else if (!expr_gen.valid_operator(o2,f2))
31306  return error_node();
31307  else
31308  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
31309  }
31310 
31311  static inline std::string id(expression_generator<Type>& expr_gen,
31312  const details::operator_type o0,
31313  const details::operator_type o1,
31314  const details::operator_type o2)
31315  {
31316  return details::build_string()
31317  << "(t" << expr_gen.to_str(o0)
31318  << "t)" << expr_gen.to_str(o1)
31319  << "(t" << expr_gen.to_str(o2)
31320  << "t)";
31321  }
31322  };
31323 
31325  {
31326  typedef typename covocov_t::type0 node_type;
31327  typedef typename covocov_t::sf4_type sf4_type;
31328  typedef typename node_type::T0 T0;
31329  typedef typename node_type::T1 T1;
31330  typedef typename node_type::T2 T2;
31331  typedef typename node_type::T3 T3;
31332 
31334  const details::operator_type& operation,
31335  expression_node_ptr (&branch)[2])
31336  {
31337  // (c0 o0 v0) o1 (c1 o2 v1)
31338  const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]);
31339  const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]);
31340  const Type c0 = cov0->c();
31341  const Type& v0 = cov0->v();
31342  const Type c1 = cov1->c();
31343  const Type& v1 = cov1->v();
31344  const details::operator_type o0 = cov0->operation();
31345  const details::operator_type o1 = operation;
31346  const details::operator_type o2 = cov1->operation();
31347 
31348  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31349  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31350  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31351 
31352  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31353  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31354 
31355  expression_node_ptr result = error_node();
31356 
31358  {
31359  // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
31360  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31361  {
31362  const bool synthesis_result =
31363  synthesize_sf3ext_expression::
31364  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31365 
31366  exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
31367 
31368  return (synthesis_result) ? result : error_node();
31369  }
31370  // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
31371  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31372  {
31373  const bool synthesis_result =
31374  synthesize_sf3ext_expression::
31375  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31376 
31377  exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
31378 
31379  return (synthesis_result) ? result : error_node();
31380  }
31381  // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1
31382  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31383  {
31384  const bool synthesis_result =
31385  synthesize_sf3ext_expression::
31386  template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result);
31387 
31388  exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n"));
31389 
31390  return (synthesis_result) ? result : error_node();
31391  }
31392  // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
31393  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31394  {
31395  const bool synthesis_result =
31396  synthesize_sf3ext_expression::
31397  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31398 
31399  exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
31400 
31401  return (synthesis_result) ? result : error_node();
31402  }
31403  // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)
31404  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31405  {
31406  const bool synthesis_result =
31407  synthesize_sf3ext_expression::
31408  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31409 
31410  exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31411 
31412  return (synthesis_result) ? result : error_node();
31413  }
31414  // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)
31415  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31416  {
31417  const bool synthesis_result =
31418  synthesize_sf3ext_expression::
31419  template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31420 
31421  exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31422 
31423  return (synthesis_result) ? result : error_node();
31424  }
31425  // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0
31426  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31427  {
31428  const bool synthesis_result =
31429  synthesize_sf3ext_expression::
31430  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result);
31431 
31432  exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n"));
31433 
31434  return (synthesis_result) ? result : error_node();
31435  }
31436  // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
31437  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31438  {
31439  const bool synthesis_result =
31440  synthesize_sf3ext_expression::
31441  template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result);
31442 
31443  exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
31444 
31445  return (synthesis_result) ? result : error_node();
31446  }
31447  // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)
31448  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31449  {
31450  const bool synthesis_result =
31451  synthesize_sf3ext_expression::
31452  template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31453 
31454  exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31455 
31456  return (synthesis_result) ? result : error_node();
31457  }
31458  // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)
31459  else if (
31460  (std::equal_to<T>()(c0,c1)) &&
31461  (details::e_mul == o0) &&
31462  (details::e_mul == o2) &&
31463  (
31464  (details::e_add == o1) ||
31465  (details::e_sub == o1)
31466  )
31467  )
31468  {
31469  std::string specfunc;
31470 
31471  switch (o1)
31472  {
31473  case details::e_add : specfunc = "t*(t+t)"; break;
31474  case details::e_sub : specfunc = "t*(t-t)"; break;
31475  default : return error_node();
31476  }
31477 
31478  const bool synthesis_result =
31479  synthesize_sf3ext_expression::
31480  template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result);
31481 
31482  exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
31483 
31484  return (synthesis_result) ? result : error_node();
31485  }
31486  }
31487 
31488  const bool synthesis_result =
31489  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31490  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
31491 
31492  if (synthesis_result)
31493  return result;
31494  else if (!expr_gen.valid_operator(o0,f0))
31495  return error_node();
31496  else if (!expr_gen.valid_operator(o1,f1))
31497  return error_node();
31498  else if (!expr_gen.valid_operator(o2,f2))
31499  return error_node();
31500  else
31501  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
31502  }
31503 
31504  static inline std::string id(expression_generator<Type>& expr_gen,
31505  const details::operator_type o0,
31506  const details::operator_type o1,
31507  const details::operator_type o2)
31508  {
31509  return details::build_string()
31510  << "(t" << expr_gen.to_str(o0)
31511  << "t)" << expr_gen.to_str(o1)
31512  << "(t" << expr_gen.to_str(o2)
31513  << "t)";
31514  }
31515  };
31516 
31518  {
31519  typedef typename vocovoc_t::type0 node_type;
31520  typedef typename vocovoc_t::sf4_type sf4_type;
31521  typedef typename node_type::T0 T0;
31522  typedef typename node_type::T1 T1;
31523  typedef typename node_type::T2 T2;
31524  typedef typename node_type::T3 T3;
31525 
31527  const details::operator_type& operation,
31528  expression_node_ptr (&branch)[2])
31529  {
31530  // (v0 o0 c0) o1 (v1 o2 c1)
31531  const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]);
31532  const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]);
31533  const Type c0 = voc0->c();
31534  const Type& v0 = voc0->v();
31535  const Type c1 = voc1->c();
31536  const Type& v1 = voc1->v();
31537  const details::operator_type o0 = voc0->operation();
31538  const details::operator_type o1 = operation;
31539  const details::operator_type o2 = voc1->operation();
31540 
31541  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31542  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31543  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31544 
31545  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31546  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31547 
31548  expression_node_ptr result = error_node();
31549 
31551  {
31552  // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31553  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31554  {
31555  const bool synthesis_result =
31556  synthesize_sf3ext_expression::
31557  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31558 
31559  exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31560 
31561  return (synthesis_result) ? result : error_node();
31562  }
31563  // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31564  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31565  {
31566  const bool synthesis_result =
31567  synthesize_sf3ext_expression::
31568  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31569 
31570  exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31571 
31572  return (synthesis_result) ? result : error_node();
31573  }
31574  // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1
31575  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31576  {
31577  const bool synthesis_result =
31578  synthesize_sf3ext_expression::
31579  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result);
31580 
31581  exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n"));
31582 
31583  return (synthesis_result) ? result : error_node();
31584  }
31585  // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31586  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31587  {
31588  const bool synthesis_result =
31589  synthesize_sf3ext_expression::
31590  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31591 
31592  exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31593 
31594  return (synthesis_result) ? result : error_node();
31595  }
31596  // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31597  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31598  {
31599  const bool synthesis_result =
31600  synthesize_sf3ext_expression::
31601  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31602 
31603  exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31604 
31605  return (synthesis_result) ? result : error_node();
31606  }
31607  // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1
31608  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31609  {
31610  const bool synthesis_result =
31611  synthesize_sf3ext_expression::
31612  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result);
31613 
31614  exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n"));
31615 
31616  return (synthesis_result) ? result : error_node();
31617  }
31618  // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1
31619  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31620  {
31621  const bool synthesis_result =
31622  synthesize_sf3ext_expression::
31623  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
31624 
31625  exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n"));
31626 
31627  return (synthesis_result) ? result : error_node();
31628  }
31629  // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31630  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31631  {
31632  const bool synthesis_result =
31633  synthesize_sf3ext_expression::
31634  template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result);
31635 
31636  exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31637 
31638  return (synthesis_result) ? result : error_node();
31639  }
31640  // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1
31641  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31642  {
31643  const bool synthesis_result =
31644  synthesize_sf3ext_expression::
31645  template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result);
31646 
31647  exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n"));
31648 
31649  return (synthesis_result) ? result : error_node();
31650  }
31651  // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)
31652  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2))
31653  {
31654  const bool synthesis_result =
31655  synthesize_sf4ext_expression::
31656  template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result);
31657 
31658  exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n"));
31659 
31660  return (synthesis_result) ? result : error_node();
31661  }
31662  // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)
31663  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2))
31664  {
31665  const bool synthesis_result =
31666  synthesize_sf4ext_expression::
31667  template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result);
31668 
31669  exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n"));
31670 
31671  return (synthesis_result) ? result : error_node();
31672  }
31673  // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31674  else if (
31675  (std::equal_to<T>()(c0,c1)) &&
31676  (details::e_mul == o0) &&
31677  (details::e_mul == o2) &&
31678  (
31679  (details::e_add == o1) ||
31680  (details::e_sub == o1)
31681  )
31682  )
31683  {
31684  std::string specfunc;
31685 
31686  switch (o1)
31687  {
31688  case details::e_add : specfunc = "t*(t+t)"; break;
31689  case details::e_sub : specfunc = "t*(t-t)"; break;
31690  default : return error_node();
31691  }
31692 
31693  const bool synthesis_result =
31694  synthesize_sf3ext_expression::
31695  template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
31696 
31697  exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
31698 
31699  return (synthesis_result) ? result : error_node();
31700  }
31701  // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c
31702  else if (
31703  (std::equal_to<T>()(c0,c1)) &&
31704  (details::e_div == o0) &&
31705  (details::e_div == o2) &&
31706  (
31707  (details::e_add == o1) ||
31708  (details::e_sub == o1)
31709  )
31710  )
31711  {
31712  std::string specfunc;
31713 
31714  switch (o1)
31715  {
31716  case details::e_add : specfunc = "(t+t)/t"; break;
31717  case details::e_sub : specfunc = "(t-t)/t"; break;
31718  default : return error_node();
31719  }
31720 
31721  const bool synthesis_result =
31722  synthesize_sf3ext_expression::
31723  template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result);
31724 
31725  exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n"));
31726 
31727  return (synthesis_result) ? result : error_node();
31728  }
31729  }
31730 
31731  const bool synthesis_result =
31732  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31733  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
31734 
31735  if (synthesis_result)
31736  return result;
31737  else if (!expr_gen.valid_operator(o0,f0))
31738  return error_node();
31739  else if (!expr_gen.valid_operator(o1,f1))
31740  return error_node();
31741  else if (!expr_gen.valid_operator(o2,f2))
31742  return error_node();
31743  else
31744  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
31745  }
31746 
31747  static inline std::string id(expression_generator<Type>& expr_gen,
31748  const details::operator_type o0,
31749  const details::operator_type o1,
31750  const details::operator_type o2)
31751  {
31752  return details::build_string()
31753  << "(t" << expr_gen.to_str(o0)
31754  << "t)" << expr_gen.to_str(o1)
31755  << "(t" << expr_gen.to_str(o2)
31756  << "t)";
31757  }
31758  };
31759 
31761  {
31762  typedef typename covovoc_t::type0 node_type;
31763  typedef typename covovoc_t::sf4_type sf4_type;
31764  typedef typename node_type::T0 T0;
31765  typedef typename node_type::T1 T1;
31766  typedef typename node_type::T2 T2;
31767  typedef typename node_type::T3 T3;
31768 
31770  const details::operator_type& operation,
31771  expression_node_ptr (&branch)[2])
31772  {
31773  // (c0 o0 v0) o1 (v1 o2 c1)
31774  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]);
31775  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]);
31776  const Type c0 = cov->c();
31777  const Type& v0 = cov->v();
31778  const Type c1 = voc->c();
31779  const Type& v1 = voc->v();
31780  const details::operator_type o0 = cov->operation();
31781  const details::operator_type o1 = operation;
31782  const details::operator_type o2 = voc->operation();
31783 
31784  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31785  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31786  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31787 
31788  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31789  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31790 
31791  expression_node_ptr result = error_node();
31792 
31794  {
31795  // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1
31796  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31797  {
31798  const bool synthesis_result =
31799  synthesize_sf3ext_expression::
31800  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31801 
31802  exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n"));
31803 
31804  return (synthesis_result) ? result : error_node();
31805  }
31806  // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1
31807  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
31808  {
31809  const bool synthesis_result =
31810  synthesize_sf3ext_expression::
31811  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
31812 
31813  exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n"));
31814 
31815  return (synthesis_result) ? result : error_node();
31816  }
31817  // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1
31818  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
31819  {
31820  const bool synthesis_result =
31821  synthesize_sf3ext_expression::
31822  template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result);
31823 
31824  exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n"));
31825 
31826  return (synthesis_result) ? result : error_node();
31827  }
31828  // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1
31829  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
31830  {
31831  const bool synthesis_result =
31832  synthesize_sf3ext_expression::
31833  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
31834 
31835  exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n"));
31836 
31837  return (synthesis_result) ? result : error_node();
31838  }
31839  // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)
31840  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
31841  {
31842  const bool synthesis_result =
31843  synthesize_sf3ext_expression::
31844  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
31845 
31846  exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n"));
31847 
31848  return (synthesis_result) ? result : error_node();
31849  }
31850  // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)
31851  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
31852  {
31853  const bool synthesis_result =
31854  synthesize_sf3ext_expression::
31855  template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result);
31856 
31857  exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n"));
31858 
31859  return (synthesis_result) ? result : error_node();
31860  }
31861  // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)
31862  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
31863  {
31864  const bool synthesis_result =
31865  synthesize_sf3ext_expression::
31866  template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result);
31867 
31868  exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n"));
31869 
31870  return (synthesis_result) ? result : error_node();
31871  }
31872  // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)
31873  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
31874  {
31875  const bool synthesis_result =
31876  synthesize_sf3ext_expression::
31877  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result);
31878 
31879  exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n"));
31880 
31881  return (synthesis_result) ? result : error_node();
31882  }
31883  // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)
31884  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
31885  {
31886  const bool synthesis_result =
31887  synthesize_sf3ext_expression::
31888  template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result);
31889 
31890  exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n"));
31891 
31892  return (synthesis_result) ? result : error_node();
31893  }
31894  // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)
31895  else if (
31896  (std::equal_to<T>()(c0,c1)) &&
31897  (details::e_mul == o0) &&
31898  (details::e_mul == o2) &&
31899  (
31900  (details::e_add == o1) ||
31901  (details::e_sub == o1)
31902  )
31903  )
31904  {
31905  std::string specfunc;
31906 
31907  switch (o1)
31908  {
31909  case details::e_add : specfunc = "t*(t+t)"; break;
31910  case details::e_sub : specfunc = "t*(t-t)"; break;
31911  default : return error_node();
31912  }
31913 
31914  const bool synthesis_result =
31915  synthesize_sf3ext_expression::
31916  template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result);
31917 
31918  exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n"));
31919 
31920  return (synthesis_result) ? result : error_node();
31921  }
31922  }
31923 
31924  const bool synthesis_result =
31925  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
31926  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
31927 
31928  if (synthesis_result)
31929  return result;
31930  else if (!expr_gen.valid_operator(o0,f0))
31931  return error_node();
31932  else if (!expr_gen.valid_operator(o1,f1))
31933  return error_node();
31934  else if (!expr_gen.valid_operator(o2,f2))
31935  return error_node();
31936  else
31937  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
31938  }
31939 
31940  static inline std::string id(expression_generator<Type>& expr_gen,
31941  const details::operator_type o0,
31942  const details::operator_type o1,
31943  const details::operator_type o2)
31944  {
31945  return details::build_string()
31946  << "(t" << expr_gen.to_str(o0)
31947  << "t)" << expr_gen.to_str(o1)
31948  << "(t" << expr_gen.to_str(o2)
31949  << "t)";
31950  }
31951  };
31952 
31954  {
31955  typedef typename vococov_t::type0 node_type;
31956  typedef typename vococov_t::sf4_type sf4_type;
31957  typedef typename node_type::T0 T0;
31958  typedef typename node_type::T1 T1;
31959  typedef typename node_type::T2 T2;
31960  typedef typename node_type::T3 T3;
31961 
31963  const details::operator_type& operation,
31964  expression_node_ptr (&branch)[2])
31965  {
31966  // (v0 o0 c0) o1 (c1 o2 v1)
31967  const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]);
31968  const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]);
31969  const Type c0 = voc->c();
31970  const Type& v0 = voc->v();
31971  const Type c1 = cov->c();
31972  const Type& v1 = cov->v();
31973  const details::operator_type o0 = voc->operation();
31974  const details::operator_type o1 = operation;
31975  const details::operator_type o2 = cov->operation();
31976 
31977  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
31978  binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0);
31979  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
31980 
31981  details::free_node(*(expr_gen.node_allocator_),branch[0]);
31982  details::free_node(*(expr_gen.node_allocator_),branch[1]);
31983 
31984  expression_node_ptr result = error_node();
31985 
31987  {
31988  // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1
31989  if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2))
31990  {
31991  const bool synthesis_result =
31992  synthesize_sf3ext_expression::
31993  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result);
31994 
31995  exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n"));
31996 
31997  return (synthesis_result) ? result : error_node();
31998  }
31999  // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1
32000  else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2))
32001  {
32002  const bool synthesis_result =
32003  synthesize_sf3ext_expression::
32004  template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result);
32005 
32006  exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n"));
32007 
32008  return (synthesis_result) ? result : error_node();
32009  }
32010  // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)
32011  else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2))
32012  {
32013  const bool synthesis_result =
32014  synthesize_sf3ext_expression::
32015  template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result);
32016 
32017  exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n"));
32018 
32019  return (synthesis_result) ? result : error_node();
32020  }
32021  // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1
32022  else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2))
32023  {
32024  const bool synthesis_result =
32025  synthesize_sf3ext_expression::
32026  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result);
32027 
32028  exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n"));
32029 
32030  return (synthesis_result) ? result : error_node();
32031  }
32032  // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)
32033  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2))
32034  {
32035  const bool synthesis_result =
32036  synthesize_sf3ext_expression::
32037  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result);
32038 
32039  exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32040 
32041  return (synthesis_result) ? result : error_node();
32042  }
32043  // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)
32044  else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2))
32045  {
32046  const bool synthesis_result =
32047  synthesize_sf3ext_expression::
32048  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result);
32049 
32050  exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n"));
32051 
32052  return (synthesis_result) ? result : error_node();
32053  }
32054  // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)
32055  else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2))
32056  {
32057  const bool synthesis_result =
32058  synthesize_sf3ext_expression::
32059  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result);
32060 
32061  exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n"));
32062 
32063  return (synthesis_result) ? result : error_node();
32064  }
32065  // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)
32066  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2))
32067  {
32068  const bool synthesis_result =
32069  synthesize_sf3ext_expression::
32070  template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result);
32071 
32072  exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n"));
32073 
32074  return (synthesis_result) ? result : error_node();
32075  }
32076  // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))
32077  else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2))
32078  {
32079  const bool synthesis_result =
32080  synthesize_sf3ext_expression::
32081  template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result);
32082 
32083  exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n"));
32084 
32085  return (synthesis_result) ? result : error_node();
32086  }
32087  // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)
32088  else if (
32089  (std::equal_to<T>()(c0,c1)) &&
32090  (details::e_mul == o0) &&
32091  (details::e_mul == o2) &&
32092  (
32093  (details::e_add == o1) || (details::e_sub == o1)
32094  )
32095  )
32096  {
32097  std::string specfunc;
32098 
32099  switch (o1)
32100  {
32101  case details::e_add : specfunc = "t*(t+t)"; break;
32102  case details::e_sub : specfunc = "t*(t-t)"; break;
32103  default : return error_node();
32104  }
32105 
32106  const bool synthesis_result =
32107  synthesize_sf3ext_expression::
32108  template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result);
32109 
32110  exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n"));
32111 
32112  return (synthesis_result) ? result : error_node();
32113  }
32114  }
32115 
32116  const bool synthesis_result =
32117  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32118  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32119 
32120  if (synthesis_result)
32121  return result;
32122  else if (!expr_gen.valid_operator(o0,f0))
32123  return error_node();
32124  else if (!expr_gen.valid_operator(o1,f1))
32125  return error_node();
32126  else if (!expr_gen.valid_operator(o2,f2))
32127  return error_node();
32128  else
32129  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32130  }
32131 
32132  static inline std::string id(expression_generator<Type>& expr_gen,
32133  const details::operator_type o0,
32134  const details::operator_type o1,
32135  const details::operator_type o2)
32136  {
32137  return details::build_string()
32138  << "(t" << expr_gen.to_str(o0)
32139  << "t)" << expr_gen.to_str(o1)
32140  << "(t" << expr_gen.to_str(o2)
32141  << "t)";
32142  }
32143  };
32144 
32146  {
32147  typedef typename vovovov_t::type1 node_type;
32148  typedef typename vovovov_t::sf4_type sf4_type;
32149  typedef typename node_type::T0 T0;
32150  typedef typename node_type::T1 T1;
32151  typedef typename node_type::T2 T2;
32152  typedef typename node_type::T3 T3;
32153 
32155  const details::operator_type& operation,
32156  expression_node_ptr (&branch)[2])
32157  {
32158  // v0 o0 (v1 o1 (v2 o2 v3))
32159  typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32160 
32161  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32162  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32163  const Type& v1 = vovov->t0();
32164  const Type& v2 = vovov->t1();
32165  const Type& v3 = vovov->t2();
32166  const details::operator_type o0 = operation;
32167  const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32168  const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32169 
32170  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32171  binary_functor_t f1 = vovov->f0();
32172  binary_functor_t f2 = vovov->f1();
32173 
32174  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32175 
32176  expression_node_ptr result = error_node();
32177 
32178  if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result))
32179  return result;
32180  else if (!expr_gen.valid_operator(o0,f0))
32181  return error_node();
32182 
32183  exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n"));
32184 
32185  return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2);
32186  }
32187 
32188  static inline std::string id(expression_generator<Type>& expr_gen,
32189  const details::operator_type o0,
32190  const details::operator_type o1,
32191  const details::operator_type o2)
32192  {
32193  return details::build_string()
32194  << "t" << expr_gen.to_str(o0)
32195  << "(t" << expr_gen.to_str(o1)
32196  << "(t" << expr_gen.to_str(o2)
32197  << "t))";
32198  }
32199  };
32200 
32202  {
32203  typedef typename vovovoc_t::type1 node_type;
32204  typedef typename vovovoc_t::sf4_type sf4_type;
32205  typedef typename node_type::T0 T0;
32206  typedef typename node_type::T1 T1;
32207  typedef typename node_type::T2 T2;
32208  typedef typename node_type::T3 T3;
32209 
32211  const details::operator_type& operation,
32212  expression_node_ptr (&branch)[2])
32213  {
32214  // v0 o0 (v1 o1 (v2 o2 c))
32215  typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32216 
32217  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32218  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32219  const Type& v1 = vovoc->t0();
32220  const Type& v2 = vovoc->t1();
32221  const Type c = vovoc->t2();
32222  const details::operator_type o0 = operation;
32223  const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32224  const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32225 
32226  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32227  binary_functor_t f1 = vovoc->f0();
32228  binary_functor_t f2 = vovoc->f1();
32229 
32230  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32231 
32232  expression_node_ptr result = error_node();
32233 
32234  const bool synthesis_result =
32235  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32236  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32237 
32238  if (synthesis_result)
32239  return result;
32240  else if (!expr_gen.valid_operator(o0,f0))
32241  return error_node();
32242 
32243  exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n"));
32244 
32245  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32246  }
32247 
32248  static inline std::string id(expression_generator<Type>& expr_gen,
32249  const details::operator_type o0,
32250  const details::operator_type o1,
32251  const details::operator_type o2)
32252  {
32253  return details::build_string()
32254  << "t" << expr_gen.to_str(o0)
32255  << "(t" << expr_gen.to_str(o1)
32256  << "(t" << expr_gen.to_str(o2)
32257  << "t))";
32258  }
32259  };
32260 
32262  {
32263  typedef typename vovocov_t::type1 node_type;
32264  typedef typename vovocov_t::sf4_type sf4_type;
32265  typedef typename node_type::T0 T0;
32266  typedef typename node_type::T1 T1;
32267  typedef typename node_type::T2 T2;
32268  typedef typename node_type::T3 T3;
32269 
32271  const details::operator_type& operation,
32272  expression_node_ptr (&branch)[2])
32273  {
32274  // v0 o0 (v1 o1 (c o2 v2))
32275  typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32276 
32277  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32278  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32279  const Type& v1 = vocov->t0();
32280  const Type c = vocov->t1();
32281  const Type& v2 = vocov->t2();
32282  const details::operator_type o0 = operation;
32283  const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32284  const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32285 
32286  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32287  binary_functor_t f1 = vocov->f0();
32288  binary_functor_t f2 = vocov->f1();
32289 
32290  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32291 
32292  expression_node_ptr result = error_node();
32293 
32294  const bool synthesis_result =
32295  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32296  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32297 
32298  if (synthesis_result)
32299  return result;
32300  if (!expr_gen.valid_operator(o0,f0))
32301  return error_node();
32302 
32303  exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n"));
32304 
32305  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32306  }
32307 
32308  static inline std::string id(expression_generator<Type>& expr_gen,
32309  const details::operator_type o0,
32310  const details::operator_type o1,
32311  const details::operator_type o2)
32312  {
32313  return details::build_string()
32314  << "t" << expr_gen.to_str(o0)
32315  << "(t" << expr_gen.to_str(o1)
32316  << "(t" << expr_gen.to_str(o2)
32317  << "t))";
32318  }
32319  };
32320 
32322  {
32323  typedef typename vocovov_t::type1 node_type;
32324  typedef typename vocovov_t::sf4_type sf4_type;
32325  typedef typename node_type::T0 T0;
32326  typedef typename node_type::T1 T1;
32327  typedef typename node_type::T2 T2;
32328  typedef typename node_type::T3 T3;
32329 
32331  const details::operator_type& operation,
32332  expression_node_ptr (&branch)[2])
32333  {
32334  // v0 o0 (c o1 (v1 o2 v2))
32335  typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
32336 
32337  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32338  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32339  const Type c = covov->t0();
32340  const Type& v1 = covov->t1();
32341  const Type& v2 = covov->t2();
32342  const details::operator_type o0 = operation;
32343  const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32344  const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32345 
32346  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32347  binary_functor_t f1 = covov->f0();
32348  binary_functor_t f2 = covov->f1();
32349 
32350  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32351 
32352  expression_node_ptr result = error_node();
32353 
32354  const bool synthesis_result =
32355  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32356  (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32357 
32358  if (synthesis_result)
32359  return result;
32360  else if (!expr_gen.valid_operator(o0,f0))
32361  return error_node();
32362 
32363  exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n"));
32364 
32365  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32366  }
32367 
32368  static inline std::string id(expression_generator<Type>& expr_gen,
32369  const details::operator_type o0,
32370  const details::operator_type o1,
32371  const details::operator_type o2)
32372  {
32373  return details::build_string()
32374  << "t" << expr_gen.to_str(o0)
32375  << "(t" << expr_gen.to_str(o1)
32376  << "(t" << expr_gen.to_str(o2)
32377  << "t))";
32378  }
32379  };
32380 
32382  {
32383  typedef typename covovov_t::type1 node_type;
32384  typedef typename covovov_t::sf4_type sf4_type;
32385  typedef typename node_type::T0 T0;
32386  typedef typename node_type::T1 T1;
32387  typedef typename node_type::T2 T2;
32388  typedef typename node_type::T3 T3;
32389 
32391  const details::operator_type& operation,
32392  expression_node_ptr (&branch)[2])
32393  {
32394  // c o0 (v0 o1 (v1 o2 v2))
32395  typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
32396 
32397  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32398  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
32399  const Type& v0 = vovov->t0();
32400  const Type& v1 = vovov->t1();
32401  const Type& v2 = vovov->t2();
32402  const details::operator_type o0 = operation;
32403  const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32404  const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32405 
32406  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32407  binary_functor_t f1 = vovov->f0();
32408  binary_functor_t f2 = vovov->f1();
32409 
32410  details::free_node(*(expr_gen.node_allocator_),branch[0]);
32411  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32412 
32413  expression_node_ptr result = error_node();
32414 
32415  const bool synthesis_result =
32416  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32417  (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32418 
32419  if (synthesis_result)
32420  return result;
32421  if (!expr_gen.valid_operator(o0,f0))
32422  return error_node();
32423 
32424  exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n"));
32425 
32426  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32427  }
32428 
32429  static inline std::string id(expression_generator<Type>& expr_gen,
32430  const details::operator_type o0,
32431  const details::operator_type o1,
32432  const details::operator_type o2)
32433  {
32434  return details::build_string()
32435  << "t" << expr_gen.to_str(o0)
32436  << "(t" << expr_gen.to_str(o1)
32437  << "(t" << expr_gen.to_str(o2)
32438  << "t))";
32439  }
32440  };
32441 
32443  {
32444  typedef typename covocov_t::type1 node_type;
32445  typedef typename covocov_t::sf4_type sf4_type;
32446  typedef typename node_type::T0 T0;
32447  typedef typename node_type::T1 T1;
32448  typedef typename node_type::T2 T2;
32449  typedef typename node_type::T3 T3;
32450 
32452  const details::operator_type& operation,
32453  expression_node_ptr (&branch)[2])
32454  {
32455  // c0 o0 (v0 o1 (c1 o2 v1))
32456  typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
32457 
32458  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32459  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32460  const Type& v0 = vocov->t0();
32461  const Type c1 = vocov->t1();
32462  const Type& v1 = vocov->t2();
32463  const details::operator_type o0 = operation;
32464  const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32465  const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32466 
32467  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32468  binary_functor_t f1 = vocov->f0();
32469  binary_functor_t f2 = vocov->f1();
32470 
32471  details::free_node(*(expr_gen.node_allocator_),branch[0]);
32472  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32473 
32474  expression_node_ptr result = error_node();
32475 
32476  const bool synthesis_result =
32477  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32478  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
32479 
32480  if (synthesis_result)
32481  return result;
32482  else if (!expr_gen.valid_operator(o0,f0))
32483  return error_node();
32484 
32485  exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n"));
32486 
32487  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
32488  }
32489 
32490  static inline std::string id(expression_generator<Type>& expr_gen,
32491  const details::operator_type o0,
32492  const details::operator_type o1,
32493  const details::operator_type o2)
32494  {
32495  return details::build_string()
32496  << "t" << expr_gen.to_str(o0)
32497  << "(t" << expr_gen.to_str(o1)
32498  << "(t" << expr_gen.to_str(o2)
32499  << "t))";
32500  }
32501  };
32502 
32504  {
32505  typedef typename vocovoc_t::type1 node_type;
32506  typedef typename vocovoc_t::sf4_type sf4_type;
32507  typedef typename node_type::T0 T0;
32508  typedef typename node_type::T1 T1;
32509  typedef typename node_type::T2 T2;
32510  typedef typename node_type::T3 T3;
32511 
32513  const details::operator_type& operation,
32514  expression_node_ptr (&branch)[2])
32515  {
32516  // v0 o0 (c0 o1 (v1 o2 c2))
32517  typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
32518 
32519  const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
32520  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32521  const Type c0 = covoc->t0();
32522  const Type& v1 = covoc->t1();
32523  const Type c1 = covoc->t2();
32524  const details::operator_type o0 = operation;
32525  const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
32526  const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
32527 
32528  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32529  binary_functor_t f1 = covoc->f0();
32530  binary_functor_t f2 = covoc->f1();
32531 
32532  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32533 
32534  expression_node_ptr result = error_node();
32535 
32536  const bool synthesis_result =
32537  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32538  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
32539 
32540  if (synthesis_result)
32541  return result;
32542  else if (!expr_gen.valid_operator(o0,f0))
32543  return error_node();
32544 
32545  exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n"));
32546 
32547  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
32548  }
32549 
32550  static inline std::string id(expression_generator<Type>& expr_gen,
32551  const details::operator_type o0,
32552  const details::operator_type o1,
32553  const details::operator_type o2)
32554  {
32555  return details::build_string()
32556  << "t" << expr_gen.to_str(o0)
32557  << "(t" << expr_gen.to_str(o1)
32558  << "(t" << expr_gen.to_str(o2)
32559  << "t))";
32560  }
32561  };
32562 
32564  {
32565  typedef typename covovoc_t::type1 node_type;
32566  typedef typename covovoc_t::sf4_type sf4_type;
32567  typedef typename node_type::T0 T0;
32568  typedef typename node_type::T1 T1;
32569  typedef typename node_type::T2 T2;
32570  typedef typename node_type::T3 T3;
32572  const details::operator_type& operation,
32573  expression_node_ptr (&branch)[2])
32574  {
32575  // c0 o0 (v0 o1 (v1 o2 c1))
32576  typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
32577 
32578  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32579  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
32580  const Type& v0 = vovoc->t0();
32581  const Type& v1 = vovoc->t1();
32582  const Type c1 = vovoc->t2();
32583  const details::operator_type o0 = operation;
32584  const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32585  const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32586 
32587  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32588  binary_functor_t f1 = vovoc->f0();
32589  binary_functor_t f2 = vovoc->f1();
32590 
32591  details::free_node(*(expr_gen.node_allocator_),branch[0]);
32592  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32593 
32594  expression_node_ptr result = error_node();
32595 
32596  const bool synthesis_result =
32597  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32598  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
32599 
32600  if (synthesis_result)
32601  return result;
32602  else if (!expr_gen.valid_operator(o0,f0))
32603  return error_node();
32604 
32605  exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n"));
32606 
32607  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
32608  }
32609 
32610  static inline std::string id(expression_generator<Type>& expr_gen,
32611  const details::operator_type o0,
32612  const details::operator_type o1,
32613  const details::operator_type o2)
32614  {
32615  return details::build_string()
32616  << "t" << expr_gen.to_str(o0)
32617  << "(t" << expr_gen.to_str(o1)
32618  << "(t" << expr_gen.to_str(o2)
32619  << "t))";
32620  }
32621  };
32622 
32624  {
32625  typedef typename vococov_t::type1 node_type;
32626  typedef typename vococov_t::sf4_type sf4_type;
32627  typedef typename node_type::T0 T0;
32628  typedef typename node_type::T1 T1;
32629  typedef typename node_type::T2 T2;
32630  typedef typename node_type::T3 T3;
32631 
32633  const details::operator_type& operation,
32634  expression_node_ptr (&branch)[2])
32635  {
32636  // v0 o0 (c0 o1 (c1 o2 v1))
32637  typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t;
32638 
32639  const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]);
32640  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32641  const Type c0 = cocov->t0();
32642  const Type c1 = cocov->t1();
32643  const Type& v1 = cocov->t2();
32644  const details::operator_type o0 = operation;
32645  const details::operator_type o1 = expr_gen.get_operator(cocov->f0());
32646  const details::operator_type o2 = expr_gen.get_operator(cocov->f1());
32647 
32648  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32649  binary_functor_t f1 = cocov->f0();
32650  binary_functor_t f2 = cocov->f1();
32651 
32652  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32653 
32654  expression_node_ptr result = error_node();
32655 
32656  const bool synthesis_result =
32657  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32658  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
32659 
32660  if (synthesis_result)
32661  return result;
32662  else if (!expr_gen.valid_operator(o0,f0))
32663  return error_node();
32664 
32665  exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n"));
32666 
32667  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
32668  }
32669 
32670  static inline std::string id(expression_generator<Type>& expr_gen,
32671  const details::operator_type o0,
32672  const details::operator_type o1,
32673  const details::operator_type o2)
32674  {
32675  return details::build_string()
32676  << "t" << expr_gen.to_str(o0)
32677  << "(t" << expr_gen.to_str(o1)
32678  << "(t" << expr_gen.to_str(o2)
32679  << "t))";
32680  }
32681  };
32682 
32684  {
32685  typedef typename vovovov_t::type2 node_type;
32686  typedef typename vovovov_t::sf4_type sf4_type;
32687  typedef typename node_type::T0 T0;
32688  typedef typename node_type::T1 T1;
32689  typedef typename node_type::T2 T2;
32690  typedef typename node_type::T3 T3;
32691 
32693  const details::operator_type& operation,
32694  expression_node_ptr (&branch)[2])
32695  {
32696  // v0 o0 ((v1 o1 v2) o2 v3)
32697  typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
32698 
32699  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32700  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32701  const Type& v1 = vovov->t0();
32702  const Type& v2 = vovov->t1();
32703  const Type& v3 = vovov->t2();
32704  const details::operator_type o0 = operation;
32705  const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32706  const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32707 
32708  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32709  binary_functor_t f1 = vovov->f0();
32710  binary_functor_t f2 = vovov->f1();
32711 
32712  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32713 
32714  expression_node_ptr result = error_node();
32715 
32716  const bool synthesis_result =
32717  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32718  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
32719 
32720  if (synthesis_result)
32721  return result;
32722  else if (!expr_gen.valid_operator(o0,f0))
32723  return error_node();
32724 
32725  exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n"));
32726 
32727  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
32728  }
32729 
32730  static inline std::string id(expression_generator<Type>& expr_gen,
32731  const details::operator_type o0,
32732  const details::operator_type o1,
32733  const details::operator_type o2)
32734  {
32735  return details::build_string()
32736  << "t" << expr_gen.to_str(o0)
32737  << "((t" << expr_gen.to_str(o1)
32738  << "t)" << expr_gen.to_str(o2)
32739  << "t)";
32740  }
32741  };
32742 
32744  {
32745  typedef typename vovovoc_t::type2 node_type;
32746  typedef typename vovovoc_t::sf4_type sf4_type;
32747  typedef typename node_type::T0 T0;
32748  typedef typename node_type::T1 T1;
32749  typedef typename node_type::T2 T2;
32750  typedef typename node_type::T3 T3;
32751 
32753  const details::operator_type& operation,
32754  expression_node_ptr (&branch)[2])
32755  {
32756  // v0 o0 ((v1 o1 v2) o2 c)
32757  typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
32758 
32759  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
32760  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32761  const Type& v1 = vovoc->t0();
32762  const Type& v2 = vovoc->t1();
32763  const Type c = vovoc->t2();
32764  const details::operator_type o0 = operation;
32765  const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
32766  const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
32767 
32768  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32769  binary_functor_t f1 = vovoc->f0();
32770  binary_functor_t f2 = vovoc->f1();
32771 
32772  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32773 
32774  expression_node_ptr result = error_node();
32775 
32776  const bool synthesis_result =
32777  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32778  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
32779 
32780  if (synthesis_result)
32781  return result;
32782  else if (!expr_gen.valid_operator(o0,f0))
32783  return error_node();
32784 
32785  exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n"));
32786 
32787  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
32788  }
32789 
32790  static inline std::string id(expression_generator<Type>& expr_gen,
32791  const details::operator_type o0,
32792  const details::operator_type o1,
32793  const details::operator_type o2)
32794  {
32795  return details::build_string()
32796  << "t" << expr_gen.to_str(o0)
32797  << "((t" << expr_gen.to_str(o1)
32798  << "t)" << expr_gen.to_str(o2)
32799  << "t)";
32800  }
32801  };
32802 
32804  {
32805  typedef typename vovocov_t::type2 node_type;
32806  typedef typename vovocov_t::sf4_type sf4_type;
32807  typedef typename node_type::T0 T0;
32808  typedef typename node_type::T1 T1;
32809  typedef typename node_type::T2 T2;
32810  typedef typename node_type::T3 T3;
32811 
32813  const details::operator_type& operation,
32814  expression_node_ptr (&branch)[2])
32815  {
32816  // v0 o0 ((v1 o1 c) o2 v2)
32817  typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
32818 
32819  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
32820  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32821  const Type& v1 = vocov->t0();
32822  const Type c = vocov->t1();
32823  const Type& v2 = vocov->t2();
32824  const details::operator_type o0 = operation;
32825  const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
32826  const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
32827 
32828  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32829  binary_functor_t f1 = vocov->f0();
32830  binary_functor_t f2 = vocov->f1();
32831 
32832  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32833 
32834  expression_node_ptr result = error_node();
32835 
32836  const bool synthesis_result =
32837  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32838  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
32839 
32840  if (synthesis_result)
32841  return result;
32842  else if (!expr_gen.valid_operator(o0,f0))
32843  return error_node();
32844 
32845  exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n"));
32846 
32847  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
32848  }
32849 
32850  static inline std::string id(expression_generator<Type>& expr_gen,
32851  const details::operator_type o0,
32852  const details::operator_type o1,
32853  const details::operator_type o2)
32854  {
32855  return details::build_string()
32856  << "t" << expr_gen.to_str(o0)
32857  << "((t" << expr_gen.to_str(o1)
32858  << "t)" << expr_gen.to_str(o2)
32859  << "t)";
32860  }
32861  };
32862 
32864  {
32865  typedef typename vocovov_t::type2 node_type;
32866  typedef typename vocovov_t::sf4_type sf4_type;
32867  typedef typename node_type::T0 T0;
32868  typedef typename node_type::T1 T1;
32869  typedef typename node_type::T2 T2;
32870  typedef typename node_type::T3 T3;
32871 
32873  const details::operator_type& operation,
32874  expression_node_ptr (&branch)[2])
32875  {
32876  // v0 o0 ((c o1 v1) o2 v2)
32877  typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
32878 
32879  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]);
32880  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
32881  const Type c = covov->t0();
32882  const Type& v1 = covov->t1();
32883  const Type& v2 = covov->t2();
32884  const details::operator_type o0 = operation;
32885  const details::operator_type o1 = expr_gen.get_operator(covov->f0());
32886  const details::operator_type o2 = expr_gen.get_operator(covov->f1());
32887 
32888  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32889  binary_functor_t f1 = covov->f0();
32890  binary_functor_t f2 = covov->f1();
32891 
32892  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32893 
32894  expression_node_ptr result = error_node();
32895 
32896  const bool synthesis_result =
32897  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32898  (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
32899 
32900  if (synthesis_result)
32901  return result;
32902  else if (!expr_gen.valid_operator(o0,f0))
32903  return error_node();
32904 
32905  exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n"));
32906 
32907  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
32908  }
32909 
32910  static inline std::string id(expression_generator<Type>& expr_gen,
32911  const details::operator_type o0,
32912  const details::operator_type o1,
32913  const details::operator_type o2)
32914  {
32915  return details::build_string()
32916  << "t" << expr_gen.to_str(o0)
32917  << "((t" << expr_gen.to_str(o1)
32918  << "t)" << expr_gen.to_str(o2)
32919  << "t)";
32920  }
32921  };
32922 
32924  {
32925  typedef typename covovov_t::type2 node_type;
32926  typedef typename covovov_t::sf4_type sf4_type;
32927  typedef typename node_type::T0 T0;
32928  typedef typename node_type::T1 T1;
32929  typedef typename node_type::T2 T2;
32930  typedef typename node_type::T3 T3;
32931 
32933  const details::operator_type& operation,
32934  expression_node_ptr (&branch)[2])
32935  {
32936  // c o0 ((v1 o1 v2) o2 v3)
32937  typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
32938 
32939  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]);
32940  const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value();
32941  const Type& v0 = vovov->t0();
32942  const Type& v1 = vovov->t1();
32943  const Type& v2 = vovov->t2();
32944  const details::operator_type o0 = operation;
32945  const details::operator_type o1 = expr_gen.get_operator(vovov->f0());
32946  const details::operator_type o2 = expr_gen.get_operator(vovov->f1());
32947 
32948  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
32949  binary_functor_t f1 = vovov->f0();
32950  binary_functor_t f2 = vovov->f1();
32951 
32952  details::free_node(*(expr_gen.node_allocator_),branch[0]);
32953  details::free_node(*(expr_gen.node_allocator_),branch[1]);
32954 
32955  expression_node_ptr result = error_node();
32956 
32957  const bool synthesis_result =
32958  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
32959  (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
32960 
32961  if (synthesis_result)
32962  return result;
32963  else if (!expr_gen.valid_operator(o0,f0))
32964  return error_node();
32965 
32966  exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n"));
32967 
32968  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
32969  }
32970 
32971  static inline std::string id(expression_generator<Type>& expr_gen,
32972  const details::operator_type o0,
32973  const details::operator_type o1,
32974  const details::operator_type o2)
32975  {
32976  return details::build_string()
32977  << "t" << expr_gen.to_str(o0)
32978  << "((t" << expr_gen.to_str(o1)
32979  << "t)" << expr_gen.to_str(o2)
32980  << "t)";
32981  }
32982  };
32983 
32985  {
32986  typedef typename covocov_t::type2 node_type;
32987  typedef typename covocov_t::sf4_type sf4_type;
32988  typedef typename node_type::T0 T0;
32989  typedef typename node_type::T1 T1;
32990  typedef typename node_type::T2 T2;
32991  typedef typename node_type::T3 T3;
32992 
32994  const details::operator_type& operation,
32995  expression_node_ptr (&branch)[2])
32996  {
32997  // c0 o0 ((v0 o1 c1) o2 v1)
32998  typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
32999 
33000  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]);
33001  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33002  const Type& v0 = vocov->t0();
33003  const Type c1 = vocov->t1();
33004  const Type& v1 = vocov->t2();
33005  const details::operator_type o0 = operation;
33006  const details::operator_type o1 = expr_gen.get_operator(vocov->f0());
33007  const details::operator_type o2 = expr_gen.get_operator(vocov->f1());
33008 
33009  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33010  binary_functor_t f1 = vocov->f0();
33011  binary_functor_t f2 = vocov->f1();
33012 
33013  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33014  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33015 
33016  expression_node_ptr result = error_node();
33017 
33018  const bool synthesis_result =
33019  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33020  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33021 
33022  if (synthesis_result)
33023  return result;
33024  else if (!expr_gen.valid_operator(o0,f0))
33025  return error_node();
33026 
33027  exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n"));
33028 
33029  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33030  }
33031 
33032  static inline std::string id(expression_generator<Type>& expr_gen,
33033  const details::operator_type o0,
33034  const details::operator_type o1,
33035  const details::operator_type o2)
33036  {
33037  return details::build_string()
33038  << "t" << expr_gen.to_str(o0)
33039  << "((t" << expr_gen.to_str(o1)
33040  << "t)" << expr_gen.to_str(o2)
33041  << "t)";
33042  }
33043  };
33044 
33046  {
33047  typedef typename vocovoc_t::type2 node_type;
33048  typedef typename vocovoc_t::sf4_type sf4_type;
33049  typedef typename node_type::T0 T0;
33050  typedef typename node_type::T1 T1;
33051  typedef typename node_type::T2 T2;
33052  typedef typename node_type::T3 T3;
33053 
33055  const details::operator_type& operation,
33056  expression_node_ptr (&branch)[2])
33057  {
33058  // v0 o0 ((c0 o1 v1) o2 c1)
33059  typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33060 
33061  const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]);
33062  const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref();
33063  const Type c0 = covoc->t0();
33064  const Type& v1 = covoc->t1();
33065  const Type c1 = covoc->t2();
33066  const details::operator_type o0 = operation;
33067  const details::operator_type o1 = expr_gen.get_operator(covoc->f0());
33068  const details::operator_type o2 = expr_gen.get_operator(covoc->f1());
33069 
33070  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33071  binary_functor_t f1 = covoc->f0();
33072  binary_functor_t f2 = covoc->f1();
33073 
33074  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33075 
33076  expression_node_ptr result = error_node();
33077 
33078  const bool synthesis_result =
33079  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33080  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33081 
33082  if (synthesis_result)
33083  return result;
33084  else if (!expr_gen.valid_operator(o0,f0))
33085  return error_node();
33086 
33087  exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n"));
33088 
33089  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33090  }
33091 
33092  static inline std::string id(expression_generator<Type>& expr_gen,
33093  const details::operator_type o0,
33094  const details::operator_type o1,
33095  const details::operator_type o2)
33096  {
33097  return details::build_string()
33098  << "t" << expr_gen.to_str(o0)
33099  << "((t" << expr_gen.to_str(o1)
33100  << "t)" << expr_gen.to_str(o2)
33101  << "t)";
33102  }
33103  };
33104 
33106  {
33107  typedef typename covovoc_t::type2 node_type;
33108  typedef typename covovoc_t::sf4_type sf4_type;
33109  typedef typename node_type::T0 T0;
33110  typedef typename node_type::T1 T1;
33111  typedef typename node_type::T2 T2;
33112  typedef typename node_type::T3 T3;
33113 
33115  const details::operator_type& operation,
33116  expression_node_ptr (&branch)[2])
33117  {
33118  // c0 o0 ((v0 o1 v1) o2 c1)
33119  typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33120 
33121  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]);
33122  const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value();
33123  const Type& v0 = vovoc->t0();
33124  const Type& v1 = vovoc->t1();
33125  const Type c1 = vovoc->t2();
33126  const details::operator_type o0 = operation;
33127  const details::operator_type o1 = expr_gen.get_operator(vovoc->f0());
33128  const details::operator_type o2 = expr_gen.get_operator(vovoc->f1());
33129 
33130  binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0);
33131  binary_functor_t f1 = vovoc->f0();
33132  binary_functor_t f2 = vovoc->f1();
33133 
33134  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33135  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33136 
33137  expression_node_ptr result = error_node();
33138 
33139  const bool synthesis_result =
33140  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33141  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33142 
33143  if (synthesis_result)
33144  return result;
33145  else if (!expr_gen.valid_operator(o0,f0))
33146  return error_node();
33147 
33148  exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n"));
33149 
33150  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33151  }
33152 
33153  static inline std::string id(expression_generator<Type>& expr_gen,
33154  const details::operator_type o0,
33155  const details::operator_type o1,
33156  const details::operator_type o2)
33157  {
33158  return details::build_string()
33159  << "t" << expr_gen.to_str(o0)
33160  << "((t" << expr_gen.to_str(o1)
33161  << "t)" << expr_gen.to_str(o2)
33162  << "t)";
33163  }
33164  };
33165 
33167  {
33168  typedef typename vococov_t::type2 node_type;
33170  {
33171  // v0 o0 ((c0 o1 c1) o2 v1) - Not possible
33172  exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n"));
33173  return error_node();
33174  }
33175 
33178  {
33179  return "INVALID";
33180  }
33181  };
33182 
33184  {
33185  typedef typename vovovov_t::type3 node_type;
33186  typedef typename vovovov_t::sf4_type sf4_type;
33187  typedef typename node_type::T0 T0;
33188  typedef typename node_type::T1 T1;
33189  typedef typename node_type::T2 T2;
33190  typedef typename node_type::T3 T3;
33191 
33193  const details::operator_type& operation,
33194  expression_node_ptr (&branch)[2])
33195  {
33196  // ((v0 o0 v1) o1 v2) o2 v3
33197  typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33198 
33199  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33200  const Type& v0 = vovov->t0();
33201  const Type& v1 = vovov->t1();
33202  const Type& v2 = vovov->t2();
33203  const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33204  const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33205  const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33206  const details::operator_type o2 = operation;
33207 
33208  binary_functor_t f0 = vovov->f0();
33209  binary_functor_t f1 = vovov->f1();
33210  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33211 
33212  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33213 
33214  expression_node_ptr result = error_node();
33215 
33216  const bool synthesis_result =
33217  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33218  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33219 
33220  if (synthesis_result)
33221  return result;
33222  else if (!expr_gen.valid_operator(o2,f2))
33223  return error_node();
33224 
33225  exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n"));
33226 
33227  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33228  }
33229 
33230  static inline std::string id(expression_generator<Type>& expr_gen,
33231  const details::operator_type o0,
33232  const details::operator_type o1,
33233  const details::operator_type o2)
33234  {
33235  return details::build_string()
33236  << "((t" << expr_gen.to_str(o0)
33237  << "t)" << expr_gen.to_str(o1)
33238  << "t)" << expr_gen.to_str(o2)
33239  << "t";
33240  }
33241  };
33242 
33244  {
33245  typedef typename vovovoc_t::type3 node_type;
33246  typedef typename vovovoc_t::sf4_type sf4_type;
33247  typedef typename node_type::T0 T0;
33248  typedef typename node_type::T1 T1;
33249  typedef typename node_type::T2 T2;
33250  typedef typename node_type::T3 T3;
33251 
33253  const details::operator_type& operation,
33254  expression_node_ptr (&branch)[2])
33255  {
33256  // ((v0 o0 v1) o1 v2) o2 c
33257  typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t;
33258 
33259  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33260  const Type& v0 = vovov->t0();
33261  const Type& v1 = vovov->t1();
33262  const Type& v2 = vovov->t2();
33263  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33264  const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33265  const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33266  const details::operator_type o2 = operation;
33267 
33268  binary_functor_t f0 = vovov->f0();
33269  binary_functor_t f1 = vovov->f1();
33270  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33271 
33272  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33273  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33274 
33275  expression_node_ptr result = error_node();
33276 
33277  const bool synthesis_result =
33278  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33279  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33280 
33281  if (synthesis_result)
33282  return result;
33283  else if (!expr_gen.valid_operator(o2,f2))
33284  return error_node();
33285 
33286  exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n"));
33287 
33288  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33289  }
33290 
33291  static inline std::string id(expression_generator<Type>& expr_gen,
33292  const details::operator_type o0,
33293  const details::operator_type o1,
33294  const details::operator_type o2)
33295  {
33296  return details::build_string()
33297  << "((t" << expr_gen.to_str(o0)
33298  << "t)" << expr_gen.to_str(o1)
33299  << "t)" << expr_gen.to_str(o2)
33300  << "t";
33301  }
33302  };
33303 
33305  {
33306  typedef typename vovocov_t::type3 node_type;
33307  typedef typename vovocov_t::sf4_type sf4_type;
33308  typedef typename node_type::T0 T0;
33309  typedef typename node_type::T1 T1;
33310  typedef typename node_type::T2 T2;
33311  typedef typename node_type::T3 T3;
33312 
33314  const details::operator_type& operation,
33315  expression_node_ptr (&branch)[2])
33316  {
33317  // ((v0 o0 v1) o1 c) o2 v2
33318  typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t;
33319 
33320  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33321  const Type& v0 = vovoc->t0();
33322  const Type& v1 = vovoc->t1();
33323  const Type c = vovoc->t2();
33324  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33325  const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33326  const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33327  const details::operator_type o2 = operation;
33328 
33329  binary_functor_t f0 = vovoc->f0();
33330  binary_functor_t f1 = vovoc->f1();
33331  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33332 
33333  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33334 
33335  expression_node_ptr result = error_node();
33336 
33337  const bool synthesis_result =
33338  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33339  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33340 
33341  if (synthesis_result)
33342  return result;
33343  else if (!expr_gen.valid_operator(o2,f2))
33344  return error_node();
33345 
33346  exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n"));
33347 
33348  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33349  }
33350 
33351  static inline std::string id(expression_generator<Type>& expr_gen,
33352  const details::operator_type o0,
33353  const details::operator_type o1,
33354  const details::operator_type o2)
33355  {
33356  return details::build_string()
33357  << "((t" << expr_gen.to_str(o0)
33358  << "t)" << expr_gen.to_str(o1)
33359  << "t)" << expr_gen.to_str(o2)
33360  << "t";
33361  }
33362  };
33363 
33365  {
33366  typedef typename vocovov_t::type3 node_type;
33367  typedef typename vocovov_t::sf4_type sf4_type;
33368  typedef typename node_type::T0 T0;
33369  typedef typename node_type::T1 T1;
33370  typedef typename node_type::T2 T2;
33371  typedef typename node_type::T3 T3;
33372 
33374  const details::operator_type& operation,
33375  expression_node_ptr (&branch)[2])
33376  {
33377  // ((v0 o0 c) o1 v1) o2 v2
33378  typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33379 
33380  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33381  const Type& v0 = vocov->t0();
33382  const Type c = vocov->t1();
33383  const Type& v1 = vocov->t2();
33384  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33385  const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33386  const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33387  const details::operator_type o2 = operation;
33388 
33389  binary_functor_t f0 = vocov->f0();
33390  binary_functor_t f1 = vocov->f1();
33391  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33392 
33393  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33394 
33395  expression_node_ptr result = error_node();
33396 
33397  const bool synthesis_result =
33398  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33399  (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33400 
33401  if (synthesis_result)
33402  return result;
33403  else if (!expr_gen.valid_operator(o2,f2))
33404  return error_node();
33405 
33406  exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n"));
33407 
33408  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33409  }
33410 
33411  static inline std::string id(expression_generator<Type>& expr_gen,
33412  const details::operator_type o0,
33413  const details::operator_type o1,
33414  const details::operator_type o2)
33415  {
33416  return details::build_string()
33417  << "((t" << expr_gen.to_str(o0)
33418  << "t)" << expr_gen.to_str(o1)
33419  << "t)" << expr_gen.to_str(o2)
33420  << "t";
33421  }
33422  };
33423 
33425  {
33426  typedef typename covovov_t::type3 node_type;
33427  typedef typename covovov_t::sf4_type sf4_type;
33428  typedef typename node_type::T0 T0;
33429  typedef typename node_type::T1 T1;
33430  typedef typename node_type::T2 T2;
33431  typedef typename node_type::T3 T3;
33432 
33434  const details::operator_type& operation,
33435  expression_node_ptr (&branch)[2])
33436  {
33437  // ((c o0 v0) o1 v1) o2 v2
33438  typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33439 
33440  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33441  const Type c = covov->t0();
33442  const Type& v0 = covov->t1();
33443  const Type& v1 = covov->t2();
33444  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33445  const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33446  const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33447  const details::operator_type o2 = operation;
33448 
33449  binary_functor_t f0 = covov->f0();
33450  binary_functor_t f1 = covov->f1();
33451  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33452 
33453  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33454 
33455  expression_node_ptr result = error_node();
33456 
33457  const bool synthesis_result =
33458  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33459  (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
33460 
33461  if (synthesis_result)
33462  return result;
33463  else if (!expr_gen.valid_operator(o2,f2))
33464  return error_node();
33465 
33466  exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n"));
33467 
33468  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
33469  }
33470 
33471  static inline std::string id(expression_generator<Type>& expr_gen,
33472  const details::operator_type o0,
33473  const details::operator_type o1,
33474  const details::operator_type o2)
33475  {
33476  return details::build_string()
33477  << "((t" << expr_gen.to_str(o0)
33478  << "t)" << expr_gen.to_str(o1)
33479  << "t)" << expr_gen.to_str(o2)
33480  << "t";
33481  }
33482  };
33483 
33485  {
33486  typedef typename covocov_t::type3 node_type;
33487  typedef typename covocov_t::sf4_type sf4_type;
33488  typedef typename node_type::T0 T0;
33489  typedef typename node_type::T1 T1;
33490  typedef typename node_type::T2 T2;
33491  typedef typename node_type::T3 T3;
33492 
33494  const details::operator_type& operation,
33495  expression_node_ptr (&branch)[2])
33496  {
33497  // ((c0 o0 v0) o1 c1) o2 v1
33498  typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t;
33499 
33500  const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
33501  const Type c0 = covoc->t0();
33502  const Type& v0 = covoc->t1();
33503  const Type c1 = covoc->t2();
33504  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33505  const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
33506  const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
33507  const details::operator_type o2 = operation;
33508 
33509  binary_functor_t f0 = covoc->f0();
33510  binary_functor_t f1 = covoc->f1();
33511  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33512 
33513  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33514 
33515  expression_node_ptr result = error_node();
33516 
33517  const bool synthesis_result =
33518  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33519  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
33520 
33521  if (synthesis_result)
33522  return result;
33523  else if (!expr_gen.valid_operator(o2,f2))
33524  return error_node();
33525 
33526  exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n"));
33527 
33528  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
33529  }
33530 
33531  static inline std::string id(expression_generator<Type>& expr_gen,
33532  const details::operator_type o0,
33533  const details::operator_type o1,
33534  const details::operator_type o2)
33535  {
33536  return details::build_string()
33537  << "((t" << expr_gen.to_str(o0)
33538  << "t)" << expr_gen.to_str(o1)
33539  << "t)" << expr_gen.to_str(o2)
33540  << "t";
33541  }
33542  };
33543 
33545  {
33546  typedef typename vocovoc_t::type3 node_type;
33547  typedef typename vocovoc_t::sf4_type sf4_type;
33548  typedef typename node_type::T0 T0;
33549  typedef typename node_type::T1 T1;
33550  typedef typename node_type::T2 T2;
33551  typedef typename node_type::T3 T3;
33552 
33554  const details::operator_type& operation,
33555  expression_node_ptr (&branch)[2])
33556  {
33557  // ((v0 o0 c0) o1 v1) o2 c1
33558  typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t;
33559 
33560  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33561  const Type& v0 = vocov->t0();
33562  const Type c0 = vocov->t1();
33563  const Type& v1 = vocov->t2();
33564  const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33565  const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33566  const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33567  const details::operator_type o2 = operation;
33568 
33569  binary_functor_t f0 = vocov->f0();
33570  binary_functor_t f1 = vocov->f1();
33571  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33572 
33573  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33574  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33575 
33576  expression_node_ptr result = error_node();
33577 
33578  const bool synthesis_result =
33579  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33580  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
33581 
33582  if (synthesis_result)
33583  return result;
33584  else if (!expr_gen.valid_operator(o2,f2))
33585  return error_node();
33586 
33587  exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n"));
33588 
33589  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
33590  }
33591 
33592  static inline std::string id(expression_generator<Type>& expr_gen,
33593  const details::operator_type o0,
33594  const details::operator_type o1,
33595  const details::operator_type o2)
33596  {
33597  return details::build_string()
33598  << "((t" << expr_gen.to_str(o0)
33599  << "t)" << expr_gen.to_str(o1)
33600  << "t)" << expr_gen.to_str(o2)
33601  << "t";
33602  }
33603  };
33604 
33606  {
33607  typedef typename covovoc_t::type3 node_type;
33608  typedef typename covovoc_t::sf4_type sf4_type;
33609  typedef typename node_type::T0 T0;
33610  typedef typename node_type::T1 T1;
33611  typedef typename node_type::T2 T2;
33612  typedef typename node_type::T3 T3;
33613 
33615  const details::operator_type& operation,
33616  expression_node_ptr (&branch)[2])
33617  {
33618  // ((c0 o0 v0) o1 v1) o2 c1
33619  typedef typename synthesize_covov_expression0::node_type lcl_covov_t;
33620 
33621  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33622  const Type c0 = covov->t0();
33623  const Type& v0 = covov->t1();
33624  const Type& v1 = covov->t2();
33625  const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
33626  const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33627  const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33628  const details::operator_type o2 = operation;
33629 
33630  binary_functor_t f0 = covov->f0();
33631  binary_functor_t f1 = covov->f1();
33632  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33633 
33634  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33635  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33636 
33637  expression_node_ptr result = error_node();
33638 
33639  const bool synthesis_result =
33640  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33641  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
33642 
33643  if (synthesis_result)
33644  return result;
33645  else if (!expr_gen.valid_operator(o2,f2))
33646  return error_node();
33647 
33648  exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n"));
33649 
33650  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
33651  }
33652 
33653  static inline std::string id(expression_generator<Type>& expr_gen,
33654  const details::operator_type o0,
33655  const details::operator_type o1,
33656  const details::operator_type o2)
33657  {
33658  return details::build_string()
33659  << "((t" << expr_gen.to_str(o0)
33660  << "t)" << expr_gen.to_str(o1)
33661  << "t)" << expr_gen.to_str(o2)
33662  << "t";
33663  }
33664  };
33665 
33667  {
33668  typedef typename vococov_t::type3 node_type;
33669  typedef typename vococov_t::sf4_type sf4_type;
33670  typedef typename node_type::T0 T0;
33671  typedef typename node_type::T1 T1;
33672  typedef typename node_type::T2 T2;
33673  typedef typename node_type::T3 T3;
33674 
33676  const details::operator_type& operation,
33677  expression_node_ptr (&branch)[2])
33678  {
33679  // ((v0 o0 c0) o1 c1) o2 v1
33680  typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t;
33681 
33682  const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]);
33683  const Type& v0 = vococ->t0();
33684  const Type c0 = vococ->t1();
33685  const Type c1 = vococ->t2();
33686  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33687  const details::operator_type o0 = expr_gen.get_operator(vococ->f0());
33688  const details::operator_type o1 = expr_gen.get_operator(vococ->f1());
33689  const details::operator_type o2 = operation;
33690 
33691  binary_functor_t f0 = vococ->f0();
33692  binary_functor_t f1 = vococ->f1();
33693  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33694 
33695  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33696 
33697  expression_node_ptr result = error_node();
33698 
33699  const bool synthesis_result =
33700  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33701  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result);
33702 
33703  if (synthesis_result)
33704  return result;
33705  else if (!expr_gen.valid_operator(o2,f2))
33706  return error_node();
33707 
33708  exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n"));
33709 
33710  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2);
33711  }
33712 
33713  static inline std::string id(expression_generator<Type>& expr_gen,
33714  const details::operator_type o0,
33715  const details::operator_type o1,
33716  const details::operator_type o2)
33717  {
33718  return details::build_string()
33719  << "((t" << expr_gen.to_str(o0)
33720  << "t)" << expr_gen.to_str(o1)
33721  << "t)" << expr_gen.to_str(o2)
33722  << "t";
33723  }
33724  };
33725 
33727  {
33728  typedef typename vovovov_t::type4 node_type;
33729  typedef typename vovovov_t::sf4_type sf4_type;
33730  typedef typename node_type::T0 T0;
33731  typedef typename node_type::T1 T1;
33732  typedef typename node_type::T2 T2;
33733  typedef typename node_type::T3 T3;
33734 
33736  const details::operator_type& operation,
33737  expression_node_ptr (&branch)[2])
33738  {
33739  // (v0 o0 (v1 o1 v2)) o2 v3
33740  typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33741 
33742  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33743  const Type& v0 = vovov->t0();
33744  const Type& v1 = vovov->t1();
33745  const Type& v2 = vovov->t2();
33746  const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33747  const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33748  const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33749  const details::operator_type o2 = operation;
33750 
33751  binary_functor_t f0 = vovov->f0();
33752  binary_functor_t f1 = vovov->f1();
33753  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33754 
33755  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33756 
33757  expression_node_ptr result = error_node();
33758 
33759  const bool synthesis_result =
33760  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33761  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result);
33762 
33763  if (synthesis_result)
33764  return result;
33765  else if (!expr_gen.valid_operator(o2,f2))
33766  return error_node();
33767 
33768  exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n"));
33769 
33770  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2);
33771  }
33772 
33773  static inline std::string id(expression_generator<Type>& expr_gen,
33774  const details::operator_type o0,
33775  const details::operator_type o1,
33776  const details::operator_type o2)
33777  {
33778  return details::build_string()
33779  << "(t" << expr_gen.to_str(o0)
33780  << "(t" << expr_gen.to_str(o1)
33781  << "t)" << expr_gen.to_str(o2)
33782  << "t";
33783  }
33784  };
33785 
33787  {
33788  typedef typename vovovoc_t::type4 node_type;
33789  typedef typename vovovoc_t::sf4_type sf4_type;
33790  typedef typename node_type::T0 T0;
33791  typedef typename node_type::T1 T1;
33792  typedef typename node_type::T2 T2;
33793  typedef typename node_type::T3 T3;
33794 
33796  const details::operator_type& operation,
33797  expression_node_ptr (&branch)[2])
33798  {
33799  // ((v0 o0 (v1 o1 v2)) o2 c)
33800  typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t;
33801 
33802  const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]);
33803  const Type& v0 = vovov->t0();
33804  const Type& v1 = vovov->t1();
33805  const Type& v2 = vovov->t2();
33806  const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value();
33807  const details::operator_type o0 = expr_gen.get_operator(vovov->f0());
33808  const details::operator_type o1 = expr_gen.get_operator(vovov->f1());
33809  const details::operator_type o2 = operation;
33810 
33811  binary_functor_t f0 = vovov->f0();
33812  binary_functor_t f1 = vovov->f1();
33813  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33814 
33815  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33816  details::free_node(*(expr_gen.node_allocator_),branch[1]);
33817 
33818  expression_node_ptr result = error_node();
33819 
33820  const bool synthesis_result =
33821  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33822  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result);
33823 
33824  if (synthesis_result)
33825  return result;
33826  else if (!expr_gen.valid_operator(o2,f2))
33827  return error_node();
33828 
33829  exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n"));
33830 
33831  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2);
33832  }
33833 
33834  static inline std::string id(expression_generator<Type>& expr_gen,
33835  const details::operator_type o0,
33836  const details::operator_type o1,
33837  const details::operator_type o2)
33838  {
33839  return details::build_string()
33840  << "(t" << expr_gen.to_str(o0)
33841  << "(t" << expr_gen.to_str(o1)
33842  << "t)" << expr_gen.to_str(o2)
33843  << "t";
33844  }
33845  };
33846 
33848  {
33849  typedef typename vovocov_t::type4 node_type;
33850  typedef typename vovocov_t::sf4_type sf4_type;
33851  typedef typename node_type::T0 T0;
33852  typedef typename node_type::T1 T1;
33853  typedef typename node_type::T2 T2;
33854  typedef typename node_type::T3 T3;
33855 
33857  const details::operator_type& operation,
33858  expression_node_ptr (&branch)[2])
33859  {
33860  // ((v0 o0 (v1 o1 c)) o2 v1)
33861  typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t;
33862 
33863  const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]);
33864  const Type& v0 = vovoc->t0();
33865  const Type& v1 = vovoc->t1();
33866  const Type c = vovoc->t2();
33867  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33868  const details::operator_type o0 = expr_gen.get_operator(vovoc->f0());
33869  const details::operator_type o1 = expr_gen.get_operator(vovoc->f1());
33870  const details::operator_type o2 = operation;
33871 
33872  binary_functor_t f0 = vovoc->f0();
33873  binary_functor_t f1 = vovoc->f1();
33874  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33875 
33876  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33877 
33878  expression_node_ptr result = error_node();
33879 
33880  const bool synthesis_result =
33881  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33882  (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result);
33883 
33884  if (synthesis_result)
33885  return result;
33886  else if (!expr_gen.valid_operator(o2,f2))
33887  return error_node();
33888 
33889  exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n"));
33890 
33891  return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2);
33892  }
33893 
33894  static inline std::string id(expression_generator<Type>& expr_gen,
33895  const details::operator_type o0,
33896  const details::operator_type o1,
33897  const details::operator_type o2)
33898  {
33899  return details::build_string()
33900  << "(t" << expr_gen.to_str(o0)
33901  << "(t" << expr_gen.to_str(o1)
33902  << "t)" << expr_gen.to_str(o2)
33903  << "t";
33904  }
33905  };
33906 
33908  {
33909  typedef typename vocovov_t::type4 node_type;
33910  typedef typename vocovov_t::sf4_type sf4_type;
33911  typedef typename node_type::T0 T0;
33912  typedef typename node_type::T1 T1;
33913  typedef typename node_type::T2 T2;
33914  typedef typename node_type::T3 T3;
33915 
33917  const details::operator_type& operation,
33918  expression_node_ptr (&branch)[2])
33919  {
33920  // ((v0 o0 (c o1 v1)) o2 v2)
33921  typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
33922 
33923  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
33924  const Type& v0 = vocov->t0();
33925  const Type c = vocov->t1();
33926  const Type& v1 = vocov->t2();
33927  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33928  const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
33929  const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
33930  const details::operator_type o2 = operation;
33931 
33932  binary_functor_t f0 = vocov->f0();
33933  binary_functor_t f1 = vocov->f1();
33934  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33935 
33936  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33937  expression_node_ptr result = error_node();
33938 
33939  const bool synthesis_result =
33940  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
33941  (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result);
33942 
33943  if (synthesis_result)
33944  return result;
33945  else if (!expr_gen.valid_operator(o2,f2))
33946  return error_node();
33947 
33948  exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n"));
33949 
33950  return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2);
33951  }
33952 
33953  static inline std::string id(expression_generator<Type>& expr_gen,
33954  const details::operator_type o0,
33955  const details::operator_type o1,
33956  const details::operator_type o2)
33957  {
33958  return details::build_string()
33959  << "(t" << expr_gen.to_str(o0)
33960  << "(t" << expr_gen.to_str(o1)
33961  << "t)" << expr_gen.to_str(o2)
33962  << "t";
33963  }
33964  };
33965 
33967  {
33968  typedef typename covovov_t::type4 node_type;
33969  typedef typename covovov_t::sf4_type sf4_type;
33970  typedef typename node_type::T0 T0;
33971  typedef typename node_type::T1 T1;
33972  typedef typename node_type::T2 T2;
33973  typedef typename node_type::T3 T3;
33974 
33976  const details::operator_type& operation,
33977  expression_node_ptr (&branch)[2])
33978  {
33979  // ((c o0 (v0 o1 v1)) o2 v2)
33980  typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
33981 
33982  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
33983  const Type c = covov->t0();
33984  const Type& v0 = covov->t1();
33985  const Type& v1 = covov->t2();
33986  const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
33987  const details::operator_type o0 = expr_gen.get_operator(covov->f0());
33988  const details::operator_type o1 = expr_gen.get_operator(covov->f1());
33989  const details::operator_type o2 = operation;
33990 
33991  binary_functor_t f0 = covov->f0();
33992  binary_functor_t f1 = covov->f1();
33993  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
33994 
33995  details::free_node(*(expr_gen.node_allocator_),branch[0]);
33996 
33997  expression_node_ptr result = error_node();
33998 
33999  const bool synthesis_result =
34000  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34001  (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result);
34002 
34003  if (synthesis_result)
34004  return result;
34005  else if (!expr_gen.valid_operator(o2,f2))
34006  return error_node();
34007 
34008  exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n"));
34009 
34010  return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2);
34011  }
34012 
34013  static inline std::string id(expression_generator<Type>& expr_gen,
34014  const details::operator_type o0,
34015  const details::operator_type o1,
34016  const details::operator_type o2)
34017  {
34018  return details::build_string()
34019  << "(t" << expr_gen.to_str(o0)
34020  << "(t" << expr_gen.to_str(o1)
34021  << "t)" << expr_gen.to_str(o2)
34022  << "t";
34023  }
34024  };
34025 
34027  {
34028  typedef typename covocov_t::type4 node_type;
34029  typedef typename covocov_t::sf4_type sf4_type;
34030  typedef typename node_type::T0 T0;
34031  typedef typename node_type::T1 T1;
34032  typedef typename node_type::T2 T2;
34033  typedef typename node_type::T3 T3;
34034 
34036  const details::operator_type& operation,
34037  expression_node_ptr (&branch)[2])
34038  {
34039  // ((c0 o0 (v0 o1 c1)) o2 v1)
34040  typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t;
34041 
34042  const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]);
34043  const Type c0 = covoc->t0();
34044  const Type& v0 = covoc->t1();
34045  const Type c1 = covoc->t2();
34046  const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref();
34047  const details::operator_type o0 = expr_gen.get_operator(covoc->f0());
34048  const details::operator_type o1 = expr_gen.get_operator(covoc->f1());
34049  const details::operator_type o2 = operation;
34050 
34051  binary_functor_t f0 = covoc->f0();
34052  binary_functor_t f1 = covoc->f1();
34053  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34054 
34055  details::free_node(*(expr_gen.node_allocator_),branch[0]);
34056 
34057  expression_node_ptr result = error_node();
34058 
34059  const bool synthesis_result =
34060  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34061  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result);
34062 
34063  if (synthesis_result)
34064  return result;
34065  else if (!expr_gen.valid_operator(o2,f2))
34066  return error_node();
34067 
34068  exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n"));
34069 
34070  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2);
34071  }
34072 
34073  static inline std::string id(expression_generator<Type>& expr_gen,
34074  const details::operator_type o0,
34075  const details::operator_type o1,
34076  const details::operator_type o2)
34077  {
34078  return details::build_string()
34079  << "(t" << expr_gen.to_str(o0)
34080  << "(t" << expr_gen.to_str(o1)
34081  << "t)" << expr_gen.to_str(o2)
34082  << "t";
34083  }
34084  };
34085 
34087  {
34088  typedef typename vocovoc_t::type4 node_type;
34089  typedef typename vocovoc_t::sf4_type sf4_type;
34090  typedef typename node_type::T0 T0;
34091  typedef typename node_type::T1 T1;
34092  typedef typename node_type::T2 T2;
34093  typedef typename node_type::T3 T3;
34094 
34096  const details::operator_type& operation,
34097  expression_node_ptr (&branch)[2])
34098  {
34099  // ((v0 o0 (c0 o1 v1)) o2 c1)
34100  typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t;
34101 
34102  const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]);
34103  const Type& v0 = vocov->t0();
34104  const Type c0 = vocov->t1();
34105  const Type& v1 = vocov->t2();
34106  const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34107  const details::operator_type o0 = expr_gen.get_operator(vocov->f0());
34108  const details::operator_type o1 = expr_gen.get_operator(vocov->f1());
34109  const details::operator_type o2 = operation;
34110 
34111  binary_functor_t f0 = vocov->f0();
34112  binary_functor_t f1 = vocov->f1();
34113  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34114 
34115  details::free_node(*(expr_gen.node_allocator_),branch[0]);
34116  details::free_node(*(expr_gen.node_allocator_),branch[1]);
34117 
34118  expression_node_ptr result = error_node();
34119 
34120  const bool synthesis_result =
34121  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34122  (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result);
34123 
34124  if (synthesis_result)
34125  return result;
34126  else if (!expr_gen.valid_operator(o2,f2))
34127  return error_node();
34128 
34129  exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n"));
34130 
34131  return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2);
34132  }
34133 
34134  static inline std::string id(expression_generator<Type>& expr_gen,
34135  const details::operator_type o0,
34136  const details::operator_type o1,
34137  const details::operator_type o2)
34138  {
34139  return details::build_string()
34140  << "(t" << expr_gen.to_str(o0)
34141  << "(t" << expr_gen.to_str(o1)
34142  << "t)" << expr_gen.to_str(o2)
34143  << "t";
34144  }
34145  };
34146 
34148  {
34149  typedef typename covovoc_t::type4 node_type;
34150  typedef typename covovoc_t::sf4_type sf4_type;
34151  typedef typename node_type::T0 T0;
34152  typedef typename node_type::T1 T1;
34153  typedef typename node_type::T2 T2;
34154  typedef typename node_type::T3 T3;
34155 
34157  const details::operator_type& operation,
34158  expression_node_ptr (&branch)[2])
34159  {
34160  // ((c0 o0 (v0 o1 v1)) o2 c1)
34161  typedef typename synthesize_covov_expression1::node_type lcl_covov_t;
34162 
34163  const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]);
34164  const Type c0 = covov->t0();
34165  const Type& v0 = covov->t1();
34166  const Type& v1 = covov->t2();
34167  const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value();
34168  const details::operator_type o0 = expr_gen.get_operator(covov->f0());
34169  const details::operator_type o1 = expr_gen.get_operator(covov->f1());
34170  const details::operator_type o2 = operation;
34171 
34172  binary_functor_t f0 = covov->f0();
34173  binary_functor_t f1 = covov->f1();
34174  binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0);
34175 
34176  details::free_node(*(expr_gen.node_allocator_),branch[0]);
34177  details::free_node(*(expr_gen.node_allocator_),branch[1]);
34178 
34179  expression_node_ptr result = error_node();
34180 
34181  const bool synthesis_result =
34182  synthesize_sf4ext_expression::template compile<T0, T1, T2, T3>
34183  (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result);
34184 
34185  if (synthesis_result)
34186  return result;
34187  else if (!expr_gen.valid_operator(o2,f2))
34188  return error_node();
34189 
34190  exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n"));
34191 
34192  return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2);
34193  }
34194 
34195  static inline std::string id(expression_generator<Type>& expr_gen,
34196  const details::operator_type o0,
34197  const details::operator_type o1,
34198  const details::operator_type o2)
34199  {
34200  return details::build_string()
34201  << "(t" << expr_gen.to_str(o0)
34202  << "(t" << expr_gen.to_str(o1)
34203  << "t)" << expr_gen.to_str(o2)
34204  << "t";
34205  }
34206  };
34207 
34209  {
34210  typedef typename vococov_t::type4 node_type;
34212  {
34213  // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible
34214  exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n"));
34215  return error_node();
34216  }
34217 
34220  {
34221  return "INVALID";
34222  }
34223  };
34224  #endif
34225 
34227  {
34228  // Definition: uv o uv
34229  details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation();
34230  details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation();
34231  const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v();
34232  const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v();
34233  unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0);
34234  unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0);
34235  binary_functor_t f = reinterpret_cast<binary_functor_t>(0);
34236 
34237  if (!valid_operator(o0,u0))
34238  return error_node();
34239  else if (!valid_operator(o1,u1))
34240  return error_node();
34241  else if (!valid_operator(operation,f))
34242  return error_node();
34243 
34244  expression_node_ptr result = error_node();
34245 
34246  if (
34247  (details::e_neg == o0) &&
34248  (details::e_neg == o1)
34249  )
34250  {
34251  switch (operation)
34252  {
34253  // (-v0 + -v1) --> -(v0 + v1)
34254  case details::e_add : result = (*this)(details::e_neg,
34255  node_allocator_->
34256  allocate_rr<typename details::
34257  vov_node<Type,details::add_op<Type> > >(v0, v1));
34258  exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n"));
34259  break;
34260 
34261  // (-v0 - -v1) --> (v1 - v0)
34262  case details::e_sub : result = node_allocator_->
34263  allocate_rr<typename details::
34264  vov_node<Type,details::sub_op<Type> > >(v1, v0);
34265  exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n"));
34266  break;
34267 
34268  // (-v0 * -v1) --> (v0 * v1)
34269  case details::e_mul : result = node_allocator_->
34270  allocate_rr<typename details::
34271  vov_node<Type,details::mul_op<Type> > >(v0, v1);
34272  exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n"));
34273  break;
34274 
34275  // (-v0 / -v1) --> (v0 / v1)
34276  case details::e_div : result = node_allocator_->
34277  allocate_rr<typename details::
34278  vov_node<Type,details::div_op<Type> > >(v0, v1);
34279  exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n"));
34280  break;
34281 
34282  default : break;
34283  }
34284  }
34285 
34286  if (0 == result)
34287  {
34288  result = node_allocator_->
34289  allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f);
34290  }
34291 
34292  details::free_all_nodes(*node_allocator_,branch);
34293  return result;
34294  }
34295 
34296  #undef basic_opr_switch_statements
34297  #undef extended_opr_switch_statements
34298  #undef unary_opr_switch_statements
34299 
34300  #ifndef exprtk_disable_string_capabilities
34301 
34302  #define string_opr_switch_statements \
34303  case_stmt(details:: e_lt ,details:: lt_op) \
34304  case_stmt(details:: e_lte ,details:: lte_op) \
34305  case_stmt(details:: e_gt ,details:: gt_op) \
34306  case_stmt(details:: e_gte ,details:: gte_op) \
34307  case_stmt(details:: e_eq ,details:: eq_op) \
34308  case_stmt(details:: e_ne ,details:: ne_op) \
34309  case_stmt(details::e_in ,details:: in_op) \
34310  case_stmt(details::e_like ,details:: like_op) \
34311  case_stmt(details::e_ilike,details::ilike_op) \
34312 
34313  template <typename T0, typename T1>
34315  T0 s0, T1 s1,
34316  range_t rp0)
34317  {
34318  switch (opr)
34319  {
34320  #define case_stmt(op0,op1) \
34321  case op0 : return node_allocator_-> \
34322  allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34323  (s0, s1, rp0); \
34324 
34326  #undef case_stmt
34327  default : return error_node();
34328  }
34329  }
34330 
34331  template <typename T0, typename T1>
34333  T0 s0, T1 s1,
34334  range_t rp1)
34335  {
34336  switch (opr)
34337  {
34338  #define case_stmt(op0,op1) \
34339  case op0 : return node_allocator_-> \
34340  allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34341  (s0, s1, rp1); \
34342 
34344  #undef case_stmt
34345  default : return error_node();
34346  }
34347  }
34348 
34349  template <typename T0, typename T1>
34351  T0 s0, T1 s1,
34352  range_t rp0, range_t rp1)
34353  {
34354  switch (opr)
34355  {
34356  #define case_stmt(op0,op1) \
34357  case op0 : return node_allocator_-> \
34358  allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \
34359  (s0, s1, rp0, rp1); \
34360 
34362  #undef case_stmt
34363  default : return error_node();
34364  }
34365  }
34366 
34367  template <typename T0, typename T1>
34369  {
34370  switch (opr)
34371  {
34372  #define case_stmt(op0,op1) \
34373  case op0 : return node_allocator_-> \
34374  allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \
34375 
34377  #undef case_stmt
34378  default : return error_node();
34379  }
34380  }
34381 
34383  {
34384  std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34385  std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34386 
34387  return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1);
34388  }
34389 
34391  {
34392  std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34393  std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34394  range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34395 
34396  static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34397 
34398  free_node(*node_allocator_,branch[0]);
34399 
34400  return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0);
34401  }
34402 
34404  {
34405  std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34406  std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34407  range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34408 
34409  static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34410 
34411  free_node(*node_allocator_,branch[1]);
34412 
34413  return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1);
34414  }
34415 
34417  {
34418  std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref ();
34419  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34420  range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34421 
34422  static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34423 
34424  free_node(*node_allocator_,branch[1]);
34425 
34426  return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1);
34427  }
34428 
34430  {
34431  std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref ();
34432  std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref ();
34433  range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range();
34434  range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range();
34435 
34436  static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34437  static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34438 
34439  details::free_node(*node_allocator_,branch[0]);
34440  details::free_node(*node_allocator_,branch[1]);
34441 
34442  return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1);
34443  }
34444 
34446  {
34447  std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34448  std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34449 
34450  details::free_node(*node_allocator_,branch[1]);
34451 
34452  return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1);
34453  }
34454 
34456  {
34457  std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34458  std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34459 
34460  details::free_node(*node_allocator_,branch[0]);
34461 
34462  return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1);
34463  }
34464 
34466  {
34467  std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str ();
34468  std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34469  range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34470 
34471  static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear();
34472 
34473  details::free_node(*node_allocator_,branch[0]);
34474  details::free_node(*node_allocator_,branch[1]);
34475 
34476  return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1);
34477  }
34478 
34480  {
34481  std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34482  std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str ();
34483  range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34484 
34485  static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear();
34486 
34487  details::free_node(*node_allocator_,branch[0]);
34488  details::free_node(*node_allocator_,branch[1]);
34489 
34490  return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0);
34491  }
34492 
34494  {
34495  std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref ();
34496  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34497  range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range();
34498  range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34499 
34500  static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear();
34501  static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34502 
34503  details::free_node(*node_allocator_,branch[0]);
34504  details::free_node(*node_allocator_,branch[1]);
34505 
34506  return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1);
34507  }
34508 
34510  {
34511  const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34512  const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34513 
34514  expression_node_ptr result = error_node();
34515 
34516  if (details::e_add == opr)
34517  result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
34518  else if (details::e_in == opr)
34519  result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1));
34520  else if (details::e_like == opr)
34521  result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1));
34522  else if (details::e_ilike == opr)
34523  result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
34524  else
34525  {
34526  expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1);
34527 
34528  const Type v = temp->value();
34529 
34530  details::free_node(*node_allocator_,temp);
34531 
34532  result = node_allocator_->allocate<literal_node_t>(v);
34533  }
34534 
34535  details::free_all_nodes(*node_allocator_,branch);
34536 
34537  return result;
34538  }
34539 
34541  {
34542  const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str ();
34543  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34544  range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34545 
34546  static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34547 
34548  free_node(*node_allocator_,branch[0]);
34549  free_node(*node_allocator_,branch[1]);
34550 
34551  return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1);
34552  }
34553 
34555  {
34556  std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34557  std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref ();
34558  range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34559 
34560  static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34561 
34562  free_node(*node_allocator_,branch[0]);
34563 
34564  return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0);
34565  }
34566 
34568  {
34569  const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34570  std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref ();
34571  range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34572  range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range();
34573 
34574  static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34575  static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear();
34576 
34577  free_node(*node_allocator_,branch[0]);
34578  free_node(*node_allocator_,branch[1]);
34579 
34580  return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1);
34581  }
34582 
34584  {
34585  std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34586  const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str ();
34587  range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34588 
34589  static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34590 
34591  details::free_all_nodes(*node_allocator_,branch);
34592 
34593  return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0);
34594  }
34595 
34597  {
34598  std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str ();
34599  std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str ();
34600  range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range();
34601  range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range();
34602 
34603  static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear();
34604  static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear();
34605 
34606  details::free_all_nodes(*node_allocator_,branch);
34607 
34608  return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1);
34609  }
34610 
34612  {
34613  switch (opr)
34614  {
34615  #define case_stmt(op0,op1) \
34616  case op0 : return node_allocator_-> \
34617  allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \
34618  (opr, branch[0], branch[1]); \
34619 
34621  #undef case_stmt
34622  default : return error_node();
34623  }
34624  }
34625  #endif
34626 
34627  #ifndef exprtk_disable_string_capabilities
34629  {
34630  if ((0 == branch[0]) || (0 == branch[1]))
34631  {
34632  details::free_all_nodes(*node_allocator_,branch);
34633 
34634  return error_node();
34635  }
34636 
34637  const bool b0_is_s = details::is_string_node (branch[0]);
34638  const bool b0_is_cs = details::is_const_string_node (branch[0]);
34639  const bool b0_is_sr = details::is_string_range_node (branch[0]);
34640  const bool b0_is_csr = details::is_const_string_range_node(branch[0]);
34641 
34642  const bool b1_is_s = details::is_string_node (branch[1]);
34643  const bool b1_is_cs = details::is_const_string_node (branch[1]);
34644  const bool b1_is_sr = details::is_string_range_node (branch[1]);
34645  const bool b1_is_csr = details::is_const_string_range_node(branch[1]);
34646 
34647  const bool b0_is_gen = details::is_string_assignment_node (branch[0]) ||
34649  details::is_string_concat_node (branch[0]) ||
34650  details::is_string_function_node (branch[0]) ||
34651  details::is_string_condition_node (branch[0]) ||
34652  details::is_string_ccondition_node (branch[0]) ||
34653  details::is_string_vararg_node (branch[0]) ;
34654 
34655  const bool b1_is_gen = details::is_string_assignment_node (branch[1]) ||
34657  details::is_string_concat_node (branch[1]) ||
34658  details::is_string_function_node (branch[1]) ||
34659  details::is_string_condition_node (branch[1]) ||
34660  details::is_string_ccondition_node (branch[1]) ||
34661  details::is_string_vararg_node (branch[1]) ;
34662 
34663  if (details::e_add == opr)
34664  {
34665  if (!b0_is_cs || !b1_is_cs)
34666  {
34667  return synthesize_expression<string_concat_node_t,2>(opr,branch);
34668  }
34669  }
34670 
34671  if (b0_is_gen || b1_is_gen)
34672  {
34673  return synthesize_strogen_expression(opr,branch);
34674  }
34675  else if (b0_is_s)
34676  {
34677  if (b1_is_s ) return synthesize_sos_expression (opr,branch);
34678  else if (b1_is_cs ) return synthesize_socs_expression (opr,branch);
34679  else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch);
34680  else if (b1_is_csr) return synthesize_socsr_expression (opr,branch);
34681  }
34682  else if (b0_is_cs)
34683  {
34684  if (b1_is_s ) return synthesize_csos_expression (opr,branch);
34685  else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch);
34686  else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch);
34687  else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch);
34688  }
34689  else if (b0_is_sr)
34690  {
34691  if (b1_is_s ) return synthesize_sros_expression (opr,branch);
34692  else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch);
34693  else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch);
34694  else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch);
34695  }
34696  else if (b0_is_csr)
34697  {
34698  if (b1_is_s ) return synthesize_csros_expression (opr,branch);
34699  else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch);
34700  else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch);
34701  else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch);
34702  }
34703 
34704  return error_node();
34705  }
34706  #else
34707  inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2])
34708  {
34709  details::free_all_nodes(*node_allocator_,branch);
34710  return error_node();
34711  }
34712  #endif
34713 
34714  #ifndef exprtk_disable_string_capabilities
34716  {
34717  if (details::e_inrange != opr)
34718  return error_node();
34719  else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
34720  {
34721  details::free_all_nodes(*node_allocator_,branch);
34722 
34723  return error_node();
34724  }
34725  else if (
34726  details::is_const_string_node(branch[0]) &&
34727  details::is_const_string_node(branch[1]) &&
34729  )
34730  {
34731  const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34732  const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34733  const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34734 
34735  const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
34736 
34737  details::free_all_nodes(*node_allocator_,branch);
34738 
34739  return node_allocator_->allocate_c<details::literal_node<Type> >(v);
34740  }
34741  else if (
34742  details::is_string_node(branch[0]) &&
34743  details::is_string_node(branch[1]) &&
34744  details::is_string_node(branch[2])
34745  )
34746  {
34747  std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref();
34748  std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref();
34749  std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref();
34750 
34752 
34753  return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2);
34754  }
34755  else if (
34756  details::is_const_string_node(branch[0]) &&
34757  details::is_string_node(branch[1]) &&
34759  )
34760  {
34761  std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34762  std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34763  std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34764 
34766 
34767  details::free_node(*node_allocator_,branch[0]);
34768  details::free_node(*node_allocator_,branch[2]);
34769 
34770  return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2);
34771  }
34772  else if (
34773  details::is_string_node(branch[0]) &&
34774  details::is_const_string_node(branch[1]) &&
34775  details::is_string_node(branch[2])
34776  )
34777  {
34778  std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34779  std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str();
34780  std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34781 
34783 
34784  details::free_node(*node_allocator_,branch[1]);
34785 
34786  return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2);
34787  }
34788  else if (
34789  details::is_string_node(branch[0]) &&
34790  details::is_string_node(branch[1]) &&
34792  )
34793  {
34794  std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref();
34795  std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34796  std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str();
34797 
34799 
34800  details::free_node(*node_allocator_,branch[2]);
34801 
34802  return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2);
34803  }
34804  else if (
34805  details::is_const_string_node(branch[0]) &&
34806  details:: is_string_node(branch[1]) &&
34807  details:: is_string_node(branch[2])
34808  )
34809  {
34810  std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str();
34811  std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref();
34812  std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref();
34813 
34815 
34816  details::free_node(*node_allocator_,branch[0]);
34817 
34818  return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2);
34819  }
34820  else
34821  return error_node();
34822  }
34823  #else
34824  inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3])
34825  {
34826  details::free_all_nodes(*node_allocator_,branch);
34827  return error_node();
34828  }
34829  #endif
34830 
34832  {
34833  /*
34834  Note: The following are the type promotion rules
34835  that relate to operations that include 'null':
34836  0. null ==/!= null --> true false
34837  1. null operation null --> null
34838  2. x ==/!= null --> true/false
34839  3. null ==/!= x --> true/false
34840  4. x operation null --> x
34841  5. null operation x --> x
34842  */
34843 
34844  typedef typename details::null_eq_node<T> nulleq_node_t;
34845 
34846  const bool b0_null = details::is_null_node(branch[0]);
34847  const bool b1_null = details::is_null_node(branch[1]);
34848 
34849  if (b0_null && b1_null)
34850  {
34851  expression_node_ptr result = error_node();
34852 
34853  if (details::e_eq == operation)
34854  result = node_allocator_->allocate_c<literal_node_t>(T(1));
34855  else if (details::e_ne == operation)
34856  result = node_allocator_->allocate_c<literal_node_t>(T(0));
34857 
34858  if (result)
34859  {
34860  details::free_node(*node_allocator_,branch[0]);
34861  details::free_node(*node_allocator_,branch[1]);
34862 
34863  return result;
34864  }
34865 
34866  details::free_node(*node_allocator_,branch[1]);
34867 
34868  return branch[0];
34869  }
34870  else if (details::e_eq == operation)
34871  {
34872  expression_node_ptr result = node_allocator_->
34873  allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true);
34874 
34875  details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34876 
34877  return result;
34878  }
34879  else if (details::e_ne == operation)
34880  {
34881  expression_node_ptr result = node_allocator_->
34882  allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false);
34883 
34884  details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]);
34885 
34886  return result;
34887  }
34888  else if (b0_null)
34889  {
34890  details::free_node(*node_allocator_,branch[0]);
34891  branch[0] = branch[1];
34892  branch[1] = error_node();
34893  }
34894  else if (b1_null)
34895  {
34896  details::free_node(*node_allocator_,branch[1]);
34897  branch[1] = error_node();
34898  }
34899 
34900  if (
34901  (details::e_add == operation) || (details::e_sub == operation) ||
34902  (details::e_mul == operation) || (details::e_div == operation) ||
34903  (details::e_mod == operation) || (details::e_pow == operation)
34904  )
34905  {
34906  return branch[0];
34907  }
34908  else if (
34909  (details::e_lt == operation) || (details::e_lte == operation) ||
34910  (details::e_gt == operation) || (details::e_gte == operation) ||
34911  (details::e_and == operation) || (details::e_nand == operation) ||
34912  (details::e_or == operation) || (details::e_nor == operation) ||
34913  (details::e_xor == operation) || (details::e_xnor == operation) ||
34914  (details::e_in == operation) || (details::e_like == operation) ||
34915  (details::e_ilike == operation)
34916  )
34917  {
34918  return node_allocator_->allocate_c<literal_node_t>(T(0));
34919  }
34920 
34921  details::free_node(*node_allocator_,branch[0]);
34922 
34923  return node_allocator_->allocate<details::null_node<Type> >();
34924  }
34925 
34926  template <typename NodeType, std::size_t N>
34928  {
34929  if (
34930  (details::e_in == operation) ||
34931  (details::e_like == operation) ||
34932  (details::e_ilike == operation)
34933  )
34934  {
34935  free_all_nodes(*node_allocator_,branch);
34936 
34937  return error_node();
34938  }
34939  else if (!details::all_nodes_valid<N>(branch))
34940  {
34941  free_all_nodes(*node_allocator_,branch);
34942 
34943  return error_node();
34944  }
34945  else if ((details::e_default != operation))
34946  {
34947  // Attempt simple constant folding optimisation.
34948  expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
34949 
34950  if (is_constant_foldable<N>(branch))
34951  {
34952  Type v = expression_point->value();
34953  details::free_node(*node_allocator_,expression_point);
34954 
34955  return node_allocator_->allocate<literal_node_t>(v);
34956  }
34957  else
34958  return expression_point;
34959  }
34960  else
34961  return error_node();
34962  }
34963 
34964  template <typename NodeType, std::size_t N>
34966  {
34967  if (!details::all_nodes_valid<N>(branch))
34968  {
34969  free_all_nodes(*node_allocator_,branch);
34970 
34971  return error_node();
34972  }
34973 
34974  typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
34975 
34976  // Attempt simple constant folding optimisation.
34977 
34978  expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
34979  function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point);
34980 
34981  if (0 == func_node_ptr)
34982  {
34983  free_all_nodes(*node_allocator_,branch);
34984 
34985  return error_node();
34986  }
34987  else
34988  func_node_ptr->init_branches(branch);
34989 
34990  if (is_constant_foldable<N>(branch) && !f->has_side_effects())
34991  {
34992  Type v = expression_point->value();
34993  details::free_node(*node_allocator_,expression_point);
34994 
34995  return node_allocator_->allocate<literal_node_t>(v);
34996  }
34997 
34998  parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)");
34999 
35000  return expression_point;
35001  }
35002 
35012  };
35013 
35014  inline void set_error(const parser_error::type& error_type)
35015  {
35016  error_list_.push_back(error_type);
35017  }
35018 
35019  inline void remove_last_error()
35020  {
35021  if (!error_list_.empty())
35022  {
35023  error_list_.pop_back();
35024  }
35025  }
35026 
35027  inline void set_synthesis_error(const std::string& synthesis_error_message)
35028  {
35029  if (synthesis_error_.empty())
35030  {
35031  synthesis_error_ = synthesis_error_message;
35032  }
35033  }
35034 
35036  {
35037  for (std::size_t i = 0; i < sem_.size(); ++i)
35038  {
35039  scope_element& se = sem_.get_element(i);
35040 
35041  if (
35042  (scope_element::e_variable == se.type) ||
35043  (scope_element::e_vecelem == se.type)
35044  )
35045  {
35046  if (se.var_node)
35047  {
35048  e.register_local_var(se.var_node);
35049  }
35050 
35051  if (se.data)
35052  {
35053  e.register_local_data(se.data, 1, 0);
35054  }
35055  }
35056  else if (scope_element::e_vector == se.type)
35057  {
35058  if (se.vec_node)
35059  {
35060  e.register_local_var(se.vec_node);
35061  }
35062 
35063  if (se.data)
35064  {
35065  e.register_local_data(se.data, se.size, 1);
35066  }
35067  }
35068  #ifndef exprtk_disable_string_capabilities
35069  else if (scope_element::e_string == se.type)
35070  {
35071  if (se.str_node)
35072  {
35073  e.register_local_var(se.str_node);
35074  }
35075 
35076  if (se.data)
35077  {
35078  e.register_local_data(se.data, se.size, 2);
35079  }
35080  }
35081  #endif
35082 
35083  se.var_node = 0;
35084  se.vec_node = 0;
35085  #ifndef exprtk_disable_string_capabilities
35086  se.str_node = 0;
35087  #endif
35088  se.data = 0;
35089  se.ref_count = 0;
35090  se.active = false;
35091  }
35092  }
35093 
35095  {
35096  e.register_return_results(results_context_);
35097  results_context_ = 0;
35098  }
35099 
35101  {
35102  #define register_unary_op(Op,UnaryFunctor) \
35103  m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \
35104 
35105  register_unary_op(details:: e_abs, details:: abs_op)
35106  register_unary_op(details:: e_acos, details:: acos_op)
35107  register_unary_op(details::e_acosh, details::acosh_op)
35108  register_unary_op(details:: e_asin, details:: asin_op)
35109  register_unary_op(details::e_asinh, details::asinh_op)
35110  register_unary_op(details::e_atanh, details::atanh_op)
35111  register_unary_op(details:: e_ceil, details:: ceil_op)
35112  register_unary_op(details:: e_cos, details:: cos_op)
35113  register_unary_op(details:: e_cosh, details:: cosh_op)
35114  register_unary_op(details:: e_exp, details:: exp_op)
35115  register_unary_op(details::e_expm1, details::expm1_op)
35116  register_unary_op(details::e_floor, details::floor_op)
35117  register_unary_op(details:: e_log, details:: log_op)
35118  register_unary_op(details::e_log10, details::log10_op)
35119  register_unary_op(details:: e_log2, details:: log2_op)
35120  register_unary_op(details::e_log1p, details::log1p_op)
35121  register_unary_op(details:: e_neg, details:: neg_op)
35122  register_unary_op(details:: e_pos, details:: pos_op)
35123  register_unary_op(details::e_round, details::round_op)
35124  register_unary_op(details:: e_sin, details:: sin_op)
35125  register_unary_op(details:: e_sinc, details:: sinc_op)
35126  register_unary_op(details:: e_sinh, details:: sinh_op)
35127  register_unary_op(details:: e_sqrt, details:: sqrt_op)
35128  register_unary_op(details:: e_tan, details:: tan_op)
35129  register_unary_op(details:: e_tanh, details:: tanh_op)
35130  register_unary_op(details:: e_cot, details:: cot_op)
35131  register_unary_op(details:: e_sec, details:: sec_op)
35132  register_unary_op(details:: e_csc, details:: csc_op)
35133  register_unary_op(details:: e_r2d, details:: r2d_op)
35134  register_unary_op(details:: e_d2r, details:: d2r_op)
35135  register_unary_op(details:: e_d2g, details:: d2g_op)
35136  register_unary_op(details:: e_g2d, details:: g2d_op)
35137  register_unary_op(details:: e_notl, details:: notl_op)
35138  register_unary_op(details:: e_sgn, details:: sgn_op)
35139  register_unary_op(details:: e_erf, details:: erf_op)
35140  register_unary_op(details:: e_erfc, details:: erfc_op)
35141  register_unary_op(details:: e_ncdf, details:: ncdf_op)
35142  register_unary_op(details:: e_frac, details:: frac_op)
35143  register_unary_op(details::e_trunc, details::trunc_op)
35144  #undef register_unary_op
35145  }
35146 
35148  {
35149  typedef typename binary_op_map_t::value_type value_type;
35150 
35151  #define register_binary_op(Op,BinaryFunctor) \
35152  m.insert(value_type(Op,BinaryFunctor<T>::process)); \
35153 
35160  register_binary_op(details:: e_lt, details:: lt_op)
35162  register_binary_op(details:: e_gt, details:: gt_op)
35164  register_binary_op(details:: e_eq, details:: eq_op)
35165  register_binary_op(details:: e_ne, details:: ne_op)
35168  register_binary_op(details:: e_or, details:: or_op)
35172  #undef register_binary_op
35173  }
35174 
35176  {
35178 
35179  #define register_binary_op(Op,BinaryFunctor) \
35180  m.insert(value_type(BinaryFunctor<T>::process,Op)); \
35181 
35188  register_binary_op(details:: e_lt, details:: lt_op)
35190  register_binary_op(details:: e_gt, details:: gt_op)
35192  register_binary_op(details:: e_eq, details:: eq_op)
35193  register_binary_op(details:: e_ne, details:: ne_op)
35196  register_binary_op(details:: e_or, details:: or_op)
35200  #undef register_binary_op
35201  }
35202 
35203  inline void load_sf3_map(sf3_map_t& sf3_map)
35204  {
35205  typedef std::pair<trinary_functor_t,details::operator_type> pair_t;
35206 
35207  #define register_sf3(Op) \
35208  sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35209 
35218  #undef register_sf3
35219 
35220  #define register_sf3_extid(Id, Op) \
35221  sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35222 
35223  register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t)
35224  #undef register_sf3_extid
35225  }
35226 
35227  inline void load_sf4_map(sf4_map_t& sf4_map)
35228  {
35229  typedef std::pair<quaternary_functor_t,details::operator_type> pair_t;
35230 
35231  #define register_sf4(Op) \
35232  sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \
35233 
35243  #undef register_sf4
35244 
35245  #define register_sf4ext(Op) \
35246  sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \
35247 
35264  #undef register_sf4ext
35265  }
35266 
35268  {
35269  if (0 == results_context_)
35270  {
35271  results_context_ = new results_context_t();
35272  }
35273 
35274  return (*results_context_);
35275  }
35276 
35277  inline void return_cleanup()
35278  {
35279  #ifndef exprtk_disable_return_statement
35280  if (results_context_)
35281  {
35282  delete results_context_;
35283  results_context_ = 0;
35284  }
35285 
35286  state_.return_stmt_present = false;
35287  #endif
35288  }
35289 
35290  private:
35291 
35292  parser(const parser<T>&);
35293  parser<T>& operator=(const parser<T>&);
35294 
35295  settings_store settings_;
35296  expression_generator<T> expression_generator_;
35298  symtab_store symtab_store_;
35299  dependent_entity_collector dec_;
35300  std::deque<parser_error::type> error_list_;
35301  std::deque<bool> brkcnt_list_;
35302  parser_state state_;
35305  unknown_symbol_resolver* unknown_symbol_resolver_;
35306  unknown_symbol_resolver default_usr_;
35314  scope_element_manager sem_;
35315 
35317 
35326 
35327  template <typename ParserType>
35328  friend void details::disable_type_checking(ParserType& p);
35329  };
35330 
35331  template <typename Allocator,
35332  template <typename, typename> class Sequence>
35333  inline bool collect_variables(const std::string& expr_str,
35334  Sequence<std::string, Allocator>& symbol_list)
35335  {
35336  typedef double T;
35339  typedef exprtk::parser<T> parser_t;
35340  typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
35341 
35344  parser_t parser;
35345 
35347 
35349  parser.dec().collect_variables() = true;
35350 
35351  if (!parser.compile(expr_str, expression))
35352  return false;
35353 
35354  std::deque<symbol_t> symb_list;
35355 
35356  parser.dec().symbols(symb_list);
35357 
35358  for (std::size_t i = 0; i < symb_list.size(); ++i)
35359  {
35360  symbol_list.push_back(symb_list[i].first);
35361  }
35362 
35363  return true;
35364  }
35365 
35366  template <typename T,
35367  typename Allocator,
35368  template <typename, typename> class Sequence>
35369  inline bool collect_variables(const std::string& expr_str,
35370  exprtk::symbol_table<T>& extrnl_symbol_table,
35371  Sequence<std::string, Allocator>& symbol_list)
35372  {
35375  typedef exprtk::parser<T> parser_t;
35376  typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35377 
35380  parser_t parser;
35381 
35383  expression.register_symbol_table(extrnl_symbol_table);
35384 
35386  parser.dec().collect_variables() = true;
35387 
35389 
35390  if (!parser.compile(expr_str, expression))
35391  return false;
35392 
35393  std::deque<symbol_t> symb_list;
35394 
35395  parser.dec().symbols(symb_list);
35396 
35397  for (std::size_t i = 0; i < symb_list.size(); ++i)
35398  {
35399  symbol_list.push_back(symb_list[i].first);
35400  }
35401 
35402  return true;
35403  }
35404 
35405  template <typename Allocator,
35406  template <typename, typename> class Sequence>
35407  inline bool collect_functions(const std::string& expr_str,
35408  Sequence<std::string, Allocator>& symbol_list)
35409  {
35410  typedef double T;
35413  typedef exprtk::parser<T> parser_t;
35414  typedef parser_t::dependent_entity_collector::symbol_t symbol_t;
35415 
35418  parser_t parser;
35419 
35421 
35423  parser.dec().collect_functions() = true;
35424 
35425  if (!parser.compile(expr_str, expression))
35426  return false;
35427 
35428  std::deque<symbol_t> symb_list;
35429 
35430  parser.dec().symbols(symb_list);
35431 
35432  for (std::size_t i = 0; i < symb_list.size(); ++i)
35433  {
35434  symbol_list.push_back(symb_list[i].first);
35435  }
35436 
35437  return true;
35438  }
35439 
35440  template <typename T,
35441  typename Allocator,
35442  template <typename, typename> class Sequence>
35443  inline bool collect_functions(const std::string& expr_str,
35444  exprtk::symbol_table<T>& extrnl_symbol_table,
35445  Sequence<std::string, Allocator>& symbol_list)
35446  {
35449  typedef exprtk::parser<T> parser_t;
35450  typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t;
35451 
35454  parser_t parser;
35455 
35457  expression.register_symbol_table(extrnl_symbol_table);
35458 
35460  parser.dec().collect_functions() = true;
35461 
35463 
35464  if (!parser.compile(expr_str, expression))
35465  return false;
35466 
35467  std::deque<symbol_t> symb_list;
35468 
35469  parser.dec().symbols(symb_list);
35470 
35471  for (std::size_t i = 0; i < symb_list.size(); ++i)
35472  {
35473  symbol_list.push_back(symb_list[i].first);
35474  }
35475 
35476  return true;
35477  }
35478 
35479  template <typename T>
35480  inline T integrate(const expression<T>& e,
35481  T& x,
35482  const T& r0, const T& r1,
35483  const std::size_t number_of_intervals = 1000000)
35484  {
35485  if (r0 > r1)
35486  return T(0);
35487 
35488  const T h = (r1 - r0) / (T(2) * number_of_intervals);
35489  T total_area = T(0);
35490 
35491  for (std::size_t i = 0; i < number_of_intervals; ++i)
35492  {
35493  x = r0 + T(2) * i * h;
35494  const T y0 = e.value(); x += h;
35495  const T y1 = e.value(); x += h;
35496  const T y2 = e.value(); x += h;
35497  total_area += h * (y0 + T(4) * y1 + y2) / T(3);
35498  }
35499 
35500  return total_area;
35501  }
35502 
35503  template <typename T>
35504  inline T integrate(const expression<T>& e,
35505  const std::string& variable_name,
35506  const T& r0, const T& r1,
35507  const std::size_t number_of_intervals = 1000000)
35508  {
35509  const symbol_table<T>& sym_table = e.get_symbol_table();
35510 
35511  if (!sym_table.valid())
35512  return std::numeric_limits<T>::quiet_NaN();
35513 
35514  details::variable_node<T>* var = sym_table.get_variable(variable_name);
35515 
35516  if (var)
35517  {
35518  T& x = var->ref();
35519  T x_original = x;
35520  T result = integrate(e, x, r0, r1, number_of_intervals);
35521  x = x_original;
35522 
35523  return result;
35524  }
35525  else
35526  return std::numeric_limits<T>::quiet_NaN();
35527  }
35528 
35529  template <typename T>
35530  inline T derivative(const expression<T>& e,
35531  T& x,
35532  const T& h = T(0.00000001))
35533  {
35534  const T x_init = x;
35535  const T _2h = T(2) * h;
35536 
35537  x = x_init + _2h;
35538  const T y0 = e.value();
35539  x = x_init + h;
35540  const T y1 = e.value();
35541  x = x_init - h;
35542  const T y2 = e.value();
35543  x = x_init - _2h;
35544  const T y3 = e.value();
35545  x = x_init;
35546 
35547  return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h);
35548  }
35549 
35550  template <typename T>
35552  T& x,
35553  const T& h = T(0.00001))
35554  {
35555  const T x_init = x;
35556  const T _2h = T(2) * h;
35557 
35558  const T y = e.value();
35559  x = x_init + _2h;
35560  const T y0 = e.value();
35561  x = x_init + h;
35562  const T y1 = e.value();
35563  x = x_init - h;
35564  const T y2 = e.value();
35565  x = x_init - _2h;
35566  const T y3 = e.value();
35567  x = x_init;
35568 
35569  return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h);
35570  }
35571 
35572  template <typename T>
35574  T& x,
35575  const T& h = T(0.0001))
35576  {
35577  const T x_init = x;
35578  const T _2h = T(2) * h;
35579 
35580  x = x_init + _2h;
35581  const T y0 = e.value();
35582  x = x_init + h;
35583  const T y1 = e.value();
35584  x = x_init - h;
35585  const T y2 = e.value();
35586  x = x_init - _2h;
35587  const T y3 = e.value();
35588  x = x_init;
35589 
35590  return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h);
35591  }
35592 
35593  template <typename T>
35594  inline T derivative(const expression<T>& e,
35595  const std::string& variable_name,
35596  const T& h = T(0.00000001))
35597  {
35598  const symbol_table<T>& sym_table = e.get_symbol_table();
35599 
35600  if (!sym_table.valid())
35601  {
35602  return std::numeric_limits<T>::quiet_NaN();
35603  }
35604 
35605  details::variable_node<T>* var = sym_table.get_variable(variable_name);
35606 
35607  if (var)
35608  {
35609  T& x = var->ref();
35610  T x_original = x;
35611  T result = derivative(e, x, h);
35612  x = x_original;
35613 
35614  return result;
35615  }
35616  else
35617  return std::numeric_limits<T>::quiet_NaN();
35618  }
35619 
35620  template <typename T>
35622  const std::string& variable_name,
35623  const T& h = T(0.00001))
35624  {
35625  const symbol_table<T>& sym_table = e.get_symbol_table();
35626 
35627  if (!sym_table.valid())
35628  {
35629  return std::numeric_limits<T>::quiet_NaN();
35630  }
35631 
35632  details::variable_node<T>* var = sym_table.get_variable(variable_name);
35633 
35634  if (var)
35635  {
35636  T& x = var->ref();
35637  const T x_original = x;
35638  const T result = second_derivative(e, x, h);
35639  x = x_original;
35640 
35641  return result;
35642  }
35643  else
35644  return std::numeric_limits<T>::quiet_NaN();
35645  }
35646 
35647  template <typename T>
35649  const std::string& variable_name,
35650  const T& h = T(0.0001))
35651  {
35652  const symbol_table<T>& sym_table = e.get_symbol_table();
35653 
35654  if (!sym_table.valid())
35655  {
35656  return std::numeric_limits<T>::quiet_NaN();
35657  }
35658 
35659  details::variable_node<T>* var = sym_table.get_variable(variable_name);
35660 
35661  if (var)
35662  {
35663  T& x = var->ref();
35664  const T x_original = x;
35665  const T result = third_derivative(e, x, h);
35666  x = x_original;
35667 
35668  return result;
35669  }
35670  else
35671  return std::numeric_limits<T>::quiet_NaN();
35672  }
35673 
35674  /*
35675  Note: The following 'compute' routines are simple helpers,
35676  for quickly setting up the required pieces of code in order
35677  to evaluate an expression. By virtue of how they operate
35678  there will be an overhead with regards to their setup and
35679  teardown and hence should not be used in time critical
35680  sections of code.
35681  Furthermore they only assume a small sub set of variables,
35682  no string variables or user defined functions.
35683  */
35684  template <typename T>
35685  inline bool compute(const std::string& expression_string, T& result)
35686  {
35687  // No variables
35690 
35693 
35694  parser<T> parser;
35695 
35696  if (parser.compile(expression_string,expression))
35697  {
35698  result = expression.value();
35699 
35700  return true;
35701  }
35702  else
35703  return false;
35704  }
35705 
35706  template <typename T>
35707  inline bool compute(const std::string& expression_string,
35708  const T& x,
35709  T& result)
35710  {
35711  // Only 'x'
35712  static const std::string x_var("x");
35713 
35716  symbol_table.add_constant(x_var,x);
35717 
35720 
35721  parser<T> parser;
35722 
35723  if (parser.compile(expression_string,expression))
35724  {
35725  result = expression.value();
35726 
35727  return true;
35728  }
35729  else
35730  return false;
35731  }
35732 
35733  template <typename T>
35734  inline bool compute(const std::string& expression_string,
35735  const T&x, const T& y,
35736  T& result)
35737  {
35738  // Only 'x' and 'y'
35739  static const std::string x_var("x");
35740  static const std::string y_var("y");
35741 
35744  symbol_table.add_constant(x_var,x);
35745  symbol_table.add_constant(y_var,y);
35746 
35749 
35750  parser<T> parser;
35751 
35752  if (parser.compile(expression_string,expression))
35753  {
35754  result = expression.value();
35755 
35756  return true;
35757  }
35758  else
35759  return false;
35760  }
35761 
35762  template <typename T>
35763  inline bool compute(const std::string& expression_string,
35764  const T& x, const T& y, const T& z,
35765  T& result)
35766  {
35767  // Only 'x', 'y' or 'z'
35768  static const std::string x_var("x");
35769  static const std::string y_var("y");
35770  static const std::string z_var("z");
35771 
35774  symbol_table.add_constant(x_var,x);
35775  symbol_table.add_constant(y_var,y);
35776  symbol_table.add_constant(z_var,z);
35777 
35780 
35781  parser<T> parser;
35782 
35783  if (parser.compile(expression_string,expression))
35784  {
35785  result = expression.value();
35786 
35787  return true;
35788  }
35789  else
35790  return false;
35791  }
35792 
35793  template <typename T, std::size_t N>
35794  class polynomial : public ifunction<T>
35795  {
35796  private:
35797 
35798  template <typename Type, std::size_t NumberOfCoefficients>
35799  struct poly_impl { };
35800 
35801  template <typename Type>
35802  struct poly_impl <Type,12>
35803  {
35804  static inline T evaluate(const Type x,
35805  const Type c12, const Type c11, const Type c10, const Type c9, const Type c8,
35806  const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
35807  const Type c2, const Type c1, const Type c0)
35808  {
35809  // 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
35810  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);
35811  }
35812  };
35813 
35814  template <typename Type>
35815  struct poly_impl <Type,11>
35816  {
35817  static inline T evaluate(const Type x,
35818  const Type c11, const Type c10, const Type c9, const Type c8, const Type c7,
35819  const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
35820  const Type c1, const Type c0)
35821  {
35822  // 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
35823  return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35824  }
35825  };
35826 
35827  template <typename Type>
35828  struct poly_impl <Type,10>
35829  {
35830  static inline T evaluate(const Type x,
35831  const Type c10, const Type c9, const Type c8, const Type c7, const Type c6,
35832  const Type c5, const Type c4, const Type c3, const Type c2, const Type c1,
35833  const Type c0)
35834  {
35835  // 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
35836  return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35837  }
35838  };
35839 
35840  template <typename Type>
35841  struct poly_impl <Type,9>
35842  {
35843  static inline T evaluate(const Type x,
35844  const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
35845  const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
35846  {
35847  // 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
35848  return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35849  }
35850  };
35851 
35852  template <typename Type>
35853  struct poly_impl <Type,8>
35854  {
35855  static inline T evaluate(const Type x,
35856  const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
35857  const Type c3, const Type c2, const Type c1, const Type c0)
35858  {
35859  // 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
35860  return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35861  }
35862  };
35863 
35864  template <typename Type>
35865  struct poly_impl <Type,7>
35866  {
35867  static inline T evaluate(const Type x,
35868  const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
35869  const Type c2, const Type c1, const Type c0)
35870  {
35871  // 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
35872  return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35873  }
35874  };
35875 
35876  template <typename Type>
35877  struct poly_impl <Type,6>
35878  {
35879  static inline T evaluate(const Type x,
35880  const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
35881  const Type c1, const Type c0)
35882  {
35883  // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35884  return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35885  }
35886  };
35887 
35888  template <typename Type>
35889  struct poly_impl <Type,5>
35890  {
35891  static inline T evaluate(const Type x,
35892  const Type c5, const Type c4, const Type c3, const Type c2,
35893  const Type c1, const Type c0)
35894  {
35895  // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35896  return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
35897  }
35898  };
35899 
35900  template <typename Type>
35901  struct poly_impl <Type,4>
35902  {
35903  static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
35904  {
35905  // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35906  return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
35907  }
35908  };
35909 
35910  template <typename Type>
35911  struct poly_impl <Type,3>
35912  {
35913  static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
35914  {
35915  // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0
35916  return (((c3 * x + c2) * x + c1) * x + c0);
35917  }
35918  };
35919 
35920  template <typename Type>
35921  struct poly_impl <Type,2>
35922  {
35923  static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
35924  {
35925  // p(x) = c_2x^2 + c_1x^1 + c_0x^0
35926  return ((c2 * x + c1) * x + c0);
35927  }
35928  };
35929 
35930  template <typename Type>
35931  struct poly_impl <Type,1>
35932  {
35933  static inline T evaluate(const Type x, const Type c1, const Type c0)
35934  {
35935  // p(x) = c_1x^1 + c_0x^0
35936  return (c1 * x + c0);
35937  }
35938  };
35939 
35940  public:
35941 
35942  using ifunction<T>::operator();
35943 
35945  : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max())
35946  {
35947  disable_has_side_effects(*this);
35948  }
35949 
35950  virtual ~polynomial()
35951  {}
35952 
35953  #define poly_rtrn(NN) \
35954  return (NN != N) ? std::numeric_limits<T>::quiet_NaN() :
35955 
35956  inline virtual T operator() (const T& x, const T& c1, const T& c0)
35957  {
35959  }
35960 
35961  inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0)
35962  {
35963  poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0);
35964  }
35965 
35966  inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
35967  {
35968  poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0);
35969  }
35970 
35971  inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
35972  {
35973  poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0);
35974  }
35975 
35976  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)
35977  {
35978  poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0);
35979  }
35980 
35981  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)
35982  {
35983  poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0);
35984  }
35985 
35986  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)
35987  {
35988  poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0);
35989  }
35990 
35991  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)
35992  {
35993  poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0);
35994  }
35995 
35996  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)
35997  {
35998  poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
35999  }
36000 
36001  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)
36002  {
36003  poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
36004  }
36005 
36006  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)
36007  {
36008  poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
36009  }
36010 
36011  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)
36012  {
36013  poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0);
36014  }
36015 
36016  #undef poly_rtrn
36017 
36018  inline virtual T operator() ()
36019  {
36020  return std::numeric_limits<T>::quiet_NaN();
36021  }
36022 
36023  inline virtual T operator() (const T&)
36024  {
36025  return std::numeric_limits<T>::quiet_NaN();
36026  }
36027 
36028  inline virtual T operator() (const T&, const T&)
36029  {
36030  return std::numeric_limits<T>::quiet_NaN();
36031  }
36032  };
36033 
36034  template <typename T>
36035  class function_compositor
36036  {
36037  public:
36038 
36043 
36044  struct function
36045  {
36046  function()
36047  {}
36048 
36049  function(const std::string& n)
36050  : name_(n)
36051  {}
36052 
36053  function(const std::string& name,
36054  const std::string& expression)
36055  : name_(name),
36056  expression_(expression)
36057  {}
36058 
36059  function(const std::string& name,
36060  const std::string& expression,
36061  const std::string& v0)
36062  : name_(name),
36063  expression_(expression)
36064  {
36065  v_.push_back(v0);
36066  }
36067 
36068  function(const std::string& name,
36069  const std::string& expression,
36070  const std::string& v0, const std::string& v1)
36071  : name_(name),
36072  expression_(expression)
36073  {
36074  v_.push_back(v0); v_.push_back(v1);
36075  }
36076 
36077  function(const std::string& name,
36078  const std::string& expression,
36079  const std::string& v0, const std::string& v1,
36080  const std::string& v2)
36081  : name_(name),
36082  expression_(expression)
36083  {
36084  v_.push_back(v0); v_.push_back(v1);
36085  v_.push_back(v2);
36086  }
36087 
36088  function(const std::string& name,
36089  const std::string& expression,
36090  const std::string& v0, const std::string& v1,
36091  const std::string& v2, const std::string& v3)
36092  : name_(name),
36093  expression_(expression)
36094  {
36095  v_.push_back(v0); v_.push_back(v1);
36096  v_.push_back(v2); v_.push_back(v3);
36097  }
36098 
36099  function(const std::string& name,
36100  const std::string& expression,
36101  const std::string& v0, const std::string& v1,
36102  const std::string& v2, const std::string& v3,
36103  const std::string& v4)
36104  : name_(name),
36105  expression_(expression)
36106  {
36107  v_.push_back(v0); v_.push_back(v1);
36108  v_.push_back(v2); v_.push_back(v3);
36109  v_.push_back(v4);
36110  }
36111 
36112  inline function& name(const std::string& n)
36113  {
36114  name_ = n;
36115  return (*this);
36116  }
36117 
36118  inline function& expression(const std::string& e)
36119  {
36120  expression_ = e;
36121  return (*this);
36122  }
36123 
36124  inline function& var(const std::string& v)
36125  {
36126  v_.push_back(v);
36127  return (*this);
36128  }
36129 
36132  std::deque<std::string> v_;
36133  };
36134 
36135  private:
36136 
36137  struct base_func : public exprtk::ifunction<T>
36138  {
36139  typedef const T& type;
36141  typedef std::vector<T*> varref_t;
36142  typedef std::vector<T> var_t;
36143  typedef std::pair<T*,std::size_t> lvarref_t;
36144  typedef std::vector<lvarref_t> lvr_vec_t;
36145 
36147 
36148  base_func(const std::size_t& pc = 0)
36149  : exprtk::ifunction<T>(pc),
36150  local_var_stack_size(0),
36151  stack_depth(0)
36152  {
36153  v.resize(pc);
36154  }
36155 
36156  virtual ~base_func()
36157  {}
36158 
36159  inline void update(const T& v0)
36160  {
36161  (*v[0]) = v0;
36162  }
36163 
36164  inline void update(const T& v0, const T& v1)
36165  {
36166  (*v[0]) = v0; (*v[1]) = v1;
36167  }
36168 
36169  inline void update(const T& v0, const T& v1, const T& v2)
36170  {
36171  (*v[0]) = v0; (*v[1]) = v1;
36172  (*v[2]) = v2;
36173  }
36174 
36175  inline void update(const T& v0, const T& v1, const T& v2, const T& v3)
36176  {
36177  (*v[0]) = v0; (*v[1]) = v1;
36178  (*v[2]) = v2; (*v[3]) = v3;
36179  }
36180 
36181  inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4)
36182  {
36183  (*v[0]) = v0; (*v[1]) = v1;
36184  (*v[2]) = v2; (*v[3]) = v3;
36185  (*v[4]) = v4;
36186  }
36187 
36188  inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5)
36189  {
36190  (*v[0]) = v0; (*v[1]) = v1;
36191  (*v[2]) = v2; (*v[3]) = v3;
36192  (*v[4]) = v4; (*v[5]) = v5;
36193  }
36194 
36196  {
36197  expression = expr;
36198 
36199  typedef typename expression_t::control_block::local_data_list_t ldl_t;
36200 
36201  ldl_t ldl = expr.local_data_list();
36202 
36203  std::vector<std::size_t> index_list;
36204 
36205  for (std::size_t i = 0; i < ldl.size(); ++i)
36206  {
36207  if (ldl[i].size)
36208  {
36209  index_list.push_back(i);
36210  }
36211  }
36212 
36213  std::size_t input_param_count = 0;
36214 
36215  for (std::size_t i = 0; i < index_list.size(); ++i)
36216  {
36217  const std::size_t index = index_list[i];
36218 
36219  if (i < (index_list.size() - v.size()))
36220  {
36221  lv.push_back(
36222  std::make_pair(
36223  reinterpret_cast<T*>(ldl[index].pointer),
36224  ldl[index].size));
36225 
36226  local_var_stack_size += ldl[index].size;
36227  }
36228  else
36229  v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer);
36230  }
36231 
36232  clear_stack();
36233 
36234  return (*this);
36235  }
36236 
36237  inline void pre()
36238  {
36239  if (stack_depth++)
36240  {
36241  if (!v.empty())
36242  {
36243  var_t var_stack(v.size(),T(0));
36244  copy(v,var_stack);
36245  param_stack.push_back(var_stack);
36246  }
36247 
36248  if (!lv.empty())
36249  {
36250  var_t local_var_stack(local_var_stack_size,T(0));
36251  copy(lv,local_var_stack);
36252  local_stack.push_back(local_var_stack);
36253  }
36254  }
36255  }
36256 
36257  inline void post()
36258  {
36259  if (--stack_depth)
36260  {
36261  if (!v.empty())
36262  {
36263  copy(param_stack.back(),v);
36264  param_stack.pop_back();
36265  }
36266 
36267  if (!lv.empty())
36268  {
36269  copy(local_stack.back(),lv);
36270  local_stack.pop_back();
36271  }
36272  }
36273  }
36274 
36275  void copy(const varref_t& src_v, var_t& dest_v)
36276  {
36277  for (std::size_t i = 0; i < src_v.size(); ++i)
36278  {
36279  dest_v[i] = (*src_v[i]);
36280  }
36281  }
36282 
36283  void copy(const var_t& src_v, varref_t& dest_v)
36284  {
36285  for (std::size_t i = 0; i < src_v.size(); ++i)
36286  {
36287  (*dest_v[i]) = src_v[i];
36288  }
36289  }
36290 
36291  void copy(const lvr_vec_t& src_v, var_t& dest_v)
36292  {
36293  typename var_t::iterator itr = dest_v.begin();
36294  typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36295 
36296  for (std::size_t i = 0; i < src_v.size(); ++i)
36297  {
36298  lvarref_t vr = src_v[i];
36299 
36300  if (1 == vr.second)
36301  *itr++ = (*vr.first);
36302  else
36303  {
36304  std::copy(vr.first, vr.first + vr.second, itr);
36305  itr += static_cast<diff_t>(vr.second);
36306  }
36307  }
36308  }
36309 
36310  void copy(const var_t& src_v, lvr_vec_t& dest_v)
36311  {
36312  typename var_t::const_iterator itr = src_v.begin();
36313  typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t;
36314 
36315  for (std::size_t i = 0; i < src_v.size(); ++i)
36316  {
36317  lvarref_t vr = dest_v[i];
36318 
36319  if (1 == vr.second)
36320  (*vr.first) = *itr++;
36321  else
36322  {
36323  std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first);
36324  itr += static_cast<diff_t>(vr.second);
36325  }
36326  }
36327  }
36328 
36329  inline void clear_stack()
36330  {
36331  for (std::size_t i = 0; i < v.size(); ++i)
36332  {
36333  (*v[i]) = 0;
36334  }
36335  }
36336 
36337  inline virtual T value(expression_t& e)
36338  {
36339  return e.value();
36340  }
36341 
36346  std::size_t stack_depth;
36347  std::deque<var_t> param_stack;
36348  std::deque<var_t> local_stack;
36349  };
36350 
36351  typedef std::map<std::string,base_func*> funcparam_t;
36352 
36353  struct func_0param : public base_func
36354  {
36356 
36358 
36359  inline T operator() ()
36360  {
36361  return this->value(base_func::expression);
36362  }
36363  };
36364 
36365  typedef const T& type;
36366 
36367  template <typename BaseFuncType>
36368  struct scoped_bft
36369  {
36370  scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); }
36371  ~scoped_bft() { bft_.post(); }
36372 
36373  BaseFuncType& bft_;
36374 
36375  private:
36376 
36378  scoped_bft& operator=(scoped_bft&);
36379  };
36380 
36381  struct func_1param : public base_func
36382  {
36384 
36386 
36387  inline T operator() (type v0)
36388  {
36389  scoped_bft<func_1param> sb(*this);
36390  base_func::update(v0);
36391  return this->value(base_func::expression);
36392  }
36393  };
36394 
36395  struct func_2param : public base_func
36396  {
36398 
36400 
36401  inline T operator() (type v0, type v1)
36402  {
36403  scoped_bft<func_2param> sb(*this);
36404  base_func::update(v0, v1);
36405  return this->value(base_func::expression);
36406  }
36407  };
36408 
36409  struct func_3param : public base_func
36410  {
36412 
36414 
36415  inline T operator() (type v0, type v1, type v2)
36416  {
36417  scoped_bft<func_3param> sb(*this);
36418  base_func::update(v0, v1, v2);
36419  return this->value(base_func::expression);
36420  }
36421  };
36422 
36423  struct func_4param : public base_func
36424  {
36426 
36428 
36429  inline T operator() (type v0, type v1, type v2, type v3)
36430  {
36431  scoped_bft<func_4param> sb(*this);
36432  base_func::update(v0, v1, v2, v3);
36433  return this->value(base_func::expression);
36434  }
36435  };
36436 
36437  struct func_5param : public base_func
36438  {
36440 
36442 
36443  inline T operator() (type v0, type v1, type v2, type v3, type v4)
36444  {
36445  scoped_bft<func_5param> sb(*this);
36446  base_func::update(v0, v1, v2, v3, v4);
36447  return this->value(base_func::expression);
36448  }
36449  };
36450 
36451  struct func_6param : public base_func
36452  {
36454 
36456 
36457  inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5)
36458  {
36459  scoped_bft<func_6param> sb(*this);
36460  base_func::update(v0, v1, v2, v3, v4, v5);
36461  return this->value(base_func::expression);
36462  }
36463  };
36464 
36466  {
36467  typedef exprtk::results_context<T> results_context_t;
36468  typedef typename results_context_t::type_store_t type_t;
36469  typedef typename type_t::scalar_view scalar_t;
36470 
36471  T result = e.value();
36472 
36473  if (e.return_invoked())
36474  {
36475  // Due to the post compilation checks, it can be safely
36476  // assumed that there will be at least one parameter
36477  // and that the first parameter will always be scalar.
36478  return scalar_t(e.results()[0])();
36479  }
36480 
36481  return result;
36482  }
36483 
36484  #define def_fp_retval(N) \
36485  struct func_##N##param_retval : public func_##N##param \
36486  { \
36487  inline T value(expression_t& e) \
36488  { \
36489  return return_value(e); \
36490  } \
36491  }; \
36492 
36493  def_fp_retval(0)
36494  def_fp_retval(1)
36495  def_fp_retval(2)
36496  def_fp_retval(3)
36497  def_fp_retval(4)
36498  def_fp_retval(5)
36499  def_fp_retval(6)
36500 
36501  template <typename Allocator,
36502  template <typename, typename> class Sequence>
36503  inline bool add(const std::string& name,
36504  const std::string& expression,
36505  const Sequence<std::string,Allocator>& var_list,
36506  const bool override = false)
36507  {
36508  const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name);
36509 
36510  if (expr_map_.end() != itr)
36511  {
36512  if (!override)
36513  {
36514  exprtk_debug(("Compositor error(add): function '%s' already defined\n",
36515  name.c_str()));
36516 
36517  return false;
36518  }
36519 
36520  remove(name, var_list.size());
36521  }
36522 
36523  if (compile_expression(name,expression,var_list))
36524  {
36525  const std::size_t n = var_list.size();
36526 
36527  fp_map_[n][name]->setup(expr_map_[name]);
36528 
36529  return true;
36530  }
36531  else
36532  {
36533  exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n",
36534  name.c_str()));
36535 
36536  return false;
36537  }
36538  }
36539 
36540  public:
36541 
36543  : parser_(settings_t::compile_all_opts +
36544  settings_t::e_disable_zero_return),
36545  fp_map_(7)
36546  {}
36547 
36549  : symbol_table_(st),
36550  parser_(settings_t::compile_all_opts +
36551  settings_t::e_disable_zero_return),
36552  fp_map_(7)
36553  {}
36554 
36556  {
36557  clear();
36558  }
36559 
36561  {
36562  return symbol_table_;
36563  }
36564 
36566  {
36567  auxiliary_symtab_list_.push_back(&symtab);
36568  }
36569 
36570  void clear()
36571  {
36572  symbol_table_.clear();
36573  expr_map_ .clear();
36574 
36575  for (std::size_t i = 0; i < fp_map_.size(); ++i)
36576  {
36577  typename funcparam_t::iterator itr = fp_map_[i].begin();
36578  typename funcparam_t::iterator end = fp_map_[i].end ();
36579 
36580  while (itr != end)
36581  {
36582  delete itr->second;
36583  ++itr;
36584  }
36585 
36586  fp_map_[i].clear();
36587  }
36588  }
36589 
36590  inline bool add(const function& f, const bool override = false)
36591  {
36592  return add(f.name_, f.expression_, f.v_,override);
36593  }
36594 
36595  private:
36596 
36597  template <typename Allocator,
36598  template <typename, typename> class Sequence>
36600  const std::string& expression,
36601  const Sequence<std::string,Allocator>& input_var_list,
36602  bool return_present = false)
36603  {
36604  expression_t compiled_expression;
36605  symbol_table_t local_symbol_table;
36606 
36607  local_symbol_table.load_from(symbol_table_);
36608  local_symbol_table.add_constants();
36609 
36610  if (!valid(name,input_var_list.size()))
36611  return false;
36612 
36613  if (!forward(name,
36614  input_var_list.size(),
36615  local_symbol_table,
36616  return_present))
36617  return false;
36618 
36619  compiled_expression.register_symbol_table(local_symbol_table);
36620 
36621  for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i)
36622  {
36623  compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i]));
36624  }
36625 
36626  std::string mod_expression;
36627 
36628  for (std::size_t i = 0; i < input_var_list.size(); ++i)
36629  {
36630  mod_expression += " var " + input_var_list[i] + "{};\n";
36631  }
36632 
36633  if (
36634  ('{' == details::front(expression)) &&
36635  ('}' == details::back (expression))
36636  )
36637  mod_expression += "~" + expression + ";";
36638  else
36639  mod_expression += "~{" + expression + "};";
36640 
36641  if (!parser_.compile(mod_expression,compiled_expression))
36642  {
36643  exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str()));
36644  exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str()));
36645 
36646  remove(name,input_var_list.size());
36647 
36648  return false;
36649  }
36650 
36651  if (!return_present && parser_.dec().return_present())
36652  {
36653  remove(name,input_var_list.size());
36654 
36655  return compile_expression(name, expression, input_var_list, true);
36656  }
36657 
36658  // Make sure every return point has a scalar as its first parameter
36659  if (parser_.dec().return_present())
36660  {
36661  typedef std::vector<std::string> str_list_t;
36662 
36663  str_list_t ret_param_list = parser_.dec().return_param_type_list();
36664 
36665  for (std::size_t i = 0; i < ret_param_list.size(); ++i)
36666  {
36667  const std::string& params = ret_param_list[i];
36668 
36669  if (params.empty() || ('T' != params[0]))
36670  {
36671  exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n",
36672  name.c_str()));
36673 
36674  remove(name,input_var_list.size());
36675 
36676  return false;
36677  }
36678  }
36679  }
36680 
36681  expr_map_[name] = compiled_expression;
36682 
36683  exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]);
36684 
36685  if (symbol_table_.add_function(name,ifunc))
36686  return true;
36687  else
36688  {
36689  exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n",
36690  name.c_str()));
36691  return false;
36692  }
36693  }
36694 
36695  inline bool symbol_used(const std::string& symbol) const
36696  {
36697  return (
36698  symbol_table_.is_variable (symbol) ||
36699  symbol_table_.is_stringvar (symbol) ||
36700  symbol_table_.is_function (symbol) ||
36701  symbol_table_.is_vector (symbol) ||
36702  symbol_table_.is_vararg_function(symbol)
36703  );
36704  }
36705 
36706  inline bool valid(const std::string& name,
36707  const std::size_t& arg_count) const
36708  {
36709  if (arg_count > 6)
36710  return false;
36711  else if (symbol_used(name))
36712  return false;
36713  else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name))
36714  return false;
36715  else
36716  return true;
36717  }
36718 
36719  inline bool forward(const std::string& name,
36720  const std::size_t& arg_count,
36721  symbol_table_t& sym_table,
36722  const bool ret_present = false)
36723  {
36724  switch (arg_count)
36725  {
36726  #define case_stmt(N) \
36727  case N : (fp_map_[arg_count])[name] = \
36728  (!ret_present) ? static_cast<base_func*> \
36729  (new func_##N##param) : \
36730  static_cast<base_func*> \
36731  (new func_##N##param_retval) ; \
36732  break; \
36733 
36734  case_stmt(0) case_stmt(1) case_stmt(2)
36735  case_stmt(3) case_stmt(4) case_stmt(5)
36736  case_stmt(6)
36737  #undef case_stmt
36738  }
36739 
36740  exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]);
36741 
36742  return sym_table.add_function(name,ifunc);
36743  }
36744 
36745  inline void remove(const std::string& name, const std::size_t& arg_count)
36746  {
36747  if (arg_count > 6)
36748  return;
36749 
36750  const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name);
36751 
36752  if (expr_map_.end() != em_itr)
36753  {
36754  expr_map_.erase(em_itr);
36755  }
36756 
36757  const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name);
36758 
36759  if (fp_map_[arg_count].end() != fp_itr)
36760  {
36761  delete fp_itr->second;
36762  fp_map_[arg_count].erase(fp_itr);
36763  }
36764 
36765  symbol_table_.remove_function(name);
36766  }
36767 
36768  private:
36769 
36772  std::map<std::string,expression_t> expr_map_;
36773  std::vector<funcparam_t> fp_map_;
36774  std::vector<symbol_table_t*> auxiliary_symtab_list_;
36775  };
36776 
36777  template <typename T>
36778  inline bool pgo_primer()
36779  {
36780  static const std::string expression_list[]
36781  = {
36782  "(y + x)",
36783  "2 * (y + x)",
36784  "(2 * y + 2 * x)",
36785  "(y + x / y) * (x - y / x)",
36786  "x / ((x + y) * (x - y)) / y",
36787  "1 - ((x * y) + (y / x)) - 3",
36788  "sin(2 * x) + cos(pi / y)",
36789  "1 - sin(2 * x) + cos(pi / y)",
36790  "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
36791  "(x^2 / sin(2 * pi / y)) -x / 2",
36792  "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
36793  "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36794  "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
36795  "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
36796  "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
36797  "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
36798  "(yy + xx)",
36799  "2 * (yy + xx)",
36800  "(2 * yy + 2 * xx)",
36801  "(yy + xx / yy) * (xx - yy / xx)",
36802  "xx / ((xx + yy) * (xx - yy)) / yy",
36803  "1 - ((xx * yy) + (yy / xx)) - 3",
36804  "sin(2 * xx) + cos(pi / yy)",
36805  "1 - sin(2 * xx) + cos(pi / yy)",
36806  "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
36807  "(xx^2 / sin(2 * pi / yy)) -xx / 2",
36808  "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
36809  "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
36810  "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
36811  "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
36812  "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55",
36813  "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))",
36814  "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)",
36815  "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)",
36816  "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)",
36817  "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)",
36818  "(x + 2) * 3", "x + (2 * 3)",
36819  "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)",
36820  "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)",
36821  "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))",
36822  "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))",
36823  "2 + (x * (y / 3))", "x + (2 * (3 / y))",
36824  "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)",
36825  "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)",
36826  "x + ((2 * 3) / y)", "(((x + y) * z) / w)",
36827  "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)",
36828  "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)",
36829  "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)",
36830  "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)",
36831  "((x + (2 * 3)) / y)",
36832  "(xx + yy) * zz", "xx + (yy * zz)",
36833  "(xx + yy) * 7", "xx + (yy * 7)",
36834  "(xx + 7) * yy", "xx + (7 * yy)",
36835  "(7 + xx) * yy", "7 + (xx * yy)",
36836  "(2 + x) * 3", "2 + (x * 3)",
36837  "(2 + 3) * x", "2 + (3 * x)",
36838  "(x + 2) * 3", "x + (2 * 3)",
36839  "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)",
36840  "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)",
36841  "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)",
36842  "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)",
36843  "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))",
36844  "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))",
36845  "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))",
36846  "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))",
36847  "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))",
36848  "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)",
36849  "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)",
36850  "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)",
36851  "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)",
36852  "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)",
36853  "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)",
36854  "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)",
36855  "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)",
36856  "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)",
36857  "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)",
36858  "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)",
36859  "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)",
36860  "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)",
36861  "((xx + (2 * 3)) / yy)"
36862  };
36863  static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
36864 
36865  T x = T(0);
36866  T y = T(0);
36867  T z = T(0);
36868  T w = T(0);
36869  T xx = T(0);
36870  T yy = T(0);
36871  T zz = T(0);
36872  T ww = T(0);
36873 
36876  symbol_table.add_variable( "x", x);
36877  symbol_table.add_variable( "y", y);
36878  symbol_table.add_variable( "z", z);
36879  symbol_table.add_variable( "w", w);
36880  symbol_table.add_variable("xx",xx);
36881  symbol_table.add_variable("yy",yy);
36882  symbol_table.add_variable("zz",zz);
36883  symbol_table.add_variable("ww",ww);
36884 
36885  typedef typename std::deque<exprtk::expression<T> > expr_list_t;
36886  expr_list_t expr_list;
36887 
36888  const std::size_t rounds = 50;
36889 
36890  {
36891  for (std::size_t r = 0; r < rounds; ++r)
36892  {
36893  expr_list.clear();
36895 
36896  for (std::size_t i = 0; i < expression_list_size; ++i)
36897  {
36900 
36901  if (!parser.compile(expression_list[i],expression))
36902  {
36903  return false;
36904  }
36905 
36906  expr_list.push_back(expression);
36907  }
36908  }
36909  }
36910 
36911  struct execute
36912  {
36913  static inline T process(T& x, T& y, expression<T>& expression)
36914  {
36915  static const T lower_bound = T(-20);
36916  static const T upper_bound = T(+20);
36917  static const T delta = T(0.1);
36918 
36919  T total = T(0);
36920 
36921  for (x = lower_bound; x <= upper_bound; x += delta)
36922  {
36923  for (y = lower_bound; y <= upper_bound; y += delta)
36924  {
36925  total += expression.value();
36926  }
36927  }
36928 
36929  return total;
36930  }
36931  };
36932 
36933  for (std::size_t i = 0; i < expr_list.size(); ++i)
36934  {
36935  execute::process( x, y, expr_list[i]);
36936  execute::process(xx, yy, expr_list[i]);
36937  }
36938 
36939  {
36940  for (std::size_t i = 0; i < 10000; ++i)
36941  {
36942  const T v = T(123.456 + i);
36943 
36945  return false;
36946 
36947  #define else_stmt(N) \
36948  else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \
36949  return false; \
36950 
36951  else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5)
36952  else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9)
36953  else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13)
36954  else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17)
36955  else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21)
36956  else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25)
36957  else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29)
36958  else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33)
36959  else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37)
36960  else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41)
36961  else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45)
36962  else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49)
36963  else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53)
36964  else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57)
36965  else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61)
36966  }
36967  }
36968 
36969  return true;
36970  }
36971 }
36972 
36973 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
36974 # ifndef NOMINMAX
36975 # define NOMINMAX
36976 # endif
36977 # ifndef WIN32_LEAN_AND_MEAN
36978 # define WIN32_LEAN_AND_MEAN
36979 # endif
36980 # include <windows.h>
36981 # include <ctime>
36982 #else
36983 # include <ctime>
36984 # include <sys/time.h>
36985 # include <sys/types.h>
36986 #endif
36987 
36988 namespace exprtk
36989 {
36990  class timer
36991  {
36992  public:
36993 
36994  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
36995  timer()
36996  : in_use_(false)
36997  {
36998  QueryPerformanceFrequency(&clock_frequency_);
36999  }
37000 
37001  inline void start()
37002  {
37003  in_use_ = true;
37004  QueryPerformanceCounter(&start_time_);
37005  }
37006 
37007  inline void stop()
37008  {
37009  QueryPerformanceCounter(&stop_time_);
37010  in_use_ = false;
37011  }
37012 
37013  inline double time() const
37014  {
37015  return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
37016  }
37017 
37018  #else
37019 
37021  : in_use_(false)
37022  {
37023  start_time_.tv_sec = 0;
37024  start_time_.tv_usec = 0;
37025  stop_time_.tv_sec = 0;
37026  stop_time_.tv_usec = 0;
37027  }
37028 
37029  inline void start()
37030  {
37031  in_use_ = true;
37032  gettimeofday(&start_time_,0);
37033  }
37034 
37035  inline void stop()
37036  {
37037  gettimeofday(&stop_time_, 0);
37038  in_use_ = false;
37039  }
37040 
37041  inline unsigned long long int usec_time() const
37042  {
37043  if (!in_use_)
37044  {
37045  if (stop_time_.tv_sec >= start_time_.tv_sec)
37046  {
37047  return 1000000LLU * static_cast<unsigned long long int>(stop_time_.tv_sec - start_time_.tv_sec ) +
37048  static_cast<unsigned long long int>(stop_time_.tv_usec - start_time_.tv_usec) ;
37049  }
37050  else
37052  }
37053  else
37055  }
37056 
37057  inline double time() const
37058  {
37059  return usec_time() * 0.000001;
37060  }
37061 
37062  #endif
37063 
37064  inline bool in_use() const
37065  {
37066  return in_use_;
37067  }
37068 
37069  private:
37070 
37071  bool in_use_;
37072 
37073  #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
37074  LARGE_INTEGER start_time_;
37075  LARGE_INTEGER stop_time_;
37076  LARGE_INTEGER clock_frequency_;
37077  #else
37078  struct timeval start_time_;
37079  struct timeval stop_time_;
37080  #endif
37081  };
37082 
37083 } // namespace exprtk
37084 
37085 #ifndef exprtk_disable_rtl_io
37086 namespace exprtk
37087 {
37088  namespace rtl { namespace io { namespace details
37089  {
37090  template <typename T>
37091  inline void print_type(const std::string& fmt,
37092  const T v,
37094  {
37095  printf(fmt.c_str(),v);
37096  }
37097 
37098  template <typename T>
37099  struct print_impl
37100  {
37107 
37108  static void process(const std::string& scalar_format, parameter_list_t parameters)
37109  {
37110  for (std::size_t i = 0; i < parameters.size(); ++i)
37111  {
37112  generic_type& gt = parameters[i];
37113 
37114  switch (gt.type)
37115  {
37116  case generic_type::e_scalar : print(scalar_format,scalar_t(gt));
37117  break;
37118 
37119  case generic_type::e_vector : print(scalar_format,vector_t(gt));
37120  break;
37121 
37123  break;
37124 
37125  default : continue;
37126  }
37127  }
37128  }
37129 
37130  static inline void print(const std::string& scalar_format, const scalar_t& s)
37131  {
37132  print_type(scalar_format,s(),num_type());
37133  }
37134 
37135  static inline void print(const std::string& scalar_format, const vector_t& v)
37136  {
37137  for (std::size_t i = 0; i < v.size(); ++i)
37138  {
37139  print_type(scalar_format,v[i],num_type());
37140 
37141  if ((i + 1) < v.size())
37142  printf(" ");
37143  }
37144  }
37145 
37146  static inline void print(const string_t& s)
37147  {
37148  printf("%s",to_str(s).c_str());
37149  }
37150  };
37151 
37152  } // namespace exprtk::rtl::io::details
37153 
37154  template <typename T>
37156  {
37158 
37160 
37161  print(const std::string& scalar_format = "%10.5f")
37162  : scalar_format_(scalar_format)
37163  {
37165  }
37166 
37167  inline T operator() (parameter_list_t parameters)
37168  {
37170  return T(0);
37171  }
37172 
37174  };
37175 
37176  template <typename T>
37178  {
37180 
37182 
37183  println(const std::string& scalar_format = "%10.5f")
37184  : scalar_format_(scalar_format)
37185  {
37187  }
37188 
37189  inline T operator() (parameter_list_t parameters)
37190  {
37192  printf("\n");
37193  return T(0);
37194  }
37195 
37197  };
37198 
37199  template <typename T>
37200  struct package
37201  {
37204 
37206  {
37207  #define exprtk_register_function(FunctionName,FunctionType) \
37208  if (!symtab.add_function(FunctionName,FunctionType)) \
37209  { \
37210  exprtk_debug(( \
37211  "exprtk::rtl::io::register_package - Failed to add function: %s\n", \
37212  FunctionName)); \
37213  return false; \
37214  } \
37215 
37216  exprtk_register_function("print" , p)
37217  exprtk_register_function("println", pl)
37218  #undef exprtk_register_function
37219 
37220  return true;
37221  }
37222  };
37223 
37224  } // namespace exprtk::rtl::io
37225  } // namespace exprtk::rtl
37226 } // namespace exprtk
37227 #endif
37228 
37229 #ifndef exprtk_disable_rtl_io_file
37230 #include <fstream>
37231 namespace exprtk
37232 {
37233  namespace rtl { namespace io { namespace file { namespace details
37234  {
37236  {
37237  e_error = 0,
37238  e_read = 1,
37239  e_write = 2,
37241  };
37242 
37244  {
37245  file_descriptor(const std::string& fname, const std::string& access)
37246  : stream_ptr(0),
37247  mode(get_file_mode(access)),
37248  file_name(fname)
37249  {}
37250 
37251  void* stream_ptr;
37254 
37255  bool open()
37256  {
37257  if (e_read == mode)
37258  {
37259  std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary);
37260 
37261  if (!(*stream))
37262  {
37263  file_name.clear();
37264  delete stream;
37265 
37266  return false;
37267  }
37268  else
37269  stream_ptr = stream;
37270 
37271  return true;
37272  }
37273  else if (e_write == mode)
37274  {
37275  std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary);
37276 
37277  if (!(*stream))
37278  {
37279  file_name.clear();
37280  delete stream;
37281 
37282  return false;
37283  }
37284  else
37285  stream_ptr = stream;
37286 
37287  return true;
37288  }
37289  else if (e_rdwrt == mode)
37290  {
37291  std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary);
37292 
37293  if (!(*stream))
37294  {
37295  file_name.clear();
37296  delete stream;
37297 
37298  return false;
37299  }
37300  else
37301  stream_ptr = stream;
37302 
37303  return true;
37304  }
37305  else
37306  return false;
37307  }
37308 
37309  template <typename Stream, typename Ptr>
37310  void close(Ptr& p)
37311  {
37312  Stream* stream = reinterpret_cast<Stream*>(p);
37313  stream->close();
37314  delete stream;
37315  p = reinterpret_cast<Ptr>(0);
37316  }
37317 
37318  bool close()
37319  {
37320  switch (mode)
37321  {
37323  break;
37324 
37326  break;
37327 
37329  break;
37330 
37331  default : return false;
37332  }
37333 
37334  return true;
37335  }
37336 
37337  template <typename View>
37338  bool write(const View& view, const std::size_t amount, const std::size_t offset = 0)
37339  {
37340  switch (mode)
37341  {
37342  case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)->
37343  write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37344  break;
37345 
37346  case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37347  write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37348  break;
37349 
37350  default : return false;
37351  }
37352 
37353  return true;
37354  }
37355 
37356  template <typename View>
37357  bool read(View& view, const std::size_t amount, const std::size_t offset = 0)
37358  {
37359  switch (mode)
37360  {
37361  case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)->
37362  read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t));
37363  break;
37364 
37365  case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)->
37366  read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t));
37367  break;
37368 
37369  default : return false;
37370  }
37371 
37372  return true;
37373  }
37374 
37376  {
37377  switch (mode)
37378  {
37379  case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s));
37380  case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s));
37381  default : return false;
37382  }
37383  }
37384 
37385  bool eof() const
37386  {
37387  switch (mode)
37388  {
37389  case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof();
37390  case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof();
37391  case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof();
37392  default : return true;
37393  }
37394  }
37395 
37396  file_mode get_file_mode(const std::string& access) const
37397  {
37398  if (access.empty() || access.size() > 2)
37399  return e_error;
37400 
37401  std::size_t w_cnt = 0;
37402  std::size_t r_cnt = 0;
37403 
37404  for (std::size_t i = 0; i < access.size(); ++i)
37405  {
37406  switch (std::tolower(access[i]))
37407  {
37408  case 'r' : r_cnt++; break;
37409  case 'w' : w_cnt++; break;
37410  default : return e_error;
37411  }
37412  }
37413 
37414  if ((0 == r_cnt) && (0 == w_cnt))
37415  return e_error;
37416  else if ((r_cnt > 1) || (w_cnt > 1))
37417  return e_error;
37418  else if ((1 == r_cnt) && (1 == w_cnt))
37419  return e_rdwrt;
37420  else if (1 == r_cnt)
37421  return e_read;
37422  else
37423  return e_write;
37424  }
37425  };
37426 
37427  template <typename T>
37429  {
37430  file_descriptor* fd = reinterpret_cast<file_descriptor*>(0);
37431 
37432  std::memcpy(reinterpret_cast<char*>(&fd),
37433  reinterpret_cast<const char*>(&v),
37434  sizeof(fd));
37435  return fd;
37436  }
37437 
37438  template <typename T>
37440  {
37441  #ifdef _MSC_VER
37442  #pragma warning(push)
37443  #pragma warning(disable: 4127)
37444  #endif
37445  if (sizeof(T) < sizeof(void*))
37446  {
37447  throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder.");
37448  }
37449  #ifdef _MSC_VER
37450  #pragma warning(pop)
37451  #endif
37452  }
37453 
37454  } // namespace exprtk::rtl::io::file::details
37455 
37456  template <typename T>
37458  {
37459  public:
37460 
37465 
37467 
37469  : exprtk::igeneric_function<T>("S|SS")
37470  { details::perform_check<T>(); }
37471 
37472  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37473  {
37474  std::string file_name = to_str(string_t(parameters[0]));
37475  std::string access;
37476 
37477  if (file_name.empty())
37478  return T(0);
37479 
37480  if (0 == ps_index)
37481  access = "r";
37482  else if (0 == string_t(parameters[1]).size())
37483  return T(0);
37484  else
37485  access = to_str(string_t(parameters[1]));
37486 
37487  details::file_descriptor* fd = new details::file_descriptor(file_name,access);
37488 
37489  if (fd->open())
37490  {
37491  T t = T(0);
37492 
37493  std::memcpy(reinterpret_cast<char*>(&t ),
37494  reinterpret_cast<char*>(&fd),
37495  sizeof(fd));
37496  return t;
37497  }
37498  else
37499  {
37500  delete fd;
37501  return T(0);
37502  }
37503  }
37504  };
37505 
37506  template <typename T>
37507  struct close : public exprtk::ifunction<T>
37508  {
37510 
37512  : exprtk::ifunction<T>(1)
37513  { details::perform_check<T>(); }
37514 
37515  inline T operator() (const T& v)
37516  {
37518 
37519  if (!fd->close())
37520  return T(0);
37521 
37522  delete fd;
37523 
37524  return T(1);
37525  }
37526  };
37527 
37528  template <typename T>
37530  {
37531  public:
37532 
37539 
37541 
37543  : igfun_t("TS|TST|TV|TVT")
37544  { details::perform_check<T>(); }
37545 
37546  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37547  {
37548  details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37549 
37550  std::size_t amount = 0;
37551 
37552  switch (ps_index)
37553  {
37554  case 0 : {
37555  const string_t buffer(parameters[1]);
37556  amount = buffer.size();
37557  return T(fd->write(buffer, amount) ? 1 : 0);
37558  }
37559 
37560  case 1 : {
37561  const string_t buffer(parameters[1]);
37562  amount = std::min(buffer.size(),
37563  static_cast<std::size_t>(scalar_t(parameters[2])()));
37564  return T(fd->write(buffer, amount) ? 1 : 0);
37565  }
37566 
37567  case 2 : {
37568  const vector_t vec(parameters[1]);
37569  amount = vec.size();
37570  return T(fd->write(vec, amount) ? 1 : 0);
37571  }
37572 
37573  case 3 : {
37574  const vector_t vec(parameters[1]);
37575  amount = std::min(vec.size(),
37576  static_cast<std::size_t>(scalar_t(parameters[2])()));
37577  return T(fd->write(vec, amount) ? 1 : 0);
37578  }
37579  }
37580 
37581  return T(0);
37582  }
37583  };
37584 
37585  template <typename T>
37587  {
37588  public:
37589 
37596 
37598 
37600  : igfun_t("TS|TST|TV|TVT")
37601  { details::perform_check<T>(); }
37602 
37603  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37604  {
37605  details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37606 
37607  std::size_t amount = 0;
37608 
37609  switch (ps_index)
37610  {
37611  case 0 : {
37612  string_t buffer(parameters[1]);
37613  amount = buffer.size();
37614  return T(fd->read(buffer,amount) ? 1 : 0);
37615  }
37616 
37617  case 1 : {
37618  string_t buffer(parameters[1]);
37619  amount = std::min(buffer.size(),
37620  static_cast<std::size_t>(scalar_t(parameters[2])()));
37621  return T(fd->read(buffer,amount) ? 1 : 0);
37622  }
37623 
37624  case 2 : {
37625  vector_t vec(parameters[1]);
37626  amount = vec.size();
37627  return T(fd->read(vec,amount) ? 1 : 0);
37628  }
37629 
37630  case 3 : {
37631  vector_t vec(parameters[1]);
37632  amount = std::min(vec.size(),
37633  static_cast<std::size_t>(scalar_t(parameters[2])()));
37634  return T(fd->read(vec,amount) ? 1 : 0);
37635  }
37636  }
37637 
37638  return T(0);
37639  }
37640  };
37641 
37642  template <typename T>
37644  {
37645  public:
37646 
37652 
37654 
37656  : igfun_t("T",igfun_t::e_rtrn_string)
37657  { details::perform_check<T>(); }
37658 
37659  inline T operator() (std::string& result,
37660  parameter_list_t parameters)
37661  {
37662  details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])());
37663  return T(fd->getline(result) ? 1 : 0);
37664  }
37665  };
37666 
37667  template <typename T>
37668  struct eof : public exprtk::ifunction<T>
37669  {
37671 
37673  : exprtk::ifunction<T>(1)
37674  { details::perform_check<T>(); }
37675 
37676  inline T operator() (const T& v)
37677  {
37679 
37680  return (fd->eof() ? T(1) : T(0));
37681  }
37682  };
37683 
37684  template <typename T>
37685  struct package
37686  {
37693 
37695  {
37696  #define exprtk_register_function(FunctionName,FunctionType) \
37697  if (!symtab.add_function(FunctionName,FunctionType)) \
37698  { \
37699  exprtk_debug(( \
37700  "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \
37701  FunctionName)); \
37702  return false; \
37703  } \
37704 
37705  exprtk_register_function("open" ,o)
37706  exprtk_register_function("close" ,c)
37707  exprtk_register_function("write" ,w)
37708  exprtk_register_function("read" ,r)
37709  exprtk_register_function("getline",g)
37710  exprtk_register_function("eof" ,e)
37711  #undef exprtk_register_function
37712 
37713  return true;
37714  }
37715  };
37716 
37717  } // namespace exprtk::rtl::io::file
37718  } // namespace exprtk::rtl::io
37719  } // namespace exprtk::rtl
37720 } // namespace exprtk
37721 #endif
37722 
37723 #ifndef exprtk_disable_rtl_vecops
37724 namespace exprtk
37725 {
37726  namespace rtl { namespace vecops {
37727 
37728  namespace helper
37729  {
37730  template <typename Vector>
37731  inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1)
37732  {
37733  if (r0 > (v.size() - 1))
37734  return true;
37735  else if (r1 > (v.size() - 1))
37736  return true;
37737  else if (r1 < r0)
37738  return true;
37739  else
37740  return false;
37741  }
37742 
37743  template <typename T>
37745  {
37751 
37752  static inline bool process(parameter_list_t& parameters,
37753  std::size_t& r0, std::size_t& r1,
37754  const std::size_t& r0_prmidx,
37755  const std::size_t& r1_prmidx,
37756  const std::size_t vec_idx = 0)
37757  {
37758  if (r0_prmidx >= parameters.size())
37759  return false;
37760 
37761  if (r1_prmidx >= parameters.size())
37762  return false;
37763 
37764  if (!scalar_t(parameters[r0_prmidx]).to_uint(r0))
37765  return false;
37766 
37767  if (!scalar_t(parameters[r1_prmidx]).to_uint(r1))
37768  return false;
37769 
37770  return !invalid_range(vector_t(parameters[vec_idx]), r0, r1);
37771  }
37772  };
37773  }
37774 
37775  namespace details
37776  {
37777  template <typename T>
37778  inline void kahan_sum(T& sum, T& error, const T v)
37779  {
37780  const T x = v - error;
37781  const T y = sum + x;
37782  error = (y - sum) - x;
37783  sum = y;
37784  }
37785 
37786  } // namespace exprtk::rtl::details
37787 
37788  template <typename T>
37790  {
37791  public:
37792 
37797 
37799 
37801  : exprtk::igeneric_function<T>("V|VTT")
37802  /*
37803  Overloads:
37804  0. V - vector
37805  1. VTT - vector, r0, r1
37806  */
37807  {}
37808 
37809  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37810  {
37811  const vector_t vec(parameters[0]);
37812 
37813  std::size_t r0 = 0;
37814  std::size_t r1 = vec.size() - 1;
37815 
37816  if (
37817  (1 == ps_index) &&
37818  !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37819  )
37820  return std::numeric_limits<T>::quiet_NaN();
37821 
37822  for (std::size_t i = r0; i <= r1; ++i)
37823  {
37824  if (vec[i] == T(0))
37825  {
37826  return T(0);
37827  }
37828  }
37829 
37830  return T(1);
37831  }
37832  };
37833 
37834  template <typename T>
37836  {
37837  public:
37838 
37843 
37845 
37847  : exprtk::igeneric_function<T>("V|VTT")
37848  /*
37849  Overloads:
37850  0. V - vector
37851  1. VTT - vector, r0, r1
37852  */
37853  {}
37854 
37855  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37856  {
37857  const vector_t vec(parameters[0]);
37858 
37859  std::size_t r0 = 0;
37860  std::size_t r1 = vec.size() - 1;
37861 
37862  if (
37863  (1 == ps_index) &&
37864  !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37865  )
37866  return std::numeric_limits<T>::quiet_NaN();
37867 
37868  for (std::size_t i = r0; i <= r1; ++i)
37869  {
37870  if (vec[i] != T(0))
37871  {
37872  return T(0);
37873  }
37874  }
37875 
37876  return T(1);
37877  }
37878  };
37879 
37880  template <typename T>
37882  {
37883  public:
37884 
37889 
37891 
37893  : exprtk::igeneric_function<T>("V|VTT")
37894  /*
37895  Overloads:
37896  0. V - vector
37897  1. VTT - vector, r0, r1
37898  */
37899  {}
37900 
37901  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37902  {
37903  const vector_t vec(parameters[0]);
37904 
37905  std::size_t r0 = 0;
37906  std::size_t r1 = vec.size() - 1;
37907 
37908  if (
37909  (1 == ps_index) &&
37910  !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37911  )
37912  return std::numeric_limits<T>::quiet_NaN();
37913 
37914  for (std::size_t i = r0; i <= r1; ++i)
37915  {
37916  if (vec[i] != T(0))
37917  {
37918  return T(1);
37919  }
37920  }
37921 
37922  return T(0);
37923  }
37924  };
37925 
37926  template <typename T>
37928  {
37929  public:
37930 
37935 
37937 
37939  : exprtk::igeneric_function<T>("V|VTT")
37940  /*
37941  Overloads:
37942  0. V - vector
37943  1. VTT - vector, r0, r1
37944  */
37945  {}
37946 
37947  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37948  {
37949  const vector_t vec(parameters[0]);
37950 
37951  std::size_t r0 = 0;
37952  std::size_t r1 = vec.size() - 1;
37953 
37954  if (
37955  (1 == ps_index) &&
37956  !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
37957  )
37958  return std::numeric_limits<T>::quiet_NaN();
37959 
37960  for (std::size_t i = r0; i <= r1; ++i)
37961  {
37962  if (vec[i] == T(0))
37963  {
37964  return T(1);
37965  }
37966  }
37967 
37968  return T(0);
37969  }
37970  };
37971 
37972  template <typename T>
37974  {
37975  public:
37976 
37981 
37983 
37985  : exprtk::igeneric_function<T>("V|VTT")
37986  /*
37987  Overloads:
37988  0. V - vector
37989  1. VTT - vector, r0, r1
37990  */
37991  {}
37992 
37993  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
37994  {
37995  const vector_t vec(parameters[0]);
37996 
37997  std::size_t r0 = 0;
37998  std::size_t r1 = vec.size() - 1;
37999 
38000  if (
38001  (1 == ps_index) &&
38002  !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)
38003  )
38004  return std::numeric_limits<T>::quiet_NaN();
38005 
38006  std::size_t cnt = 0;
38007 
38008  for (std::size_t i = r0; i <= r1; ++i)
38009  {
38010  if (vec[i] != T(0)) ++cnt;
38011  }
38012 
38013  return T(cnt);
38014  }
38015  };
38016 
38017  template <typename T>
38019  {
38020  public:
38021 
38027 
38029 
38031  : exprtk::igeneric_function<T>("VV|VTTVTT")
38032  /*
38033  Overloads:
38034  0. VV - x(vector), y(vector)
38035  1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1,
38036  */
38037  {}
38038 
38039  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38040  {
38041  const vector_t x(parameters[0]);
38042  vector_t y(parameters[(0 == ps_index) ? 1 : 3]);
38043 
38044  std::size_t xr0 = 0;
38045  std::size_t xr1 = x.size() - 1;
38046 
38047  std::size_t yr0 = 0;
38048  std::size_t yr1 = y.size() - 1;
38049 
38050  if (1 == ps_index)
38051  {
38052  if (
38053  !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) ||
38054  !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3)
38055  )
38056  return T(0);
38057  }
38058 
38059  const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1);
38060 
38061  std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0);
38062 
38063  return T(n);
38064  }
38065  };
38066 
38067  template <typename T>
38068  class rol : public exprtk::igeneric_function<T>
38069  {
38070  public:
38071 
38077 
38079 
38081  : exprtk::igeneric_function<T>("VT|VTTT")
38082  /*
38083  Overloads:
38084  0. VT - vector, N
38085  1. VTTT - vector, N, r0, r1
38086  */
38087  {}
38088 
38089  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38090  {
38091  vector_t vec(parameters[0]);
38092 
38093  std::size_t n = 0;
38094  std::size_t r0 = 0;
38095  std::size_t r1 = vec.size() - 1;
38096 
38097  if (!scalar_t(parameters[1]).to_uint(n))
38098  return T(0);
38099 
38100  if (
38101  (1 == ps_index) &&
38102  !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38103  )
38104  return T(0);
38105 
38106  std::size_t dist = r1 - r0 + 1;
38107  std::size_t shift = n % dist;
38108 
38109  std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38110 
38111  return T(1);
38112  }
38113  };
38114 
38115  template <typename T>
38116  class ror : public exprtk::igeneric_function<T>
38117  {
38118  public:
38119 
38125 
38127 
38129  : exprtk::igeneric_function<T>("VT|VTTT")
38130  /*
38131  Overloads:
38132  0. VT - vector, N
38133  1. VTTT - vector, N, r0, r1
38134  */
38135  {}
38136 
38137  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38138  {
38139  vector_t vec(parameters[0]);
38140 
38141  std::size_t n = 0;
38142  std::size_t r0 = 0;
38143  std::size_t r1 = vec.size() - 1;
38144 
38145  if (!scalar_t(parameters[1]).to_uint(n))
38146  return T(0);
38147 
38148  if (
38149  (1 == ps_index) &&
38150  !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38151  )
38152  return T(0);
38153 
38154  std::size_t dist = r1 - r0 + 1;
38155  std::size_t shift = (dist - (n % dist)) % dist;
38156 
38157  std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38158 
38159  return T(1);
38160  }
38161  };
38162 
38163  template <typename T>
38165  {
38166  public:
38167 
38173 
38175 
38177  : exprtk::igeneric_function<T>("VT|VTTT")
38178  /*
38179  Overloads:
38180  0. VT - vector, N
38181  1. VTTT - vector, N, r0, r1
38182  */
38183  {}
38184 
38185  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38186  {
38187  vector_t vec(parameters[0]);
38188 
38189  std::size_t n = 0;
38190  std::size_t r0 = 0;
38191  std::size_t r1 = vec.size() - 1;
38192 
38193  if (!scalar_t(parameters[1]).to_uint(n))
38194  return T(0);
38195 
38196  if (
38197  (1 == ps_index) &&
38198  !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38199  )
38200  return T(0);
38201 
38202  std::size_t dist = r1 - r0 + 1;
38203 
38204  if (n > dist)
38205  return T(0);
38206 
38207  std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1);
38208 
38209  for (std::size_t i = r1 - n + 1; i <= r1; ++i)
38210  {
38211  vec[i] = T(0);
38212  }
38213 
38214  return T(1);
38215  }
38216  };
38217 
38218  template <typename T>
38220  {
38221  public:
38222 
38228 
38230 
38232  : exprtk::igeneric_function<T>("VT|VTTT")
38233  /*
38234  Overloads:
38235  0. VT - vector, N
38236  1. VTTT - vector, N, r0, r1
38237  */
38238  {}
38239 
38240  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38241  {
38242  vector_t vec(parameters[0]);
38243 
38244  std::size_t n = 0;
38245  std::size_t r0 = 0;
38246  std::size_t r1 = vec.size() - 1;
38247 
38248  if (!scalar_t(parameters[1]).to_uint(n))
38249  return T(0);
38250 
38251  if (
38252  (1 == ps_index) &&
38253  !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)
38254  )
38255  return T(0);
38256 
38257  std::size_t dist = r1 - r0 + 1;
38258 
38259  if (n > dist)
38260  return T(0);
38261 
38262  std::size_t shift = (dist - (n % dist)) % dist;
38263 
38264  std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1);
38265 
38266  for (std::size_t i = r0; i < r0 + n; ++i)
38267  {
38268  vec[i] = T(0);
38269  }
38270 
38271  return T(1);
38272  }
38273  };
38274 
38275  template <typename T>
38277  {
38278  public:
38279 
38285 
38287 
38289  : exprtk::igeneric_function<T>("V|VTT|VS|VSTT")
38290  /*
38291  Overloads:
38292  0. V - vector
38293  1. VTT - vector, r0, r1
38294  2. VS - vector, string
38295  3. VSTT - vector, string, r0, r1
38296  */
38297  {}
38298 
38299  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38300  {
38301  vector_t vec(parameters[0]);
38302 
38303  std::size_t r0 = 0;
38304  std::size_t r1 = vec.size() - 1;
38305 
38306  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38307  return T(0);
38308  if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38309  return T(0);
38310 
38311  bool ascending = true;
38312 
38313  if ((2 == ps_index) || (3 == ps_index))
38314  {
38315  if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending"))
38316  ascending = true;
38317  else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending"))
38318  ascending = false;
38319  else
38320  return T(0);
38321  }
38322 
38323  if (ascending)
38324  std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ());
38325  else
38326  std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>());
38327 
38328  return T(1);
38329  }
38330  };
38331 
38332  template <typename T>
38334  {
38335  public:
38336 
38342 
38344 
38346  : exprtk::igeneric_function<T>("VT|VTTT")
38347  /*
38348  Overloads:
38349  0. VT - vector, nth-element
38350  1. VTTT - vector, nth-element, r0, r1
38351  */
38352  {}
38353 
38354  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38355  {
38356  vector_t vec(parameters[0]);
38357 
38358  std::size_t n = 0;
38359  std::size_t r0 = 0;
38360  std::size_t r1 = vec.size() - 1;
38361 
38362  if (!scalar_t(parameters[1]).to_uint(n))
38363  return T(0);
38364 
38365  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38366  return std::numeric_limits<T>::quiet_NaN();
38367 
38368  std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1);
38369 
38370  return T(1);
38371  }
38372  };
38373 
38374  template <typename T>
38376  {
38377  public:
38378 
38384 
38386 
38388  : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT")
38389  /*
38390  Overloads:
38391  0. VT - vector, increment
38392  1. VTT - vector, increment, base
38393  2. VTTTT - vector, increment, r0, r1
38394  3. VTTTT - vector, increment, base, r0, r1
38395  */
38396  {}
38397 
38398  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38399  {
38400  vector_t vec(parameters[0]);
38401 
38402  T increment = scalar_t(parameters[1])();
38403  T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0);
38404 
38405  std::size_t r0 = 0;
38406  std::size_t r1 = vec.size() - 1;
38407 
38408  if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38409  return std::numeric_limits<T>::quiet_NaN();
38410  else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0))
38411  return std::numeric_limits<T>::quiet_NaN();
38412  else
38413  {
38414  long long j = 0;
38415 
38416  for (std::size_t i = r0; i <= r1; ++i, ++j)
38417  {
38418  vec[i] = base + (increment * j);
38419  }
38420  }
38421 
38422  return T(1);
38423  }
38424  };
38425 
38426  template <typename T>
38428  {
38429  public:
38430 
38435 
38437 
38439  : exprtk::igeneric_function<T>("V|VTT")
38440  /*
38441  Overloads:
38442  0. V - vector
38443  1. VTT - vector, r0, r1
38444  */
38445  {}
38446 
38447  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38448  {
38449  const vector_t vec(parameters[0]);
38450 
38451  std::size_t r0 = 0;
38452  std::size_t r1 = vec.size() - 1;
38453 
38454  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0))
38455  return std::numeric_limits<T>::quiet_NaN();
38456 
38457  T result = T(0);
38458  T error = T(0);
38459 
38460  for (std::size_t i = r0; i <= r1; ++i)
38461  {
38462  details::kahan_sum(result, error, vec[i]);
38463  }
38464 
38465  return result;
38466  }
38467  };
38468 
38469  template <typename T>
38471  {
38472  public:
38473 
38479 
38481 
38483  : exprtk::igeneric_function<T>("TVV|TVVTT")
38484  /*
38485  y <- ax + y
38486  Overloads:
38487  0. TVV - a, x(vector), y(vector)
38488  1. TVVTT - a, x(vector), y(vector), r0, r1
38489  */
38490  {}
38491 
38492  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38493  {
38494  const vector_t x(parameters[1]);
38495  vector_t y(parameters[2]);
38496 
38497  std::size_t r0 = 0;
38498  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38499 
38500  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38501  return std::numeric_limits<T>::quiet_NaN();
38502  else if (helper::invalid_range(y, r0, r1))
38503  return std::numeric_limits<T>::quiet_NaN();
38504 
38505  const T a = scalar_t(parameters[0])();
38506 
38507  for (std::size_t i = r0; i <= r1; ++i)
38508  {
38509  y[i] = (a * x[i]) + y[i];
38510  }
38511 
38512  return T(1);
38513  }
38514  };
38515 
38516  template <typename T>
38518  {
38519  public:
38520 
38526 
38528 
38530  : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38531  /*
38532  y <- ax + by
38533  Overloads:
38534  0. TVTV - a, x(vector), b, y(vector)
38535  1. TVTVTT - a, x(vector), b, y(vector), r0, r1
38536  */
38537  {}
38538 
38539  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38540  {
38541  const vector_t x(parameters[1]);
38542  vector_t y(parameters[3]);
38543 
38544  std::size_t r0 = 0;
38545  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38546 
38547  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38548  return std::numeric_limits<T>::quiet_NaN();
38549  else if (helper::invalid_range(y, r0, r1))
38550  return std::numeric_limits<T>::quiet_NaN();
38551 
38552  const T a = scalar_t(parameters[0])();
38553  const T b = scalar_t(parameters[2])();
38554 
38555  for (std::size_t i = r0; i <= r1; ++i)
38556  {
38557  y[i] = (a * x[i]) + (b * y[i]);
38558  }
38559 
38560  return T(1);
38561  }
38562  };
38563 
38564  template <typename T>
38566  {
38567  public:
38568 
38574 
38576 
38578  : exprtk::igeneric_function<T>("TVVV|TVVVTT")
38579  /*
38580  z <- ax + y
38581  Overloads:
38582  0. TVVV - a, x(vector), y(vector), z(vector)
38583  1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1
38584  */
38585  {}
38586 
38587  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38588  {
38589  const vector_t x(parameters[1]);
38590  const vector_t y(parameters[2]);
38591  vector_t z(parameters[3]);
38592 
38593  std::size_t r0 = 0;
38594  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38595 
38596  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1))
38597  return std::numeric_limits<T>::quiet_NaN();
38598  else if (helper::invalid_range(y, r0, r1))
38599  return std::numeric_limits<T>::quiet_NaN();
38600  else if (helper::invalid_range(z, r0, r1))
38601  return std::numeric_limits<T>::quiet_NaN();
38602 
38603  const T a = scalar_t(parameters[0])();
38604 
38605  for (std::size_t i = r0; i <= r1; ++i)
38606  {
38607  z[i] = (a * x[i]) + y[i];
38608  }
38609 
38610  return T(1);
38611  }
38612  };
38613 
38614  template <typename T>
38616  {
38617  public:
38618 
38624 
38626 
38628  : exprtk::igeneric_function<T>("TVTVV|TVTVVTT")
38629  /*
38630  z <- ax + by
38631  Overloads:
38632  0. TVTVV - a, x(vector), b, y(vector), z(vector)
38633  1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1
38634  */
38635  {}
38636 
38637  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38638  {
38639  const vector_t x(parameters[1]);
38640  const vector_t y(parameters[3]);
38641  vector_t z(parameters[4]);
38642 
38643  std::size_t r0 = 0;
38644  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38645 
38646  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38647  return std::numeric_limits<T>::quiet_NaN();
38648  else if (helper::invalid_range(y, r0, r1))
38649  return std::numeric_limits<T>::quiet_NaN();
38650  else if (helper::invalid_range(z, r0, r1))
38651  return std::numeric_limits<T>::quiet_NaN();
38652 
38653  const T a = scalar_t(parameters[0])();
38654  const T b = scalar_t(parameters[2])();
38655 
38656  for (std::size_t i = r0; i <= r1; ++i)
38657  {
38658  z[i] = (a * x[i]) + (b * y[i]);
38659  }
38660 
38661  return T(1);
38662  }
38663  };
38664 
38665  template <typename T>
38667  {
38668  public:
38669 
38675 
38677 
38679  : exprtk::igeneric_function<T>("TVTV|TVTVTT")
38680  /*
38681  z <- ax + b
38682  Overloads:
38683  0. TVTV - a, x(vector), b, z(vector)
38684  1. TVTVTT - a, x(vector), b, z(vector), r0, r1
38685  */
38686  {}
38687 
38688  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38689  {
38690  const vector_t x(parameters[1]);
38691  vector_t z(parameters[3]);
38692 
38693  std::size_t r0 = 0;
38694  std::size_t r1 = x.size() - 1;
38695 
38696  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1))
38697  return std::numeric_limits<T>::quiet_NaN();
38698  else if (helper::invalid_range(z, r0, r1))
38699  return std::numeric_limits<T>::quiet_NaN();
38700 
38701  const T a = scalar_t(parameters[0])();
38702  const T b = scalar_t(parameters[2])();
38703 
38704  for (std::size_t i = r0; i <= r1; ++i)
38705  {
38706  z[i] = (a * x[i]) + b;
38707  }
38708 
38709  return T(1);
38710  }
38711  };
38712 
38713  template <typename T>
38714  class dot : public exprtk::igeneric_function<T>
38715  {
38716  public:
38717 
38723 
38725 
38727  : exprtk::igeneric_function<T>("VV|VVTT")
38728  /*
38729  Overloads:
38730  0. VV - x(vector), y(vector)
38731  1. VVTT - x(vector), y(vector), r0, r1
38732  */
38733  {}
38734 
38735  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38736  {
38737  const vector_t x(parameters[0]);
38738  const vector_t y(parameters[1]);
38739 
38740  std::size_t r0 = 0;
38741  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38742 
38743  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38744  return std::numeric_limits<T>::quiet_NaN();
38745  else if (helper::invalid_range(y, r0, r1))
38746  return std::numeric_limits<T>::quiet_NaN();
38747 
38748  T result = T(0);
38749 
38750  for (std::size_t i = r0; i <= r1; ++i)
38751  {
38752  result += (x[i] * y[i]);
38753  }
38754 
38755  return result;
38756  }
38757  };
38758 
38759  template <typename T>
38761  {
38762  public:
38763 
38769 
38771 
38773  : exprtk::igeneric_function<T>("VV|VVTT")
38774  /*
38775  Overloads:
38776  0. VV - x(vector), y(vector)
38777  1. VVTT - x(vector), y(vector), r0, r1
38778  */
38779  {}
38780 
38781  inline T operator() (const std::size_t& ps_index, parameter_list_t parameters)
38782  {
38783  const vector_t x(parameters[0]);
38784  const vector_t y(parameters[1]);
38785 
38786  std::size_t r0 = 0;
38787  std::size_t r1 = std::min(x.size(),y.size()) - 1;
38788 
38789  if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0))
38790  return std::numeric_limits<T>::quiet_NaN();
38791  else if (helper::invalid_range(y, r0, r1))
38792  return std::numeric_limits<T>::quiet_NaN();
38793 
38794  T result = T(0);
38795  T error = T(0);
38796 
38797  for (std::size_t i = r0; i <= r1; ++i)
38798  {
38799  details::kahan_sum(result, error, (x[i] * y[i]));
38800  }
38801 
38802  return result;
38803  }
38804  };
38805 
38806  template <typename T>
38807  struct package
38808  {
38830 
38832  {
38833  #define exprtk_register_function(FunctionName,FunctionType) \
38834  if (!symtab.add_function(FunctionName,FunctionType)) \
38835  { \
38836  exprtk_debug(( \
38837  "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \
38838  FunctionName)); \
38839  return false; \
38840  } \
38841 
38842  exprtk_register_function("all_true" ,at)
38843  exprtk_register_function("all_false" ,af)
38844  exprtk_register_function("any_true" ,nt)
38845  exprtk_register_function("any_false" ,nf)
38846  exprtk_register_function("count" , c)
38847  exprtk_register_function("copy" ,cp)
38848  exprtk_register_function("rotate_left" ,rl)
38850  exprtk_register_function("rotate_right" ,rr)
38852  exprtk_register_function("shftl" ,sl)
38853  exprtk_register_function("shftr" ,sr)
38854  exprtk_register_function("sort" ,st)
38855  exprtk_register_function("nth_element" ,ne)
38856  exprtk_register_function("iota" ,ia)
38857  exprtk_register_function("sumk" ,sk)
38864  exprtk_register_function("dotk" ,dtk)
38865  #undef exprtk_register_function
38866 
38867  return true;
38868  }
38869  };
38870 
38871  } // namespace exprtk::rtl::vecops
38872  } // namespace exprtk::rtl
38873 } // namespace exprtk
38874 #endif
38875 
38876 namespace exprtk
38877 {
38878  namespace information
38879  {
38880  static const char* library = "Mathematical Expression Toolkit";
38881  static const char* version = "2.71828182845904523536028747135266249775724709369995957"
38882  "4966967627724076630353547594571382178525166427427466391";
38883  static const char* date = "20190818";
38884 
38885  static inline std::string data()
38886  {
38887  static const std::string info_str = std::string(library) +
38888  std::string(" v") + std::string(version) +
38889  std::string(" (") + date + std::string(")");
38890  return info_str;
38891  }
38892 
38893  } // namespace information
38894 
38895  #ifdef exprtk_debug
38896  #undef exprtk_debug
38897  #endif
38898 
38899  #ifdef exprtk_error_location
38900  #undef exprtk_error_location
38901  #endif
38902 
38903  #ifdef exprtk_disable_fallthrough_begin
38904  #undef exprtk_disable_fallthrough_begin
38905  #endif
38906 
38907  #ifdef exprtk_disable_fallthrough_end
38908  #undef exprtk_disable_fallthrough_end
38909  #endif
38910 
38911 } // namespace exprtk
38912 
38913 #endif