]>
Commit | Line | Data |
---|---|---|
4640a84e SA |
1 | /* |
2 | ****************************************************************** | |
3 | * C++ Mathematical Expression Toolkit Library * | |
4 | * * | |
5 | * Author: Arash Partow (1999-2020) * | |
6 | * URL: http://www.partow.net/programming/exprtk/index.html * | |
7 | * * | |
8 | * Copyright notice: * | |
9 | * Free use of the C++ Mathematical Expression Toolkit Library is * | |
10 | * permitted under the guidelines and in accordance with the most * | |
11 | * current version of the MIT License. * | |
12 | * http://www.opensource.org/licenses/MIT * | |
13 | * * | |
14 | * Example expressions: * | |
15 | * (00) (y + x / y) * (x - y / x) * | |
16 | * (01) (x^2 / sin(2 * pi / y)) - x / 2 * | |
17 | * (02) sqrt(1 - (x^2)) * | |
18 | * (03) 1 - sin(2 * x) + cos(pi / y) * | |
19 | * (04) a * exp(2 * t) + c * | |
20 | * (05) if(((x + 2) == 3) and ((y + 5) <= 9),1 + w, 2 / z) * | |
21 | * (06) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x * | |
22 | * (07) z := x + sin(2 * pi / y) * | |
23 | * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) * | |
24 | * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) * | |
25 | * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) * | |
26 | * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) * | |
27 | * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] * | |
28 | * * | |
29 | ****************************************************************** | |
30 | */ | |
31 | ||
32 | ||
33 | #ifndef INCLUDE_EXPRTK_HPP | |
34 | #define INCLUDE_EXPRTK_HPP | |
35 | ||
36 | ||
37 | #include <algorithm> | |
38 | #include <cctype> | |
39 | #include <cmath> | |
40 | #include <complex> | |
41 | #include <cstdio> | |
42 | #include <cstdlib> | |
43 | #include <cstring> | |
44 | #include <deque> | |
45 | #include <exception> | |
46 | #include <functional> | |
47 | #include <iterator> | |
48 | #include <limits> | |
49 | #include <list> | |
50 | #include <map> | |
51 | #include <set> | |
52 | #include <stack> | |
53 | #include <stdexcept> | |
54 | #include <string> | |
55 | #include <utility> | |
56 | #include <vector> | |
57 | ||
58 | ||
59 | namespace exprtk | |
60 | { | |
61 | #ifdef exprtk_enable_debugging | |
62 | #define exprtk_debug(params) printf params | |
63 | #else | |
64 | #define exprtk_debug(params) (void)0 | |
65 | #endif | |
66 | ||
67 | #define exprtk_error_location \ | |
68 | "exprtk.hpp:" + details::to_str(__LINE__) \ | |
69 | ||
70 | #if defined(__GNUC__) && (__GNUC__ >= 7) | |
71 | ||
72 | #define exprtk_disable_fallthrough_begin \ | |
73 | _Pragma ("GCC diagnostic push") \ | |
74 | _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") \ | |
75 | ||
76 | #define exprtk_disable_fallthrough_end \ | |
77 | _Pragma ("GCC diagnostic pop") \ | |
78 | ||
79 | #else | |
80 | #define exprtk_disable_fallthrough_begin (void)0; | |
81 | #define exprtk_disable_fallthrough_end (void)0; | |
82 | #endif | |
83 | ||
84 | namespace details | |
85 | { | |
86 | typedef unsigned char uchar_t; | |
87 | typedef char char_t; | |
88 | typedef uchar_t* uchar_ptr; | |
89 | typedef char_t* char_ptr; | |
90 | typedef uchar_t const* uchar_cptr; | |
91 | typedef char_t const* char_cptr; | |
92 | typedef unsigned long long int _uint64_t; | |
93 | typedef long long int _int64_t; | |
94 | ||
95 | inline bool is_whitespace(const char_t c) | |
96 | { | |
97 | return (' ' == c) || ('\n' == c) || | |
98 | ('\r' == c) || ('\t' == c) || | |
99 | ('\b' == c) || ('\v' == c) || | |
100 | ('\f' == c) ; | |
101 | } | |
102 | ||
103 | inline bool is_operator_char(const char_t c) | |
104 | { | |
105 | return ('+' == c) || ('-' == c) || | |
106 | ('*' == c) || ('/' == c) || | |
107 | ('^' == c) || ('<' == c) || | |
108 | ('>' == c) || ('=' == c) || | |
109 | (',' == c) || ('!' == c) || | |
110 | ('(' == c) || (')' == c) || | |
111 | ('[' == c) || (']' == c) || | |
112 | ('{' == c) || ('}' == c) || | |
113 | ('%' == c) || (':' == c) || | |
114 | ('?' == c) || ('&' == c) || | |
115 | ('|' == c) || (';' == c) ; | |
116 | } | |
117 | ||
118 | inline bool is_letter(const char_t c) | |
119 | { | |
120 | return (('a' <= c) && (c <= 'z')) || | |
121 | (('A' <= c) && (c <= 'Z')) ; | |
122 | } | |
123 | ||
124 | inline bool is_digit(const char_t c) | |
125 | { | |
126 | return ('0' <= c) && (c <= '9'); | |
127 | } | |
128 | ||
129 | inline bool is_letter_or_digit(const char_t c) | |
130 | { | |
131 | return is_letter(c) || is_digit(c); | |
132 | } | |
133 | ||
134 | inline bool is_left_bracket(const char_t c) | |
135 | { | |
136 | return ('(' == c) || ('[' == c) || ('{' == c); | |
137 | } | |
138 | ||
139 | inline bool is_right_bracket(const char_t c) | |
140 | { | |
141 | return (')' == c) || (']' == c) || ('}' == c); | |
142 | } | |
143 | ||
144 | inline bool is_bracket(const char_t c) | |
145 | { | |
146 | return is_left_bracket(c) || is_right_bracket(c); | |
147 | } | |
148 | ||
149 | inline bool is_sign(const char_t c) | |
150 | { | |
151 | return ('+' == c) || ('-' == c); | |
152 | } | |
153 | ||
154 | inline bool is_invalid(const char_t c) | |
155 | { | |
156 | return !is_whitespace (c) && | |
157 | !is_operator_char(c) && | |
158 | !is_letter (c) && | |
159 | !is_digit (c) && | |
160 | ('.' != c) && | |
161 | ('_' != c) && | |
162 | ('$' != c) && | |
163 | ('~' != c) && | |
164 | ('\'' != c); | |
165 | } | |
166 | ||
167 | #ifndef exprtk_disable_caseinsensitivity | |
168 | inline void case_normalise(std::string& s) | |
169 | { | |
170 | for (std::size_t i = 0; i < s.size(); ++i) | |
171 | { | |
172 | s[i] = static_cast<std::string::value_type>(std::tolower(s[i])); | |
173 | } | |
174 | } | |
175 | ||
176 | inline bool imatch(const char_t c1, const char_t c2) | |
177 | { | |
178 | return std::tolower(c1) == std::tolower(c2); | |
179 | } | |
180 | ||
181 | inline bool imatch(const std::string& s1, const std::string& s2) | |
182 | { | |
183 | if (s1.size() == s2.size()) | |
184 | { | |
185 | for (std::size_t i = 0; i < s1.size(); ++i) | |
186 | { | |
187 | if (std::tolower(s1[i]) != std::tolower(s2[i])) | |
188 | { | |
189 | return false; | |
190 | } | |
191 | } | |
192 | ||
193 | return true; | |
194 | } | |
195 | ||
196 | return false; | |
197 | } | |
198 | ||
199 | struct ilesscompare | |
200 | { | |
201 | inline bool operator() (const std::string& s1, const std::string& s2) const | |
202 | { | |
203 | const std::size_t length = std::min(s1.size(),s2.size()); | |
204 | ||
205 | for (std::size_t i = 0; i < length; ++i) | |
206 | { | |
207 | const char_t c1 = static_cast<char>(std::tolower(s1[i])); | |
208 | const char_t c2 = static_cast<char>(std::tolower(s2[i])); | |
209 | ||
210 | if (c1 > c2) | |
211 | return false; | |
212 | else if (c1 < c2) | |
213 | return true; | |
214 | } | |
215 | ||
216 | return s1.size() < s2.size(); | |
217 | } | |
218 | }; | |
219 | ||
220 | #else | |
221 | inline void case_normalise(std::string&) | |
222 | {} | |
223 | ||
224 | inline bool imatch(const char_t c1, const char_t c2) | |
225 | { | |
226 | return c1 == c2; | |
227 | } | |
228 | ||
229 | inline bool imatch(const std::string& s1, const std::string& s2) | |
230 | { | |
231 | return s1 == s2; | |
232 | } | |
233 | ||
234 | struct ilesscompare | |
235 | { | |
236 | inline bool operator() (const std::string& s1, const std::string& s2) const | |
237 | { | |
238 | return s1 < s2; | |
239 | } | |
240 | }; | |
241 | #endif | |
242 | ||
243 | inline bool is_valid_sf_symbol(const std::string& symbol) | |
244 | { | |
245 | // Special function: $f12 or $F34 | |
246 | return (4 == symbol.size()) && | |
247 | ('$' == symbol[0]) && | |
248 | imatch('f',symbol[1]) && | |
249 | is_digit(symbol[2]) && | |
250 | is_digit(symbol[3]); | |
251 | } | |
252 | ||
253 | inline const char_t& front(const std::string& s) | |
254 | { | |
255 | return s[0]; | |
256 | } | |
257 | ||
258 | inline const char_t& back(const std::string& s) | |
259 | { | |
260 | return s[s.size() - 1]; | |
261 | } | |
262 | ||
263 | inline std::string to_str(int i) | |
264 | { | |
265 | if (0 == i) | |
266 | return std::string("0"); | |
267 | ||
268 | std::string result; | |
269 | ||
270 | if (i < 0) | |
271 | { | |
272 | for ( ; i; i /= 10) | |
273 | { | |
274 | result += '0' + char(-(i % 10)); | |
275 | } | |
276 | ||
277 | result += '-'; | |
278 | } | |
279 | else | |
280 | { | |
281 | for ( ; i; i /= 10) | |
282 | { | |
283 | result += '0' + char(i % 10); | |
284 | } | |
285 | } | |
286 | ||
287 | std::reverse(result.begin(), result.end()); | |
288 | ||
289 | return result; | |
290 | } | |
291 | ||
292 | inline std::string to_str(std::size_t i) | |
293 | { | |
294 | return to_str(static_cast<int>(i)); | |
295 | } | |
296 | ||
297 | inline bool is_hex_digit(const std::string::value_type digit) | |
298 | { | |
299 | return (('0' <= digit) && (digit <= '9')) || | |
300 | (('A' <= digit) && (digit <= 'F')) || | |
301 | (('a' <= digit) && (digit <= 'f')) ; | |
302 | } | |
303 | ||
304 | inline uchar_t hex_to_bin(uchar_t h) | |
305 | { | |
306 | if (('0' <= h) && (h <= '9')) | |
307 | return (h - '0'); | |
308 | else | |
309 | return static_cast<unsigned char>(std::toupper(h) - 'A'); | |
310 | } | |
311 | ||
312 | template <typename Iterator> | |
313 | inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result) | |
314 | { | |
315 | if ( | |
316 | (end != (itr )) && | |
317 | (end != (itr + 1)) && | |
318 | (end != (itr + 2)) && | |
319 | (end != (itr + 3)) && | |
320 | ('0' == *(itr )) && | |
321 | ( | |
322 | ('x' == *(itr + 1)) || | |
323 | ('X' == *(itr + 1)) | |
324 | ) && | |
325 | (is_hex_digit(*(itr + 2))) && | |
326 | (is_hex_digit(*(itr + 3))) | |
327 | ) | |
328 | { | |
329 | result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | | |
330 | hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; | |
331 | itr += 3; | |
332 | } | |
333 | else | |
334 | result = '\0'; | |
335 | } | |
336 | ||
337 | inline void cleanup_escapes(std::string& s) | |
338 | { | |
339 | typedef std::string::iterator str_itr_t; | |
340 | ||
341 | str_itr_t itr1 = s.begin(); | |
342 | str_itr_t itr2 = s.begin(); | |
343 | str_itr_t end = s.end (); | |
344 | ||
345 | std::size_t removal_count = 0; | |
346 | ||
347 | while (end != itr1) | |
348 | { | |
349 | if ('\\' == (*itr1)) | |
350 | { | |
351 | ++removal_count; | |
352 | ||
353 | if (end == ++itr1) | |
354 | break; | |
355 | else if ('\\' != (*itr1)) | |
356 | { | |
357 | switch (*itr1) | |
358 | { | |
359 | case 'n' : (*itr1) = '\n'; break; | |
360 | case 'r' : (*itr1) = '\r'; break; | |
361 | case 't' : (*itr1) = '\t'; break; | |
362 | case '0' : parse_hex(itr1, end, (*itr1)); | |
363 | removal_count += 3; | |
364 | break; | |
365 | } | |
366 | ||
367 | continue; | |
368 | } | |
369 | } | |
370 | ||
371 | if (itr1 != itr2) | |
372 | { | |
373 | (*itr2) = (*itr1); | |
374 | } | |
375 | ||
376 | ++itr1; | |
377 | ++itr2; | |
378 | } | |
379 | ||
380 | s.resize(s.size() - removal_count); | |
381 | } | |
382 | ||
383 | class build_string | |
384 | { | |
385 | public: | |
386 | ||
387 | build_string(const std::size_t& initial_size = 64) | |
388 | { | |
389 | data_.reserve(initial_size); | |
390 | } | |
391 | ||
392 | inline build_string& operator << (const std::string& s) | |
393 | { | |
394 | data_ += s; | |
395 | return (*this); | |
396 | } | |
397 | ||
398 | inline build_string& operator << (char_cptr s) | |
399 | { | |
400 | data_ += std::string(s); | |
401 | return (*this); | |
402 | } | |
403 | ||
404 | inline operator std::string () const | |
405 | { | |
406 | return data_; | |
407 | } | |
408 | ||
409 | inline std::string as_string() const | |
410 | { | |
411 | return data_; | |
412 | } | |
413 | ||
414 | private: | |
415 | ||
416 | std::string data_; | |
417 | }; | |
418 | ||
419 | static const std::string reserved_words[] = | |
420 | { | |
421 | "break", "case", "continue", "default", "false", "for", | |
422 | "if", "else", "ilike", "in", "like", "and", "nand", "nor", | |
423 | "not", "null", "or", "repeat", "return", "shl", "shr", | |
424 | "swap", "switch", "true", "until", "var", "while", "xnor", | |
425 | "xor", "&", "|" | |
426 | }; | |
427 | ||
428 | static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string); | |
429 | ||
430 | static const std::string reserved_symbols[] = | |
431 | { | |
432 | "abs", "acos", "acosh", "and", "asin", "asinh", "atan", | |
433 | "atanh", "atan2", "avg", "break", "case", "ceil", "clamp", | |
434 | "continue", "cos", "cosh", "cot", "csc", "default", | |
435 | "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp", | |
436 | "expm1", "false", "floor", "for", "frac", "grad2deg", | |
437 | "hypot", "iclamp", "if", "else", "ilike", "in", "inrange", | |
438 | "like", "log", "log10", "log2", "logn", "log1p", "mand", | |
439 | "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor", | |
440 | "not", "not_equal", "null", "or", "pow", "rad2deg", | |
441 | "repeat", "return", "root", "round", "roundn", "sec", "sgn", | |
442 | "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap", | |
443 | "switch", "tan", "tanh", "true", "trunc", "until", "var", | |
444 | "while", "xnor", "xor", "&", "|" | |
445 | }; | |
446 | ||
447 | static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string); | |
448 | ||
449 | static const std::string base_function_list[] = | |
450 | { | |
451 | "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh", | |
452 | "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot", | |
453 | "csc", "equal", "erf", "erfc", "exp", "expm1", "floor", | |
454 | "frac", "hypot", "iclamp", "like", "log", "log10", "log2", | |
455 | "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul", | |
456 | "ncdf", "pow", "root", "round", "roundn", "sec", "sgn", | |
457 | "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh", | |
458 | "trunc", "not_equal", "inrange", "deg2grad", "deg2rad", | |
459 | "rad2deg", "grad2deg" | |
460 | }; | |
461 | ||
462 | static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string); | |
463 | ||
464 | static const std::string logic_ops_list[] = | |
465 | { | |
466 | "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|" | |
467 | }; | |
468 | ||
469 | static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string); | |
470 | ||
471 | static const std::string cntrl_struct_list[] = | |
472 | { | |
473 | "if", "switch", "for", "while", "repeat", "return" | |
474 | }; | |
475 | ||
476 | static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string); | |
477 | ||
478 | static const std::string arithmetic_ops_list[] = | |
479 | { | |
480 | "+", "-", "*", "/", "%", "^" | |
481 | }; | |
482 | ||
483 | static const std::size_t arithmetic_ops_list_size = sizeof(arithmetic_ops_list) / sizeof(std::string); | |
484 | ||
485 | static const std::string assignment_ops_list[] = | |
486 | { | |
487 | ":=", "+=", "-=", | |
488 | "*=", "/=", "%=" | |
489 | }; | |
490 | ||
491 | static const std::size_t assignment_ops_list_size = sizeof(assignment_ops_list) / sizeof(std::string); | |
492 | ||
493 | static const std::string inequality_ops_list[] = | |
494 | { | |
495 | "<", "<=", "==", | |
496 | "=", "!=", "<>", | |
497 | ">=", ">" | |
498 | }; | |
499 | ||
500 | static const std::size_t inequality_ops_list_size = sizeof(inequality_ops_list) / sizeof(std::string); | |
501 | ||
502 | inline bool is_reserved_word(const std::string& symbol) | |
503 | { | |
504 | for (std::size_t i = 0; i < reserved_words_size; ++i) | |
505 | { | |
506 | if (imatch(symbol, reserved_words[i])) | |
507 | { | |
508 | return true; | |
509 | } | |
510 | } | |
511 | ||
512 | return false; | |
513 | } | |
514 | ||
515 | inline bool is_reserved_symbol(const std::string& symbol) | |
516 | { | |
517 | for (std::size_t i = 0; i < reserved_symbols_size; ++i) | |
518 | { | |
519 | if (imatch(symbol, reserved_symbols[i])) | |
520 | { | |
521 | return true; | |
522 | } | |
523 | } | |
524 | ||
525 | return false; | |
526 | } | |
527 | ||
528 | inline bool is_base_function(const std::string& function_name) | |
529 | { | |
530 | for (std::size_t i = 0; i < base_function_list_size; ++i) | |
531 | { | |
532 | if (imatch(function_name, base_function_list[i])) | |
533 | { | |
534 | return true; | |
535 | } | |
536 | } | |
537 | ||
538 | return false; | |
539 | } | |
540 | ||
541 | inline bool is_control_struct(const std::string& cntrl_strct) | |
542 | { | |
543 | for (std::size_t i = 0; i < cntrl_struct_list_size; ++i) | |
544 | { | |
545 | if (imatch(cntrl_strct, cntrl_struct_list[i])) | |
546 | { | |
547 | return true; | |
548 | } | |
549 | } | |
550 | ||
551 | return false; | |
552 | } | |
553 | ||
554 | inline bool is_logic_opr(const std::string& lgc_opr) | |
555 | { | |
556 | for (std::size_t i = 0; i < logic_ops_list_size; ++i) | |
557 | { | |
558 | if (imatch(lgc_opr, logic_ops_list[i])) | |
559 | { | |
560 | return true; | |
561 | } | |
562 | } | |
563 | ||
564 | return false; | |
565 | } | |
566 | ||
567 | struct cs_match | |
568 | { | |
569 | static inline bool cmp(const char_t c0, const char_t c1) | |
570 | { | |
571 | return (c0 == c1); | |
572 | } | |
573 | }; | |
574 | ||
575 | struct cis_match | |
576 | { | |
577 | static inline bool cmp(const char_t c0, const char_t c1) | |
578 | { | |
579 | return (std::tolower(c0) == std::tolower(c1)); | |
580 | } | |
581 | }; | |
582 | ||
583 | template <typename Iterator, typename Compare> | |
584 | inline bool match_impl(const Iterator pattern_begin, | |
585 | const Iterator pattern_end , | |
586 | const Iterator data_begin , | |
587 | const Iterator data_end , | |
588 | const typename std::iterator_traits<Iterator>::value_type& zero_or_more, | |
589 | const typename std::iterator_traits<Iterator>::value_type& zero_or_one ) | |
590 | { | |
591 | const Iterator null_itr(0); | |
592 | ||
593 | Iterator d_itr = data_begin; | |
594 | Iterator p_itr = pattern_begin; | |
595 | Iterator tb_p_itr = null_itr; | |
596 | Iterator tb_d_itr = null_itr; | |
597 | ||
598 | while (d_itr != data_end) | |
599 | { | |
600 | if (zero_or_more == *p_itr) | |
601 | { | |
602 | while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) | |
603 | { | |
604 | ++p_itr; | |
605 | } | |
606 | ||
607 | if (pattern_end == p_itr) | |
608 | return true; | |
609 | ||
610 | const typename std::iterator_traits<Iterator>::value_type c = *(p_itr); | |
611 | ||
612 | while ((data_end != d_itr) && !Compare::cmp(c,*d_itr)) | |
613 | { | |
614 | ++d_itr; | |
615 | } | |
616 | ||
617 | tb_p_itr = p_itr; | |
618 | tb_d_itr = d_itr; | |
619 | ||
620 | continue; | |
621 | } | |
622 | else if (!Compare::cmp(*p_itr, *d_itr) && (zero_or_one != *p_itr)) | |
623 | { | |
624 | if (null_itr == tb_d_itr) | |
625 | return false; | |
626 | ||
627 | d_itr = tb_d_itr++; | |
628 | p_itr = tb_p_itr; | |
629 | ||
630 | continue; | |
631 | } | |
632 | ||
633 | ++p_itr; | |
634 | ++d_itr; | |
635 | } | |
636 | ||
637 | while ((pattern_end != p_itr) && ((zero_or_more == *p_itr) || (zero_or_one == *p_itr))) | |
638 | { | |
639 | ++p_itr; | |
640 | } | |
641 | ||
642 | return (pattern_end == p_itr); | |
643 | } | |
644 | ||
645 | inline bool wc_match(const std::string& wild_card, | |
646 | const std::string& str) | |
647 | { | |
648 | return match_impl<char_cptr,cs_match>(wild_card.data(), | |
649 | wild_card.data() + wild_card.size(), | |
650 | str.data(), | |
651 | str.data() + str.size(), | |
652 | '*', | |
653 | '?'); | |
654 | } | |
655 | ||
656 | inline bool wc_imatch(const std::string& wild_card, | |
657 | const std::string& str) | |
658 | { | |
659 | return match_impl<char_cptr,cis_match>(wild_card.data(), | |
660 | wild_card.data() + wild_card.size(), | |
661 | str.data(), | |
662 | str.data() + str.size(), | |
663 | '*', | |
664 | '?'); | |
665 | } | |
666 | ||
667 | inline bool sequence_match(const std::string& pattern, | |
668 | const std::string& str, | |
669 | std::size_t& diff_index, | |
670 | char_t& diff_value) | |
671 | { | |
672 | if (str.empty()) | |
673 | { | |
674 | return ("Z" == pattern); | |
675 | } | |
676 | else if ('*' == pattern[0]) | |
677 | return false; | |
678 | ||
679 | typedef std::string::const_iterator itr_t; | |
680 | ||
681 | itr_t p_itr = pattern.begin(); | |
682 | itr_t s_itr = str .begin(); | |
683 | ||
684 | itr_t p_end = pattern.end(); | |
685 | itr_t s_end = str .end(); | |
686 | ||
687 | while ((s_end != s_itr) && (p_end != p_itr)) | |
688 | { | |
689 | if ('*' == (*p_itr)) | |
690 | { | |
691 | const char_t target = static_cast<char>(std::toupper(*(p_itr - 1))); | |
692 | ||
693 | if ('*' == target) | |
694 | { | |
695 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); | |
696 | diff_value = static_cast<char>(std::toupper(*p_itr)); | |
697 | ||
698 | return false; | |
699 | } | |
700 | else | |
701 | ++p_itr; | |
702 | ||
703 | while (s_itr != s_end) | |
704 | { | |
705 | if (target != std::toupper(*s_itr)) | |
706 | break; | |
707 | else | |
708 | ++s_itr; | |
709 | } | |
710 | ||
711 | continue; | |
712 | } | |
713 | else if ( | |
714 | ('?' != *p_itr) && | |
715 | std::toupper(*p_itr) != std::toupper(*s_itr) | |
716 | ) | |
717 | { | |
718 | diff_index = static_cast<std::size_t>(std::distance(str.begin(),s_itr)); | |
719 | diff_value = static_cast<char>(std::toupper(*p_itr)); | |
720 | ||
721 | return false; | |
722 | } | |
723 | ||
724 | ++p_itr; | |
725 | ++s_itr; | |
726 | } | |
727 | ||
728 | return ( | |
729 | (s_end == s_itr) && | |
730 | ( | |
731 | (p_end == p_itr) || | |
732 | ('*' == *p_itr) | |
733 | ) | |
734 | ); | |
735 | } | |
736 | ||
737 | static const double pow10[] = { | |
738 | 1.0, | |
739 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, | |
740 | 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, | |
741 | 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012, | |
742 | 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016 | |
743 | }; | |
744 | ||
745 | static const std::size_t pow10_size = sizeof(pow10) / sizeof(double); | |
746 | ||
747 | namespace numeric | |
748 | { | |
749 | namespace constant | |
750 | { | |
751 | static const double e = 2.71828182845904523536028747135266249775724709369996; | |
752 | static const double pi = 3.14159265358979323846264338327950288419716939937510; | |
753 | static const double pi_2 = 1.57079632679489661923132169163975144209858469968755; | |
754 | static const double pi_4 = 0.78539816339744830961566084581987572104929234984378; | |
755 | static const double pi_180 = 0.01745329251994329576923690768488612713442871888542; | |
756 | static const double _1_pi = 0.31830988618379067153776752674502872406891929148091; | |
757 | static const double _2_pi = 0.63661977236758134307553505349005744813783858296183; | |
758 | static const double _180_pi = 57.29577951308232087679815481410517033240547246656443; | |
759 | static const double log2 = 0.69314718055994530941723212145817656807550013436026; | |
760 | static const double sqrt2 = 1.41421356237309504880168872420969807856967187537695; | |
761 | } | |
762 | ||
763 | namespace details | |
764 | { | |
765 | struct unknown_type_tag { unknown_type_tag() {} }; | |
766 | struct real_type_tag { real_type_tag () {} }; | |
767 | struct complex_type_tag { complex_type_tag() {} }; | |
768 | struct int_type_tag { int_type_tag () {} }; | |
769 | ||
770 | template <typename T> | |
771 | struct number_type | |
772 | { | |
773 | typedef unknown_type_tag type; | |
774 | number_type() {} | |
775 | }; | |
776 | ||
777 | #define exprtk_register_real_type_tag(T) \ | |
778 | template<> struct number_type<T> \ | |
779 | { typedef real_type_tag type; number_type() {} }; \ | |
780 | ||
781 | #define exprtk_register_complex_type_tag(T) \ | |
782 | template<> struct number_type<std::complex<T> > \ | |
783 | { typedef complex_type_tag type; number_type() {} }; \ | |
784 | ||
785 | #define exprtk_register_int_type_tag(T) \ | |
786 | template<> struct number_type<T> \ | |
787 | { typedef int_type_tag type; number_type() {} }; \ | |
788 | ||
789 | exprtk_register_real_type_tag(double ) | |
790 | exprtk_register_real_type_tag(long double) | |
791 | exprtk_register_real_type_tag(float ) | |
792 | ||
793 | exprtk_register_complex_type_tag(double ) | |
794 | exprtk_register_complex_type_tag(long double) | |
795 | exprtk_register_complex_type_tag(float ) | |
796 | ||
797 | exprtk_register_int_type_tag(short ) | |
798 | exprtk_register_int_type_tag(int ) | |
799 | exprtk_register_int_type_tag(_int64_t ) | |
800 | exprtk_register_int_type_tag(unsigned short) | |
801 | exprtk_register_int_type_tag(unsigned int ) | |
802 | exprtk_register_int_type_tag(_uint64_t ) | |
803 | ||
804 | #undef exprtk_register_real_type_tag | |
805 | #undef exprtk_register_int_type_tag | |
806 | ||
807 | template <typename T> | |
808 | struct epsilon_type | |
809 | { | |
810 | static inline T value() | |
811 | { | |
812 | const T epsilon = T(0.0000000001); | |
813 | return epsilon; | |
814 | } | |
815 | }; | |
816 | ||
817 | template <> | |
818 | struct epsilon_type <float> | |
819 | { | |
820 | static inline float value() | |
821 | { | |
822 | const float epsilon = float(0.000001f); | |
823 | return epsilon; | |
824 | } | |
825 | }; | |
826 | ||
827 | template <> | |
828 | struct epsilon_type <long double> | |
829 | { | |
830 | static inline long double value() | |
831 | { | |
832 | const long double epsilon = (long double)(0.000000000001); | |
833 | return epsilon; | |
834 | } | |
835 | }; | |
836 | ||
837 | template <typename T> | |
838 | inline bool is_nan_impl(const T v, real_type_tag) | |
839 | { | |
840 | return std::not_equal_to<T>()(v,v); | |
841 | } | |
842 | ||
843 | template <typename T> | |
844 | inline int to_int32_impl(const T v, real_type_tag) | |
845 | { | |
846 | return static_cast<int>(v); | |
847 | } | |
848 | ||
849 | template <typename T> | |
850 | inline _int64_t to_int64_impl(const T v, real_type_tag) | |
851 | { | |
852 | return static_cast<_int64_t>(v); | |
853 | } | |
854 | ||
855 | template <typename T> | |
856 | inline bool is_true_impl(const T v) | |
857 | { | |
858 | return std::not_equal_to<T>()(T(0),v); | |
859 | } | |
860 | ||
861 | template <typename T> | |
862 | inline bool is_false_impl(const T v) | |
863 | { | |
864 | return std::equal_to<T>()(T(0),v); | |
865 | } | |
866 | ||
867 | template <typename T> | |
868 | inline T abs_impl(const T v, real_type_tag) | |
869 | { | |
870 | return ((v < T(0)) ? -v : v); | |
871 | } | |
872 | ||
873 | template <typename T> | |
874 | inline T min_impl(const T v0, const T v1, real_type_tag) | |
875 | { | |
876 | return std::min<T>(v0,v1); | |
877 | } | |
878 | ||
879 | template <typename T> | |
880 | inline T max_impl(const T v0, const T v1, real_type_tag) | |
881 | { | |
882 | return std::max<T>(v0,v1); | |
883 | } | |
884 | ||
885 | template <typename T> | |
886 | inline T equal_impl(const T v0, const T v1, real_type_tag) | |
887 | { | |
888 | const T epsilon = epsilon_type<T>::value(); | |
889 | return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0); | |
890 | } | |
891 | ||
892 | inline float equal_impl(const float v0, const float v1, real_type_tag) | |
893 | { | |
894 | const float epsilon = epsilon_type<float>::value(); | |
895 | return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f; | |
896 | } | |
897 | ||
898 | template <typename T> | |
899 | inline T equal_impl(const T v0, const T v1, int_type_tag) | |
900 | { | |
901 | return (v0 == v1) ? 1 : 0; | |
902 | } | |
903 | ||
904 | template <typename T> | |
905 | inline T expm1_impl(const T v, real_type_tag) | |
906 | { | |
907 | // return std::expm1<T>(v); | |
908 | if (abs_impl(v,real_type_tag()) < T(0.00001)) | |
909 | return v + (T(0.5) * v * v); | |
910 | else | |
911 | return std::exp(v) - T(1); | |
912 | } | |
913 | ||
914 | template <typename T> | |
915 | inline T expm1_impl(const T v, int_type_tag) | |
916 | { | |
917 | return T(std::exp<double>(v)) - T(1); | |
918 | } | |
919 | ||
920 | template <typename T> | |
921 | inline T nequal_impl(const T v0, const T v1, real_type_tag) | |
922 | { | |
923 | typedef real_type_tag rtg; | |
924 | const T epsilon = epsilon_type<T>::value(); | |
925 | return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0); | |
926 | } | |
927 | ||
928 | inline float nequal_impl(const float v0, const float v1, real_type_tag) | |
929 | { | |
930 | typedef real_type_tag rtg; | |
931 | const float epsilon = epsilon_type<float>::value(); | |
932 | return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f; | |
933 | } | |
934 | ||
935 | template <typename T> | |
936 | inline T nequal_impl(const T v0, const T v1, int_type_tag) | |
937 | { | |
938 | return (v0 != v1) ? 1 : 0; | |
939 | } | |
940 | ||
941 | template <typename T> | |
942 | inline T modulus_impl(const T v0, const T v1, real_type_tag) | |
943 | { | |
944 | return std::fmod(v0,v1); | |
945 | } | |
946 | ||
947 | template <typename T> | |
948 | inline T modulus_impl(const T v0, const T v1, int_type_tag) | |
949 | { | |
950 | return v0 % v1; | |
951 | } | |
952 | ||
953 | template <typename T> | |
954 | inline T pow_impl(const T v0, const T v1, real_type_tag) | |
955 | { | |
956 | return std::pow(v0,v1); | |
957 | } | |
958 | ||
959 | template <typename T> | |
960 | inline T pow_impl(const T v0, const T v1, int_type_tag) | |
961 | { | |
962 | return std::pow(static_cast<double>(v0),static_cast<double>(v1)); | |
963 | } | |
964 | ||
965 | template <typename T> | |
966 | inline T logn_impl(const T v0, const T v1, real_type_tag) | |
967 | { | |
968 | return std::log(v0) / std::log(v1); | |
969 | } | |
970 | ||
971 | template <typename T> | |
972 | inline T logn_impl(const T v0, const T v1, int_type_tag) | |
973 | { | |
974 | return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag())); | |
975 | } | |
976 | ||
977 | template <typename T> | |
978 | inline T log1p_impl(const T v, real_type_tag) | |
979 | { | |
980 | if (v > T(-1)) | |
981 | { | |
982 | if (abs_impl(v,real_type_tag()) > T(0.0001)) | |
983 | { | |
984 | return std::log(T(1) + v); | |
985 | } | |
986 | else | |
987 | return (T(-0.5) * v + T(1)) * v; | |
988 | } | |
989 | else | |
990 | return std::numeric_limits<T>::quiet_NaN(); | |
991 | } | |
992 | ||
993 | template <typename T> | |
994 | inline T log1p_impl(const T v, int_type_tag) | |
995 | { | |
996 | if (v > T(-1)) | |
997 | { | |
998 | return std::log(T(1) + v); | |
999 | } | |
1000 | else | |
1001 | return std::numeric_limits<T>::quiet_NaN(); | |
1002 | } | |
1003 | ||
1004 | template <typename T> | |
1005 | inline T root_impl(const T v0, const T v1, real_type_tag) | |
1006 | { | |
1007 | if (v1 < T(0)) | |
1008 | return std::numeric_limits<T>::quiet_NaN(); | |
1009 | ||
1010 | const std::size_t n = static_cast<std::size_t>(v1); | |
1011 | ||
1012 | if ((v0 < T(0)) && (0 == (n % 2))) | |
1013 | return std::numeric_limits<T>::quiet_NaN(); | |
1014 | ||
1015 | return std::pow(v0, T(1) / n); | |
1016 | } | |
1017 | ||
1018 | template <typename T> | |
1019 | inline T root_impl(const T v0, const T v1, int_type_tag) | |
1020 | { | |
1021 | return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()); | |
1022 | } | |
1023 | ||
1024 | template <typename T> | |
1025 | inline T round_impl(const T v, real_type_tag) | |
1026 | { | |
1027 | return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5))); | |
1028 | } | |
1029 | ||
1030 | template <typename T> | |
1031 | inline T roundn_impl(const T v0, const T v1, real_type_tag) | |
1032 | { | |
1033 | const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1))); | |
1034 | const T p10 = T(pow10[index]); | |
1035 | ||
1036 | if (v0 < T(0)) | |
1037 | return T(std::ceil ((v0 * p10) - T(0.5)) / p10); | |
1038 | else | |
1039 | return T(std::floor((v0 * p10) + T(0.5)) / p10); | |
1040 | } | |
1041 | ||
1042 | template <typename T> | |
1043 | inline T roundn_impl(const T v0, const T, int_type_tag) | |
1044 | { | |
1045 | return v0; | |
1046 | } | |
1047 | ||
1048 | template <typename T> | |
1049 | inline T hypot_impl(const T v0, const T v1, real_type_tag) | |
1050 | { | |
1051 | return std::sqrt((v0 * v0) + (v1 * v1)); | |
1052 | } | |
1053 | ||
1054 | template <typename T> | |
1055 | inline T hypot_impl(const T v0, const T v1, int_type_tag) | |
1056 | { | |
1057 | return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1)))); | |
1058 | } | |
1059 | ||
1060 | template <typename T> | |
1061 | inline T atan2_impl(const T v0, const T v1, real_type_tag) | |
1062 | { | |
1063 | return std::atan2(v0,v1); | |
1064 | } | |
1065 | ||
1066 | template <typename T> | |
1067 | inline T atan2_impl(const T, const T, int_type_tag) | |
1068 | { | |
1069 | return 0; | |
1070 | } | |
1071 | ||
1072 | template <typename T> | |
1073 | inline T shr_impl(const T v0, const T v1, real_type_tag) | |
1074 | { | |
1075 | return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1)))); | |
1076 | } | |
1077 | ||
1078 | template <typename T> | |
1079 | inline T shr_impl(const T v0, const T v1, int_type_tag) | |
1080 | { | |
1081 | return v0 >> v1; | |
1082 | } | |
1083 | ||
1084 | template <typename T> | |
1085 | inline T shl_impl(const T v0, const T v1, real_type_tag) | |
1086 | { | |
1087 | return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1))); | |
1088 | } | |
1089 | ||
1090 | template <typename T> | |
1091 | inline T shl_impl(const T v0, const T v1, int_type_tag) | |
1092 | { | |
1093 | return v0 << v1; | |
1094 | } | |
1095 | ||
1096 | template <typename T> | |
1097 | inline T sgn_impl(const T v, real_type_tag) | |
1098 | { | |
1099 | if (v > T(0)) return T(+1); | |
1100 | else if (v < T(0)) return T(-1); | |
1101 | else return T( 0); | |
1102 | } | |
1103 | ||
1104 | template <typename T> | |
1105 | inline T sgn_impl(const T v, int_type_tag) | |
1106 | { | |
1107 | if (v > T(0)) return T(+1); | |
1108 | else if (v < T(0)) return T(-1); | |
1109 | else return T( 0); | |
1110 | } | |
1111 | ||
1112 | template <typename T> | |
1113 | inline T and_impl(const T v0, const T v1, real_type_tag) | |
1114 | { | |
1115 | return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0); | |
1116 | } | |
1117 | ||
1118 | template <typename T> | |
1119 | inline T and_impl(const T v0, const T v1, int_type_tag) | |
1120 | { | |
1121 | return v0 && v1; | |
1122 | } | |
1123 | ||
1124 | template <typename T> | |
1125 | inline T nand_impl(const T v0, const T v1, real_type_tag) | |
1126 | { | |
1127 | return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0); | |
1128 | } | |
1129 | ||
1130 | template <typename T> | |
1131 | inline T nand_impl(const T v0, const T v1, int_type_tag) | |
1132 | { | |
1133 | return !(v0 && v1); | |
1134 | } | |
1135 | ||
1136 | template <typename T> | |
1137 | inline T or_impl(const T v0, const T v1, real_type_tag) | |
1138 | { | |
1139 | return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0); | |
1140 | } | |
1141 | ||
1142 | template <typename T> | |
1143 | inline T or_impl(const T v0, const T v1, int_type_tag) | |
1144 | { | |
1145 | return (v0 || v1); | |
1146 | } | |
1147 | ||
1148 | template <typename T> | |
1149 | inline T nor_impl(const T v0, const T v1, real_type_tag) | |
1150 | { | |
1151 | return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0); | |
1152 | } | |
1153 | ||
1154 | template <typename T> | |
1155 | inline T nor_impl(const T v0, const T v1, int_type_tag) | |
1156 | { | |
1157 | return !(v0 || v1); | |
1158 | } | |
1159 | ||
1160 | template <typename T> | |
1161 | inline T xor_impl(const T v0, const T v1, real_type_tag) | |
1162 | { | |
1163 | return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0); | |
1164 | } | |
1165 | ||
1166 | template <typename T> | |
1167 | inline T xor_impl(const T v0, const T v1, int_type_tag) | |
1168 | { | |
1169 | return v0 ^ v1; | |
1170 | } | |
1171 | ||
1172 | template <typename T> | |
1173 | inline T xnor_impl(const T v0, const T v1, real_type_tag) | |
1174 | { | |
1175 | const bool v0_true = is_true_impl(v0); | |
1176 | const bool v1_true = is_true_impl(v1); | |
1177 | ||
1178 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) | |
1179 | return T(1); | |
1180 | else | |
1181 | return T(0); | |
1182 | } | |
1183 | ||
1184 | template <typename T> | |
1185 | inline T xnor_impl(const T v0, const T v1, int_type_tag) | |
1186 | { | |
1187 | const bool v0_true = is_true_impl(v0); | |
1188 | const bool v1_true = is_true_impl(v1); | |
1189 | ||
1190 | if ((v0_true && v1_true) || (!v0_true && !v1_true)) | |
1191 | return T(1); | |
1192 | else | |
1193 | return T(0); | |
1194 | } | |
1195 | ||
1196 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) | |
1197 | #define exprtk_define_erf(TT,impl) \ | |
1198 | inline TT erf_impl(TT v) { return impl(v); } \ | |
1199 | ||
1200 | exprtk_define_erf( float,::erff) | |
1201 | exprtk_define_erf( double,::erf ) | |
1202 | exprtk_define_erf(long double,::erfl) | |
1203 | #undef exprtk_define_erf | |
1204 | #endif | |
1205 | ||
1206 | template <typename T> | |
1207 | inline T erf_impl(T v, real_type_tag) | |
1208 | { | |
1209 | #if defined(_MSC_VER) && (_MSC_VER < 1900) | |
1210 | // Credits: Abramowitz & Stegun Equations 7.1.25-28 | |
1211 | static const T c[] = { | |
1212 | T( 1.26551223), T(1.00002368), | |
1213 | T( 0.37409196), T(0.09678418), | |
1214 | T(-0.18628806), T(0.27886807), | |
1215 | T(-1.13520398), T(1.48851587), | |
1216 | T(-0.82215223), T(0.17087277) | |
1217 | }; | |
1218 | ||
1219 | const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag())); | |
1220 | ||
1221 | T result = T(1) - t * std::exp((-v * v) - | |
1222 | c[0] + t * (c[1] + t * | |
1223 | (c[2] + t * (c[3] + t * | |
1224 | (c[4] + t * (c[5] + t * | |
1225 | (c[6] + t * (c[7] + t * | |
1226 | (c[8] + t * (c[9])))))))))); | |
1227 | ||
1228 | return (v >= T(0)) ? result : -result; | |
1229 | #else | |
1230 | return erf_impl(v); | |
1231 | #endif | |
1232 | } | |
1233 | ||
1234 | template <typename T> | |
1235 | inline T erf_impl(T v, int_type_tag) | |
1236 | { | |
1237 | return erf_impl(static_cast<double>(v),real_type_tag()); | |
1238 | } | |
1239 | ||
1240 | #if (defined(_MSC_VER) && (_MSC_VER >= 1900)) || !defined(_MSC_VER) | |
1241 | #define exprtk_define_erfc(TT,impl) \ | |
1242 | inline TT erfc_impl(TT v) { return impl(v); } \ | |
1243 | ||
1244 | exprtk_define_erfc( float,::erfcf) | |
1245 | exprtk_define_erfc( double,::erfc ) | |
1246 | exprtk_define_erfc(long double,::erfcl) | |
1247 | #undef exprtk_define_erfc | |
1248 | #endif | |
1249 | ||
1250 | template <typename T> | |
1251 | inline T erfc_impl(T v, real_type_tag) | |
1252 | { | |
1253 | #if defined(_MSC_VER) && (_MSC_VER < 1900) | |
1254 | return T(1) - erf_impl(v,real_type_tag()); | |
1255 | #else | |
1256 | return erfc_impl(v); | |
1257 | #endif | |
1258 | } | |
1259 | ||
1260 | template <typename T> | |
1261 | inline T erfc_impl(T v, int_type_tag) | |
1262 | { | |
1263 | return erfc_impl(static_cast<double>(v),real_type_tag()); | |
1264 | } | |
1265 | ||
1266 | template <typename T> | |
1267 | inline T ncdf_impl(T v, real_type_tag) | |
1268 | { | |
1269 | T cnd = T(0.5) * (T(1) + erf_impl( | |
1270 | abs_impl(v,real_type_tag()) / | |
1271 | T(numeric::constant::sqrt2),real_type_tag())); | |
1272 | return (v < T(0)) ? (T(1) - cnd) : cnd; | |
1273 | } | |
1274 | ||
1275 | template <typename T> | |
1276 | inline T ncdf_impl(T v, int_type_tag) | |
1277 | { | |
1278 | return ncdf_impl(static_cast<double>(v),real_type_tag()); | |
1279 | } | |
1280 | ||
1281 | template <typename T> | |
1282 | inline T sinc_impl(T v, real_type_tag) | |
1283 | { | |
1284 | if (std::abs(v) >= std::numeric_limits<T>::epsilon()) | |
1285 | return(std::sin(v) / v); | |
1286 | else | |
1287 | return T(1); | |
1288 | } | |
1289 | ||
1290 | template <typename T> | |
1291 | inline T sinc_impl(T v, int_type_tag) | |
1292 | { | |
1293 | return sinc_impl(static_cast<double>(v),real_type_tag()); | |
1294 | } | |
1295 | ||
1296 | template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); } | |
1297 | template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); } | |
1298 | template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); } | |
1299 | template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); } | |
1300 | template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); } | |
1301 | template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - std::log(T(1) - v)) / T(2); } | |
1302 | template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); } | |
1303 | template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); } | |
1304 | template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); } | |
1305 | template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); } | |
1306 | template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); } | |
1307 | template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); } | |
1308 | template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); } | |
1309 | template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); } | |
1310 | template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; } | |
1311 | template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; } | |
1312 | template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); } | |
1313 | template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); } | |
1314 | template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); } | |
1315 | template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); } | |
1316 | template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); } | |
1317 | template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); } | |
1318 | template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); } | |
1319 | template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); } | |
1320 | template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); } | |
1321 | template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); } | |
1322 | template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); } | |
1323 | template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); } | |
1324 | template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); } | |
1325 | template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); } | |
1326 | template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); } | |
1327 | ||
1328 | template <typename T> inline T const_pi_impl(real_type_tag) { return T(numeric::constant::pi); } | |
1329 | template <typename T> inline T const_e_impl (real_type_tag) { return T(numeric::constant::e); } | |
1330 | ||
1331 | template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); } | |
1332 | template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); } | |
1333 | template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); } | |
1334 | template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); } | |
1335 | template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); } | |
1336 | template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; } | |
1337 | template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; } | |
1338 | template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; } | |
1339 | template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; } | |
1340 | template <typename T> inline T round_impl(const T v, int_type_tag) { return v; } | |
1341 | template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; } | |
1342 | template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); } | |
1343 | template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); } | |
1344 | template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; } | |
1345 | template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1346 | template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1347 | template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1348 | template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1349 | template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1350 | template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1351 | template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1352 | template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1353 | template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1354 | template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1355 | template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1356 | template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1357 | template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1358 | template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1359 | template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); } | |
1360 | ||
1361 | template <typename T> | |
1362 | inline bool is_integer_impl(const T& v, real_type_tag) | |
1363 | { | |
1364 | return std::equal_to<T>()(T(0),std::fmod(v,T(1))); | |
1365 | } | |
1366 | ||
1367 | template <typename T> | |
1368 | inline bool is_integer_impl(const T&, int_type_tag) | |
1369 | { | |
1370 | return true; | |
1371 | } | |
1372 | } | |
1373 | ||
1374 | template <typename Type> | |
1375 | struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; | |
1376 | ||
1377 | template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; | |
1378 | template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; | |
1379 | template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; | |
1380 | template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; | |
1381 | ||
1382 | template <typename T> | |
1383 | inline int to_int32(const T v) | |
1384 | { | |
1385 | const typename details::number_type<T>::type num_type; | |
1386 | return to_int32_impl(v, num_type); | |
1387 | } | |
1388 | ||
1389 | template <typename T> | |
1390 | inline _int64_t to_int64(const T v) | |
1391 | { | |
1392 | const typename details::number_type<T>::type num_type; | |
1393 | return to_int64_impl(v, num_type); | |
1394 | } | |
1395 | ||
1396 | template <typename T> | |
1397 | inline bool is_nan(const T v) | |
1398 | { | |
1399 | const typename details::number_type<T>::type num_type; | |
1400 | return is_nan_impl(v, num_type); | |
1401 | } | |
1402 | ||
1403 | template <typename T> | |
1404 | inline T min(const T v0, const T v1) | |
1405 | { | |
1406 | const typename details::number_type<T>::type num_type; | |
1407 | return min_impl(v0, v1, num_type); | |
1408 | } | |
1409 | ||
1410 | template <typename T> | |
1411 | inline T max(const T v0, const T v1) | |
1412 | { | |
1413 | const typename details::number_type<T>::type num_type; | |
1414 | return max_impl(v0, v1, num_type); | |
1415 | } | |
1416 | ||
1417 | template <typename T> | |
1418 | inline T equal(const T v0, const T v1) | |
1419 | { | |
1420 | const typename details::number_type<T>::type num_type; | |
1421 | return equal_impl(v0, v1, num_type); | |
1422 | } | |
1423 | ||
1424 | template <typename T> | |
1425 | inline T nequal(const T v0, const T v1) | |
1426 | { | |
1427 | const typename details::number_type<T>::type num_type; | |
1428 | return nequal_impl(v0, v1, num_type); | |
1429 | } | |
1430 | ||
1431 | template <typename T> | |
1432 | inline T modulus(const T v0, const T v1) | |
1433 | { | |
1434 | const typename details::number_type<T>::type num_type; | |
1435 | return modulus_impl(v0, v1, num_type); | |
1436 | } | |
1437 | ||
1438 | template <typename T> | |
1439 | inline T pow(const T v0, const T v1) | |
1440 | { | |
1441 | const typename details::number_type<T>::type num_type; | |
1442 | return pow_impl(v0, v1, num_type); | |
1443 | } | |
1444 | ||
1445 | template <typename T> | |
1446 | inline T logn(const T v0, const T v1) | |
1447 | { | |
1448 | const typename details::number_type<T>::type num_type; | |
1449 | return logn_impl(v0, v1, num_type); | |
1450 | } | |
1451 | ||
1452 | template <typename T> | |
1453 | inline T root(const T v0, const T v1) | |
1454 | { | |
1455 | const typename details::number_type<T>::type num_type; | |
1456 | return root_impl(v0, v1, num_type); | |
1457 | } | |
1458 | ||
1459 | template <typename T> | |
1460 | inline T roundn(const T v0, const T v1) | |
1461 | { | |
1462 | const typename details::number_type<T>::type num_type; | |
1463 | return roundn_impl(v0, v1, num_type); | |
1464 | } | |
1465 | ||
1466 | template <typename T> | |
1467 | inline T hypot(const T v0, const T v1) | |
1468 | { | |
1469 | const typename details::number_type<T>::type num_type; | |
1470 | return hypot_impl(v0, v1, num_type); | |
1471 | } | |
1472 | ||
1473 | template <typename T> | |
1474 | inline T atan2(const T v0, const T v1) | |
1475 | { | |
1476 | const typename details::number_type<T>::type num_type; | |
1477 | return atan2_impl(v0, v1, num_type); | |
1478 | } | |
1479 | ||
1480 | template <typename T> | |
1481 | inline T shr(const T v0, const T v1) | |
1482 | { | |
1483 | const typename details::number_type<T>::type num_type; | |
1484 | return shr_impl(v0, v1, num_type); | |
1485 | } | |
1486 | ||
1487 | template <typename T> | |
1488 | inline T shl(const T v0, const T v1) | |
1489 | { | |
1490 | const typename details::number_type<T>::type num_type; | |
1491 | return shl_impl(v0, v1, num_type); | |
1492 | } | |
1493 | ||
1494 | template <typename T> | |
1495 | inline T and_opr(const T v0, const T v1) | |
1496 | { | |
1497 | const typename details::number_type<T>::type num_type; | |
1498 | return and_impl(v0, v1, num_type); | |
1499 | } | |
1500 | ||
1501 | template <typename T> | |
1502 | inline T nand_opr(const T v0, const T v1) | |
1503 | { | |
1504 | const typename details::number_type<T>::type num_type; | |
1505 | return nand_impl(v0, v1, num_type); | |
1506 | } | |
1507 | ||
1508 | template <typename T> | |
1509 | inline T or_opr(const T v0, const T v1) | |
1510 | { | |
1511 | const typename details::number_type<T>::type num_type; | |
1512 | return or_impl(v0, v1, num_type); | |
1513 | } | |
1514 | ||
1515 | template <typename T> | |
1516 | inline T nor_opr(const T v0, const T v1) | |
1517 | { | |
1518 | const typename details::number_type<T>::type num_type; | |
1519 | return nor_impl(v0, v1, num_type); | |
1520 | } | |
1521 | ||
1522 | template <typename T> | |
1523 | inline T xor_opr(const T v0, const T v1) | |
1524 | { | |
1525 | const typename details::number_type<T>::type num_type; | |
1526 | return xor_impl(v0, v1, num_type); | |
1527 | } | |
1528 | ||
1529 | template <typename T> | |
1530 | inline T xnor_opr(const T v0, const T v1) | |
1531 | { | |
1532 | const typename details::number_type<T>::type num_type; | |
1533 | return xnor_impl(v0, v1, num_type); | |
1534 | } | |
1535 | ||
1536 | template <typename T> | |
1537 | inline bool is_integer(const T v) | |
1538 | { | |
1539 | const typename details::number_type<T>::type num_type; | |
1540 | return is_integer_impl(v, num_type); | |
1541 | } | |
1542 | ||
1543 | template <typename T, unsigned int N> | |
1544 | struct fast_exp | |
1545 | { | |
1546 | static inline T result(T v) | |
1547 | { | |
1548 | unsigned int k = N; | |
1549 | T l = T(1); | |
1550 | ||
1551 | while (k) | |
1552 | { | |
1553 | if (k & 1) | |
1554 | { | |
1555 | l *= v; | |
1556 | --k; | |
1557 | } | |
1558 | ||
1559 | v *= v; | |
1560 | k >>= 1; | |
1561 | } | |
1562 | ||
1563 | return l; | |
1564 | } | |
1565 | }; | |
1566 | ||
1567 | template <typename T> struct fast_exp<T,10> { static inline T result(T v) { T v_5 = fast_exp<T,5>::result(v); return v_5 * v_5; } }; | |
1568 | template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } }; | |
1569 | template <typename T> struct fast_exp<T, 8> { static inline T result(T v) { T v_4 = fast_exp<T,4>::result(v); return v_4 * v_4; } }; | |
1570 | template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } }; | |
1571 | template <typename T> struct fast_exp<T, 6> { static inline T result(T v) { T v_3 = fast_exp<T,3>::result(v); return v_3 * v_3; } }; | |
1572 | template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } }; | |
1573 | template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } }; | |
1574 | template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } }; | |
1575 | template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } }; | |
1576 | template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } }; | |
1577 | template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } }; | |
1578 | ||
1579 | #define exprtk_define_unary_function(FunctionName) \ | |
1580 | template <typename T> \ | |
1581 | inline T FunctionName (const T v) \ | |
1582 | { \ | |
1583 | const typename details::number_type<T>::type num_type; \ | |
1584 | return FunctionName##_impl(v,num_type); \ | |
1585 | } \ | |
1586 | ||
1587 | exprtk_define_unary_function(abs ) | |
1588 | exprtk_define_unary_function(acos ) | |
1589 | exprtk_define_unary_function(acosh) | |
1590 | exprtk_define_unary_function(asin ) | |
1591 | exprtk_define_unary_function(asinh) | |
1592 | exprtk_define_unary_function(atan ) | |
1593 | exprtk_define_unary_function(atanh) | |
1594 | exprtk_define_unary_function(ceil ) | |
1595 | exprtk_define_unary_function(cos ) | |
1596 | exprtk_define_unary_function(cosh ) | |
1597 | exprtk_define_unary_function(exp ) | |
1598 | exprtk_define_unary_function(expm1) | |
1599 | exprtk_define_unary_function(floor) | |
1600 | exprtk_define_unary_function(log ) | |
1601 | exprtk_define_unary_function(log10) | |
1602 | exprtk_define_unary_function(log2 ) | |
1603 | exprtk_define_unary_function(log1p) | |
1604 | exprtk_define_unary_function(neg ) | |
1605 | exprtk_define_unary_function(pos ) | |
1606 | exprtk_define_unary_function(round) | |
1607 | exprtk_define_unary_function(sin ) | |
1608 | exprtk_define_unary_function(sinc ) | |
1609 | exprtk_define_unary_function(sinh ) | |
1610 | exprtk_define_unary_function(sqrt ) | |
1611 | exprtk_define_unary_function(tan ) | |
1612 | exprtk_define_unary_function(tanh ) | |
1613 | exprtk_define_unary_function(cot ) | |
1614 | exprtk_define_unary_function(sec ) | |
1615 | exprtk_define_unary_function(csc ) | |
1616 | exprtk_define_unary_function(r2d ) | |
1617 | exprtk_define_unary_function(d2r ) | |
1618 | exprtk_define_unary_function(d2g ) | |
1619 | exprtk_define_unary_function(g2d ) | |
1620 | exprtk_define_unary_function(notl ) | |
1621 | exprtk_define_unary_function(sgn ) | |
1622 | exprtk_define_unary_function(erf ) | |
1623 | exprtk_define_unary_function(erfc ) | |
1624 | exprtk_define_unary_function(ncdf ) | |
1625 | exprtk_define_unary_function(frac ) | |
1626 | exprtk_define_unary_function(trunc) | |
1627 | #undef exprtk_define_unary_function | |
1628 | } | |
1629 | ||
1630 | template <typename T> | |
1631 | inline T compute_pow10(T d, const int exponent) | |
1632 | { | |
1633 | static const double fract10[] = | |
1634 | { | |
1635 | 0.0, | |
1636 | 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004, 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008, 1.0E+009, 1.0E+010, | |
1637 | 1.0E+011, 1.0E+012, 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016, 1.0E+017, 1.0E+018, 1.0E+019, 1.0E+020, | |
1638 | 1.0E+021, 1.0E+022, 1.0E+023, 1.0E+024, 1.0E+025, 1.0E+026, 1.0E+027, 1.0E+028, 1.0E+029, 1.0E+030, | |
1639 | 1.0E+031, 1.0E+032, 1.0E+033, 1.0E+034, 1.0E+035, 1.0E+036, 1.0E+037, 1.0E+038, 1.0E+039, 1.0E+040, | |
1640 | 1.0E+041, 1.0E+042, 1.0E+043, 1.0E+044, 1.0E+045, 1.0E+046, 1.0E+047, 1.0E+048, 1.0E+049, 1.0E+050, | |
1641 | 1.0E+051, 1.0E+052, 1.0E+053, 1.0E+054, 1.0E+055, 1.0E+056, 1.0E+057, 1.0E+058, 1.0E+059, 1.0E+060, | |
1642 | 1.0E+061, 1.0E+062, 1.0E+063, 1.0E+064, 1.0E+065, 1.0E+066, 1.0E+067, 1.0E+068, 1.0E+069, 1.0E+070, | |
1643 | 1.0E+071, 1.0E+072, 1.0E+073, 1.0E+074, 1.0E+075, 1.0E+076, 1.0E+077, 1.0E+078, 1.0E+079, 1.0E+080, | |
1644 | 1.0E+081, 1.0E+082, 1.0E+083, 1.0E+084, 1.0E+085, 1.0E+086, 1.0E+087, 1.0E+088, 1.0E+089, 1.0E+090, | |
1645 | 1.0E+091, 1.0E+092, 1.0E+093, 1.0E+094, 1.0E+095, 1.0E+096, 1.0E+097, 1.0E+098, 1.0E+099, 1.0E+100, | |
1646 | 1.0E+101, 1.0E+102, 1.0E+103, 1.0E+104, 1.0E+105, 1.0E+106, 1.0E+107, 1.0E+108, 1.0E+109, 1.0E+110, | |
1647 | 1.0E+111, 1.0E+112, 1.0E+113, 1.0E+114, 1.0E+115, 1.0E+116, 1.0E+117, 1.0E+118, 1.0E+119, 1.0E+120, | |
1648 | 1.0E+121, 1.0E+122, 1.0E+123, 1.0E+124, 1.0E+125, 1.0E+126, 1.0E+127, 1.0E+128, 1.0E+129, 1.0E+130, | |
1649 | 1.0E+131, 1.0E+132, 1.0E+133, 1.0E+134, 1.0E+135, 1.0E+136, 1.0E+137, 1.0E+138, 1.0E+139, 1.0E+140, | |
1650 | 1.0E+141, 1.0E+142, 1.0E+143, 1.0E+144, 1.0E+145, 1.0E+146, 1.0E+147, 1.0E+148, 1.0E+149, 1.0E+150, | |
1651 | 1.0E+151, 1.0E+152, 1.0E+153, 1.0E+154, 1.0E+155, 1.0E+156, 1.0E+157, 1.0E+158, 1.0E+159, 1.0E+160, | |
1652 | 1.0E+161, 1.0E+162, 1.0E+163, 1.0E+164, 1.0E+165, 1.0E+166, 1.0E+167, 1.0E+168, 1.0E+169, 1.0E+170, | |
1653 | 1.0E+171, 1.0E+172, 1.0E+173, 1.0E+174, 1.0E+175, 1.0E+176, 1.0E+177, 1.0E+178, 1.0E+179, 1.0E+180, | |
1654 | 1.0E+181, 1.0E+182, 1.0E+183, 1.0E+184, 1.0E+185, 1.0E+186, 1.0E+187, 1.0E+188, 1.0E+189, 1.0E+190, | |
1655 | 1.0E+191, 1.0E+192, 1.0E+193, 1.0E+194, 1.0E+195, 1.0E+196, 1.0E+197, 1.0E+198, 1.0E+199, 1.0E+200, | |
1656 | 1.0E+201, 1.0E+202, 1.0E+203, 1.0E+204, 1.0E+205, 1.0E+206, 1.0E+207, 1.0E+208, 1.0E+209, 1.0E+210, | |
1657 | 1.0E+211, 1.0E+212, 1.0E+213, 1.0E+214, 1.0E+215, 1.0E+216, 1.0E+217, 1.0E+218, 1.0E+219, 1.0E+220, | |
1658 | 1.0E+221, 1.0E+222, 1.0E+223, 1.0E+224, 1.0E+225, 1.0E+226, 1.0E+227, 1.0E+228, 1.0E+229, 1.0E+230, | |
1659 | 1.0E+231, 1.0E+232, 1.0E+233, 1.0E+234, 1.0E+235, 1.0E+236, 1.0E+237, 1.0E+238, 1.0E+239, 1.0E+240, | |
1660 | 1.0E+241, 1.0E+242, 1.0E+243, 1.0E+244, 1.0E+245, 1.0E+246, 1.0E+247, 1.0E+248, 1.0E+249, 1.0E+250, | |
1661 | 1.0E+251, 1.0E+252, 1.0E+253, 1.0E+254, 1.0E+255, 1.0E+256, 1.0E+257, 1.0E+258, 1.0E+259, 1.0E+260, | |
1662 | 1.0E+261, 1.0E+262, 1.0E+263, 1.0E+264, 1.0E+265, 1.0E+266, 1.0E+267, 1.0E+268, 1.0E+269, 1.0E+270, | |
1663 | 1.0E+271, 1.0E+272, 1.0E+273, 1.0E+274, 1.0E+275, 1.0E+276, 1.0E+277, 1.0E+278, 1.0E+279, 1.0E+280, | |
1664 | 1.0E+281, 1.0E+282, 1.0E+283, 1.0E+284, 1.0E+285, 1.0E+286, 1.0E+287, 1.0E+288, 1.0E+289, 1.0E+290, | |
1665 | 1.0E+291, 1.0E+292, 1.0E+293, 1.0E+294, 1.0E+295, 1.0E+296, 1.0E+297, 1.0E+298, 1.0E+299, 1.0E+300, | |
1666 | 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308 | |
1667 | }; | |
1668 | ||
1669 | static const int fract10_size = static_cast<int>(sizeof(fract10) / sizeof(double)); | |
1670 | ||
1671 | const int e = std::abs(exponent); | |
1672 | ||
1673 | if (exponent >= std::numeric_limits<T>::min_exponent10) | |
1674 | { | |
1675 | if (e < fract10_size) | |
1676 | { | |
1677 | if (exponent > 0) | |
1678 | return T(d * fract10[e]); | |
1679 | else | |
1680 | return T(d / fract10[e]); | |
1681 | } | |
1682 | else | |
1683 | return T(d * std::pow(10.0, 10.0 * exponent)); | |
1684 | } | |
1685 | else | |
1686 | { | |
1687 | d /= T(fract10[ -std::numeric_limits<T>::min_exponent10]); | |
1688 | return T(d / fract10[-exponent + std::numeric_limits<T>::min_exponent10]); | |
1689 | } | |
1690 | } | |
1691 | ||
1692 | template <typename Iterator, typename T> | |
1693 | inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, T& result) | |
1694 | { | |
1695 | if (itr == end) | |
1696 | return false; | |
1697 | ||
1698 | const bool negative = ('-' == (*itr)); | |
1699 | ||
1700 | if (negative || ('+' == (*itr))) | |
1701 | { | |
1702 | if (end == ++itr) | |
1703 | return false; | |
1704 | } | |
1705 | ||
1706 | static const uchar_t zero = static_cast<uchar_t>('0'); | |
1707 | ||
1708 | while ((end != itr) && (zero == (*itr))) ++itr; | |
1709 | ||
1710 | bool return_result = true; | |
1711 | unsigned int digit = 0; | |
1712 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); | |
1713 | ||
1714 | if (length <= 4) | |
1715 | { | |
1716 | exprtk_disable_fallthrough_begin | |
1717 | switch (length) | |
1718 | { | |
1719 | #ifdef exprtk_use_lut | |
1720 | ||
1721 | #define exprtk_process_digit \ | |
1722 | if ((digit = details::digit_table[(int)*itr++]) < 10) \ | |
1723 | result = result * 10 + (digit); \ | |
1724 | else \ | |
1725 | { \ | |
1726 | return_result = false; \ | |
1727 | break; \ | |
1728 | } \ | |
1729 | ||
1730 | #else | |
1731 | ||
1732 | #define exprtk_process_digit \ | |
1733 | if ((digit = (*itr++ - zero)) < 10) \ | |
1734 | result = result * T(10) + digit; \ | |
1735 | else \ | |
1736 | { \ | |
1737 | return_result = false; \ | |
1738 | break; \ | |
1739 | } \ | |
1740 | ||
1741 | #endif | |
1742 | ||
1743 | case 4 : exprtk_process_digit | |
1744 | case 3 : exprtk_process_digit | |
1745 | case 2 : exprtk_process_digit | |
1746 | case 1 : if ((digit = (*itr - zero))>= 10) { digit = 0; return_result = false; } | |
1747 | ||
1748 | #undef exprtk_process_digit | |
1749 | } | |
1750 | exprtk_disable_fallthrough_end | |
1751 | } | |
1752 | else | |
1753 | return_result = false; | |
1754 | ||
1755 | if (length && return_result) | |
1756 | { | |
1757 | result = result * 10 + static_cast<T>(digit); | |
1758 | ++itr; | |
1759 | } | |
1760 | ||
1761 | result = negative ? -result : result; | |
1762 | return return_result; | |
1763 | } | |
1764 | ||
1765 | template <typename Iterator, typename T> | |
1766 | static inline bool parse_nan(Iterator& itr, const Iterator end, T& t) | |
1767 | { | |
1768 | typedef typename std::iterator_traits<Iterator>::value_type type; | |
1769 | ||
1770 | static const std::size_t nan_length = 3; | |
1771 | ||
1772 | if (std::distance(itr,end) != static_cast<int>(nan_length)) | |
1773 | return false; | |
1774 | ||
1775 | if (static_cast<type>('n') == (*itr)) | |
1776 | { | |
1777 | if ( | |
1778 | (static_cast<type>('a') != *(itr + 1)) || | |
1779 | (static_cast<type>('n') != *(itr + 2)) | |
1780 | ) | |
1781 | { | |
1782 | return false; | |
1783 | } | |
1784 | } | |
1785 | else if ( | |
1786 | (static_cast<type>('A') != *(itr + 1)) || | |
1787 | (static_cast<type>('N') != *(itr + 2)) | |
1788 | ) | |
1789 | { | |
1790 | return false; | |
1791 | } | |
1792 | ||
1793 | t = std::numeric_limits<T>::quiet_NaN(); | |
1794 | ||
1795 | return true; | |
1796 | } | |
1797 | ||
1798 | template <typename Iterator, typename T> | |
1799 | static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative) | |
1800 | { | |
1801 | static const char_t inf_uc[] = "INFINITY"; | |
1802 | static const char_t inf_lc[] = "infinity"; | |
1803 | static const std::size_t inf_length = 8; | |
1804 | ||
1805 | const std::size_t length = static_cast<std::size_t>(std::distance(itr,end)); | |
1806 | ||
1807 | if ((3 != length) && (inf_length != length)) | |
1808 | return false; | |
1809 | ||
1810 | char_cptr inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc; | |
1811 | ||
1812 | while (end != itr) | |
1813 | { | |
1814 | if (*inf_itr == static_cast<char>(*itr)) | |
1815 | { | |
1816 | ++itr; | |
1817 | ++inf_itr; | |
1818 | continue; | |
1819 | } | |
1820 | else | |
1821 | return false; | |
1822 | } | |
1823 | ||
1824 | if (negative) | |
1825 | t = -std::numeric_limits<T>::infinity(); | |
1826 | else | |
1827 | t = std::numeric_limits<T>::infinity(); | |
1828 | ||
1829 | return true; | |
1830 | } | |
1831 | ||
1832 | template <typename Iterator, typename T> | |
1833 | inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) | |
1834 | { | |
1835 | if (end == itr_external) return false; | |
1836 | ||
1837 | Iterator itr = itr_external; | |
1838 | ||
1839 | T d = T(0); | |
1840 | ||
1841 | const bool negative = ('-' == (*itr)); | |
1842 | ||
1843 | if (negative || '+' == (*itr)) | |
1844 | { | |
1845 | if (end == ++itr) | |
1846 | return false; | |
1847 | } | |
1848 | ||
1849 | bool instate = false; | |
1850 | ||
1851 | static const char_t zero = static_cast<uchar_t>('0'); | |
1852 | ||
1853 | #define parse_digit_1(d) \ | |
1854 | if ((digit = (*itr - zero)) < 10) \ | |
1855 | { d = d * T(10) + digit; } \ | |
1856 | else \ | |
1857 | { break; } \ | |
1858 | if (end == ++itr) break; \ | |
1859 | ||
1860 | #define parse_digit_2(d) \ | |
1861 | if ((digit = (*itr - zero)) < 10) \ | |
1862 | { d = d * T(10) + digit; } \ | |
1863 | else { break; } \ | |
1864 | ++itr; \ | |
1865 | ||
1866 | if ('.' != (*itr)) | |
1867 | { | |
1868 | const Iterator curr = itr; | |
1869 | ||
1870 | while ((end != itr) && (zero == (*itr))) ++itr; | |
1871 | ||
1872 | unsigned int digit; | |
1873 | ||
1874 | while (end != itr) | |
1875 | { | |
1876 | // Note: For 'physical' superscalar architectures it | |
1877 | // is advised that the following loop be: 4xPD1 and 1xPD2 | |
1878 | #ifdef exprtk_enable_superscalar | |
1879 | parse_digit_1(d) | |
1880 | parse_digit_1(d) | |
1881 | #endif | |
1882 | parse_digit_1(d) | |
1883 | parse_digit_1(d) | |
1884 | parse_digit_2(d) | |
1885 | } | |
1886 | ||
1887 | if (curr != itr) instate = true; | |
1888 | } | |
1889 | ||
1890 | int exponent = 0; | |
1891 | ||
1892 | if (end != itr) | |
1893 | { | |
1894 | if ('.' == (*itr)) | |
1895 | { | |
1896 | const Iterator curr = ++itr; | |
1897 | unsigned int digit; | |
1898 | T tmp_d = T(0); | |
1899 | ||
1900 | while (end != itr) | |
1901 | { | |
1902 | #ifdef exprtk_enable_superscalar | |
1903 | parse_digit_1(tmp_d) | |
1904 | parse_digit_1(tmp_d) | |
1905 | parse_digit_1(tmp_d) | |
1906 | #endif | |
1907 | parse_digit_1(tmp_d) | |
1908 | parse_digit_1(tmp_d) | |
1909 | parse_digit_2(tmp_d) | |
1910 | } | |
1911 | ||
1912 | if (curr != itr) | |
1913 | { | |
1914 | instate = true; | |
1915 | d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr))); | |
1916 | } | |
1917 | ||
1918 | #undef parse_digit_1 | |
1919 | #undef parse_digit_2 | |
1920 | } | |
1921 | ||
1922 | if (end != itr) | |
1923 | { | |
1924 | typename std::iterator_traits<Iterator>::value_type c = (*itr); | |
1925 | ||
1926 | if (('e' == c) || ('E' == c)) | |
1927 | { | |
1928 | int exp = 0; | |
1929 | ||
1930 | if (!details::string_to_type_converter_impl_ref(++itr, end, exp)) | |
1931 | { | |
1932 | if (end == itr) | |
1933 | return false; | |
1934 | else | |
1935 | c = (*itr); | |
1936 | } | |
1937 | ||
1938 | exponent += exp; | |
1939 | } | |
1940 | ||
1941 | if (end != itr) | |
1942 | { | |
1943 | if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c)) | |
1944 | ++itr; | |
1945 | else if ('#' == c) | |
1946 | { | |
1947 | if (end == ++itr) | |
1948 | return false; | |
1949 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) | |
1950 | { | |
1951 | if (('i' == (*itr)) || ('I' == (*itr))) | |
1952 | { | |
1953 | return parse_inf(itr, end, t, negative); | |
1954 | } | |
1955 | else if (('n' == (*itr)) || ('N' == (*itr))) | |
1956 | { | |
1957 | return parse_nan(itr, end, t); | |
1958 | } | |
1959 | else | |
1960 | return false; | |
1961 | } | |
1962 | else | |
1963 | return false; | |
1964 | } | |
1965 | else if (('I' <= (*itr)) && ((*itr) <= 'n')) | |
1966 | { | |
1967 | if (('i' == (*itr)) || ('I' == (*itr))) | |
1968 | { | |
1969 | return parse_inf(itr, end, t, negative); | |
1970 | } | |
1971 | else if (('n' == (*itr)) || ('N' == (*itr))) | |
1972 | { | |
1973 | return parse_nan(itr, end, t); | |
1974 | } | |
1975 | else | |
1976 | return false; | |
1977 | } | |
1978 | else | |
1979 | return false; | |
1980 | } | |
1981 | } | |
1982 | } | |
1983 | ||
1984 | if ((end != itr) || (!instate)) | |
1985 | return false; | |
1986 | else if (exponent) | |
1987 | d = compute_pow10(d,exponent); | |
1988 | ||
1989 | t = static_cast<T>((negative) ? -d : d); | |
1990 | return true; | |
1991 | } | |
1992 | ||
1993 | template <typename T> | |
1994 | inline bool string_to_real(const std::string& s, T& t) | |
1995 | { | |
1996 | const typename numeric::details::number_type<T>::type num_type; | |
1997 | ||
1998 | char_cptr begin = s.data(); | |
1999 | char_cptr end = s.data() + s.size(); | |
2000 | ||
2001 | return string_to_real(begin, end, t, num_type); | |
2002 | } | |
2003 | ||
2004 | template <typename T> | |
2005 | struct functor_t | |
2006 | { | |
2007 | /* | |
2008 | Note: The following definitions for Type, may require tweaking | |
2009 | based on the compiler and target architecture. The benchmark | |
2010 | should provide enough information to make the right choice. | |
2011 | */ | |
2012 | //typedef T Type; | |
2013 | //typedef const T Type; | |
2014 | typedef const T& Type; | |
2015 | typedef T& RefType; | |
2016 | typedef T (*qfunc_t)(Type t0, Type t1, Type t2, Type t3); | |
2017 | typedef T (*tfunc_t)(Type t0, Type t1, Type t2); | |
2018 | typedef T (*bfunc_t)(Type t0, Type t1); | |
2019 | typedef T (*ufunc_t)(Type t0); | |
2020 | }; | |
2021 | ||
2022 | } // namespace details | |
2023 | ||
2024 | namespace lexer | |
2025 | { | |
2026 | struct token | |
2027 | { | |
2028 | enum token_type | |
2029 | { | |
2030 | e_none = 0, e_error = 1, e_err_symbol = 2, | |
2031 | e_err_number = 3, e_err_string = 4, e_err_sfunc = 5, | |
2032 | e_eof = 6, e_number = 7, e_symbol = 8, | |
2033 | e_string = 9, e_assign = 10, e_addass = 11, | |
2034 | e_subass = 12, e_mulass = 13, e_divass = 14, | |
2035 | e_modass = 15, e_shr = 16, e_shl = 17, | |
2036 | e_lte = 18, e_ne = 19, e_gte = 20, | |
2037 | e_swap = 21, e_lt = '<', e_gt = '>', | |
2038 | e_eq = '=', e_rbracket = ')', e_lbracket = '(', | |
2039 | e_rsqrbracket = ']', e_lsqrbracket = '[', e_rcrlbracket = '}', | |
2040 | e_lcrlbracket = '{', e_comma = ',', e_add = '+', | |
2041 | e_sub = '-', e_div = '/', e_mul = '*', | |
2042 | e_mod = '%', e_pow = '^', e_colon = ':', | |
2043 | e_ternary = '?' | |
2044 | }; | |
2045 | ||
2046 | token() | |
2047 | : type(e_none), | |
2048 | value(""), | |
2049 | position(std::numeric_limits<std::size_t>::max()) | |
2050 | {} | |
2051 | ||
2052 | void clear() | |
2053 | { | |
2054 | type = e_none; | |
2055 | value = ""; | |
2056 | position = std::numeric_limits<std::size_t>::max(); | |
2057 | } | |
2058 | ||
2059 | template <typename Iterator> | |
2060 | inline token& set_operator(const token_type tt, | |
2061 | const Iterator begin, const Iterator end, | |
2062 | const Iterator base_begin = Iterator(0)) | |
2063 | { | |
2064 | type = tt; | |
2065 | value.assign(begin,end); | |
2066 | if (base_begin) | |
2067 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); | |
2068 | return (*this); | |
2069 | } | |
2070 | ||
2071 | template <typename Iterator> | |
2072 | inline token& set_symbol(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) | |
2073 | { | |
2074 | type = e_symbol; | |
2075 | value.assign(begin,end); | |
2076 | if (base_begin) | |
2077 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); | |
2078 | return (*this); | |
2079 | } | |
2080 | ||
2081 | template <typename Iterator> | |
2082 | inline token& set_numeric(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) | |
2083 | { | |
2084 | type = e_number; | |
2085 | value.assign(begin,end); | |
2086 | if (base_begin) | |
2087 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); | |
2088 | return (*this); | |
2089 | } | |
2090 | ||
2091 | template <typename Iterator> | |
2092 | inline token& set_string(const Iterator begin, const Iterator end, const Iterator base_begin = Iterator(0)) | |
2093 | { | |
2094 | type = e_string; | |
2095 | value.assign(begin,end); | |
2096 | if (base_begin) | |
2097 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); | |
2098 | return (*this); | |
2099 | } | |
2100 | ||
2101 | inline token& set_string(const std::string& s, const std::size_t p) | |
2102 | { | |
2103 | type = e_string; | |
2104 | value = s; | |
2105 | position = p; | |
2106 | return (*this); | |
2107 | } | |
2108 | ||
2109 | template <typename Iterator> | |
2110 | inline token& set_error(const token_type et, | |
2111 | const Iterator begin, const Iterator end, | |
2112 | const Iterator base_begin = Iterator(0)) | |
2113 | { | |
2114 | if ( | |
2115 | (e_error == et) || | |
2116 | (e_err_symbol == et) || | |
2117 | (e_err_number == et) || | |
2118 | (e_err_string == et) || | |
2119 | (e_err_sfunc == et) | |
2120 | ) | |
2121 | { | |
2122 | type = et; | |
2123 | } | |
2124 | else | |
2125 | type = e_error; | |
2126 | ||
2127 | value.assign(begin,end); | |
2128 | ||
2129 | if (base_begin) | |
2130 | position = static_cast<std::size_t>(std::distance(base_begin,begin)); | |
2131 | ||
2132 | return (*this); | |
2133 | } | |
2134 | ||
2135 | static inline std::string to_str(token_type t) | |
2136 | { | |
2137 | switch (t) | |
2138 | { | |
2139 | case e_none : return "NONE"; | |
2140 | case e_error : return "ERROR"; | |
2141 | case e_err_symbol : return "ERROR_SYMBOL"; | |
2142 | case e_err_number : return "ERROR_NUMBER"; | |
2143 | case e_err_string : return "ERROR_STRING"; | |
2144 | case e_eof : return "EOF"; | |
2145 | case e_number : return "NUMBER"; | |
2146 | case e_symbol : return "SYMBOL"; | |
2147 | case e_string : return "STRING"; | |
2148 | case e_assign : return ":="; | |
2149 | case e_addass : return "+="; | |
2150 | case e_subass : return "-="; | |
2151 | case e_mulass : return "*="; | |
2152 | case e_divass : return "/="; | |
2153 | case e_modass : return "%="; | |
2154 | case e_shr : return ">>"; | |
2155 | case e_shl : return "<<"; | |
2156 | case e_lte : return "<="; | |
2157 | case e_ne : return "!="; | |
2158 | case e_gte : return ">="; | |
2159 | case e_lt : return "<"; | |
2160 | case e_gt : return ">"; | |
2161 | case e_eq : return "="; | |
2162 | case e_rbracket : return ")"; | |
2163 | case e_lbracket : return "("; | |
2164 | case e_rsqrbracket : return "]"; | |
2165 | case e_lsqrbracket : return "["; | |
2166 | case e_rcrlbracket : return "}"; | |
2167 | case e_lcrlbracket : return "{"; | |
2168 | case e_comma : return ","; | |
2169 | case e_add : return "+"; | |
2170 | case e_sub : return "-"; | |
2171 | case e_div : return "/"; | |
2172 | case e_mul : return "*"; | |
2173 | case e_mod : return "%"; | |
2174 | case e_pow : return "^"; | |
2175 | case e_colon : return ":"; | |
2176 | case e_ternary : return "?"; | |
2177 | case e_swap : return "<=>"; | |
2178 | default : return "UNKNOWN"; | |
2179 | } | |
2180 | } | |
2181 | ||
2182 | inline bool is_error() const | |
2183 | { | |
2184 | return ( | |
2185 | (e_error == type) || | |
2186 | (e_err_symbol == type) || | |
2187 | (e_err_number == type) || | |
2188 | (e_err_string == type) || | |
2189 | (e_err_sfunc == type) | |
2190 | ); | |
2191 | } | |
2192 | ||
2193 | token_type type; | |
2194 | std::string value; | |
2195 | std::size_t position; | |
2196 | }; | |
2197 | ||
2198 | class generator | |
2199 | { | |
2200 | public: | |
2201 | ||
2202 | typedef token token_t; | |
2203 | typedef std::vector<token_t> token_list_t; | |
2204 | typedef std::vector<token_t>::iterator token_list_itr_t; | |
2205 | typedef details::char_t char_t; | |
2206 | ||
2207 | generator() | |
2208 | : base_itr_(0), | |
2209 | s_itr_ (0), | |
2210 | s_end_ (0) | |
2211 | { | |
2212 | clear(); | |
2213 | } | |
2214 | ||
2215 | inline void clear() | |
2216 | { | |
2217 | base_itr_ = 0; | |
2218 | s_itr_ = 0; | |
2219 | s_end_ = 0; | |
2220 | token_list_.clear(); | |
2221 | token_itr_ = token_list_.end(); | |
2222 | store_token_itr_ = token_list_.end(); | |
2223 | } | |
2224 | ||
2225 | inline bool process(const std::string& str) | |
2226 | { | |
2227 | base_itr_ = str.data(); | |
2228 | s_itr_ = str.data(); | |
2229 | s_end_ = str.data() + str.size(); | |
2230 | ||
2231 | eof_token_.set_operator(token_t::e_eof,s_end_,s_end_,base_itr_); | |
2232 | token_list_.clear(); | |
2233 | ||
2234 | while (!is_end(s_itr_)) | |
2235 | { | |
2236 | scan_token(); | |
2237 | ||
2238 | if (!token_list_.empty() && token_list_.back().is_error()) | |
2239 | return false; | |
2240 | } | |
2241 | ||
2242 | return true; | |
2243 | } | |
2244 | ||
2245 | inline bool empty() const | |
2246 | { | |
2247 | return token_list_.empty(); | |
2248 | } | |
2249 | ||
2250 | inline std::size_t size() const | |
2251 | { | |
2252 | return token_list_.size(); | |
2253 | } | |
2254 | ||
2255 | inline void begin() | |
2256 | { | |
2257 | token_itr_ = token_list_.begin(); | |
2258 | store_token_itr_ = token_list_.begin(); | |
2259 | } | |
2260 | ||
2261 | inline void store() | |
2262 | { | |
2263 | store_token_itr_ = token_itr_; | |
2264 | } | |
2265 | ||
2266 | inline void restore() | |
2267 | { | |
2268 | token_itr_ = store_token_itr_; | |
2269 | } | |
2270 | ||
2271 | inline token_t& next_token() | |
2272 | { | |
2273 | if (token_list_.end() != token_itr_) | |
2274 | { | |
2275 | return *token_itr_++; | |
2276 | } | |
2277 | else | |
2278 | return eof_token_; | |
2279 | } | |
2280 | ||
2281 | inline token_t& peek_next_token() | |
2282 | { | |
2283 | if (token_list_.end() != token_itr_) | |
2284 | { | |
2285 | return *token_itr_; | |
2286 | } | |
2287 | else | |
2288 | return eof_token_; | |
2289 | } | |
2290 | ||
2291 | inline token_t& operator[](const std::size_t& index) | |
2292 | { | |
2293 | if (index < token_list_.size()) | |
2294 | return token_list_[index]; | |
2295 | else | |
2296 | return eof_token_; | |
2297 | } | |
2298 | ||
2299 | inline token_t operator[](const std::size_t& index) const | |
2300 | { | |
2301 | if (index < token_list_.size()) | |
2302 | return token_list_[index]; | |
2303 | else | |
2304 | return eof_token_; | |
2305 | } | |
2306 | ||
2307 | inline bool finished() const | |
2308 | { | |
2309 | return (token_list_.end() == token_itr_); | |
2310 | } | |
2311 | ||
2312 | inline void insert_front(token_t::token_type tk_type) | |
2313 | { | |
2314 | if ( | |
2315 | !token_list_.empty() && | |
2316 | (token_list_.end() != token_itr_) | |
2317 | ) | |
2318 | { | |
2319 | token_t t = *token_itr_; | |
2320 | ||
2321 | t.type = tk_type; | |
2322 | token_itr_ = token_list_.insert(token_itr_,t); | |
2323 | } | |
2324 | } | |
2325 | ||
2326 | inline std::string substr(const std::size_t& begin, const std::size_t& end) | |
2327 | { | |
2328 | const details::char_cptr begin_itr = ((base_itr_ + begin) < s_end_) ? (base_itr_ + begin) : s_end_; | |
2329 | const details::char_cptr end_itr = ((base_itr_ + end) < s_end_) ? (base_itr_ + end) : s_end_; | |
2330 | ||
2331 | return std::string(begin_itr,end_itr); | |
2332 | } | |
2333 | ||
2334 | inline std::string remaining() const | |
2335 | { | |
2336 | if (finished()) | |
2337 | return ""; | |
2338 | else if (token_list_.begin() != token_itr_) | |
2339 | return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); | |
2340 | else | |
2341 | return std::string(base_itr_ + token_itr_->position, s_end_); | |
2342 | } | |
2343 | ||
2344 | private: | |
2345 | ||
2346 | inline bool is_end(details::char_cptr itr) | |
2347 | { | |
2348 | return (s_end_ == itr); | |
2349 | } | |
2350 | ||
2351 | inline bool is_comment_start(details::char_cptr itr) | |
2352 | { | |
2353 | #ifndef exprtk_disable_comments | |
2354 | const char_t c0 = *(itr + 0); | |
2355 | const char_t c1 = *(itr + 1); | |
2356 | ||
2357 | if ('#' == c0) | |
2358 | return true; | |
2359 | else if (!is_end(itr + 1)) | |
2360 | { | |
2361 | if (('/' == c0) && ('/' == c1)) return true; | |
2362 | if (('/' == c0) && ('*' == c1)) return true; | |
2363 | } | |
2364 | #endif | |
2365 | return false; | |
2366 | } | |
2367 | ||
2368 | inline void skip_whitespace() | |
2369 | { | |
2370 | while (!is_end(s_itr_) && details::is_whitespace(*s_itr_)) | |
2371 | { | |
2372 | ++s_itr_; | |
2373 | } | |
2374 | } | |
2375 | ||
2376 | inline void skip_comments() | |
2377 | { | |
2378 | #ifndef exprtk_disable_comments | |
2379 | // The following comment styles are supported: | |
2380 | // 1. // .... \n | |
2381 | // 2. # .... \n | |
2382 | // 3. /* .... */ | |
2383 | struct test | |
2384 | { | |
2385 | static inline bool comment_start(const char_t c0, const char_t c1, int& mode, int& incr) | |
2386 | { | |
2387 | mode = 0; | |
2388 | if ('#' == c0) { mode = 1; incr = 1; } | |
2389 | else if ('/' == c0) | |
2390 | { | |
2391 | if ('/' == c1) { mode = 1; incr = 2; } | |
2392 | else if ('*' == c1) { mode = 2; incr = 2; } | |
2393 | } | |
2394 | return (0 != mode); | |
2395 | } | |
2396 | ||
2397 | static inline bool comment_end(const char_t c0, const char_t c1, int& mode) | |
2398 | { | |
2399 | if ( | |
2400 | ((1 == mode) && ('\n' == c0)) || | |
2401 | ((2 == mode) && ( '*' == c0) && ('/' == c1)) | |
2402 | ) | |
2403 | { | |
2404 | mode = 0; | |
2405 | return true; | |
2406 | } | |
2407 | else | |
2408 | return false; | |
2409 | } | |
2410 | }; | |
2411 | ||
2412 | int mode = 0; | |
2413 | int increment = 0; | |
2414 | ||
2415 | if (is_end(s_itr_)) | |
2416 | return; | |
2417 | else if (!test::comment_start(*s_itr_, *(s_itr_ + 1), mode, increment)) | |
2418 | return; | |
2419 | ||
2420 | details::char_cptr cmt_start = s_itr_; | |
2421 | ||
2422 | s_itr_ += increment; | |
2423 | ||
2424 | while (!is_end(s_itr_)) | |
2425 | { | |
2426 | if ((1 == mode) && test::comment_end(*s_itr_, 0, mode)) | |
2427 | { | |
2428 | ++s_itr_; | |
2429 | return; | |
2430 | } | |
2431 | ||
2432 | if ((2 == mode)) | |
2433 | { | |
2434 | if (!is_end((s_itr_ + 1)) && test::comment_end(*s_itr_, *(s_itr_ + 1), mode)) | |
2435 | { | |
2436 | s_itr_ += 2; | |
2437 | return; | |
2438 | } | |
2439 | } | |
2440 | ||
2441 | ++s_itr_; | |
2442 | } | |
2443 | ||
2444 | if (2 == mode) | |
2445 | { | |
2446 | token_t t; | |
2447 | t.set_error(token::e_error, cmt_start, cmt_start + mode, base_itr_); | |
2448 | token_list_.push_back(t); | |
2449 | } | |
2450 | #endif | |
2451 | } | |
2452 | ||
2453 | inline void scan_token() | |
2454 | { | |
2455 | if (details::is_whitespace(*s_itr_)) | |
2456 | { | |
2457 | skip_whitespace(); | |
2458 | return; | |
2459 | } | |
2460 | else if (is_comment_start(s_itr_)) | |
2461 | { | |
2462 | skip_comments(); | |
2463 | return; | |
2464 | } | |
2465 | else if (details::is_operator_char(*s_itr_)) | |
2466 | { | |
2467 | scan_operator(); | |
2468 | return; | |
2469 | } | |
2470 | else if (details::is_letter(*s_itr_)) | |
2471 | { | |
2472 | scan_symbol(); | |
2473 | return; | |
2474 | } | |
2475 | else if (details::is_digit((*s_itr_)) || ('.' == (*s_itr_))) | |
2476 | { | |
2477 | scan_number(); | |
2478 | return; | |
2479 | } | |
2480 | else if ('$' == (*s_itr_)) | |
2481 | { | |
2482 | scan_special_function(); | |
2483 | return; | |
2484 | } | |
2485 | #ifndef exprtk_disable_string_capabilities | |
2486 | else if ('\'' == (*s_itr_)) | |
2487 | { | |
2488 | scan_string(); | |
2489 | return; | |
2490 | } | |
2491 | #endif | |
2492 | else if ('~' == (*s_itr_)) | |
2493 | { | |
2494 | token_t t; | |
2495 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); | |
2496 | token_list_.push_back(t); | |
2497 | ++s_itr_; | |
2498 | return; | |
2499 | } | |
2500 | else | |
2501 | { | |
2502 | token_t t; | |
2503 | t.set_error(token::e_error, s_itr_, s_itr_ + 2, base_itr_); | |
2504 | token_list_.push_back(t); | |
2505 | ++s_itr_; | |
2506 | } | |
2507 | } | |
2508 | ||
2509 | inline void scan_operator() | |
2510 | { | |
2511 | token_t t; | |
2512 | ||
2513 | const char_t c0 = s_itr_[0]; | |
2514 | ||
2515 | if (!is_end(s_itr_ + 1)) | |
2516 | { | |
2517 | const char_t c1 = s_itr_[1]; | |
2518 | ||
2519 | if (!is_end(s_itr_ + 2)) | |
2520 | { | |
2521 | const char_t c2 = s_itr_[2]; | |
2522 | ||
2523 | if ((c0 == '<') && (c1 == '=') && (c2 == '>')) | |
2524 | { | |
2525 | t.set_operator(token_t::e_swap, s_itr_, s_itr_ + 3, base_itr_); | |
2526 | token_list_.push_back(t); | |
2527 | s_itr_ += 3; | |
2528 | return; | |
2529 | } | |
2530 | } | |
2531 | ||
2532 | token_t::token_type ttype = token_t::e_none; | |
2533 | ||
2534 | if ((c0 == '<') && (c1 == '=')) ttype = token_t::e_lte; | |
2535 | else if ((c0 == '>') && (c1 == '=')) ttype = token_t::e_gte; | |
2536 | else if ((c0 == '<') && (c1 == '>')) ttype = token_t::e_ne; | |
2537 | else if ((c0 == '!') && (c1 == '=')) ttype = token_t::e_ne; | |
2538 | else if ((c0 == '=') && (c1 == '=')) ttype = token_t::e_eq; | |
2539 | else if ((c0 == ':') && (c1 == '=')) ttype = token_t::e_assign; | |
2540 | else if ((c0 == '<') && (c1 == '<')) ttype = token_t::e_shl; | |
2541 | else if ((c0 == '>') && (c1 == '>')) ttype = token_t::e_shr; | |
2542 | else if ((c0 == '+') && (c1 == '=')) ttype = token_t::e_addass; | |
2543 | else if ((c0 == '-') && (c1 == '=')) ttype = token_t::e_subass; | |
2544 | else if ((c0 == '*') && (c1 == '=')) ttype = token_t::e_mulass; | |
2545 | else if ((c0 == '/') && (c1 == '=')) ttype = token_t::e_divass; | |
2546 | else if ((c0 == '%') && (c1 == '=')) ttype = token_t::e_modass; | |
2547 | ||
2548 | if (token_t::e_none != ttype) | |
2549 | { | |
2550 | t.set_operator(ttype, s_itr_, s_itr_ + 2, base_itr_); | |
2551 | token_list_.push_back(t); | |
2552 | s_itr_ += 2; | |
2553 | return; | |
2554 | } | |
2555 | } | |
2556 | ||
2557 | if ('<' == c0) | |
2558 | t.set_operator(token_t::e_lt , s_itr_, s_itr_ + 1, base_itr_); | |
2559 | else if ('>' == c0) | |
2560 | t.set_operator(token_t::e_gt , s_itr_, s_itr_ + 1, base_itr_); | |
2561 | else if (';' == c0) | |
2562 | t.set_operator(token_t::e_eof, s_itr_, s_itr_ + 1, base_itr_); | |
2563 | else if ('&' == c0) | |
2564 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); | |
2565 | else if ('|' == c0) | |
2566 | t.set_symbol(s_itr_, s_itr_ + 1, base_itr_); | |
2567 | else | |
2568 | t.set_operator(token_t::token_type(c0), s_itr_, s_itr_ + 1, base_itr_); | |
2569 | ||
2570 | token_list_.push_back(t); | |
2571 | ++s_itr_; | |
2572 | } | |
2573 | ||
2574 | inline void scan_symbol() | |
2575 | { | |
2576 | details::char_cptr initial_itr = s_itr_; | |
2577 | ||
2578 | while (!is_end(s_itr_)) | |
2579 | { | |
2580 | if (!details::is_letter_or_digit(*s_itr_) && ('_' != (*s_itr_))) | |
2581 | { | |
2582 | if ('.' != (*s_itr_)) | |
2583 | break; | |
2584 | /* | |
2585 | Permit symbols that contain a 'dot' | |
2586 | Allowed : abc.xyz, a123.xyz, abc.123, abc_.xyz a123_.xyz abc._123 | |
2587 | Disallowed: .abc, abc.<white-space>, abc.<eof>, abc.<operator +,-,*,/...> | |
2588 | */ | |
2589 | if ( | |
2590 | (s_itr_ != initial_itr) && | |
2591 | !is_end(s_itr_ + 1) && | |
2592 | !details::is_letter_or_digit(*(s_itr_ + 1)) && | |
2593 | ('_' != (*(s_itr_ + 1))) | |
2594 | ) | |
2595 | break; | |
2596 | } | |
2597 | ||
2598 | ++s_itr_; | |
2599 | } | |
2600 | ||
2601 | token_t t; | |
2602 | t.set_symbol(initial_itr,s_itr_,base_itr_); | |
2603 | token_list_.push_back(t); | |
2604 | } | |
2605 | ||
2606 | inline void scan_number() | |
2607 | { | |
2608 | /* | |
2609 | Attempt to match a valid numeric value in one of the following formats: | |
2610 | (01) 123456 | |
2611 | (02) 123456. | |
2612 | (03) 123.456 | |
2613 | (04) 123.456e3 | |
2614 | (05) 123.456E3 | |
2615 | (06) 123.456e+3 | |
2616 | (07) 123.456E+3 | |
2617 | (08) 123.456e-3 | |
2618 | (09) 123.456E-3 | |
2619 | (00) .1234 | |
2620 | (11) .1234e3 | |
2621 | (12) .1234E+3 | |
2622 | (13) .1234e+3 | |
2623 | (14) .1234E-3 | |
2624 | (15) .1234e-3 | |
2625 | */ | |
2626 | ||
2627 | details::char_cptr initial_itr = s_itr_; | |
2628 | bool dot_found = false; | |
2629 | bool e_found = false; | |
2630 | bool post_e_sign_found = false; | |
2631 | bool post_e_digit_found = false; | |
2632 | token_t t; | |
2633 | ||
2634 | while (!is_end(s_itr_)) | |
2635 | { | |
2636 | if ('.' == (*s_itr_)) | |
2637 | { | |
2638 | if (dot_found) | |
2639 | { | |
2640 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); | |
2641 | token_list_.push_back(t); | |
2642 | return; | |
2643 | } | |
2644 | ||
2645 | dot_found = true; | |
2646 | ++s_itr_; | |
2647 | ||
2648 | continue; | |
2649 | } | |
2650 | else if ('e' == std::tolower(*s_itr_)) | |
2651 | { | |
2652 | const char_t& c = *(s_itr_ + 1); | |
2653 | ||
2654 | if (is_end(s_itr_ + 1)) | |
2655 | { | |
2656 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); | |
2657 | token_list_.push_back(t); | |
2658 | ||
2659 | return; | |
2660 | } | |
2661 | else if ( | |
2662 | ('+' != c) && | |
2663 | ('-' != c) && | |
2664 | !details::is_digit(c) | |
2665 | ) | |
2666 | { | |
2667 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); | |
2668 | token_list_.push_back(t); | |
2669 | ||
2670 | return; | |
2671 | } | |
2672 | ||
2673 | e_found = true; | |
2674 | ++s_itr_; | |
2675 | ||
2676 | continue; | |
2677 | } | |
2678 | else if (e_found && details::is_sign(*s_itr_) && !post_e_digit_found) | |
2679 | { | |
2680 | if (post_e_sign_found) | |
2681 | { | |
2682 | t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); | |
2683 | token_list_.push_back(t); | |
2684 | ||
2685 | return; | |
2686 | } | |
2687 | ||
2688 | post_e_sign_found = true; | |
2689 | ++s_itr_; | |
2690 | ||
2691 | continue; | |
2692 | } | |
2693 | else if (e_found && details::is_digit(*s_itr_)) | |
2694 | { | |
2695 | post_e_digit_found = true; | |
2696 | ++s_itr_; | |
2697 | ||
2698 | continue; | |
2699 | } | |
2700 | else if (('.' != (*s_itr_)) && !details::is_digit(*s_itr_)) | |
2701 | break; | |
2702 | else | |
2703 | ++s_itr_; | |
2704 | } | |
2705 | ||
2706 | t.set_numeric(initial_itr, s_itr_, base_itr_); | |
2707 | token_list_.push_back(t); | |
2708 | ||
2709 | return; | |
2710 | } | |
2711 | ||
2712 | inline void scan_special_function() | |
2713 | { | |
2714 | details::char_cptr initial_itr = s_itr_; | |
2715 | token_t t; | |
2716 | ||
2717 | // $fdd(x,x,x) = at least 11 chars | |
2718 | if (std::distance(s_itr_,s_end_) < 11) | |
2719 | { | |
2720 | t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); | |
2721 | token_list_.push_back(t); | |
2722 | ||
2723 | return; | |
2724 | } | |
2725 | ||
2726 | if ( | |
2727 | !(('$' == *s_itr_) && | |
2728 | (details::imatch ('f',*(s_itr_ + 1))) && | |
2729 | (details::is_digit(*(s_itr_ + 2))) && | |
2730 | (details::is_digit(*(s_itr_ + 3)))) | |
2731 | ) | |
2732 | { | |
2733 | t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); | |
2734 | token_list_.push_back(t); | |
2735 | ||
2736 | return; | |
2737 | } | |
2738 | ||
2739 | s_itr_ += 4; // $fdd = 4chars | |
2740 | ||
2741 | t.set_symbol(initial_itr, s_itr_, base_itr_); | |
2742 | token_list_.push_back(t); | |
2743 | ||
2744 | return; | |
2745 | } | |
2746 | ||
2747 | #ifndef exprtk_disable_string_capabilities | |
2748 | inline void scan_string() | |
2749 | { | |
2750 | details::char_cptr initial_itr = s_itr_ + 1; | |
2751 | token_t t; | |
2752 | ||
2753 | if (std::distance(s_itr_,s_end_) < 2) | |
2754 | { | |
2755 | t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); | |
2756 | token_list_.push_back(t); | |
2757 | return; | |
2758 | } | |
2759 | ||
2760 | ++s_itr_; | |
2761 | ||
2762 | bool escaped_found = false; | |
2763 | bool escaped = false; | |
2764 | ||
2765 | while (!is_end(s_itr_)) | |
2766 | { | |
2767 | if (!escaped && ('\\' == *s_itr_)) | |
2768 | { | |
2769 | escaped_found = true; | |
2770 | escaped = true; | |
2771 | ++s_itr_; | |
2772 | ||
2773 | continue; | |
2774 | } | |
2775 | else if (!escaped) | |
2776 | { | |
2777 | if ('\'' == *s_itr_) | |
2778 | break; | |
2779 | } | |
2780 | else if (escaped) | |
2781 | { | |
2782 | if (!is_end(s_itr_) && ('0' == *(s_itr_))) | |
2783 | { | |
2784 | /* | |
2785 | Note: The following 'awkward' conditional is | |
2786 | due to various broken msvc compilers. | |
2787 | */ | |
2788 | #if defined(_MSC_VER) && (_MSC_VER == 1600) | |
2789 | const bool within_range = !is_end(s_itr_ + 2) && | |
2790 | !is_end(s_itr_ + 3) ; | |
2791 | #else | |
2792 | const bool within_range = !is_end(s_itr_ + 1) && | |
2793 | !is_end(s_itr_ + 2) && | |
2794 | !is_end(s_itr_ + 3) ; | |
2795 | #endif | |
2796 | ||
2797 | const bool x_seperator = ('x' == *(s_itr_ + 1)) || | |
2798 | ('X' == *(s_itr_ + 1)) ; | |
2799 | ||
2800 | const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && | |
2801 | details::is_hex_digit(*(s_itr_ + 3)) ; | |
2802 | ||
2803 | if (!within_range || !x_seperator || !both_digits) | |
2804 | { | |
2805 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); | |
2806 | token_list_.push_back(t); | |
2807 | ||
2808 | return; | |
2809 | } | |
2810 | else | |
2811 | s_itr_ += 3; | |
2812 | } | |
2813 | ||
2814 | escaped = false; | |
2815 | } | |
2816 | ||
2817 | ++s_itr_; | |
2818 | } | |
2819 | ||
2820 | if (is_end(s_itr_)) | |
2821 | { | |
2822 | t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); | |
2823 | token_list_.push_back(t); | |
2824 | ||
2825 | return; | |
2826 | } | |
2827 | ||
2828 | if (!escaped_found) | |
2829 | t.set_string(initial_itr, s_itr_, base_itr_); | |
2830 | else | |
2831 | { | |
2832 | std::string parsed_string(initial_itr,s_itr_); | |
2833 | ||
2834 | details::cleanup_escapes(parsed_string); | |
2835 | ||
2836 | t.set_string( | |
2837 | parsed_string, | |
2838 | static_cast<std::size_t>(std::distance(base_itr_,initial_itr))); | |
2839 | } | |
2840 | ||
2841 | token_list_.push_back(t); | |
2842 | ++s_itr_; | |
2843 | ||
2844 | return; | |
2845 | } | |
2846 | #endif | |
2847 | ||
2848 | private: | |
2849 | ||
2850 | token_list_t token_list_; | |
2851 | token_list_itr_t token_itr_; | |
2852 | token_list_itr_t store_token_itr_; | |
2853 | token_t eof_token_; | |
2854 | details::char_cptr base_itr_; | |
2855 | details::char_cptr s_itr_; | |
2856 | details::char_cptr s_end_; | |
2857 | ||
2858 | friend class token_scanner; | |
2859 | friend class token_modifier; | |
2860 | friend class token_inserter; | |
2861 | friend class token_joiner; | |
2862 | }; | |
2863 | ||
2864 | class helper_interface | |
2865 | { | |
2866 | public: | |
2867 | ||
2868 | virtual void init() { } | |
2869 | virtual void reset() { } | |
2870 | virtual bool result() { return true; } | |
2871 | virtual std::size_t process(generator&) { return 0; } | |
2872 | virtual ~helper_interface() { } | |
2873 | }; | |
2874 | ||
2875 | class token_scanner : public helper_interface | |
2876 | { | |
2877 | public: | |
2878 | ||
2879 | virtual ~token_scanner() | |
2880 | {} | |
2881 | ||
2882 | explicit token_scanner(const std::size_t& stride) | |
2883 | : stride_(stride) | |
2884 | { | |
2885 | if (stride > 4) | |
2886 | { | |
2887 | throw std::invalid_argument("token_scanner() - Invalid stride value"); | |
2888 | } | |
2889 | } | |
2890 | ||
2891 | inline std::size_t process(generator& g) | |
2892 | { | |
2893 | if (g.token_list_.size() >= stride_) | |
2894 | { | |
2895 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) | |
2896 | { | |
2897 | token t; | |
2898 | ||
2899 | switch (stride_) | |
2900 | { | |
2901 | case 1 : | |
2902 | { | |
2903 | const token& t0 = g.token_list_[i]; | |
2904 | ||
2905 | if (!operator()(t0)) | |
2906 | { | |
2907 | return i; | |
2908 | } | |
2909 | } | |
2910 | break; | |
2911 | ||
2912 | case 2 : | |
2913 | { | |
2914 | const token& t0 = g.token_list_[i ]; | |
2915 | const token& t1 = g.token_list_[i + 1]; | |
2916 | ||
2917 | if (!operator()(t0, t1)) | |
2918 | { | |
2919 | return i; | |
2920 | } | |
2921 | } | |
2922 | break; | |
2923 | ||
2924 | case 3 : | |
2925 | { | |
2926 | const token& t0 = g.token_list_[i ]; | |
2927 | const token& t1 = g.token_list_[i + 1]; | |
2928 | const token& t2 = g.token_list_[i + 2]; | |
2929 | ||
2930 | if (!operator()(t0, t1, t2)) | |
2931 | { | |
2932 | return i; | |
2933 | } | |
2934 | } | |
2935 | break; | |
2936 | ||
2937 | case 4 : | |
2938 | { | |
2939 | const token& t0 = g.token_list_[i ]; | |
2940 | const token& t1 = g.token_list_[i + 1]; | |
2941 | const token& t2 = g.token_list_[i + 2]; | |
2942 | const token& t3 = g.token_list_[i + 3]; | |
2943 | ||
2944 | if (!operator()(t0, t1, t2, t3)) | |
2945 | { | |
2946 | return i; | |
2947 | } | |
2948 | } | |
2949 | break; | |
2950 | } | |
2951 | } | |
2952 | } | |
2953 | ||
2954 | return (g.token_list_.size() - stride_ + 1); | |
2955 | } | |
2956 | ||
2957 | virtual bool operator() (const token&) | |
2958 | { | |
2959 | return false; | |
2960 | } | |
2961 | ||
2962 | virtual bool operator() (const token&, const token&) | |
2963 | { | |
2964 | return false; | |
2965 | } | |
2966 | ||
2967 | virtual bool operator() (const token&, const token&, const token&) | |
2968 | { | |
2969 | return false; | |
2970 | } | |
2971 | ||
2972 | virtual bool operator() (const token&, const token&, const token&, const token&) | |
2973 | { | |
2974 | return false; | |
2975 | } | |
2976 | ||
2977 | private: | |
2978 | ||
2979 | const std::size_t stride_; | |
2980 | }; | |
2981 | ||
2982 | class token_modifier : public helper_interface | |
2983 | { | |
2984 | public: | |
2985 | ||
2986 | inline std::size_t process(generator& g) | |
2987 | { | |
2988 | std::size_t changes = 0; | |
2989 | ||
2990 | for (std::size_t i = 0; i < g.token_list_.size(); ++i) | |
2991 | { | |
2992 | if (modify(g.token_list_[i])) changes++; | |
2993 | } | |
2994 | ||
2995 | return changes; | |
2996 | } | |
2997 | ||
2998 | virtual bool modify(token& t) = 0; | |
2999 | }; | |
3000 | ||
3001 | class token_inserter : public helper_interface | |
3002 | { | |
3003 | public: | |
3004 | ||
3005 | explicit token_inserter(const std::size_t& stride) | |
3006 | : stride_(stride) | |
3007 | { | |
3008 | if (stride > 5) | |
3009 | { | |
3010 | throw std::invalid_argument("token_inserter() - Invalid stride value"); | |
3011 | } | |
3012 | } | |
3013 | ||
3014 | inline std::size_t process(generator& g) | |
3015 | { | |
3016 | if (g.token_list_.empty()) | |
3017 | return 0; | |
3018 | else if (g.token_list_.size() < stride_) | |
3019 | return 0; | |
3020 | ||
3021 | std::size_t changes = 0; | |
3022 | ||
3023 | for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) | |
3024 | { | |
3025 | int insert_index = -1; | |
3026 | token t; | |
3027 | ||
3028 | switch (stride_) | |
3029 | { | |
3030 | case 1 : insert_index = insert(g.token_list_[i],t); | |
3031 | break; | |
3032 | ||
3033 | case 2 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], t); | |
3034 | break; | |
3035 | ||
3036 | case 3 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], t); | |
3037 | break; | |
3038 | ||
3039 | case 4 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], t); | |
3040 | break; | |
3041 | ||
3042 | case 5 : insert_index = insert(g.token_list_[i], g.token_list_[i + 1], g.token_list_[i + 2], g.token_list_[i + 3], g.token_list_[i + 4], t); | |
3043 | break; | |
3044 | } | |
3045 | ||
3046 | typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; | |
3047 | ||
3048 | if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) | |
3049 | { | |
3050 | g.token_list_.insert( | |
3051 | g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t); | |
3052 | ||
3053 | changes++; | |
3054 | } | |
3055 | } | |
3056 | ||
3057 | return changes; | |
3058 | } | |
3059 | ||
3060 | #define token_inserter_empty_body \ | |
3061 | { \ | |
3062 | return -1; \ | |
3063 | } \ | |
3064 | ||
3065 | inline virtual int insert(const token&, token&) | |
3066 | token_inserter_empty_body | |
3067 | ||
3068 | inline virtual int insert(const token&, const token&, token&) | |
3069 | token_inserter_empty_body | |
3070 | ||
3071 | inline virtual int insert(const token&, const token&, const token&, token&) | |
3072 | token_inserter_empty_body | |
3073 | ||
3074 | inline virtual int insert(const token&, const token&, const token&, const token&, token&) | |
3075 | token_inserter_empty_body | |
3076 | ||
3077 | inline virtual int insert(const token&, const token&, const token&, const token&, const token&, token&) | |
3078 | token_inserter_empty_body | |
3079 | ||
3080 | #undef token_inserter_empty_body | |
3081 | ||
3082 | private: | |
3083 | ||
3084 | const std::size_t stride_; | |
3085 | }; | |
3086 | ||
3087 | class token_joiner : public helper_interface | |
3088 | { | |
3089 | public: | |
3090 | ||
3091 | explicit token_joiner(const std::size_t& stride) | |
3092 | : stride_(stride) | |
3093 | {} | |
3094 | ||
3095 | inline std::size_t process(generator& g) | |
3096 | { | |
3097 | if (g.token_list_.empty()) | |
3098 | return 0; | |
3099 | ||
3100 | switch (stride_) | |
3101 | { | |
3102 | case 2 : return process_stride_2(g); | |
3103 | case 3 : return process_stride_3(g); | |
3104 | default : return 0; | |
3105 | } | |
3106 | } | |
3107 | ||
3108 | virtual bool join(const token&, const token&, token&) { return false; } | |
3109 | virtual bool join(const token&, const token&, const token&, token&) { return false; } | |
3110 | ||
3111 | private: | |
3112 | ||
3113 | inline std::size_t process_stride_2(generator& g) | |
3114 | { | |
3115 | typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; | |
3116 | ||
3117 | if (g.token_list_.size() < 2) | |
3118 | return 0; | |
3119 | ||
3120 | std::size_t changes = 0; | |
3121 | ||
3122 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) | |
3123 | { | |
3124 | token t; | |
3125 | ||
3126 | while (join(g[i], g[i + 1], t)) | |
3127 | { | |
3128 | g.token_list_[i] = t; | |
3129 | ||
3130 | g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1)); | |
3131 | ||
3132 | ++changes; | |
3133 | ||
3134 | if (static_cast<std::size_t>(i + 1) >= g.token_list_.size()) | |
3135 | break; | |
3136 | } | |
3137 | } | |
3138 | ||
3139 | return changes; | |
3140 | } | |
3141 | ||
3142 | inline std::size_t process_stride_3(generator& g) | |
3143 | { | |
3144 | typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; | |
3145 | ||
3146 | if (g.token_list_.size() < 3) | |
3147 | return 0; | |
3148 | ||
3149 | std::size_t changes = 0; | |
3150 | ||
3151 | for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) | |
3152 | { | |
3153 | token t; | |
3154 | ||
3155 | while (join(g[i], g[i + 1], g[i + 2], t)) | |
3156 | { | |
3157 | g.token_list_[i] = t; | |
3158 | ||
3159 | g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1), | |
3160 | g.token_list_.begin() + static_cast<diff_t>(i + 3)); | |
3161 | ++changes; | |
3162 | ||
3163 | if (static_cast<std::size_t>(i + 2) >= g.token_list_.size()) | |
3164 | break; | |
3165 | } | |
3166 | } | |
3167 | ||
3168 | return changes; | |
3169 | } | |
3170 | ||
3171 | const std::size_t stride_; | |
3172 | }; | |
3173 | ||
3174 | namespace helper | |
3175 | { | |
3176 | ||
3177 | inline void dump(lexer::generator& generator) | |
3178 | { | |
3179 | for (std::size_t i = 0; i < generator.size(); ++i) | |
3180 | { | |
3181 | lexer::token t = generator[i]; | |
3182 | printf("Token[%02d] @ %03d %6s --> '%s'\n", | |
3183 | static_cast<int>(i), | |
3184 | static_cast<int>(t.position), | |
3185 | t.to_str(t.type).c_str(), | |
3186 | t.value.c_str()); | |
3187 | } | |
3188 | } | |
3189 | ||
3190 | class commutative_inserter : public lexer::token_inserter | |
3191 | { | |
3192 | public: | |
3193 | ||
3194 | using lexer::token_inserter::insert; | |
3195 | ||
3196 | commutative_inserter() | |
3197 | : lexer::token_inserter(2) | |
3198 | {} | |
3199 | ||
3200 | inline void ignore_symbol(const std::string& symbol) | |
3201 | { | |
3202 | ignore_set_.insert(symbol); | |
3203 | } | |
3204 | ||
3205 | inline int insert(const lexer::token& t0, const lexer::token& t1, lexer::token& new_token) | |
3206 | { | |
3207 | bool match = false; | |
3208 | new_token.type = lexer::token::e_mul; | |
3209 | new_token.value = "*"; | |
3210 | new_token.position = t1.position; | |
3211 | ||
3212 | if (t0.type == lexer::token::e_symbol) | |
3213 | { | |
3214 | if (ignore_set_.end() != ignore_set_.find(t0.value)) | |
3215 | { | |
3216 | return -1; | |
3217 | } | |
3218 | else if (!t0.value.empty() && ('$' == t0.value[0])) | |
3219 | { | |
3220 | return -1; | |
3221 | } | |
3222 | } | |
3223 | ||
3224 | if (t1.type == lexer::token::e_symbol) | |
3225 | { | |
3226 | if (ignore_set_.end() != ignore_set_.find(t1.value)) | |
3227 | { | |
3228 | return -1; | |
3229 | } | |
3230 | } | |
3231 | if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_symbol )) match = true; | |
3232 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lbracket )) match = true; | |
3233 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lcrlbracket)) match = true; | |
3234 | else if ((t0.type == lexer::token::e_number ) && (t1.type == lexer::token::e_lsqrbracket)) match = true; | |
3235 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_number )) match = true; | |
3236 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_number )) match = true; | |
3237 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_number )) match = true; | |
3238 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_number )) match = true; | |
3239 | else if ((t0.type == lexer::token::e_rbracket ) && (t1.type == lexer::token::e_symbol )) match = true; | |
3240 | else if ((t0.type == lexer::token::e_rcrlbracket) && (t1.type == lexer::token::e_symbol )) match = true; | |
3241 | else if ((t0.type == lexer::token::e_rsqrbracket) && (t1.type == lexer::token::e_symbol )) match = true; | |
3242 | else if ((t0.type == lexer::token::e_symbol ) && (t1.type == lexer::token::e_symbol )) match = true; | |
3243 | ||
3244 | return (match) ? 1 : -1; | |
3245 | } | |
3246 | ||
3247 | private: | |
3248 | ||
3249 | std::set<std::string,details::ilesscompare> ignore_set_; | |
3250 | }; | |
3251 | ||
3252 | class operator_joiner : public token_joiner | |
3253 | { | |
3254 | public: | |
3255 | ||
3256 | explicit operator_joiner(const std::size_t& stride) | |
3257 | : token_joiner(stride) | |
3258 | {} | |
3259 | ||
3260 | inline bool join(const lexer::token& t0, const lexer::token& t1, lexer::token& t) | |
3261 | { | |
3262 | // ': =' --> ':=' | |
3263 | if ((t0.type == lexer::token::e_colon) && (t1.type == lexer::token::e_eq)) | |
3264 | { | |
3265 | t.type = lexer::token::e_assign; | |
3266 | t.value = ":="; | |
3267 | t.position = t0.position; | |
3268 | ||
3269 | return true; | |
3270 | } | |
3271 | // '+ =' --> '+=' | |
3272 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_eq)) | |
3273 | { | |
3274 | t.type = lexer::token::e_addass; | |
3275 | t.value = "+="; | |
3276 | t.position = t0.position; | |
3277 | ||
3278 | return true; | |
3279 | } | |
3280 | // '- =' --> '-=' | |
3281 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_eq)) | |
3282 | { | |
3283 | t.type = lexer::token::e_subass; | |
3284 | t.value = "-="; | |
3285 | t.position = t0.position; | |
3286 | ||
3287 | return true; | |
3288 | } | |
3289 | // '* =' --> '*=' | |
3290 | else if ((t0.type == lexer::token::e_mul) && (t1.type == lexer::token::e_eq)) | |
3291 | { | |
3292 | t.type = lexer::token::e_mulass; | |
3293 | t.value = "*="; | |
3294 | t.position = t0.position; | |
3295 | ||
3296 | return true; | |
3297 | } | |
3298 | // '/ =' --> '/=' | |
3299 | else if ((t0.type == lexer::token::e_div) && (t1.type == lexer::token::e_eq)) | |
3300 | { | |
3301 | t.type = lexer::token::e_divass; | |
3302 | t.value = "/="; | |
3303 | t.position = t0.position; | |
3304 | ||
3305 | return true; | |
3306 | } | |
3307 | // '% =' --> '%=' | |
3308 | else if ((t0.type == lexer::token::e_mod) && (t1.type == lexer::token::e_eq)) | |
3309 | { | |
3310 | t.type = lexer::token::e_modass; | |
3311 | t.value = "%="; | |
3312 | t.position = t0.position; | |
3313 | ||
3314 | return true; | |
3315 | } | |
3316 | // '> =' --> '>=' | |
3317 | else if ((t0.type == lexer::token::e_gt) && (t1.type == lexer::token::e_eq)) | |
3318 | { | |
3319 | t.type = lexer::token::e_gte; | |
3320 | t.value = ">="; | |
3321 | t.position = t0.position; | |
3322 | ||
3323 | return true; | |
3324 | } | |
3325 | // '< =' --> '<=' | |
3326 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_eq)) | |
3327 | { | |
3328 | t.type = lexer::token::e_lte; | |
3329 | t.value = "<="; | |
3330 | t.position = t0.position; | |
3331 | ||
3332 | return true; | |
3333 | } | |
3334 | // '= =' --> '==' | |
3335 | else if ((t0.type == lexer::token::e_eq) && (t1.type == lexer::token::e_eq)) | |
3336 | { | |
3337 | t.type = lexer::token::e_eq; | |
3338 | t.value = "=="; | |
3339 | t.position = t0.position; | |
3340 | ||
3341 | return true; | |
3342 | } | |
3343 | // '! =' --> '!=' | |
3344 | else if ((static_cast<char>(t0.type) == '!') && (t1.type == lexer::token::e_eq)) | |
3345 | { | |
3346 | t.type = lexer::token::e_ne; | |
3347 | t.value = "!="; | |
3348 | t.position = t0.position; | |
3349 | ||
3350 | return true; | |
3351 | } | |
3352 | // '< >' --> '<>' | |
3353 | else if ((t0.type == lexer::token::e_lt) && (t1.type == lexer::token::e_gt)) | |
3354 | { | |
3355 | t.type = lexer::token::e_ne; | |
3356 | t.value = "<>"; | |
3357 | t.position = t0.position; | |
3358 | ||
3359 | return true; | |
3360 | } | |
3361 | // '<= >' --> '<=>' | |
3362 | else if ((t0.type == lexer::token::e_lte) && (t1.type == lexer::token::e_gt)) | |
3363 | { | |
3364 | t.type = lexer::token::e_swap; | |
3365 | t.value = "<=>"; | |
3366 | t.position = t0.position; | |
3367 | ||
3368 | return true; | |
3369 | } | |
3370 | // '+ -' --> '-' | |
3371 | else if ((t0.type == lexer::token::e_add) && (t1.type == lexer::token::e_sub)) | |
3372 | { | |
3373 | t.type = lexer::token::e_sub; | |
3374 | t.value = "-"; | |
3375 | t.position = t0.position; | |
3376 | ||
3377 | return true; | |
3378 | } | |
3379 | // '- +' --> '-' | |
3380 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_add)) | |
3381 | { | |
3382 | t.type = lexer::token::e_sub; | |
3383 | t.value = "-"; | |
3384 | t.position = t0.position; | |
3385 | ||
3386 | return true; | |
3387 | } | |
3388 | // '- -' --> '+' | |
3389 | else if ((t0.type == lexer::token::e_sub) && (t1.type == lexer::token::e_sub)) | |
3390 | { | |
3391 | /* | |
3392 | Note: May need to reconsider this when wanting to implement | |
3393 | pre/postfix decrement operator | |
3394 | */ | |
3395 | t.type = lexer::token::e_add; | |
3396 | t.value = "+"; | |
3397 | t.position = t0.position; | |
3398 | ||
3399 | return true; | |
3400 | } | |
3401 | else | |
3402 | return false; | |
3403 | } | |
3404 | ||
3405 | inline bool join(const lexer::token& t0, const lexer::token& t1, const lexer::token& t2, lexer::token& t) | |
3406 | { | |
3407 | // '[ * ]' --> '[*]' | |
3408 | if ( | |
3409 | (t0.type == lexer::token::e_lsqrbracket) && | |
3410 | (t1.type == lexer::token::e_mul ) && | |
3411 | (t2.type == lexer::token::e_rsqrbracket) | |
3412 | ) | |
3413 | { | |
3414 | t.type = lexer::token::e_symbol; | |
3415 | t.value = "[*]"; | |
3416 | t.position = t0.position; | |
3417 | ||
3418 | return true; | |
3419 | } | |
3420 | else | |
3421 | return false; | |
3422 | } | |
3423 | }; | |
3424 | ||
3425 | class bracket_checker : public lexer::token_scanner | |
3426 | { | |
3427 | public: | |
3428 | ||
3429 | using lexer::token_scanner::operator(); | |
3430 | ||
3431 | bracket_checker() | |
3432 | : token_scanner(1), | |
3433 | state_(true) | |
3434 | {} | |
3435 | ||
3436 | bool result() | |
3437 | { | |
3438 | if (!stack_.empty()) | |
3439 | { | |
3440 | lexer::token t; | |
3441 | t.value = stack_.top().first; | |
3442 | t.position = stack_.top().second; | |
3443 | error_token_ = t; | |
3444 | state_ = false; | |
3445 | ||
3446 | return false; | |
3447 | } | |
3448 | else | |
3449 | return state_; | |
3450 | } | |
3451 | ||
3452 | lexer::token error_token() | |
3453 | { | |
3454 | return error_token_; | |
3455 | } | |
3456 | ||
3457 | void reset() | |
3458 | { | |
3459 | // Why? because msvc doesn't support swap properly. | |
3460 | stack_ = std::stack<std::pair<char,std::size_t> >(); | |
3461 | state_ = true; | |
3462 | error_token_.clear(); | |
3463 | } | |
3464 | ||
3465 | bool operator() (const lexer::token& t) | |
3466 | { | |
3467 | if ( | |
3468 | !t.value.empty() && | |
3469 | (lexer::token::e_string != t.type) && | |
3470 | (lexer::token::e_symbol != t.type) && | |
3471 | exprtk::details::is_bracket(t.value[0]) | |
3472 | ) | |
3473 | { | |
3474 | details::char_t c = t.value[0]; | |
3475 | ||
3476 | if (t.type == lexer::token::e_lbracket ) stack_.push(std::make_pair(')',t.position)); | |
3477 | else if (t.type == lexer::token::e_lcrlbracket) stack_.push(std::make_pair('}',t.position)); | |
3478 | else if (t.type == lexer::token::e_lsqrbracket) stack_.push(std::make_pair(']',t.position)); | |
3479 | else if (exprtk::details::is_right_bracket(c)) | |
3480 | { | |
3481 | if (stack_.empty()) | |
3482 | { | |
3483 | state_ = false; | |
3484 | error_token_ = t; | |
3485 | ||
3486 | return false; | |
3487 | } | |
3488 | else if (c != stack_.top().first) | |
3489 | { | |
3490 | state_ = false; | |
3491 | error_token_ = t; | |
3492 | ||
3493 | return false; | |
3494 | } | |
3495 | else | |
3496 | stack_.pop(); | |
3497 | } | |
3498 | } | |
3499 | ||
3500 | return true; | |
3501 | } | |
3502 | ||
3503 | private: | |
3504 | ||
3505 | bool state_; | |
3506 | std::stack<std::pair<char,std::size_t> > stack_; | |
3507 | lexer::token error_token_; | |
3508 | }; | |
3509 | ||
3510 | class numeric_checker : public lexer::token_scanner | |
3511 | { | |
3512 | public: | |
3513 | ||
3514 | using lexer::token_scanner::operator(); | |
3515 | ||
3516 | numeric_checker() | |
3517 | : token_scanner (1), | |
3518 | current_index_(0) | |
3519 | {} | |
3520 | ||
3521 | bool result() | |
3522 | { | |
3523 | return error_list_.empty(); | |
3524 | } | |
3525 | ||
3526 | void reset() | |
3527 | { | |
3528 | error_list_.clear(); | |
3529 | current_index_ = 0; | |
3530 | } | |
3531 | ||
3532 | bool operator() (const lexer::token& t) | |
3533 | { | |
3534 | if (token::e_number == t.type) | |
3535 | { | |
3536 | double v; | |
3537 | ||
3538 | if (!exprtk::details::string_to_real(t.value,v)) | |
3539 | { | |
3540 | error_list_.push_back(current_index_); | |
3541 | } | |
3542 | } | |
3543 | ||
3544 | ++current_index_; | |
3545 | ||
3546 | return true; | |
3547 | } | |
3548 | ||
3549 | std::size_t error_count() const | |
3550 | { | |
3551 | return error_list_.size(); | |
3552 | } | |
3553 | ||
3554 | std::size_t error_index(const std::size_t& i) | |
3555 | { | |
3556 | if (i < error_list_.size()) | |
3557 | return error_list_[i]; | |
3558 | else | |
3559 | return std::numeric_limits<std::size_t>::max(); | |
3560 | } | |
3561 | ||
3562 | void clear_errors() | |
3563 | { | |
3564 | error_list_.clear(); | |
3565 | } | |
3566 | ||
3567 | private: | |
3568 | ||
3569 | std::size_t current_index_; | |
3570 | std::vector<std::size_t> error_list_; | |
3571 | }; | |
3572 | ||
3573 | class symbol_replacer : public lexer::token_modifier | |
3574 | { | |
3575 | private: | |
3576 | ||
3577 | typedef std::map<std::string,std::pair<std::string,token::token_type>,details::ilesscompare> replace_map_t; | |
3578 | ||
3579 | public: | |
3580 | ||
3581 | bool remove(const std::string& target_symbol) | |
3582 | { | |
3583 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); | |
3584 | ||
3585 | if (replace_map_.end() == itr) | |
3586 | return false; | |
3587 | ||
3588 | replace_map_.erase(itr); | |
3589 | ||
3590 | return true; | |
3591 | } | |
3592 | ||
3593 | bool add_replace(const std::string& target_symbol, | |
3594 | const std::string& replace_symbol, | |
3595 | const lexer::token::token_type token_type = lexer::token::e_symbol) | |
3596 | { | |
3597 | const replace_map_t::iterator itr = replace_map_.find(target_symbol); | |
3598 | ||
3599 | if (replace_map_.end() != itr) | |
3600 | { | |
3601 | return false; | |
3602 | } | |
3603 | ||
3604 | replace_map_[target_symbol] = std::make_pair(replace_symbol,token_type); | |
3605 | ||
3606 | return true; | |
3607 | } | |
3608 | ||
3609 | void clear() | |
3610 | { | |
3611 | replace_map_.clear(); | |
3612 | } | |
3613 | ||
3614 | private: | |
3615 | ||
3616 | bool modify(lexer::token& t) | |
3617 | { | |
3618 | if (lexer::token::e_symbol == t.type) | |
3619 | { | |
3620 | if (replace_map_.empty()) | |
3621 | return false; | |
3622 | ||
3623 | const replace_map_t::iterator itr = replace_map_.find(t.value); | |
3624 | ||
3625 | if (replace_map_.end() != itr) | |
3626 | { | |
3627 | t.value = itr->second.first; | |
3628 | t.type = itr->second.second; | |
3629 | ||
3630 | return true; | |
3631 | } | |
3632 | } | |
3633 | ||
3634 | return false; | |
3635 | } | |
3636 | ||
3637 | replace_map_t replace_map_; | |
3638 | }; | |
3639 | ||
3640 | class sequence_validator : public lexer::token_scanner | |
3641 | { | |
3642 | private: | |
3643 | ||
3644 | typedef std::pair<lexer::token::token_type,lexer::token::token_type> token_pair_t; | |
3645 | typedef std::set<token_pair_t> set_t; | |
3646 | ||
3647 | public: | |
3648 | ||
3649 | using lexer::token_scanner::operator(); | |
3650 | ||
3651 | sequence_validator() | |
3652 | : lexer::token_scanner(2) | |
3653 | { | |
3654 | add_invalid(lexer::token::e_number, lexer::token::e_number); | |
3655 | add_invalid(lexer::token::e_string, lexer::token::e_string); | |
3656 | add_invalid(lexer::token::e_number, lexer::token::e_string); | |
3657 | add_invalid(lexer::token::e_string, lexer::token::e_number); | |
3658 | ||
3659 | add_invalid_set1(lexer::token::e_assign ); | |
3660 | add_invalid_set1(lexer::token::e_shr ); | |
3661 | add_invalid_set1(lexer::token::e_shl ); | |
3662 | add_invalid_set1(lexer::token::e_lte ); | |
3663 | add_invalid_set1(lexer::token::e_ne ); | |
3664 | add_invalid_set1(lexer::token::e_gte ); | |
3665 | add_invalid_set1(lexer::token::e_lt ); | |
3666 | add_invalid_set1(lexer::token::e_gt ); | |
3667 | add_invalid_set1(lexer::token::e_eq ); | |
3668 | add_invalid_set1(lexer::token::e_comma ); | |
3669 | add_invalid_set1(lexer::token::e_add ); | |
3670 | add_invalid_set1(lexer::token::e_sub ); | |
3671 | add_invalid_set1(lexer::token::e_div ); | |
3672 | add_invalid_set1(lexer::token::e_mul ); | |
3673 | add_invalid_set1(lexer::token::e_mod ); | |
3674 | add_invalid_set1(lexer::token::e_pow ); | |
3675 | add_invalid_set1(lexer::token::e_colon ); | |
3676 | add_invalid_set1(lexer::token::e_ternary); | |
3677 | } | |
3678 | ||
3679 | bool result() | |
3680 | { | |
3681 | return error_list_.empty(); | |
3682 | } | |
3683 | ||
3684 | bool operator() (const lexer::token& t0, const lexer::token& t1) | |
3685 | { | |
3686 | const set_t::value_type p = std::make_pair(t0.type,t1.type); | |
3687 | ||
3688 | if (invalid_bracket_check(t0.type,t1.type)) | |
3689 | { | |
3690 | error_list_.push_back(std::make_pair(t0,t1)); | |
3691 | } | |
3692 | else if (invalid_comb_.find(p) != invalid_comb_.end()) | |
3693 | { | |
3694 | error_list_.push_back(std::make_pair(t0,t1)); | |
3695 | } | |
3696 | ||
3697 | return true; | |
3698 | } | |
3699 | ||
3700 | std::size_t error_count() const | |
3701 | { | |
3702 | return error_list_.size(); | |
3703 | } | |
3704 | ||
3705 | std::pair<lexer::token,lexer::token> error(const std::size_t index) | |
3706 | { | |
3707 | if (index < error_list_.size()) | |
3708 | { | |
3709 | return error_list_[index]; | |
3710 | } | |
3711 | else | |
3712 | { | |
3713 | static const lexer::token error_token; | |
3714 | return std::make_pair(error_token,error_token); | |
3715 | } | |
3716 | } | |
3717 | ||
3718 | void clear_errors() | |
3719 | { | |
3720 | error_list_.clear(); | |
3721 | } | |
3722 | ||
3723 | private: | |
3724 | ||
3725 | void add_invalid(lexer::token::token_type base, lexer::token::token_type t) | |
3726 | { | |
3727 | invalid_comb_.insert(std::make_pair(base,t)); | |
3728 | } | |
3729 | ||
3730 | void add_invalid_set1(lexer::token::token_type t) | |
3731 | { | |
3732 | add_invalid(t, lexer::token::e_assign); | |
3733 | add_invalid(t, lexer::token::e_shr ); | |
3734 | add_invalid(t, lexer::token::e_shl ); | |
3735 | add_invalid(t, lexer::token::e_lte ); | |
3736 | add_invalid(t, lexer::token::e_ne ); | |
3737 | add_invalid(t, lexer::token::e_gte ); | |
3738 | add_invalid(t, lexer::token::e_lt ); | |
3739 | add_invalid(t, lexer::token::e_gt ); | |
3740 | add_invalid(t, lexer::token::e_eq ); | |
3741 | add_invalid(t, lexer::token::e_comma ); | |
3742 | add_invalid(t, lexer::token::e_div ); | |
3743 | add_invalid(t, lexer::token::e_mul ); | |
3744 | add_invalid(t, lexer::token::e_mod ); | |
3745 | add_invalid(t, lexer::token::e_pow ); | |
3746 | add_invalid(t, lexer::token::e_colon ); | |
3747 | } | |
3748 | ||
3749 | bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) | |
3750 | { | |
3751 | if (details::is_right_bracket(static_cast<char>(base))) | |
3752 | { | |
3753 | switch (t) | |
3754 | { | |
3755 | case lexer::token::e_assign : return (']' != base); | |
3756 | case lexer::token::e_string : return (')' != base); | |
3757 | default : return false; | |
3758 | } | |
3759 | } | |
3760 | else if (details::is_left_bracket(static_cast<char>(base))) | |
3761 | { | |
3762 | if (details::is_right_bracket(static_cast<char>(t))) | |
3763 | return false; | |
3764 | else if (details::is_left_bracket(static_cast<char>(t))) | |
3765 | return false; | |
3766 | else | |
3767 | { | |
3768 | switch (t) | |
3769 | { | |
3770 | case lexer::token::e_number : return false; | |
3771 | case lexer::token::e_symbol : return false; | |
3772 | case lexer::token::e_string : return false; | |
3773 | case lexer::token::e_add : return false; | |
3774 | case lexer::token::e_sub : return false; | |
3775 | case lexer::token::e_colon : return false; | |
3776 | case lexer::token::e_ternary : return false; | |
3777 | default : return true ; | |
3778 | } | |
3779 | } | |
3780 | } | |
3781 | else if (details::is_right_bracket(static_cast<char>(t))) | |
3782 | { | |
3783 | switch (base) | |
3784 | { | |
3785 | case lexer::token::e_number : return false; | |
3786 | case lexer::token::e_symbol : return false; | |
3787 | case lexer::token::e_string : return false; | |
3788 | case lexer::token::e_eof : return false; | |
3789 | case lexer::token::e_colon : return false; | |
3790 | case lexer::token::e_ternary : return false; | |
3791 | default : return true ; | |
3792 | } | |
3793 | } | |
3794 | else if (details::is_left_bracket(static_cast<char>(t))) | |
3795 | { | |
3796 | switch (base) | |
3797 | { | |
3798 | case lexer::token::e_rbracket : return true; | |
3799 | case lexer::token::e_rsqrbracket : return true; | |
3800 | case lexer::token::e_rcrlbracket : return true; | |
3801 | default : return false; | |
3802 | } | |
3803 | } | |
3804 | ||
3805 | return false; | |
3806 | } | |
3807 | ||
3808 | set_t invalid_comb_; | |
3809 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; | |
3810 | }; | |
3811 | ||
3812 | class sequence_validator_3tokens : public lexer::token_scanner | |
3813 | { | |
3814 | private: | |
3815 | ||
3816 | typedef lexer::token::token_type token_t; | |
3817 | typedef std::pair<token_t,std::pair<token_t,token_t> > token_triplet_t; | |
3818 | typedef std::set<token_triplet_t> set_t; | |
3819 | ||
3820 | public: | |
3821 | ||
3822 | using lexer::token_scanner::operator(); | |
3823 | ||
3824 | sequence_validator_3tokens() | |
3825 | : lexer::token_scanner(3) | |
3826 | { | |
3827 | add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number); | |
3828 | add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string); | |
3829 | add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); | |
3830 | ||
3831 | add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); | |
3832 | add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); | |
3833 | add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); | |
3834 | add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); | |
3835 | add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); | |
3836 | add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); | |
3837 | ||
3838 | add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); | |
3839 | add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); | |
3840 | add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); | |
3841 | add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); | |
3842 | add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); | |
3843 | add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); | |
3844 | } | |
3845 | ||
3846 | bool result() | |
3847 | { | |
3848 | return error_list_.empty(); | |
3849 | } | |
3850 | ||
3851 | bool operator() (const lexer::token& t0, const lexer::token& t1, const lexer::token& t2) | |
3852 | { | |
3853 | const set_t::value_type p = std::make_pair(t0.type,std::make_pair(t1.type,t2.type)); | |
3854 | ||
3855 | if (invalid_comb_.find(p) != invalid_comb_.end()) | |
3856 | { | |
3857 | error_list_.push_back(std::make_pair(t0,t1)); | |
3858 | } | |
3859 | ||
3860 | return true; | |
3861 | } | |
3862 | ||
3863 | std::size_t error_count() const | |
3864 | { | |
3865 | return error_list_.size(); | |
3866 | } | |
3867 | ||
3868 | std::pair<lexer::token,lexer::token> error(const std::size_t index) | |
3869 | { | |
3870 | if (index < error_list_.size()) | |
3871 | { | |
3872 | return error_list_[index]; | |
3873 | } | |
3874 | else | |
3875 | { | |
3876 | static const lexer::token error_token; | |
3877 | return std::make_pair(error_token,error_token); | |
3878 | } | |
3879 | } | |
3880 | ||
3881 | void clear_errors() | |
3882 | { | |
3883 | error_list_.clear(); | |
3884 | } | |
3885 | ||
3886 | private: | |
3887 | ||
3888 | void add_invalid(token_t t0, token_t t1, token_t t2) | |
3889 | { | |
3890 | invalid_comb_.insert(std::make_pair(t0,std::make_pair(t1,t2))); | |
3891 | } | |
3892 | ||
3893 | set_t invalid_comb_; | |
3894 | std::vector<std::pair<lexer::token,lexer::token> > error_list_; | |
3895 | }; | |
3896 | ||
3897 | struct helper_assembly | |
3898 | { | |
3899 | inline bool register_scanner(lexer::token_scanner* scanner) | |
3900 | { | |
3901 | if (token_scanner_list.end() != std::find(token_scanner_list.begin(), | |
3902 | token_scanner_list.end (), | |
3903 | scanner)) | |
3904 | { | |
3905 | return false; | |
3906 | } | |
3907 | ||
3908 | token_scanner_list.push_back(scanner); | |
3909 | ||
3910 | return true; | |
3911 | } | |
3912 | ||
3913 | inline bool register_modifier(lexer::token_modifier* modifier) | |
3914 | { | |
3915 | if (token_modifier_list.end() != std::find(token_modifier_list.begin(), | |
3916 | token_modifier_list.end (), | |
3917 | modifier)) | |
3918 | { | |
3919 | return false; | |
3920 | } | |
3921 | ||
3922 | token_modifier_list.push_back(modifier); | |
3923 | ||
3924 | return true; | |
3925 | } | |
3926 | ||
3927 | inline bool register_joiner(lexer::token_joiner* joiner) | |
3928 | { | |
3929 | if (token_joiner_list.end() != std::find(token_joiner_list.begin(), | |
3930 | token_joiner_list.end (), | |
3931 | joiner)) | |
3932 | { | |
3933 | return false; | |
3934 | } | |
3935 | ||
3936 | token_joiner_list.push_back(joiner); | |
3937 | ||
3938 | return true; | |
3939 | } | |
3940 | ||
3941 | inline bool register_inserter(lexer::token_inserter* inserter) | |
3942 | { | |
3943 | if (token_inserter_list.end() != std::find(token_inserter_list.begin(), | |
3944 | token_inserter_list.end (), | |
3945 | inserter)) | |
3946 | { | |
3947 | return false; | |
3948 | } | |
3949 | ||
3950 | token_inserter_list.push_back(inserter); | |
3951 | ||
3952 | return true; | |
3953 | } | |
3954 | ||
3955 | inline bool run_modifiers(lexer::generator& g) | |
3956 | { | |
3957 | error_token_modifier = reinterpret_cast<lexer::token_modifier*>(0); | |
3958 | ||
3959 | for (std::size_t i = 0; i < token_modifier_list.size(); ++i) | |
3960 | { | |
3961 | lexer::token_modifier& modifier = (*token_modifier_list[i]); | |
3962 | ||
3963 | modifier.reset(); | |
3964 | modifier.process(g); | |
3965 | ||
3966 | if (!modifier.result()) | |
3967 | { | |
3968 | error_token_modifier = token_modifier_list[i]; | |
3969 | ||
3970 | return false; | |
3971 | } | |
3972 | } | |
3973 | ||
3974 | return true; | |
3975 | } | |
3976 | ||
3977 | inline bool run_joiners(lexer::generator& g) | |
3978 | { | |
3979 | error_token_joiner = reinterpret_cast<lexer::token_joiner*>(0); | |
3980 | ||
3981 | for (std::size_t i = 0; i < token_joiner_list.size(); ++i) | |
3982 | { | |
3983 | lexer::token_joiner& joiner = (*token_joiner_list[i]); | |
3984 | ||
3985 | joiner.reset(); | |
3986 | joiner.process(g); | |
3987 | ||
3988 | if (!joiner.result()) | |
3989 | { | |
3990 | error_token_joiner = token_joiner_list[i]; | |
3991 | ||
3992 | return false; | |
3993 | } | |
3994 | } | |
3995 | ||
3996 | return true; | |
3997 | } | |
3998 | ||
3999 | inline bool run_inserters(lexer::generator& g) | |
4000 | { | |
4001 | error_token_inserter = reinterpret_cast<lexer::token_inserter*>(0); | |
4002 | ||
4003 | for (std::size_t i = 0; i < token_inserter_list.size(); ++i) | |
4004 | { | |
4005 | lexer::token_inserter& inserter = (*token_inserter_list[i]); | |
4006 | ||
4007 | inserter.reset(); | |
4008 | inserter.process(g); | |
4009 | ||
4010 | if (!inserter.result()) | |
4011 | { | |
4012 | error_token_inserter = token_inserter_list[i]; | |
4013 | ||
4014 | return false; | |
4015 | } | |
4016 | } | |
4017 | ||
4018 | return true; | |
4019 | } | |
4020 | ||
4021 | inline bool run_scanners(lexer::generator& g) | |
4022 | { | |
4023 | error_token_scanner = reinterpret_cast<lexer::token_scanner*>(0); | |
4024 | ||
4025 | for (std::size_t i = 0; i < token_scanner_list.size(); ++i) | |
4026 | { | |
4027 | lexer::token_scanner& scanner = (*token_scanner_list[i]); | |
4028 | ||
4029 | scanner.reset(); | |
4030 | scanner.process(g); | |
4031 | ||
4032 | if (!scanner.result()) | |
4033 | { | |
4034 | error_token_scanner = token_scanner_list[i]; | |
4035 | ||
4036 | return false; | |
4037 | } | |
4038 | } | |
4039 | ||
4040 | return true; | |
4041 | } | |
4042 | ||
4043 | std::vector<lexer::token_scanner*> token_scanner_list; | |
4044 | std::vector<lexer::token_modifier*> token_modifier_list; | |
4045 | std::vector<lexer::token_joiner*> token_joiner_list; | |
4046 | std::vector<lexer::token_inserter*> token_inserter_list; | |
4047 | ||
4048 | lexer::token_scanner* error_token_scanner; | |
4049 | lexer::token_modifier* error_token_modifier; | |
4050 | lexer::token_joiner* error_token_joiner; | |
4051 | lexer::token_inserter* error_token_inserter; | |
4052 | }; | |
4053 | } | |
4054 | ||
4055 | class parser_helper | |
4056 | { | |
4057 | public: | |
4058 | ||
4059 | typedef token token_t; | |
4060 | typedef generator generator_t; | |
4061 | ||
4062 | inline bool init(const std::string& str) | |
4063 | { | |
4064 | if (!lexer_.process(str)) | |
4065 | { | |
4066 | return false; | |
4067 | } | |
4068 | ||
4069 | lexer_.begin(); | |
4070 | ||
4071 | next_token(); | |
4072 | ||
4073 | return true; | |
4074 | } | |
4075 | ||
4076 | inline generator_t& lexer() | |
4077 | { | |
4078 | return lexer_; | |
4079 | } | |
4080 | ||
4081 | inline const generator_t& lexer() const | |
4082 | { | |
4083 | return lexer_; | |
4084 | } | |
4085 | ||
4086 | inline void store_token() | |
4087 | { | |
4088 | lexer_.store(); | |
4089 | store_current_token_ = current_token_; | |
4090 | } | |
4091 | ||
4092 | inline void restore_token() | |
4093 | { | |
4094 | lexer_.restore(); | |
4095 | current_token_ = store_current_token_; | |
4096 | } | |
4097 | ||
4098 | inline void next_token() | |
4099 | { | |
4100 | current_token_ = lexer_.next_token(); | |
4101 | } | |
4102 | ||
4103 | inline const token_t& current_token() const | |
4104 | { | |
4105 | return current_token_; | |
4106 | } | |
4107 | ||
4108 | enum token_advance_mode | |
4109 | { | |
4110 | e_hold = 0, | |
4111 | e_advance = 1 | |
4112 | }; | |
4113 | ||
4114 | inline void advance_token(const token_advance_mode mode) | |
4115 | { | |
4116 | if (e_advance == mode) | |
4117 | { | |
4118 | next_token(); | |
4119 | } | |
4120 | } | |
4121 | ||
4122 | inline bool token_is(const token_t::token_type& ttype, const token_advance_mode mode = e_advance) | |
4123 | { | |
4124 | if (current_token().type != ttype) | |
4125 | { | |
4126 | return false; | |
4127 | } | |
4128 | ||
4129 | advance_token(mode); | |
4130 | ||
4131 | return true; | |
4132 | } | |
4133 | ||
4134 | inline bool token_is(const token_t::token_type& ttype, | |
4135 | const std::string& value, | |
4136 | const token_advance_mode mode = e_advance) | |
4137 | { | |
4138 | if ( | |
4139 | (current_token().type != ttype) || | |
4140 | !exprtk::details::imatch(value,current_token().value) | |
4141 | ) | |
4142 | { | |
4143 | return false; | |
4144 | } | |
4145 | ||
4146 | advance_token(mode); | |
4147 | ||
4148 | return true; | |
4149 | } | |
4150 | ||
4151 | inline bool peek_token_is(const token_t::token_type& ttype) | |
4152 | { | |
4153 | return (lexer_.peek_next_token().type == ttype); | |
4154 | } | |
4155 | ||
4156 | inline bool peek_token_is(const std::string& s) | |
4157 | { | |
4158 | return (exprtk::details::imatch(lexer_.peek_next_token().value,s)); | |
4159 | } | |
4160 | ||
4161 | private: | |
4162 | ||
4163 | generator_t lexer_; | |
4164 | token_t current_token_; | |
4165 | token_t store_current_token_; | |
4166 | }; | |
4167 | } | |
4168 | ||
4169 | template <typename T> | |
4170 | class vector_view | |
4171 | { | |
4172 | public: | |
4173 | ||
4174 | typedef T* data_ptr_t; | |
4175 | ||
4176 | vector_view(data_ptr_t data, const std::size_t& size) | |
4177 | : size_(size), | |
4178 | data_(data), | |
4179 | data_ref_(0) | |
4180 | {} | |
4181 | ||
4182 | vector_view(const vector_view<T>& vv) | |
4183 | : size_(vv.size_), | |
4184 | data_(vv.data_), | |
4185 | data_ref_(0) | |
4186 | {} | |
4187 | ||
4188 | inline void rebase(data_ptr_t data) | |
4189 | { | |
4190 | data_ = data; | |
4191 | ||
4192 | if (!data_ref_.empty()) | |
4193 | { | |
4194 | for (std::size_t i = 0; i < data_ref_.size(); ++i) | |
4195 | { | |
4196 | (*data_ref_[i]) = data; | |
4197 | } | |
4198 | } | |
4199 | } | |
4200 | ||
4201 | inline data_ptr_t data() const | |
4202 | { | |
4203 | return data_; | |
4204 | } | |
4205 | ||
4206 | inline std::size_t size() const | |
4207 | { | |
4208 | return size_; | |
4209 | } | |
4210 | ||
4211 | inline const T& operator[](const std::size_t index) const | |
4212 | { | |
4213 | return data_[index]; | |
4214 | } | |
4215 | ||
4216 | inline T& operator[](const std::size_t index) | |
4217 | { | |
4218 | return data_[index]; | |
4219 | } | |
4220 | ||
4221 | void set_ref(data_ptr_t* data_ref) | |
4222 | { | |
4223 | data_ref_.push_back(data_ref); | |
4224 | } | |
4225 | ||
4226 | private: | |
4227 | ||
4228 | const std::size_t size_; | |
4229 | data_ptr_t data_; | |
4230 | std::vector<data_ptr_t*> data_ref_; | |
4231 | }; | |
4232 | ||
4233 | template <typename T> | |
4234 | inline vector_view<T> make_vector_view(T* data, | |
4235 | const std::size_t size, const std::size_t offset = 0) | |
4236 | { | |
4237 | return vector_view<T>(data + offset, size); | |
4238 | } | |
4239 | ||
4240 | template <typename T> | |
4241 | inline vector_view<T> make_vector_view(std::vector<T>& v, | |
4242 | const std::size_t size, const std::size_t offset = 0) | |
4243 | { | |
4244 | return vector_view<T>(v.data() + offset, size); | |
4245 | } | |
4246 | ||
4247 | template <typename T> class results_context; | |
4248 | ||
4249 | template <typename T> | |
4250 | struct type_store | |
4251 | { | |
4252 | enum store_type | |
4253 | { | |
4254 | e_unknown, | |
4255 | e_scalar , | |
4256 | e_vector , | |
4257 | e_string | |
4258 | }; | |
4259 | ||
4260 | type_store() | |
4261 | : data(0), | |
4262 | size(0), | |
4263 | type(e_unknown) | |
4264 | {} | |
4265 | ||
4266 | union | |
4267 | { | |
4268 | void* data; | |
4269 | T* vec_data; | |
4270 | }; | |
4271 | ||
4272 | std::size_t size; | |
4273 | store_type type; | |
4274 | ||
4275 | class parameter_list | |
4276 | { | |
4277 | public: | |
4278 | ||
4279 | parameter_list(std::vector<type_store>& pl) | |
4280 | : parameter_list_(pl) | |
4281 | {} | |
4282 | ||
4283 | inline bool empty() const | |
4284 | { | |
4285 | return parameter_list_.empty(); | |
4286 | } | |
4287 | ||
4288 | inline std::size_t size() const | |
4289 | { | |
4290 | return parameter_list_.size(); | |
4291 | } | |
4292 | ||
4293 | inline type_store& operator[](const std::size_t& index) | |
4294 | { | |
4295 | return parameter_list_[index]; | |
4296 | } | |
4297 | ||
4298 | inline const type_store& operator[](const std::size_t& index) const | |
4299 | { | |
4300 | return parameter_list_[index]; | |
4301 | } | |
4302 | ||
4303 | inline type_store& front() | |
4304 | { | |
4305 | return parameter_list_[0]; | |
4306 | } | |
4307 | ||
4308 | inline const type_store& front() const | |
4309 | { | |
4310 | return parameter_list_[0]; | |
4311 | } | |
4312 | ||
4313 | inline type_store& back() | |
4314 | { | |
4315 | return parameter_list_.back(); | |
4316 | } | |
4317 | ||
4318 | inline const type_store& back() const | |
4319 | { | |
4320 | return parameter_list_.back(); | |
4321 | } | |
4322 | ||
4323 | private: | |
4324 | ||
4325 | std::vector<type_store>& parameter_list_; | |
4326 | ||
4327 | friend class results_context<T>; | |
4328 | }; | |
4329 | ||
4330 | template <typename ViewType> | |
4331 | struct type_view | |
4332 | { | |
4333 | typedef type_store<T> type_store_t; | |
4334 | typedef ViewType value_t; | |
4335 | ||
4336 | type_view(type_store_t& ts) | |
4337 | : ts_(ts), | |
4338 | data_(reinterpret_cast<value_t*>(ts_.data)) | |
4339 | {} | |
4340 | ||
4341 | type_view(const type_store_t& ts) | |
4342 | : ts_(const_cast<type_store_t&>(ts)), | |
4343 | data_(reinterpret_cast<value_t*>(ts_.data)) | |
4344 | {} | |
4345 | ||
4346 | inline std::size_t size() const | |
4347 | { | |
4348 | return ts_.size; | |
4349 | } | |
4350 | ||
4351 | inline value_t& operator[](const std::size_t& i) | |
4352 | { | |
4353 | return data_[i]; | |
4354 | } | |
4355 | ||
4356 | inline const value_t& operator[](const std::size_t& i) const | |
4357 | { | |
4358 | return data_[i]; | |
4359 | } | |
4360 | ||
4361 | inline const value_t* begin() const { return data_; } | |
4362 | inline value_t* begin() { return data_; } | |
4363 | ||
4364 | inline const value_t* end() const | |
4365 | { | |
4366 | return static_cast<value_t*>(data_ + ts_.size); | |
4367 | } | |
4368 | ||
4369 | inline value_t* end() | |
4370 | { | |
4371 | return static_cast<value_t*>(data_ + ts_.size); | |
4372 | } | |
4373 | ||
4374 | type_store_t& ts_; | |
4375 | value_t* data_; | |
4376 | }; | |
4377 | ||
4378 | typedef type_view<T> vector_view; | |
4379 | typedef type_view<char> string_view; | |
4380 | ||
4381 | struct scalar_view | |
4382 | { | |
4383 | typedef type_store<T> type_store_t; | |
4384 | typedef T value_t; | |
4385 | ||
4386 | scalar_view(type_store_t& ts) | |
4387 | : v_(*reinterpret_cast<value_t*>(ts.data)) | |
4388 | {} | |
4389 | ||
4390 | scalar_view(const type_store_t& ts) | |
4391 | : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) | |
4392 | {} | |
4393 | ||
4394 | inline value_t& operator() () | |
4395 | { | |
4396 | return v_; | |
4397 | } | |
4398 | ||
4399 | inline const value_t& operator() () const | |
4400 | { | |
4401 | return v_; | |
4402 | } | |
4403 | ||
4404 | template <typename IntType> | |
4405 | inline bool to_int(IntType& i) const | |
4406 | { | |
4407 | if (!exprtk::details::numeric::is_integer(v_)) | |
4408 | return false; | |
4409 | ||
4410 | i = static_cast<IntType>(v_); | |
4411 | ||
4412 | return true; | |
4413 | } | |
4414 | ||
4415 | template <typename UIntType> | |
4416 | inline bool to_uint(UIntType& u) const | |
4417 | { | |
4418 | if (v_ < T(0)) | |
4419 | return false; | |
4420 | else if (!exprtk::details::numeric::is_integer(v_)) | |
4421 | return false; | |
4422 | ||
4423 | u = static_cast<UIntType>(v_); | |
4424 | ||
4425 | return true; | |
4426 | } | |
4427 | ||
4428 | T& v_; | |
4429 | }; | |
4430 | }; | |
4431 | ||
4432 | template <typename StringView> | |
4433 | inline std::string to_str(const StringView& view) | |
4434 | { | |
4435 | return std::string(view.begin(),view.size()); | |
4436 | } | |
4437 | ||
4438 | #ifndef exprtk_disable_return_statement | |
4439 | namespace details | |
4440 | { | |
4441 | template <typename T> class return_node; | |
4442 | template <typename T> class return_envelope_node; | |
4443 | } | |
4444 | #endif | |
4445 | ||
4446 | template <typename T> | |
4447 | class results_context | |
4448 | { | |
4449 | public: | |
4450 | ||
4451 | typedef type_store<T> type_store_t; | |
4452 | ||
4453 | results_context() | |
4454 | : results_available_(false) | |
4455 | {} | |
4456 | ||
4457 | inline std::size_t count() const | |
4458 | { | |
4459 | if (results_available_) | |
4460 | return parameter_list_.size(); | |
4461 | else | |
4462 | return 0; | |
4463 | } | |
4464 | ||
4465 | inline type_store_t& operator[](const std::size_t& index) | |
4466 | { | |
4467 | return parameter_list_[index]; | |
4468 | } | |
4469 | ||
4470 | inline const type_store_t& operator[](const std::size_t& index) const | |
4471 | { | |
4472 | return parameter_list_[index]; | |
4473 | } | |
4474 | ||
4475 | private: | |
4476 | ||
4477 | inline void clear() | |
4478 | { | |
4479 | results_available_ = false; | |
4480 | } | |
4481 | ||
4482 | typedef std::vector<type_store_t> ts_list_t; | |
4483 | typedef typename type_store_t::parameter_list parameter_list_t; | |
4484 | ||
4485 | inline void assign(const parameter_list_t& pl) | |
4486 | { | |
4487 | parameter_list_ = pl.parameter_list_; | |
4488 | results_available_ = true; | |
4489 | } | |
4490 | ||
4491 | bool results_available_; | |
4492 | ts_list_t parameter_list_; | |
4493 | ||
4494 | #ifndef exprtk_disable_return_statement | |
4495 | friend class details::return_node<T>; | |
4496 | friend class details::return_envelope_node<T>; | |
4497 | #endif | |
4498 | }; | |
4499 | ||
4500 | namespace details | |
4501 | { | |
4502 | enum operator_type | |
4503 | { | |
4504 | e_default , e_null , e_add , e_sub , | |
4505 | e_mul , e_div , e_mod , e_pow , | |
4506 | e_atan2 , e_min , e_max , e_avg , | |
4507 | e_sum , e_prod , e_lt , e_lte , | |
4508 | e_eq , e_equal , e_ne , e_nequal , | |
4509 | e_gte , e_gt , e_and , e_nand , | |
4510 | e_or , e_nor , e_xor , e_xnor , | |
4511 | e_mand , e_mor , e_scand , e_scor , | |
4512 | e_shr , e_shl , e_abs , e_acos , | |
4513 | e_acosh , e_asin , e_asinh , e_atan , | |
4514 | e_atanh , e_ceil , e_cos , e_cosh , | |
4515 | e_exp , e_expm1 , e_floor , e_log , | |
4516 | e_log10 , e_log2 , e_log1p , e_logn , | |
4517 | e_neg , e_pos , e_round , e_roundn , | |
4518 | e_root , e_sqrt , e_sin , e_sinc , | |
4519 | e_sinh , e_sec , e_csc , e_tan , | |
4520 | e_tanh , e_cot , e_clamp , e_iclamp , | |
4521 | e_inrange , e_sgn , e_r2d , e_d2r , | |
4522 | e_d2g , e_g2d , e_hypot , e_notl , | |
4523 | e_erf , e_erfc , e_ncdf , e_frac , | |
4524 | e_trunc , e_assign , e_addass , e_subass , | |
4525 | e_mulass , e_divass , e_modass , e_in , | |
4526 | e_like , e_ilike , e_multi , e_smulti , | |
4527 | e_swap , | |
4528 | ||
4529 | // Do not add new functions/operators after this point. | |
4530 | e_sf00 = 1000, e_sf01 = 1001, e_sf02 = 1002, e_sf03 = 1003, | |
4531 | e_sf04 = 1004, e_sf05 = 1005, e_sf06 = 1006, e_sf07 = 1007, | |
4532 | e_sf08 = 1008, e_sf09 = 1009, e_sf10 = 1010, e_sf11 = 1011, | |
4533 | e_sf12 = 1012, e_sf13 = 1013, e_sf14 = 1014, e_sf15 = 1015, | |
4534 | e_sf16 = 1016, e_sf17 = 1017, e_sf18 = 1018, e_sf19 = 1019, | |
4535 | e_sf20 = 1020, e_sf21 = 1021, e_sf22 = 1022, e_sf23 = 1023, | |
4536 | e_sf24 = 1024, e_sf25 = 1025, e_sf26 = 1026, e_sf27 = 1027, | |
4537 | e_sf28 = 1028, e_sf29 = 1029, e_sf30 = 1030, e_sf31 = 1031, | |
4538 | e_sf32 = 1032, e_sf33 = 1033, e_sf34 = 1034, e_sf35 = 1035, | |
4539 | e_sf36 = 1036, e_sf37 = 1037, e_sf38 = 1038, e_sf39 = 1039, | |
4540 | e_sf40 = 1040, e_sf41 = 1041, e_sf42 = 1042, e_sf43 = 1043, | |
4541 | e_sf44 = 1044, e_sf45 = 1045, e_sf46 = 1046, e_sf47 = 1047, | |
4542 | e_sf48 = 1048, e_sf49 = 1049, e_sf50 = 1050, e_sf51 = 1051, | |
4543 | e_sf52 = 1052, e_sf53 = 1053, e_sf54 = 1054, e_sf55 = 1055, | |
4544 | e_sf56 = 1056, e_sf57 = 1057, e_sf58 = 1058, e_sf59 = 1059, | |
4545 | e_sf60 = 1060, e_sf61 = 1061, e_sf62 = 1062, e_sf63 = 1063, | |
4546 | e_sf64 = 1064, e_sf65 = 1065, e_sf66 = 1066, e_sf67 = 1067, | |
4547 | e_sf68 = 1068, e_sf69 = 1069, e_sf70 = 1070, e_sf71 = 1071, | |
4548 | e_sf72 = 1072, e_sf73 = 1073, e_sf74 = 1074, e_sf75 = 1075, | |
4549 | e_sf76 = 1076, e_sf77 = 1077, e_sf78 = 1078, e_sf79 = 1079, | |
4550 | e_sf80 = 1080, e_sf81 = 1081, e_sf82 = 1082, e_sf83 = 1083, | |
4551 | e_sf84 = 1084, e_sf85 = 1085, e_sf86 = 1086, e_sf87 = 1087, | |
4552 | e_sf88 = 1088, e_sf89 = 1089, e_sf90 = 1090, e_sf91 = 1091, | |
4553 | e_sf92 = 1092, e_sf93 = 1093, e_sf94 = 1094, e_sf95 = 1095, | |
4554 | e_sf96 = 1096, e_sf97 = 1097, e_sf98 = 1098, e_sf99 = 1099, | |
4555 | e_sffinal = 1100, | |
4556 | e_sf4ext00 = 2000, e_sf4ext01 = 2001, e_sf4ext02 = 2002, e_sf4ext03 = 2003, | |
4557 | e_sf4ext04 = 2004, e_sf4ext05 = 2005, e_sf4ext06 = 2006, e_sf4ext07 = 2007, | |
4558 | e_sf4ext08 = 2008, e_sf4ext09 = 2009, e_sf4ext10 = 2010, e_sf4ext11 = 2011, | |
4559 | e_sf4ext12 = 2012, e_sf4ext13 = 2013, e_sf4ext14 = 2014, e_sf4ext15 = 2015, | |
4560 | e_sf4ext16 = 2016, e_sf4ext17 = 2017, e_sf4ext18 = 2018, e_sf4ext19 = 2019, | |
4561 | e_sf4ext20 = 2020, e_sf4ext21 = 2021, e_sf4ext22 = 2022, e_sf4ext23 = 2023, | |
4562 | e_sf4ext24 = 2024, e_sf4ext25 = 2025, e_sf4ext26 = 2026, e_sf4ext27 = 2027, | |
4563 | e_sf4ext28 = 2028, e_sf4ext29 = 2029, e_sf4ext30 = 2030, e_sf4ext31 = 2031, | |
4564 | e_sf4ext32 = 2032, e_sf4ext33 = 2033, e_sf4ext34 = 2034, e_sf4ext35 = 2035, | |
4565 | e_sf4ext36 = 2036, e_sf4ext37 = 2037, e_sf4ext38 = 2038, e_sf4ext39 = 2039, | |
4566 | e_sf4ext40 = 2040, e_sf4ext41 = 2041, e_sf4ext42 = 2042, e_sf4ext43 = 2043, | |
4567 | e_sf4ext44 = 2044, e_sf4ext45 = 2045, e_sf4ext46 = 2046, e_sf4ext47 = 2047, | |
4568 | e_sf4ext48 = 2048, e_sf4ext49 = 2049, e_sf4ext50 = 2050, e_sf4ext51 = 2051, | |
4569 | e_sf4ext52 = 2052, e_sf4ext53 = 2053, e_sf4ext54 = 2054, e_sf4ext55 = 2055, | |
4570 | e_sf4ext56 = 2056, e_sf4ext57 = 2057, e_sf4ext58 = 2058, e_sf4ext59 = 2059, | |
4571 | e_sf4ext60 = 2060, e_sf4ext61 = 2061 | |
4572 | }; | |
4573 | ||
4574 | inline std::string to_str(const operator_type opr) | |
4575 | { | |
4576 | switch (opr) | |
4577 | { | |
4578 | case e_add : return "+" ; | |
4579 | case e_sub : return "-" ; | |
4580 | case e_mul : return "*" ; | |
4581 | case e_div : return "/" ; | |
4582 | case e_mod : return "%" ; | |
4583 | case e_pow : return "^" ; | |
4584 | case e_assign : return ":=" ; | |
4585 | case e_addass : return "+=" ; | |
4586 | case e_subass : return "-=" ; | |
4587 | case e_mulass : return "*=" ; | |
4588 | case e_divass : return "/=" ; | |
4589 | case e_modass : return "%=" ; | |
4590 | case e_lt : return "<" ; | |
4591 | case e_lte : return "<=" ; | |
4592 | case e_eq : return "==" ; | |
4593 | case e_equal : return "=" ; | |
4594 | case e_ne : return "!=" ; | |
4595 | case e_nequal : return "<>" ; | |
4596 | case e_gte : return ">=" ; | |
4597 | case e_gt : return ">" ; | |
4598 | case e_and : return "and" ; | |
4599 | case e_or : return "or" ; | |
4600 | case e_xor : return "xor" ; | |
4601 | case e_nand : return "nand"; | |
4602 | case e_nor : return "nor" ; | |
4603 | case e_xnor : return "xnor"; | |
4604 | default : return "N/A" ; | |
4605 | } | |
4606 | } | |
4607 | ||
4608 | struct base_operation_t | |
4609 | { | |
4610 | base_operation_t(const operator_type t, const unsigned int& np) | |
4611 | : type(t), | |
4612 | num_params(np) | |
4613 | {} | |
4614 | ||
4615 | operator_type type; | |
4616 | unsigned int num_params; | |
4617 | }; | |
4618 | ||
4619 | namespace loop_unroll | |
4620 | { | |
4621 | #ifndef exprtk_disable_superscalar_unroll | |
4622 | const unsigned int global_loop_batch_size = 16; | |
4623 | #else | |
4624 | const unsigned int global_loop_batch_size = 4; | |
4625 | #endif | |
4626 | ||
4627 | struct details | |
4628 | { | |
4629 | details(const std::size_t& vsize, | |
4630 | const unsigned int loop_batch_size = global_loop_batch_size) | |
4631 | : batch_size(loop_batch_size ), | |
4632 | remainder (vsize % batch_size), | |
4633 | upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) | |
4634 | {} | |
4635 | ||
4636 | unsigned int batch_size; | |
4637 | int remainder; | |
4638 | int upper_bound; | |
4639 | }; | |
4640 | } | |
4641 | ||
4642 | #ifdef exprtk_enable_debugging | |
4643 | inline void dump_ptr(const std::string& s, const void* ptr, const std::size_t size = 0) | |
4644 | { | |
4645 | if (size) | |
4646 | exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr)); | |
4647 | else | |
4648 | exprtk_debug(("%s - addr: %p size: %d\n", | |
4649 | s.c_str(), | |
4650 | ptr, | |
4651 | static_cast<unsigned int>(size))); | |
4652 | } | |
4653 | #else | |
4654 | inline void dump_ptr(const std::string&, const void*) {} | |
4655 | inline void dump_ptr(const std::string&, const void*, const std::size_t) {} | |
4656 | #endif | |
4657 | ||
4658 | template <typename T> | |
4659 | class vec_data_store | |
4660 | { | |
4661 | public: | |
4662 | ||
4663 | typedef vec_data_store<T> type; | |
4664 | typedef T* data_t; | |
4665 | ||
4666 | private: | |
4667 | ||
4668 | struct control_block | |
4669 | { | |
4670 | control_block() | |
4671 | : ref_count(1), | |
4672 | size (0), | |
4673 | data (0), | |
4674 | destruct (true) | |
4675 | {} | |
4676 | ||
4677 | control_block(const std::size_t& dsize) | |
4678 | : ref_count(1 ), | |
4679 | size (dsize), | |
4680 | data (0 ), | |
4681 | destruct (true ) | |
4682 | { create_data(); } | |
4683 | ||
4684 | control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false) | |
4685 | : ref_count(1 ), | |
4686 | size (dsize ), | |
4687 | data (dptr ), | |
4688 | destruct (dstrct) | |
4689 | {} | |
4690 | ||
4691 | ~control_block() | |
4692 | { | |
4693 | if (data && destruct && (0 == ref_count)) | |
4694 | { | |
4695 | dump_ptr("~control_block() data",data); | |
4696 | delete[] data; | |
4697 | data = reinterpret_cast<data_t>(0); | |
4698 | } | |
4699 | } | |
4700 | ||
4701 | static inline control_block* create(const std::size_t& dsize, data_t data_ptr = data_t(0), bool dstrct = false) | |
4702 | { | |
4703 | if (dsize) | |
4704 | { | |
4705 | if (0 == data_ptr) | |
4706 | return (new control_block(dsize)); | |
4707 | else | |
4708 | return (new control_block(dsize, data_ptr, dstrct)); | |
4709 | } | |
4710 | else | |
4711 | return (new control_block); | |
4712 | } | |
4713 | ||
4714 | static inline void destroy(control_block*& cntrl_blck) | |
4715 | { | |
4716 | if (cntrl_blck) | |
4717 | { | |
4718 | if ( | |
4719 | (0 != cntrl_blck->ref_count) && | |
4720 | (0 == --cntrl_blck->ref_count) | |
4721 | ) | |
4722 | { | |
4723 | delete cntrl_blck; | |
4724 | } | |
4725 | ||
4726 | cntrl_blck = 0; | |
4727 | } | |
4728 | } | |
4729 | ||
4730 | std::size_t ref_count; | |
4731 | std::size_t size; | |
4732 | data_t data; | |
4733 | bool destruct; | |
4734 | ||
4735 | private: | |
4736 | ||
4737 | control_block(const control_block&); | |
4738 | control_block& operator=(const control_block&); | |
4739 | ||
4740 | inline void create_data() | |
4741 | { | |
4742 | destruct = true; | |
4743 | data = new T[size]; | |
4744 | std::fill_n(data,size,T(0)); | |
4745 | dump_ptr("control_block::create_data() - data",data,size); | |
4746 | } | |
4747 | }; | |
4748 | ||
4749 | public: | |
4750 | ||
4751 | vec_data_store() | |
4752 | : control_block_(control_block::create(0)) | |
4753 | {} | |
4754 | ||
4755 | vec_data_store(const std::size_t& size) | |
4756 | : control_block_(control_block::create(size,(data_t)(0),true)) | |
4757 | {} | |
4758 | ||
4759 | vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) | |
4760 | : control_block_(control_block::create(size, data, dstrct)) | |
4761 | {} | |
4762 | ||
4763 | vec_data_store(const type& vds) | |
4764 | { | |
4765 | control_block_ = vds.control_block_; | |
4766 | control_block_->ref_count++; | |
4767 | } | |
4768 | ||
4769 | ~vec_data_store() | |
4770 | { | |
4771 | control_block::destroy(control_block_); | |
4772 | } | |
4773 | ||
4774 | type& operator=(const type& vds) | |
4775 | { | |
4776 | if (this != &vds) | |
4777 | { | |
4778 | std::size_t final_size = min_size(control_block_, vds.control_block_); | |
4779 | ||
4780 | vds.control_block_->size = final_size; | |
4781 | control_block_->size = final_size; | |
4782 | ||
4783 | if (control_block_->destruct || (0 == control_block_->data)) | |
4784 | { | |
4785 | control_block::destroy(control_block_); | |
4786 | ||
4787 | control_block_ = vds.control_block_; | |
4788 | control_block_->ref_count++; | |
4789 | } | |
4790 | } | |
4791 | ||
4792 | return (*this); | |
4793 | } | |
4794 | ||
4795 | inline data_t data() | |
4796 | { | |
4797 | return control_block_->data; | |
4798 | } | |
4799 | ||
4800 | inline data_t data() const | |
4801 | { | |
4802 | return control_block_->data; | |
4803 | } | |
4804 | ||
4805 | inline std::size_t size() | |
4806 | { | |
4807 | return control_block_->size; | |
4808 | } | |
4809 | ||
4810 | inline std::size_t size() const | |
4811 | { | |
4812 | return control_block_->size; | |
4813 | } | |
4814 | ||
4815 | inline data_t& ref() | |
4816 | { | |
4817 | return control_block_->data; | |
4818 | } | |
4819 | ||
4820 | inline void dump() const | |
4821 | { | |
4822 | #ifdef exprtk_enable_debugging | |
4823 | exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n", | |
4824 | size(), | |
4825 | data(), | |
4826 | (control_block_->destruct ? 'T' : 'F'))); | |
4827 | ||
4828 | for (std::size_t i = 0; i < size(); ++i) | |
4829 | { | |
4830 | if (5 == i) | |
4831 | exprtk_debug(("\n")); | |
4832 | ||
4833 | exprtk_debug(("%15.10f ",data()[i])); | |
4834 | } | |
4835 | exprtk_debug(("\n")); | |
4836 | #endif | |
4837 | } | |
4838 | ||
4839 | static inline void match_sizes(type& vds0, type& vds1) | |
4840 | { | |
4841 | std::size_t size = min_size(vds0.control_block_,vds1.control_block_); | |
4842 | vds0.control_block_->size = size; | |
4843 | vds1.control_block_->size = size; | |
4844 | } | |
4845 | ||
4846 | private: | |
4847 | ||
4848 | static inline std::size_t min_size(control_block* cb0, control_block* cb1) | |
4849 | { | |
4850 | const std::size_t size0 = cb0->size; | |
4851 | const std::size_t size1 = cb1->size; | |
4852 | ||
4853 | if (size0 && size1) | |
4854 | return std::min(size0,size1); | |
4855 | else | |
4856 | return (size0) ? size0 : size1; | |
4857 | } | |
4858 | ||
4859 | control_block* control_block_; | |
4860 | }; | |
4861 | ||
4862 | namespace numeric | |
4863 | { | |
4864 | namespace details | |
4865 | { | |
4866 | template <typename T> | |
4867 | inline T process_impl(const operator_type operation, const T arg) | |
4868 | { | |
4869 | switch (operation) | |
4870 | { | |
4871 | case e_abs : return numeric::abs (arg); | |
4872 | case e_acos : return numeric::acos (arg); | |
4873 | case e_acosh : return numeric::acosh(arg); | |
4874 | case e_asin : return numeric::asin (arg); | |
4875 | case e_asinh : return numeric::asinh(arg); | |
4876 | case e_atan : return numeric::atan (arg); | |
4877 | case e_atanh : return numeric::atanh(arg); | |
4878 | case e_ceil : return numeric::ceil (arg); | |
4879 | case e_cos : return numeric::cos (arg); | |
4880 | case e_cosh : return numeric::cosh (arg); | |
4881 | case e_exp : return numeric::exp (arg); | |
4882 | case e_expm1 : return numeric::expm1(arg); | |
4883 | case e_floor : return numeric::floor(arg); | |
4884 | case e_log : return numeric::log (arg); | |
4885 | case e_log10 : return numeric::log10(arg); | |
4886 | case e_log2 : return numeric::log2 (arg); | |
4887 | case e_log1p : return numeric::log1p(arg); | |
4888 | case e_neg : return numeric::neg (arg); | |
4889 | case e_pos : return numeric::pos (arg); | |
4890 | case e_round : return numeric::round(arg); | |
4891 | case e_sin : return numeric::sin (arg); | |
4892 | case e_sinc : return numeric::sinc (arg); | |
4893 | case e_sinh : return numeric::sinh (arg); | |
4894 | case e_sqrt : return numeric::sqrt (arg); | |
4895 | case e_tan : return numeric::tan (arg); | |
4896 | case e_tanh : return numeric::tanh (arg); | |
4897 | case e_cot : return numeric::cot (arg); | |
4898 | case e_sec : return numeric::sec (arg); | |
4899 | case e_csc : return numeric::csc (arg); | |
4900 | case e_r2d : return numeric::r2d (arg); | |
4901 | case e_d2r : return numeric::d2r (arg); | |
4902 | case e_d2g : return numeric::d2g (arg); | |
4903 | case e_g2d : return numeric::g2d (arg); | |
4904 | case e_notl : return numeric::notl (arg); | |
4905 | case e_sgn : return numeric::sgn (arg); | |
4906 | case e_erf : return numeric::erf (arg); | |
4907 | case e_erfc : return numeric::erfc (arg); | |
4908 | case e_ncdf : return numeric::ncdf (arg); | |
4909 | case e_frac : return numeric::frac (arg); | |
4910 | case e_trunc : return numeric::trunc(arg); | |
4911 | ||
4912 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid unary operation.\n")); | |
4913 | return std::numeric_limits<T>::quiet_NaN(); | |
4914 | } | |
4915 | } | |
4916 | ||
4917 | template <typename T> | |
4918 | inline T process_impl(const operator_type operation, const T arg0, const T arg1) | |
4919 | { | |
4920 | switch (operation) | |
4921 | { | |
4922 | case e_add : return (arg0 + arg1); | |
4923 | case e_sub : return (arg0 - arg1); | |
4924 | case e_mul : return (arg0 * arg1); | |
4925 | case e_div : return (arg0 / arg1); | |
4926 | case e_mod : return modulus<T>(arg0,arg1); | |
4927 | case e_pow : return pow<T>(arg0,arg1); | |
4928 | case e_atan2 : return atan2<T>(arg0,arg1); | |
4929 | case e_min : return std::min<T>(arg0,arg1); | |
4930 | case e_max : return std::max<T>(arg0,arg1); | |
4931 | case e_logn : return logn<T>(arg0,arg1); | |
4932 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); | |
4933 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); | |
4934 | case e_eq : return std::equal_to<T>()(arg0,arg1) ? T(1) : T(0); | |
4935 | case e_ne : return std::not_equal_to<T>()(arg0,arg1) ? T(1) : T(0); | |
4936 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); | |
4937 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); | |
4938 | case e_and : return and_opr <T>(arg0,arg1); | |
4939 | case e_nand : return nand_opr<T>(arg0,arg1); | |
4940 | case e_or : return or_opr <T>(arg0,arg1); | |
4941 | case e_nor : return nor_opr <T>(arg0,arg1); | |
4942 | case e_xor : return xor_opr <T>(arg0,arg1); | |
4943 | case e_xnor : return xnor_opr<T>(arg0,arg1); | |
4944 | case e_root : return root <T>(arg0,arg1); | |
4945 | case e_roundn : return roundn <T>(arg0,arg1); | |
4946 | case e_equal : return equal (arg0,arg1); | |
4947 | case e_nequal : return nequal (arg0,arg1); | |
4948 | case e_hypot : return hypot <T>(arg0,arg1); | |
4949 | case e_shr : return shr <T>(arg0,arg1); | |
4950 | case e_shl : return shl <T>(arg0,arg1); | |
4951 | ||
4952 | default : exprtk_debug(("numeric::details::process_impl<T> - Invalid binary operation.\n")); | |
4953 | return std::numeric_limits<T>::quiet_NaN(); | |
4954 | } | |
4955 | } | |
4956 | ||
4957 | template <typename T> | |
4958 | inline T process_impl(const operator_type operation, const T arg0, const T arg1, int_type_tag) | |
4959 | { | |
4960 | switch (operation) | |
4961 | { | |
4962 | case e_add : return (arg0 + arg1); | |
4963 | case e_sub : return (arg0 - arg1); | |
4964 | case e_mul : return (arg0 * arg1); | |
4965 | case e_div : return (arg0 / arg1); | |
4966 | case e_mod : return arg0 % arg1; | |
4967 | case e_pow : return pow<T>(arg0,arg1); | |
4968 | case e_min : return std::min<T>(arg0,arg1); | |
4969 | case e_max : return std::max<T>(arg0,arg1); | |
4970 | case e_logn : return logn<T>(arg0,arg1); | |
4971 | case e_lt : return (arg0 < arg1) ? T(1) : T(0); | |
4972 | case e_lte : return (arg0 <= arg1) ? T(1) : T(0); | |
4973 | case e_eq : return (arg0 == arg1) ? T(1) : T(0); | |
4974 | case e_ne : return (arg0 != arg1) ? T(1) : T(0); | |
4975 | case e_gte : return (arg0 >= arg1) ? T(1) : T(0); | |
4976 | case e_gt : return (arg0 > arg1) ? T(1) : T(0); | |
4977 | case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0); | |
4978 | case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1); | |
4979 | case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0); | |
4980 | case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1); | |
4981 | case e_xor : return arg0 ^ arg1; | |
4982 | case e_xnor : return !(arg0 ^ arg1); | |
4983 | case e_root : return root<T>(arg0,arg1); | |
4984 | case e_equal : return arg0 == arg1; | |
4985 | case e_nequal : return arg0 != arg1; | |
4986 | case e_hypot : return hypot<T>(arg0,arg1); | |
4987 | case e_shr : return arg0 >> arg1; | |
4988 | case e_shl : return arg0 << arg1; | |
4989 | ||
4990 | default : exprtk_debug(("numeric::details::process_impl<IntType> - Invalid binary operation.\n")); | |
4991 | return std::numeric_limits<T>::quiet_NaN(); | |
4992 | } | |
4993 | } | |
4994 | } | |
4995 | ||
4996 | template <typename T> | |
4997 | inline T process(const operator_type operation, const T arg) | |
4998 | { | |
4999 | return exprtk::details::numeric::details::process_impl(operation,arg); | |
5000 | } | |
5001 | ||
5002 | template <typename T> | |
5003 | inline T process(const operator_type operation, const T arg0, const T arg1) | |
5004 | { | |
5005 | return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); | |
5006 | } | |
5007 | } | |
5008 | ||
5009 | template <typename T> | |
5010 | class expression_node | |
5011 | { | |
5012 | public: | |
5013 | ||
5014 | enum node_type | |
5015 | { | |
5016 | e_none , e_null , e_constant , e_unary , | |
5017 | e_binary , e_binary_ext , e_trinary , e_quaternary , | |
5018 | e_vararg , e_conditional , e_while , e_repeat , | |
5019 | e_for , e_switch , e_mswitch , e_return , | |
5020 | e_retenv , e_variable , e_stringvar , e_stringconst , | |
5021 | e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , | |
5022 | e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , | |
5023 | e_function , e_vafunction , e_genfunction , e_strfunction , | |
5024 | e_strcondition , e_strccondition , e_add , e_sub , | |
5025 | e_mul , e_div , e_mod , e_pow , | |
5026 | e_lt , e_lte , e_gt , e_gte , | |
5027 | e_eq , e_ne , e_and , e_nand , | |
5028 | e_or , e_nor , e_xor , e_xnor , | |
5029 | e_in , e_like , e_ilike , e_inranges , | |
5030 | e_ipow , e_ipowinv , e_abs , e_acos , | |
5031 | e_acosh , e_asin , e_asinh , e_atan , | |
5032 | e_atanh , e_ceil , e_cos , e_cosh , | |
5033 | e_exp , e_expm1 , e_floor , e_log , | |
5034 | e_log10 , e_log2 , e_log1p , e_neg , | |
5035 | e_pos , e_round , e_sin , e_sinc , | |
5036 | e_sinh , e_sqrt , e_tan , e_tanh , | |
5037 | e_cot , e_sec , e_csc , e_r2d , | |
5038 | e_d2r , e_d2g , e_g2d , e_notl , | |
5039 | e_sgn , e_erf , e_erfc , e_ncdf , | |
5040 | e_frac , e_trunc , e_uvouv , e_vov , | |
5041 | e_cov , e_voc , e_vob , e_bov , | |
5042 | e_cob , e_boc , e_vovov , e_vovoc , | |
5043 | e_vocov , e_covov , e_covoc , e_vovovov , | |
5044 | e_vovovoc , e_vovocov , e_vocovov , e_covovov , | |
5045 | e_covocov , e_vocovoc , e_covovoc , e_vococov , | |
5046 | e_sf3ext , e_sf4ext , e_nulleq , e_strass , | |
5047 | e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , | |
5048 | e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , | |
5049 | e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , | |
5050 | e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , | |
5051 | e_valvecarith , e_vecunaryop , e_break , e_continue , | |
5052 | e_swap | |
5053 | }; | |
5054 | ||
5055 | typedef T value_type; | |
5056 | typedef expression_node<T>* expression_ptr; | |
5057 | ||
5058 | virtual ~expression_node() | |
5059 | {} | |
5060 | ||
5061 | inline virtual T value() const | |
5062 | { | |
5063 | return std::numeric_limits<T>::quiet_NaN(); | |
5064 | } | |
5065 | ||
5066 | inline virtual expression_node<T>* branch(const std::size_t& index = 0) const | |
5067 | { | |
5068 | return reinterpret_cast<expression_ptr>(index * 0); | |
5069 | } | |
5070 | ||
5071 | inline virtual node_type type() const | |
5072 | { | |
5073 | return e_none; | |
5074 | } | |
5075 | }; | |
5076 | ||
5077 | template <typename T> | |
5078 | inline bool is_generally_string_node(const expression_node<T>* node); | |
5079 | ||
5080 | inline bool is_true(const double v) | |
5081 | { | |
5082 | return std::not_equal_to<double>()(0.0,v); | |
5083 | } | |
5084 | ||
5085 | inline bool is_true(const long double v) | |
5086 | { | |
5087 | return std::not_equal_to<long double>()(0.0L,v); | |
5088 | } | |
5089 | ||
5090 | inline bool is_true(const float v) | |
5091 | { | |
5092 | return std::not_equal_to<float>()(0.0f,v); | |
5093 | } | |
5094 | ||
5095 | template <typename T> | |
5096 | inline bool is_true(const std::complex<T>& v) | |
5097 | { | |
5098 | return std::not_equal_to<std::complex<T> >()(std::complex<T>(0),v); | |
5099 | } | |
5100 | ||
5101 | template <typename T> | |
5102 | inline bool is_true(const expression_node<T>* node) | |
5103 | { | |
5104 | return std::not_equal_to<T>()(T(0),node->value()); | |
5105 | } | |
5106 | ||
5107 | template <typename T> | |
5108 | inline bool is_false(const expression_node<T>* node) | |
5109 | { | |
5110 | return std::equal_to<T>()(T(0),node->value()); | |
5111 | } | |
5112 | ||
5113 | template <typename T> | |
5114 | inline bool is_unary_node(const expression_node<T>* node) | |
5115 | { | |
5116 | return node && (details::expression_node<T>::e_unary == node->type()); | |
5117 | } | |
5118 | ||
5119 | template <typename T> | |
5120 | inline bool is_neg_unary_node(const expression_node<T>* node) | |
5121 | { | |
5122 | return node && (details::expression_node<T>::e_neg == node->type()); | |
5123 | } | |
5124 | ||
5125 | template <typename T> | |
5126 | inline bool is_binary_node(const expression_node<T>* node) | |
5127 | { | |
5128 | return node && (details::expression_node<T>::e_binary == node->type()); | |
5129 | } | |
5130 | ||
5131 | template <typename T> | |
5132 | inline bool is_variable_node(const expression_node<T>* node) | |
5133 | { | |
5134 | return node && (details::expression_node<T>::e_variable == node->type()); | |
5135 | } | |
5136 | ||
5137 | template <typename T> | |
5138 | inline bool is_ivariable_node(const expression_node<T>* node) | |
5139 | { | |
5140 | return node && | |
5141 | ( | |
5142 | details::expression_node<T>::e_variable == node->type() || | |
5143 | details::expression_node<T>::e_vecelem == node->type() || | |
5144 | details::expression_node<T>::e_rbvecelem == node->type() || | |
5145 | details::expression_node<T>::e_rbveccelem == node->type() | |
5146 | ); | |
5147 | } | |
5148 | ||
5149 | template <typename T> | |
5150 | inline bool is_vector_elem_node(const expression_node<T>* node) | |
5151 | { | |
5152 | return node && (details::expression_node<T>::e_vecelem == node->type()); | |
5153 | } | |
5154 | ||
5155 | template <typename T> | |
5156 | inline bool is_rebasevector_elem_node(const expression_node<T>* node) | |
5157 | { | |
5158 | return node && (details::expression_node<T>::e_rbvecelem == node->type()); | |
5159 | } | |
5160 | ||
5161 | template <typename T> | |
5162 | inline bool is_rebasevector_celem_node(const expression_node<T>* node) | |
5163 | { | |
5164 | return node && (details::expression_node<T>::e_rbveccelem == node->type()); | |
5165 | } | |
5166 | ||
5167 | template <typename T> | |
5168 | inline bool is_vector_node(const expression_node<T>* node) | |
5169 | { | |
5170 | return node && (details::expression_node<T>::e_vector == node->type()); | |
5171 | } | |
5172 | ||
5173 | template <typename T> | |
5174 | inline bool is_ivector_node(const expression_node<T>* node) | |
5175 | { | |
5176 | if (node) | |
5177 | { | |
5178 | switch (node->type()) | |
5179 | { | |
5180 | case details::expression_node<T>::e_vector : | |
5181 | case details::expression_node<T>::e_vecvalass : | |
5182 | case details::expression_node<T>::e_vecvecass : | |
5183 | case details::expression_node<T>::e_vecopvalass : | |
5184 | case details::expression_node<T>::e_vecopvecass : | |
5185 | case details::expression_node<T>::e_vecvecswap : | |
5186 | case details::expression_node<T>::e_vecvecarith : | |
5187 | case details::expression_node<T>::e_vecvalarith : | |
5188 | case details::expression_node<T>::e_valvecarith : | |
5189 | case details::expression_node<T>::e_vecunaryop : return true; | |
5190 | default : return false; | |
5191 | } | |
5192 | } | |
5193 | else | |
5194 | return false; | |
5195 | } | |
5196 | ||
5197 | template <typename T> | |
5198 | inline bool is_constant_node(const expression_node<T>* node) | |
5199 | { | |
5200 | return node && (details::expression_node<T>::e_constant == node->type()); | |
5201 | } | |
5202 | ||
5203 | template <typename T> | |
5204 | inline bool is_null_node(const expression_node<T>* node) | |
5205 | { | |
5206 | return node && (details::expression_node<T>::e_null == node->type()); | |
5207 | } | |
5208 | ||
5209 | template <typename T> | |
5210 | inline bool is_break_node(const expression_node<T>* node) | |
5211 | { | |
5212 | return node && (details::expression_node<T>::e_break == node->type()); | |
5213 | } | |
5214 | ||
5215 | template <typename T> | |
5216 | inline bool is_continue_node(const expression_node<T>* node) | |
5217 | { | |
5218 | return node && (details::expression_node<T>::e_continue == node->type()); | |
5219 | } | |
5220 | ||
5221 | template <typename T> | |
5222 | inline bool is_swap_node(const expression_node<T>* node) | |
5223 | { | |
5224 | return node && (details::expression_node<T>::e_swap == node->type()); | |
5225 | } | |
5226 | ||
5227 | template <typename T> | |
5228 | inline bool is_function(const expression_node<T>* node) | |
5229 | { | |
5230 | return node && (details::expression_node<T>::e_function == node->type()); | |
5231 | } | |
5232 | ||
5233 | template <typename T> | |
5234 | inline bool is_return_node(const expression_node<T>* node) | |
5235 | { | |
5236 | return node && (details::expression_node<T>::e_return == node->type()); | |
5237 | } | |
5238 | ||
5239 | template <typename T> class unary_node; | |
5240 | ||
5241 | template <typename T> | |
5242 | inline bool is_negate_node(const expression_node<T>* node) | |
5243 | { | |
5244 | if (node && is_unary_node(node)) | |
5245 | { | |
5246 | return (details::e_neg == static_cast<const unary_node<T>*>(node)->operation()); | |
5247 | } | |
5248 | else | |
5249 | return false; | |
5250 | } | |
5251 | ||
5252 | template <typename T> | |
5253 | inline bool branch_deletable(expression_node<T>* node) | |
5254 | { | |
5255 | return !is_variable_node(node) && | |
5256 | !is_string_node (node) ; | |
5257 | } | |
5258 | ||
5259 | template <std::size_t N, typename T> | |
5260 | inline bool all_nodes_valid(expression_node<T>* (&b)[N]) | |
5261 | { | |
5262 | for (std::size_t i = 0; i < N; ++i) | |
5263 | { | |
5264 | if (0 == b[i]) return false; | |
5265 | } | |
5266 | ||
5267 | return true; | |
5268 | } | |
5269 | ||
5270 | template <typename T, | |
5271 | typename Allocator, | |
5272 | template <typename, typename> class Sequence> | |
5273 | inline bool all_nodes_valid(const Sequence<expression_node<T>*,Allocator>& b) | |
5274 | { | |
5275 | for (std::size_t i = 0; i < b.size(); ++i) | |
5276 | { | |
5277 | if (0 == b[i]) return false; | |
5278 | } | |
5279 | ||
5280 | return true; | |
5281 | } | |
5282 | ||
5283 | template <std::size_t N, typename T> | |
5284 | inline bool all_nodes_variables(expression_node<T>* (&b)[N]) | |
5285 | { | |
5286 | for (std::size_t i = 0; i < N; ++i) | |
5287 | { | |
5288 | if (0 == b[i]) | |
5289 | return false; | |
5290 | else if (!is_variable_node(b[i])) | |
5291 | return false; | |
5292 | } | |
5293 | ||
5294 | return true; | |
5295 | } | |
5296 | ||
5297 | template <typename T, | |
5298 | typename Allocator, | |
5299 | template <typename, typename> class Sequence> | |
5300 | inline bool all_nodes_variables(Sequence<expression_node<T>*,Allocator>& b) | |
5301 | { | |
5302 | for (std::size_t i = 0; i < b.size(); ++i) | |
5303 | { | |
5304 | if (0 == b[i]) | |
5305 | return false; | |
5306 | else if (!is_variable_node(b[i])) | |
5307 | return false; | |
5308 | } | |
5309 | ||
5310 | return true; | |
5311 | } | |
5312 | ||
5313 | template <typename NodeAllocator, typename T, std::size_t N> | |
5314 | inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) | |
5315 | { | |
5316 | for (std::size_t i = 0; i < N; ++i) | |
5317 | { | |
5318 | free_node(node_allocator,b[i]); | |
5319 | } | |
5320 | } | |
5321 | ||
5322 | template <typename NodeAllocator, | |
5323 | typename T, | |
5324 | typename Allocator, | |
5325 | template <typename, typename> class Sequence> | |
5326 | inline void free_all_nodes(NodeAllocator& node_allocator, Sequence<expression_node<T>*,Allocator>& b) | |
5327 | { | |
5328 | for (std::size_t i = 0; i < b.size(); ++i) | |
5329 | { | |
5330 | free_node(node_allocator,b[i]); | |
5331 | } | |
5332 | ||
5333 | b.clear(); | |
5334 | } | |
5335 | ||
5336 | template <typename NodeAllocator, typename T> | |
5337 | inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false) | |
5338 | { | |
5339 | if (0 != node) | |
5340 | { | |
5341 | if ( | |
5342 | (is_variable_node(node) || is_string_node(node)) || | |
5343 | force_delete | |
5344 | ) | |
5345 | return; | |
5346 | ||
5347 | node_allocator.free(node); | |
5348 | node = reinterpret_cast<expression_node<T>*>(0); | |
5349 | } | |
5350 | } | |
5351 | ||
5352 | template <typename T> | |
5353 | inline void destroy_node(expression_node<T>*& node) | |
5354 | { | |
5355 | delete node; | |
5356 | node = reinterpret_cast<expression_node<T>*>(0); | |
5357 | } | |
5358 | ||
5359 | template <typename Type> | |
5360 | class vector_holder | |
5361 | { | |
5362 | private: | |
5363 | ||
5364 | typedef Type value_type; | |
5365 | typedef value_type* value_ptr; | |
5366 | typedef const value_ptr const_value_ptr; | |
5367 | ||
5368 | class vector_holder_base | |
5369 | { | |
5370 | public: | |
5371 | ||
5372 | virtual ~vector_holder_base() {} | |
5373 | ||
5374 | inline value_ptr operator[](const std::size_t& index) const | |
5375 | { | |
5376 | return value_at(index); | |
5377 | } | |
5378 | ||
5379 | inline std::size_t size() const | |
5380 | { | |
5381 | return vector_size(); | |
5382 | } | |
5383 | ||
5384 | inline value_ptr data() const | |
5385 | { | |
5386 | return value_at(0); | |
5387 | } | |
5388 | ||
5389 | virtual inline bool rebaseable() const | |
5390 | { | |
5391 | return false; | |
5392 | } | |
5393 | ||
5394 | virtual void set_ref(value_ptr*) {} | |
5395 | ||
5396 | protected: | |
5397 | ||
5398 | virtual value_ptr value_at(const std::size_t&) const = 0; | |
5399 | virtual std::size_t vector_size() const = 0; | |
5400 | }; | |
5401 | ||
5402 | class array_vector_impl : public vector_holder_base | |
5403 | { | |
5404 | public: | |
5405 | ||
5406 | array_vector_impl(const Type* vec, const std::size_t& vec_size) | |
5407 | : vec_(vec), | |
5408 | size_(vec_size) | |
5409 | {} | |
5410 | ||
5411 | protected: | |
5412 | ||
5413 | value_ptr value_at(const std::size_t& index) const | |
5414 | { | |
5415 | if (index < size_) | |
5416 | return const_cast<const_value_ptr>(vec_ + index); | |
5417 | else | |
5418 | return const_value_ptr(0); | |
5419 | } | |
5420 | ||
5421 | std::size_t vector_size() const | |
5422 | { | |
5423 | return size_; | |
5424 | } | |
5425 | ||
5426 | private: | |
5427 | ||
5428 | array_vector_impl operator=(const array_vector_impl&); | |
5429 | ||
5430 | const Type* vec_; | |
5431 | const std::size_t size_; | |
5432 | }; | |
5433 | ||
5434 | template <typename Allocator, | |
5435 | template <typename, typename> class Sequence> | |
5436 | class sequence_vector_impl : public vector_holder_base | |
5437 | { | |
5438 | public: | |
5439 | ||
5440 | typedef Sequence<Type,Allocator> sequence_t; | |
5441 | ||
5442 | sequence_vector_impl(sequence_t& seq) | |
5443 | : sequence_(seq) | |
5444 | {} | |
5445 | ||
5446 | protected: | |
5447 | ||
5448 | value_ptr value_at(const std::size_t& index) const | |
5449 | { | |
5450 | return (index < sequence_.size()) ? (&sequence_[index]) : const_value_ptr(0); | |
5451 | } | |
5452 | ||
5453 | std::size_t vector_size() const | |
5454 | { | |
5455 | return sequence_.size(); | |
5456 | } | |
5457 | ||
5458 | private: | |
5459 | ||
5460 | sequence_vector_impl operator=(const sequence_vector_impl&); | |
5461 | ||
5462 | sequence_t& sequence_; | |
5463 | }; | |
5464 | ||
5465 | class vector_view_impl : public vector_holder_base | |
5466 | { | |
5467 | public: | |
5468 | ||
5469 | typedef exprtk::vector_view<Type> vector_view_t; | |
5470 | ||
5471 | vector_view_impl(vector_view_t& vec_view) | |
5472 | : vec_view_(vec_view) | |
5473 | {} | |
5474 | ||
5475 | void set_ref(value_ptr* ref) | |
5476 | { | |
5477 | vec_view_.set_ref(ref); | |
5478 | } | |
5479 | ||
5480 | virtual inline bool rebaseable() const | |
5481 | { | |
5482 | return true; | |
5483 | } | |
5484 | ||
5485 | protected: | |
5486 | ||
5487 | value_ptr value_at(const std::size_t& index) const | |
5488 | { | |
5489 | return (index < vec_view_.size()) ? (&vec_view_[index]) : const_value_ptr(0); | |
5490 | } | |
5491 | ||
5492 | std::size_t vector_size() const | |
5493 | { | |
5494 | return vec_view_.size(); | |
5495 | } | |
5496 | ||
5497 | private: | |
5498 | ||
5499 | vector_view_impl operator=(const vector_view_impl&); | |
5500 | ||
5501 | vector_view_t& vec_view_; | |
5502 | }; | |
5503 | ||
5504 | public: | |
5505 | ||
5506 | typedef typename details::vec_data_store<Type> vds_t; | |
5507 | ||
5508 | vector_holder(Type* vec, const std::size_t& vec_size) | |
5509 | : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size)) | |
5510 | {} | |
5511 | ||
5512 | vector_holder(const vds_t& vds) | |
5513 | : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size())) | |
5514 | {} | |
5515 | ||
5516 | template <typename Allocator> | |
5517 | vector_holder(std::vector<Type,Allocator>& vec) | |
5518 | : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec)) | |
5519 | {} | |
5520 | ||
5521 | vector_holder(exprtk::vector_view<Type>& vec) | |
5522 | : vector_holder_base_(new(buffer)vector_view_impl(vec)) | |
5523 | {} | |
5524 | ||
5525 | inline value_ptr operator[](const std::size_t& index) const | |
5526 | { | |
5527 | return (*vector_holder_base_)[index]; | |
5528 | } | |
5529 | ||
5530 | inline std::size_t size() const | |
5531 | { | |
5532 | return vector_holder_base_->size(); | |
5533 | } | |
5534 | ||
5535 | inline value_ptr data() const | |
5536 | { | |
5537 | return vector_holder_base_->data(); | |
5538 | } | |
5539 | ||
5540 | void set_ref(value_ptr* ref) | |
5541 | { | |
5542 | vector_holder_base_->set_ref(ref); | |
5543 | } | |
5544 | ||
5545 | bool rebaseable() const | |
5546 | { | |
5547 | return vector_holder_base_->rebaseable(); | |
5548 | } | |
5549 | ||
5550 | private: | |
5551 | ||
5552 | mutable vector_holder_base* vector_holder_base_; | |
5553 | uchar_t buffer[64]; | |
5554 | }; | |
5555 | ||
5556 | template <typename T> | |
5557 | class null_node : public expression_node<T> | |
5558 | { | |
5559 | public: | |
5560 | ||
5561 | inline T value() const | |
5562 | { | |
5563 | return std::numeric_limits<T>::quiet_NaN(); | |
5564 | } | |
5565 | ||
5566 | inline typename expression_node<T>::node_type type() const | |
5567 | { | |
5568 | return expression_node<T>::e_null; | |
5569 | } | |
5570 | }; | |
5571 | ||
5572 | template <typename T> | |
5573 | class null_eq_node : public expression_node<T> | |
5574 | { | |
5575 | public: | |
5576 | ||
5577 | typedef expression_node<T>* expression_ptr; | |
5578 | ||
5579 | null_eq_node(expression_ptr brnch, const bool equality = true) | |
5580 | : branch_(brnch), | |
5581 | branch_deletable_(branch_deletable(branch_)), | |
5582 | equality_(equality) | |
5583 | {} | |
5584 | ||
5585 | ~null_eq_node() | |
5586 | { | |
5587 | if (branch_ && branch_deletable_) | |
5588 | { | |
5589 | destroy_node(branch_); | |
5590 | } | |
5591 | } | |
5592 | ||
5593 | inline T value() const | |
5594 | { | |
5595 | const T v = branch_->value(); | |
5596 | const bool result = details::numeric::is_nan(v); | |
5597 | ||
5598 | if (result) | |
5599 | return (equality_) ? T(1) : T(0); | |
5600 | else | |
5601 | return (equality_) ? T(0) : T(1); | |
5602 | } | |
5603 | ||
5604 | inline typename expression_node<T>::node_type type() const | |
5605 | { | |
5606 | return expression_node<T>::e_nulleq; | |
5607 | } | |
5608 | ||
5609 | inline operator_type operation() const | |
5610 | { | |
5611 | return details::e_eq; | |
5612 | } | |
5613 | ||
5614 | inline expression_node<T>* branch(const std::size_t&) const | |
5615 | { | |
5616 | return branch_; | |
5617 | } | |
5618 | ||
5619 | private: | |
5620 | ||
5621 | expression_ptr branch_; | |
5622 | const bool branch_deletable_; | |
5623 | bool equality_; | |
5624 | }; | |
5625 | ||
5626 | template <typename T> | |
5627 | class literal_node : public expression_node<T> | |
5628 | { | |
5629 | public: | |
5630 | ||
5631 | explicit literal_node(const T& v) | |
5632 | : value_(v) | |
5633 | {} | |
5634 | ||
5635 | inline T value() const | |
5636 | { | |
5637 | return value_; | |
5638 | } | |
5639 | ||
5640 | inline typename expression_node<T>::node_type type() const | |
5641 | { | |
5642 | return expression_node<T>::e_constant; | |
5643 | } | |
5644 | ||
5645 | inline expression_node<T>* branch(const std::size_t&) const | |
5646 | { | |
5647 | return reinterpret_cast<expression_node<T>*>(0); | |
5648 | } | |
5649 | ||
5650 | private: | |
5651 | ||
5652 | literal_node(literal_node<T>&) {} | |
5653 | literal_node<T>& operator=(literal_node<T>&) { return (*this); } | |
5654 | ||
5655 | const T value_; | |
5656 | }; | |
5657 | ||
5658 | template <typename T> | |
5659 | struct range_pack; | |
5660 | ||
5661 | template <typename T> | |
5662 | struct range_data_type; | |
5663 | ||
5664 | template <typename T> | |
5665 | class range_interface | |
5666 | { | |
5667 | public: | |
5668 | ||
5669 | typedef range_pack<T> range_t; | |
5670 | ||
5671 | virtual ~range_interface() | |
5672 | {} | |
5673 | ||
5674 | virtual range_t& range_ref() = 0; | |
5675 | ||
5676 | virtual const range_t& range_ref() const = 0; | |
5677 | }; | |
5678 | ||
5679 | #ifndef exprtk_disable_string_capabilities | |
5680 | template <typename T> | |
5681 | class string_base_node | |
5682 | { | |
5683 | public: | |
5684 | ||
5685 | typedef range_data_type<T> range_data_type_t; | |
5686 | ||
5687 | virtual ~string_base_node() | |
5688 | {} | |
5689 | ||
5690 | virtual std::string str () const = 0; | |
5691 | ||
5692 | virtual char_cptr base() const = 0; | |
5693 | ||
5694 | virtual std::size_t size() const = 0; | |
5695 | }; | |
5696 | ||
5697 | template <typename T> | |
5698 | class string_literal_node : public expression_node <T>, | |
5699 | public string_base_node<T>, | |
5700 | public range_interface <T> | |
5701 | { | |
5702 | public: | |
5703 | ||
5704 | typedef range_pack<T> range_t; | |
5705 | ||
5706 | explicit string_literal_node(const std::string& v) | |
5707 | : value_(v) | |
5708 | { | |
5709 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
5710 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1); | |
5711 | rp_.cache.first = rp_.n0_c.second; | |
5712 | rp_.cache.second = rp_.n1_c.second; | |
5713 | } | |
5714 | ||
5715 | inline T value() const | |
5716 | { | |
5717 | return std::numeric_limits<T>::quiet_NaN(); | |
5718 | } | |
5719 | ||
5720 | inline typename expression_node<T>::node_type type() const | |
5721 | { | |
5722 | return expression_node<T>::e_stringconst; | |
5723 | } | |
5724 | ||
5725 | inline expression_node<T>* branch(const std::size_t&) const | |
5726 | { | |
5727 | return reinterpret_cast<expression_node<T>*>(0); | |
5728 | } | |
5729 | ||
5730 | std::string str() const | |
5731 | { | |
5732 | return value_; | |
5733 | } | |
5734 | ||
5735 | char_cptr base() const | |
5736 | { | |
5737 | return value_.data(); | |
5738 | } | |
5739 | ||
5740 | std::size_t size() const | |
5741 | { | |
5742 | return value_.size(); | |
5743 | } | |
5744 | ||
5745 | range_t& range_ref() | |
5746 | { | |
5747 | return rp_; | |
5748 | } | |
5749 | ||
5750 | const range_t& range_ref() const | |
5751 | { | |
5752 | return rp_; | |
5753 | } | |
5754 | ||
5755 | private: | |
5756 | ||
5757 | string_literal_node(const string_literal_node<T>&); | |
5758 | string_literal_node<T>& operator=(const string_literal_node<T>&); | |
5759 | ||
5760 | const std::string value_; | |
5761 | range_t rp_; | |
5762 | }; | |
5763 | #endif | |
5764 | ||
5765 | template <typename T> | |
5766 | class unary_node : public expression_node<T> | |
5767 | { | |
5768 | public: | |
5769 | ||
5770 | typedef expression_node<T>* expression_ptr; | |
5771 | ||
5772 | unary_node(const operator_type& opr, | |
5773 | expression_ptr brnch) | |
5774 | : operation_(opr), | |
5775 | branch_(brnch), | |
5776 | branch_deletable_(branch_deletable(branch_)) | |
5777 | {} | |
5778 | ||
5779 | ~unary_node() | |
5780 | { | |
5781 | if (branch_ && branch_deletable_) | |
5782 | { | |
5783 | destroy_node(branch_); | |
5784 | } | |
5785 | } | |
5786 | ||
5787 | inline T value() const | |
5788 | { | |
5789 | const T arg = branch_->value(); | |
5790 | ||
5791 | return numeric::process<T>(operation_,arg); | |
5792 | } | |
5793 | ||
5794 | inline typename expression_node<T>::node_type type() const | |
5795 | { | |
5796 | return expression_node<T>::e_unary; | |
5797 | } | |
5798 | ||
5799 | inline operator_type operation() const | |
5800 | { | |
5801 | return operation_; | |
5802 | } | |
5803 | ||
5804 | inline expression_node<T>* branch(const std::size_t&) const | |
5805 | { | |
5806 | return branch_; | |
5807 | } | |
5808 | ||
5809 | inline void release() | |
5810 | { | |
5811 | branch_deletable_ = false; | |
5812 | } | |
5813 | ||
5814 | protected: | |
5815 | ||
5816 | operator_type operation_; | |
5817 | expression_ptr branch_; | |
5818 | bool branch_deletable_; | |
5819 | }; | |
5820 | ||
5821 | template <typename T, std::size_t D, bool B> | |
5822 | struct construct_branch_pair | |
5823 | { | |
5824 | template <std::size_t N> | |
5825 | static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*) | |
5826 | {} | |
5827 | }; | |
5828 | ||
5829 | template <typename T, std::size_t D> | |
5830 | struct construct_branch_pair<T,D,true> | |
5831 | { | |
5832 | template <std::size_t N> | |
5833 | static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b) | |
5834 | { | |
5835 | if (b) | |
5836 | { | |
5837 | branch[D] = std::make_pair(b,branch_deletable(b)); | |
5838 | } | |
5839 | } | |
5840 | }; | |
5841 | ||
5842 | template <std::size_t N, typename T> | |
5843 | inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], | |
5844 | expression_node<T>* b0, | |
5845 | expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), | |
5846 | expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), | |
5847 | expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), | |
5848 | expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), | |
5849 | expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), | |
5850 | expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), | |
5851 | expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), | |
5852 | expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), | |
5853 | expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) | |
5854 | { | |
5855 | construct_branch_pair<T,0,(N > 0)>::process(branch,b0); | |
5856 | construct_branch_pair<T,1,(N > 1)>::process(branch,b1); | |
5857 | construct_branch_pair<T,2,(N > 2)>::process(branch,b2); | |
5858 | construct_branch_pair<T,3,(N > 3)>::process(branch,b3); | |
5859 | construct_branch_pair<T,4,(N > 4)>::process(branch,b4); | |
5860 | construct_branch_pair<T,5,(N > 5)>::process(branch,b5); | |
5861 | construct_branch_pair<T,6,(N > 6)>::process(branch,b6); | |
5862 | construct_branch_pair<T,7,(N > 7)>::process(branch,b7); | |
5863 | construct_branch_pair<T,8,(N > 8)>::process(branch,b8); | |
5864 | construct_branch_pair<T,9,(N > 9)>::process(branch,b9); | |
5865 | } | |
5866 | ||
5867 | struct cleanup_branches | |
5868 | { | |
5869 | template <typename T, std::size_t N> | |
5870 | static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N]) | |
5871 | { | |
5872 | for (std::size_t i = 0; i < N; ++i) | |
5873 | { | |
5874 | if (branch[i].first && branch[i].second) | |
5875 | { | |
5876 | destroy_node(branch[i].first); | |
5877 | } | |
5878 | } | |
5879 | } | |
5880 | ||
5881 | template <typename T, | |
5882 | typename Allocator, | |
5883 | template <typename, typename> class Sequence> | |
5884 | static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch) | |
5885 | { | |
5886 | for (std::size_t i = 0; i < branch.size(); ++i) | |
5887 | { | |
5888 | if (branch[i].first && branch[i].second) | |
5889 | { | |
5890 | destroy_node(branch[i].first); | |
5891 | } | |
5892 | } | |
5893 | } | |
5894 | }; | |
5895 | ||
5896 | template <typename T> | |
5897 | class binary_node : public expression_node<T> | |
5898 | { | |
5899 | public: | |
5900 | ||
5901 | typedef expression_node<T>* expression_ptr; | |
5902 | typedef std::pair<expression_ptr,bool> branch_t; | |
5903 | ||
5904 | binary_node(const operator_type& opr, | |
5905 | expression_ptr branch0, | |
5906 | expression_ptr branch1) | |
5907 | : operation_(opr) | |
5908 | { | |
5909 | init_branches<2>(branch_, branch0, branch1); | |
5910 | } | |
5911 | ||
5912 | ~binary_node() | |
5913 | { | |
5914 | cleanup_branches::execute<T,2>(branch_); | |
5915 | } | |
5916 | ||
5917 | inline T value() const | |
5918 | { | |
5919 | const T arg0 = branch_[0].first->value(); | |
5920 | const T arg1 = branch_[1].first->value(); | |
5921 | ||
5922 | return numeric::process<T>(operation_,arg0,arg1); | |
5923 | } | |
5924 | ||
5925 | inline typename expression_node<T>::node_type type() const | |
5926 | { | |
5927 | return expression_node<T>::e_binary; | |
5928 | } | |
5929 | ||
5930 | inline operator_type operation() | |
5931 | { | |
5932 | return operation_; | |
5933 | } | |
5934 | ||
5935 | inline expression_node<T>* branch(const std::size_t& index = 0) const | |
5936 | { | |
5937 | if (0 == index) | |
5938 | return branch_[0].first; | |
5939 | else if (1 == index) | |
5940 | return branch_[1].first; | |
5941 | else | |
5942 | return reinterpret_cast<expression_ptr>(0); | |
5943 | } | |
5944 | ||
5945 | protected: | |
5946 | ||
5947 | operator_type operation_; | |
5948 | branch_t branch_[2]; | |
5949 | }; | |
5950 | ||
5951 | template <typename T, typename Operation> | |
5952 | class binary_ext_node : public expression_node<T> | |
5953 | { | |
5954 | public: | |
5955 | ||
5956 | typedef expression_node<T>* expression_ptr; | |
5957 | typedef std::pair<expression_ptr,bool> branch_t; | |
5958 | ||
5959 | binary_ext_node(expression_ptr branch0, expression_ptr branch1) | |
5960 | { | |
5961 | init_branches<2>(branch_, branch0, branch1); | |
5962 | } | |
5963 | ||
5964 | ~binary_ext_node() | |
5965 | { | |
5966 | cleanup_branches::execute<T,2>(branch_); | |
5967 | } | |
5968 | ||
5969 | inline T value() const | |
5970 | { | |
5971 | const T arg0 = branch_[0].first->value(); | |
5972 | const T arg1 = branch_[1].first->value(); | |
5973 | ||
5974 | return Operation::process(arg0,arg1); | |
5975 | } | |
5976 | ||
5977 | inline typename expression_node<T>::node_type type() const | |
5978 | { | |
5979 | return expression_node<T>::e_binary_ext; | |
5980 | } | |
5981 | ||
5982 | inline operator_type operation() | |
5983 | { | |
5984 | return Operation::operation(); | |
5985 | } | |
5986 | ||
5987 | inline expression_node<T>* branch(const std::size_t& index = 0) const | |
5988 | { | |
5989 | if (0 == index) | |
5990 | return branch_[0].first; | |
5991 | else if (1 == index) | |
5992 | return branch_[1].first; | |
5993 | else | |
5994 | return reinterpret_cast<expression_ptr>(0); | |
5995 | } | |
5996 | ||
5997 | protected: | |
5998 | ||
5999 | branch_t branch_[2]; | |
6000 | }; | |
6001 | ||
6002 | template <typename T> | |
6003 | class trinary_node : public expression_node<T> | |
6004 | { | |
6005 | public: | |
6006 | ||
6007 | typedef expression_node<T>* expression_ptr; | |
6008 | typedef std::pair<expression_ptr,bool> branch_t; | |
6009 | ||
6010 | trinary_node(const operator_type& opr, | |
6011 | expression_ptr branch0, | |
6012 | expression_ptr branch1, | |
6013 | expression_ptr branch2) | |
6014 | : operation_(opr) | |
6015 | { | |
6016 | init_branches<3>(branch_, branch0, branch1, branch2); | |
6017 | } | |
6018 | ||
6019 | ~trinary_node() | |
6020 | { | |
6021 | cleanup_branches::execute<T,3>(branch_); | |
6022 | } | |
6023 | ||
6024 | inline T value() const | |
6025 | { | |
6026 | const T arg0 = branch_[0].first->value(); | |
6027 | const T arg1 = branch_[1].first->value(); | |
6028 | const T arg2 = branch_[2].first->value(); | |
6029 | ||
6030 | switch (operation_) | |
6031 | { | |
6032 | case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1)); | |
6033 | ||
6034 | case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1); | |
6035 | ||
6036 | case e_iclamp : if ((arg1 <= arg0) || (arg1 >= arg2)) | |
6037 | return arg1; | |
6038 | else | |
6039 | return ((T(2) * arg1 <= (arg2 + arg0)) ? arg0 : arg2); | |
6040 | ||
6041 | default : exprtk_debug(("trinary_node::value() - Error: Invalid operation\n")); | |
6042 | return std::numeric_limits<T>::quiet_NaN(); | |
6043 | } | |
6044 | } | |
6045 | ||
6046 | inline typename expression_node<T>::node_type type() const | |
6047 | { | |
6048 | return expression_node<T>::e_trinary; | |
6049 | } | |
6050 | ||
6051 | protected: | |
6052 | ||
6053 | operator_type operation_; | |
6054 | branch_t branch_[3]; | |
6055 | }; | |
6056 | ||
6057 | template <typename T> | |
6058 | class quaternary_node : public expression_node<T> | |
6059 | { | |
6060 | public: | |
6061 | ||
6062 | typedef expression_node<T>* expression_ptr; | |
6063 | typedef std::pair<expression_ptr,bool> branch_t; | |
6064 | ||
6065 | quaternary_node(const operator_type& opr, | |
6066 | expression_ptr branch0, | |
6067 | expression_ptr branch1, | |
6068 | expression_ptr branch2, | |
6069 | expression_ptr branch3) | |
6070 | : operation_(opr) | |
6071 | { | |
6072 | init_branches<4>(branch_, branch0, branch1, branch2, branch3); | |
6073 | } | |
6074 | ||
6075 | ~quaternary_node() | |
6076 | { | |
6077 | cleanup_branches::execute<T,4>(branch_); | |
6078 | } | |
6079 | ||
6080 | inline T value() const | |
6081 | { | |
6082 | return std::numeric_limits<T>::quiet_NaN(); | |
6083 | } | |
6084 | ||
6085 | inline typename expression_node<T>::node_type type() const | |
6086 | { | |
6087 | return expression_node<T>::e_quaternary; | |
6088 | } | |
6089 | ||
6090 | protected: | |
6091 | ||
6092 | operator_type operation_; | |
6093 | branch_t branch_[4]; | |
6094 | }; | |
6095 | ||
6096 | template <typename T> | |
6097 | class conditional_node : public expression_node<T> | |
6098 | { | |
6099 | public: | |
6100 | ||
6101 | typedef expression_node<T>* expression_ptr; | |
6102 | ||
6103 | conditional_node(expression_ptr test, | |
6104 | expression_ptr consequent, | |
6105 | expression_ptr alternative) | |
6106 | : test_(test), | |
6107 | consequent_(consequent), | |
6108 | alternative_(alternative), | |
6109 | test_deletable_(branch_deletable(test_)), | |
6110 | consequent_deletable_(branch_deletable(consequent_)), | |
6111 | alternative_deletable_(branch_deletable(alternative_)) | |
6112 | {} | |
6113 | ||
6114 | ~conditional_node() | |
6115 | { | |
6116 | if (test_ && test_deletable_) | |
6117 | { | |
6118 | destroy_node(test_); | |
6119 | } | |
6120 | ||
6121 | if (consequent_ && consequent_deletable_ ) | |
6122 | { | |
6123 | destroy_node(consequent_); | |
6124 | } | |
6125 | ||
6126 | if (alternative_ && alternative_deletable_) | |
6127 | { | |
6128 | destroy_node(alternative_); | |
6129 | } | |
6130 | } | |
6131 | ||
6132 | inline T value() const | |
6133 | { | |
6134 | if (is_true(test_)) | |
6135 | return consequent_->value(); | |
6136 | else | |
6137 | return alternative_->value(); | |
6138 | } | |
6139 | ||
6140 | inline typename expression_node<T>::node_type type() const | |
6141 | { | |
6142 | return expression_node<T>::e_conditional; | |
6143 | } | |
6144 | ||
6145 | private: | |
6146 | ||
6147 | expression_ptr test_; | |
6148 | expression_ptr consequent_; | |
6149 | expression_ptr alternative_; | |
6150 | const bool test_deletable_; | |
6151 | const bool consequent_deletable_; | |
6152 | const bool alternative_deletable_; | |
6153 | }; | |
6154 | ||
6155 | template <typename T> | |
6156 | class cons_conditional_node : public expression_node<T> | |
6157 | { | |
6158 | public: | |
6159 | ||
6160 | // Consequent only conditional statement node | |
6161 | typedef expression_node<T>* expression_ptr; | |
6162 | ||
6163 | cons_conditional_node(expression_ptr test, | |
6164 | expression_ptr consequent) | |
6165 | : test_(test), | |
6166 | consequent_(consequent), | |
6167 | test_deletable_(branch_deletable(test_)), | |
6168 | consequent_deletable_(branch_deletable(consequent_)) | |
6169 | {} | |
6170 | ||
6171 | ~cons_conditional_node() | |
6172 | { | |
6173 | if (test_ && test_deletable_) | |
6174 | { | |
6175 | destroy_node(test_); | |
6176 | } | |
6177 | ||
6178 | if (consequent_ && consequent_deletable_) | |
6179 | { | |
6180 | destroy_node(consequent_); | |
6181 | } | |
6182 | } | |
6183 | ||
6184 | inline T value() const | |
6185 | { | |
6186 | if (is_true(test_)) | |
6187 | return consequent_->value(); | |
6188 | else | |
6189 | return std::numeric_limits<T>::quiet_NaN(); | |
6190 | } | |
6191 | ||
6192 | inline typename expression_node<T>::node_type type() const | |
6193 | { | |
6194 | return expression_node<T>::e_conditional; | |
6195 | } | |
6196 | ||
6197 | private: | |
6198 | ||
6199 | expression_ptr test_; | |
6200 | expression_ptr consequent_; | |
6201 | const bool test_deletable_; | |
6202 | const bool consequent_deletable_; | |
6203 | }; | |
6204 | ||
6205 | #ifndef exprtk_disable_break_continue | |
6206 | template <typename T> | |
6207 | class break_exception | |
6208 | { | |
6209 | public: | |
6210 | ||
6211 | break_exception(const T& v) | |
6212 | : value(v) | |
6213 | {} | |
6214 | ||
6215 | T value; | |
6216 | }; | |
6217 | ||
6218 | class continue_exception | |
6219 | {}; | |
6220 | ||
6221 | template <typename T> | |
6222 | class break_node : public expression_node<T> | |
6223 | { | |
6224 | public: | |
6225 | ||
6226 | typedef expression_node<T>* expression_ptr; | |
6227 | ||
6228 | break_node(expression_ptr ret = expression_ptr(0)) | |
6229 | : return_(ret), | |
6230 | return_deletable_(branch_deletable(return_)) | |
6231 | {} | |
6232 | ||
6233 | ~break_node() | |
6234 | { | |
6235 | if (return_deletable_) | |
6236 | { | |
6237 | destroy_node(return_); | |
6238 | } | |
6239 | } | |
6240 | ||
6241 | inline T value() const | |
6242 | { | |
6243 | throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN()); | |
6244 | #ifndef _MSC_VER | |
6245 | return std::numeric_limits<T>::quiet_NaN(); | |
6246 | #endif | |
6247 | } | |
6248 | ||
6249 | inline typename expression_node<T>::node_type type() const | |
6250 | { | |
6251 | return expression_node<T>::e_break; | |
6252 | } | |
6253 | ||
6254 | private: | |
6255 | ||
6256 | expression_ptr return_; | |
6257 | const bool return_deletable_; | |
6258 | }; | |
6259 | ||
6260 | template <typename T> | |
6261 | class continue_node : public expression_node<T> | |
6262 | { | |
6263 | public: | |
6264 | ||
6265 | inline T value() const | |
6266 | { | |
6267 | throw continue_exception(); | |
6268 | #ifndef _MSC_VER | |
6269 | return std::numeric_limits<T>::quiet_NaN(); | |
6270 | #endif | |
6271 | } | |
6272 | ||
6273 | inline typename expression_node<T>::node_type type() const | |
6274 | { | |
6275 | return expression_node<T>::e_break; | |
6276 | } | |
6277 | }; | |
6278 | #endif | |
6279 | ||
6280 | template <typename T> | |
6281 | class while_loop_node : public expression_node<T> | |
6282 | { | |
6283 | public: | |
6284 | ||
6285 | typedef expression_node<T>* expression_ptr; | |
6286 | ||
6287 | while_loop_node(expression_ptr condition, expression_ptr loop_body) | |
6288 | : condition_(condition), | |
6289 | loop_body_(loop_body), | |
6290 | condition_deletable_(branch_deletable(condition_)), | |
6291 | loop_body_deletable_(branch_deletable(loop_body_)) | |
6292 | {} | |
6293 | ||
6294 | ~while_loop_node() | |
6295 | { | |
6296 | if (condition_ && condition_deletable_) | |
6297 | { | |
6298 | destroy_node(condition_); | |
6299 | } | |
6300 | ||
6301 | if (loop_body_ && loop_body_deletable_) | |
6302 | { | |
6303 | destroy_node(loop_body_); | |
6304 | } | |
6305 | } | |
6306 | ||
6307 | inline T value() const | |
6308 | { | |
6309 | T result = T(0); | |
6310 | ||
6311 | while (is_true(condition_)) | |
6312 | { | |
6313 | result = loop_body_->value(); | |
6314 | } | |
6315 | ||
6316 | return result; | |
6317 | } | |
6318 | ||
6319 | inline typename expression_node<T>::node_type type() const | |
6320 | { | |
6321 | return expression_node<T>::e_while; | |
6322 | } | |
6323 | ||
6324 | private: | |
6325 | ||
6326 | expression_ptr condition_; | |
6327 | expression_ptr loop_body_; | |
6328 | const bool condition_deletable_; | |
6329 | const bool loop_body_deletable_; | |
6330 | }; | |
6331 | ||
6332 | template <typename T> | |
6333 | class repeat_until_loop_node : public expression_node<T> | |
6334 | { | |
6335 | public: | |
6336 | ||
6337 | typedef expression_node<T>* expression_ptr; | |
6338 | ||
6339 | repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body) | |
6340 | : condition_(condition), | |
6341 | loop_body_(loop_body), | |
6342 | condition_deletable_(branch_deletable(condition_)), | |
6343 | loop_body_deletable_(branch_deletable(loop_body_)) | |
6344 | {} | |
6345 | ||
6346 | ~repeat_until_loop_node() | |
6347 | { | |
6348 | if (condition_ && condition_deletable_) | |
6349 | { | |
6350 | destroy_node(condition_); | |
6351 | } | |
6352 | ||
6353 | if (loop_body_ && loop_body_deletable_) | |
6354 | { | |
6355 | destroy_node(loop_body_); | |
6356 | } | |
6357 | } | |
6358 | ||
6359 | inline T value() const | |
6360 | { | |
6361 | T result = T(0); | |
6362 | ||
6363 | do | |
6364 | { | |
6365 | result = loop_body_->value(); | |
6366 | } | |
6367 | while (is_false(condition_)); | |
6368 | ||
6369 | return result; | |
6370 | } | |
6371 | ||
6372 | inline typename expression_node<T>::node_type type() const | |
6373 | { | |
6374 | return expression_node<T>::e_repeat; | |
6375 | } | |
6376 | ||
6377 | private: | |
6378 | ||
6379 | expression_ptr condition_; | |
6380 | expression_ptr loop_body_; | |
6381 | const bool condition_deletable_; | |
6382 | const bool loop_body_deletable_; | |
6383 | }; | |
6384 | ||
6385 | template <typename T> | |
6386 | class for_loop_node : public expression_node<T> | |
6387 | { | |
6388 | public: | |
6389 | ||
6390 | typedef expression_node<T>* expression_ptr; | |
6391 | ||
6392 | for_loop_node(expression_ptr initialiser, | |
6393 | expression_ptr condition, | |
6394 | expression_ptr incrementor, | |
6395 | expression_ptr loop_body) | |
6396 | : initialiser_(initialiser), | |
6397 | condition_ (condition ), | |
6398 | incrementor_(incrementor), | |
6399 | loop_body_ (loop_body ), | |
6400 | initialiser_deletable_(branch_deletable(initialiser_)), | |
6401 | condition_deletable_ (branch_deletable(condition_ )), | |
6402 | incrementor_deletable_(branch_deletable(incrementor_)), | |
6403 | loop_body_deletable_ (branch_deletable(loop_body_ )) | |
6404 | {} | |
6405 | ||
6406 | ~for_loop_node() | |
6407 | { | |
6408 | if (initialiser_ && initialiser_deletable_) | |
6409 | { | |
6410 | destroy_node(initialiser_); | |
6411 | } | |
6412 | ||
6413 | if (condition_ && condition_deletable_) | |
6414 | { | |
6415 | destroy_node(condition_); | |
6416 | } | |
6417 | ||
6418 | if (incrementor_ && incrementor_deletable_) | |
6419 | { | |
6420 | destroy_node(incrementor_); | |
6421 | } | |
6422 | ||
6423 | if (loop_body_ && loop_body_deletable_) | |
6424 | { | |
6425 | destroy_node(loop_body_); | |
6426 | } | |
6427 | } | |
6428 | ||
6429 | inline T value() const | |
6430 | { | |
6431 | T result = T(0); | |
6432 | ||
6433 | if (initialiser_) | |
6434 | initialiser_->value(); | |
6435 | ||
6436 | if (incrementor_) | |
6437 | { | |
6438 | while (is_true(condition_)) | |
6439 | { | |
6440 | result = loop_body_->value(); | |
6441 | incrementor_->value(); | |
6442 | } | |
6443 | } | |
6444 | else | |
6445 | { | |
6446 | while (is_true(condition_)) | |
6447 | { | |
6448 | result = loop_body_->value(); | |
6449 | } | |
6450 | } | |
6451 | ||
6452 | return result; | |
6453 | } | |
6454 | ||
6455 | inline typename expression_node<T>::node_type type() const | |
6456 | { | |
6457 | return expression_node<T>::e_for; | |
6458 | } | |
6459 | ||
6460 | private: | |
6461 | ||
6462 | expression_ptr initialiser_ ; | |
6463 | expression_ptr condition_ ; | |
6464 | expression_ptr incrementor_ ; | |
6465 | expression_ptr loop_body_ ; | |
6466 | const bool initialiser_deletable_; | |
6467 | const bool condition_deletable_ ; | |
6468 | const bool incrementor_deletable_; | |
6469 | const bool loop_body_deletable_ ; | |
6470 | }; | |
6471 | ||
6472 | #ifndef exprtk_disable_break_continue | |
6473 | template <typename T> | |
6474 | class while_loop_bc_node : public expression_node<T> | |
6475 | { | |
6476 | public: | |
6477 | ||
6478 | typedef expression_node<T>* expression_ptr; | |
6479 | ||
6480 | while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) | |
6481 | : condition_(condition), | |
6482 | loop_body_(loop_body), | |
6483 | condition_deletable_(branch_deletable(condition_)), | |
6484 | loop_body_deletable_(branch_deletable(loop_body_)) | |
6485 | {} | |
6486 | ||
6487 | ~while_loop_bc_node() | |
6488 | { | |
6489 | if (condition_ && condition_deletable_) | |
6490 | { | |
6491 | destroy_node(condition_); | |
6492 | } | |
6493 | ||
6494 | if (loop_body_ && loop_body_deletable_) | |
6495 | { | |
6496 | destroy_node(loop_body_); | |
6497 | } | |
6498 | } | |
6499 | ||
6500 | inline T value() const | |
6501 | { | |
6502 | T result = T(0); | |
6503 | ||
6504 | while (is_true(condition_)) | |
6505 | { | |
6506 | try | |
6507 | { | |
6508 | result = loop_body_->value(); | |
6509 | } | |
6510 | catch(const break_exception<T>& e) | |
6511 | { | |
6512 | return e.value; | |
6513 | } | |
6514 | catch(const continue_exception&) | |
6515 | {} | |
6516 | } | |
6517 | ||
6518 | return result; | |
6519 | } | |
6520 | ||
6521 | inline typename expression_node<T>::node_type type() const | |
6522 | { | |
6523 | return expression_node<T>::e_while; | |
6524 | } | |
6525 | ||
6526 | private: | |
6527 | ||
6528 | expression_ptr condition_; | |
6529 | expression_ptr loop_body_; | |
6530 | const bool condition_deletable_; | |
6531 | const bool loop_body_deletable_; | |
6532 | }; | |
6533 | ||
6534 | template <typename T> | |
6535 | class repeat_until_loop_bc_node : public expression_node<T> | |
6536 | { | |
6537 | public: | |
6538 | ||
6539 | typedef expression_node<T>* expression_ptr; | |
6540 | ||
6541 | repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) | |
6542 | : condition_(condition), | |
6543 | loop_body_(loop_body), | |
6544 | condition_deletable_(branch_deletable(condition_)), | |
6545 | loop_body_deletable_(branch_deletable(loop_body_)) | |
6546 | {} | |
6547 | ||
6548 | ~repeat_until_loop_bc_node() | |
6549 | { | |
6550 | if (condition_ && condition_deletable_) | |
6551 | { | |
6552 | destroy_node(condition_); | |
6553 | } | |
6554 | ||
6555 | if (loop_body_ && loop_body_deletable_) | |
6556 | { | |
6557 | destroy_node(loop_body_); | |
6558 | } | |
6559 | } | |
6560 | ||
6561 | inline T value() const | |
6562 | { | |
6563 | T result = T(0); | |
6564 | ||
6565 | do | |
6566 | { | |
6567 | try | |
6568 | { | |
6569 | result = loop_body_->value(); | |
6570 | } | |
6571 | catch(const break_exception<T>& e) | |
6572 | { | |
6573 | return e.value; | |
6574 | } | |
6575 | catch(const continue_exception&) | |
6576 | {} | |
6577 | } | |
6578 | while (is_false(condition_)); | |
6579 | ||
6580 | return result; | |
6581 | } | |
6582 | ||
6583 | inline typename expression_node<T>::node_type type() const | |
6584 | { | |
6585 | return expression_node<T>::e_repeat; | |
6586 | } | |
6587 | ||
6588 | private: | |
6589 | ||
6590 | expression_ptr condition_; | |
6591 | expression_ptr loop_body_; | |
6592 | const bool condition_deletable_; | |
6593 | const bool loop_body_deletable_; | |
6594 | }; | |
6595 | ||
6596 | template <typename T> | |
6597 | class for_loop_bc_node : public expression_node<T> | |
6598 | { | |
6599 | public: | |
6600 | ||
6601 | typedef expression_node<T>* expression_ptr; | |
6602 | ||
6603 | for_loop_bc_node(expression_ptr initialiser, | |
6604 | expression_ptr condition, | |
6605 | expression_ptr incrementor, | |
6606 | expression_ptr loop_body) | |
6607 | : initialiser_(initialiser), | |
6608 | condition_ (condition ), | |
6609 | incrementor_(incrementor), | |
6610 | loop_body_ (loop_body ), | |
6611 | initialiser_deletable_(branch_deletable(initialiser_)), | |
6612 | condition_deletable_ (branch_deletable(condition_ )), | |
6613 | incrementor_deletable_(branch_deletable(incrementor_)), | |
6614 | loop_body_deletable_ (branch_deletable(loop_body_ )) | |
6615 | {} | |
6616 | ||
6617 | ~for_loop_bc_node() | |
6618 | { | |
6619 | if (initialiser_ && initialiser_deletable_) | |
6620 | { | |
6621 | destroy_node(initialiser_); | |
6622 | } | |
6623 | ||
6624 | if (condition_ && condition_deletable_) | |
6625 | { | |
6626 | destroy_node(condition_); | |
6627 | } | |
6628 | ||
6629 | if (incrementor_ && incrementor_deletable_) | |
6630 | { | |
6631 | destroy_node(incrementor_); | |
6632 | } | |
6633 | ||
6634 | if (loop_body_ && loop_body_deletable_) | |
6635 | { | |
6636 | destroy_node(loop_body_); | |
6637 | } | |
6638 | } | |
6639 | ||
6640 | inline T value() const | |
6641 | { | |
6642 | T result = T(0); | |
6643 | ||
6644 | if (initialiser_) | |
6645 | initialiser_->value(); | |
6646 | ||
6647 | if (incrementor_) | |
6648 | { | |
6649 | while (is_true(condition_)) | |
6650 | { | |
6651 | try | |
6652 | { | |
6653 | result = loop_body_->value(); | |
6654 | } | |
6655 | catch(const break_exception<T>& e) | |
6656 | { | |
6657 | return e.value; | |
6658 | } | |
6659 | catch(const continue_exception&) | |
6660 | {} | |
6661 | ||
6662 | incrementor_->value(); | |
6663 | } | |
6664 | } | |
6665 | else | |
6666 | { | |
6667 | while (is_true(condition_)) | |
6668 | { | |
6669 | try | |
6670 | { | |
6671 | result = loop_body_->value(); | |
6672 | } | |
6673 | catch(const break_exception<T>& e) | |
6674 | { | |
6675 | return e.value; | |
6676 | } | |
6677 | catch(const continue_exception&) | |
6678 | {} | |
6679 | } | |
6680 | } | |
6681 | ||
6682 | return result; | |
6683 | } | |
6684 | ||
6685 | inline typename expression_node<T>::node_type type() const | |
6686 | { | |
6687 | return expression_node<T>::e_for; | |
6688 | } | |
6689 | ||
6690 | private: | |
6691 | ||
6692 | expression_ptr initialiser_; | |
6693 | expression_ptr condition_ ; | |
6694 | expression_ptr incrementor_; | |
6695 | expression_ptr loop_body_ ; | |
6696 | const bool initialiser_deletable_; | |
6697 | const bool condition_deletable_ ; | |
6698 | const bool incrementor_deletable_; | |
6699 | const bool loop_body_deletable_ ; | |
6700 | }; | |
6701 | #endif | |
6702 | ||
6703 | template <typename T> | |
6704 | class switch_node : public expression_node<T> | |
6705 | { | |
6706 | public: | |
6707 | ||
6708 | typedef expression_node<T>* expression_ptr; | |
6709 | ||
6710 | template <typename Allocator, | |
6711 | template <typename, typename> class Sequence> | |
6712 | explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) | |
6713 | { | |
6714 | if (1 != (arg_list.size() & 1)) | |
6715 | return; | |
6716 | ||
6717 | arg_list_.resize(arg_list.size()); | |
6718 | delete_branch_.resize(arg_list.size()); | |
6719 | ||
6720 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
6721 | { | |
6722 | if (arg_list[i]) | |
6723 | { | |
6724 | arg_list_[i] = arg_list[i]; | |
6725 | delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); | |
6726 | } | |
6727 | else | |
6728 | { | |
6729 | arg_list_.clear(); | |
6730 | delete_branch_.clear(); | |
6731 | return; | |
6732 | } | |
6733 | } | |
6734 | } | |
6735 | ||
6736 | ~switch_node() | |
6737 | { | |
6738 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
6739 | { | |
6740 | if (arg_list_[i] && delete_branch_[i]) | |
6741 | { | |
6742 | destroy_node(arg_list_[i]); | |
6743 | } | |
6744 | } | |
6745 | } | |
6746 | ||
6747 | inline T value() const | |
6748 | { | |
6749 | if (!arg_list_.empty()) | |
6750 | { | |
6751 | const std::size_t upper_bound = (arg_list_.size() - 1); | |
6752 | ||
6753 | for (std::size_t i = 0; i < upper_bound; i += 2) | |
6754 | { | |
6755 | expression_ptr condition = arg_list_[i ]; | |
6756 | expression_ptr consequent = arg_list_[i + 1]; | |
6757 | ||
6758 | if (is_true(condition)) | |
6759 | { | |
6760 | return consequent->value(); | |
6761 | } | |
6762 | } | |
6763 | ||
6764 | return arg_list_[upper_bound]->value(); | |
6765 | } | |
6766 | else | |
6767 | return std::numeric_limits<T>::quiet_NaN(); | |
6768 | } | |
6769 | ||
6770 | inline typename expression_node<T>::node_type type() const | |
6771 | { | |
6772 | return expression_node<T>::e_switch; | |
6773 | } | |
6774 | ||
6775 | protected: | |
6776 | ||
6777 | std::vector<expression_ptr> arg_list_; | |
6778 | std::vector<unsigned char> delete_branch_; | |
6779 | }; | |
6780 | ||
6781 | template <typename T, typename Switch_N> | |
6782 | class switch_n_node : public switch_node<T> | |
6783 | { | |
6784 | public: | |
6785 | ||
6786 | typedef expression_node<T>* expression_ptr; | |
6787 | ||
6788 | template <typename Allocator, | |
6789 | template <typename, typename> class Sequence> | |
6790 | explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) | |
6791 | : switch_node<T>(arg_list) | |
6792 | {} | |
6793 | ||
6794 | inline T value() const | |
6795 | { | |
6796 | return Switch_N::process(switch_node<T>::arg_list_); | |
6797 | } | |
6798 | }; | |
6799 | ||
6800 | template <typename T> | |
6801 | class multi_switch_node : public expression_node<T> | |
6802 | { | |
6803 | public: | |
6804 | ||
6805 | typedef expression_node<T>* expression_ptr; | |
6806 | ||
6807 | template <typename Allocator, | |
6808 | template <typename, typename> class Sequence> | |
6809 | explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) | |
6810 | { | |
6811 | if (0 != (arg_list.size() & 1)) | |
6812 | return; | |
6813 | ||
6814 | arg_list_.resize(arg_list.size()); | |
6815 | delete_branch_.resize(arg_list.size()); | |
6816 | ||
6817 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
6818 | { | |
6819 | if (arg_list[i]) | |
6820 | { | |
6821 | arg_list_[i] = arg_list[i]; | |
6822 | delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); | |
6823 | } | |
6824 | else | |
6825 | { | |
6826 | arg_list_.clear(); | |
6827 | delete_branch_.clear(); | |
6828 | return; | |
6829 | } | |
6830 | } | |
6831 | } | |
6832 | ||
6833 | ~multi_switch_node() | |
6834 | { | |
6835 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
6836 | { | |
6837 | if (arg_list_[i] && delete_branch_[i]) | |
6838 | { | |
6839 | destroy_node(arg_list_[i]); | |
6840 | } | |
6841 | } | |
6842 | } | |
6843 | ||
6844 | inline T value() const | |
6845 | { | |
6846 | T result = T(0); | |
6847 | ||
6848 | if (arg_list_.empty()) | |
6849 | { | |
6850 | return std::numeric_limits<T>::quiet_NaN(); | |
6851 | } | |
6852 | ||
6853 | const std::size_t upper_bound = (arg_list_.size() - 1); | |
6854 | ||
6855 | for (std::size_t i = 0; i < upper_bound; i += 2) | |
6856 | { | |
6857 | expression_ptr condition = arg_list_[i ]; | |
6858 | expression_ptr consequent = arg_list_[i + 1]; | |
6859 | ||
6860 | if (is_true(condition)) | |
6861 | { | |
6862 | result = consequent->value(); | |
6863 | } | |
6864 | } | |
6865 | ||
6866 | return result; | |
6867 | } | |
6868 | ||
6869 | inline typename expression_node<T>::node_type type() const | |
6870 | { | |
6871 | return expression_node<T>::e_mswitch; | |
6872 | } | |
6873 | ||
6874 | private: | |
6875 | ||
6876 | std::vector<expression_ptr> arg_list_; | |
6877 | std::vector<unsigned char> delete_branch_; | |
6878 | }; | |
6879 | ||
6880 | template <typename T> | |
6881 | class ivariable | |
6882 | { | |
6883 | public: | |
6884 | ||
6885 | virtual ~ivariable() | |
6886 | {} | |
6887 | ||
6888 | virtual T& ref() = 0; | |
6889 | virtual const T& ref() const = 0; | |
6890 | }; | |
6891 | ||
6892 | template <typename T> | |
6893 | class variable_node : public expression_node<T>, | |
6894 | public ivariable <T> | |
6895 | { | |
6896 | public: | |
6897 | ||
6898 | static T null_value; | |
6899 | ||
6900 | explicit variable_node() | |
6901 | : value_(&null_value) | |
6902 | {} | |
6903 | ||
6904 | explicit variable_node(T& v) | |
6905 | : value_(&v) | |
6906 | {} | |
6907 | ||
6908 | inline bool operator <(const variable_node<T>& v) const | |
6909 | { | |
6910 | return this < (&v); | |
6911 | } | |
6912 | ||
6913 | inline T value() const | |
6914 | { | |
6915 | return (*value_); | |
6916 | } | |
6917 | ||
6918 | inline T& ref() | |
6919 | { | |
6920 | return (*value_); | |
6921 | } | |
6922 | ||
6923 | inline const T& ref() const | |
6924 | { | |
6925 | return (*value_); | |
6926 | } | |
6927 | ||
6928 | inline typename expression_node<T>::node_type type() const | |
6929 | { | |
6930 | return expression_node<T>::e_variable; | |
6931 | } | |
6932 | ||
6933 | private: | |
6934 | ||
6935 | T* value_; | |
6936 | }; | |
6937 | ||
6938 | template <typename T> | |
6939 | T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN()); | |
6940 | ||
6941 | template <typename T> | |
6942 | struct range_pack | |
6943 | { | |
6944 | typedef expression_node<T>* expression_node_ptr; | |
6945 | typedef std::pair<std::size_t,std::size_t> cached_range_t; | |
6946 | ||
6947 | range_pack() | |
6948 | : n0_e (std::make_pair(false,expression_node_ptr(0))), | |
6949 | n1_e (std::make_pair(false,expression_node_ptr(0))), | |
6950 | n0_c (std::make_pair(false,0)), | |
6951 | n1_c (std::make_pair(false,0)), | |
6952 | cache(std::make_pair(0,0)) | |
6953 | {} | |
6954 | ||
6955 | void clear() | |
6956 | { | |
6957 | n0_e = std::make_pair(false,expression_node_ptr(0)); | |
6958 | n1_e = std::make_pair(false,expression_node_ptr(0)); | |
6959 | n0_c = std::make_pair(false,0); | |
6960 | n1_c = std::make_pair(false,0); | |
6961 | cache = std::make_pair(0,0); | |
6962 | } | |
6963 | ||
6964 | void free() | |
6965 | { | |
6966 | if (n0_e.first && n0_e.second) | |
6967 | { | |
6968 | n0_e.first = false; | |
6969 | ||
6970 | if ( | |
6971 | !is_variable_node(n0_e.second) && | |
6972 | !is_string_node (n0_e.second) | |
6973 | ) | |
6974 | { | |
6975 | destroy_node(n0_e.second); | |
6976 | } | |
6977 | } | |
6978 | ||
6979 | if (n1_e.first && n1_e.second) | |
6980 | { | |
6981 | n1_e.first = false; | |
6982 | ||
6983 | if ( | |
6984 | !is_variable_node(n1_e.second) && | |
6985 | !is_string_node (n1_e.second) | |
6986 | ) | |
6987 | { | |
6988 | destroy_node(n1_e.second); | |
6989 | } | |
6990 | } | |
6991 | } | |
6992 | ||
6993 | bool const_range() | |
6994 | { | |
6995 | return ( n0_c.first && n1_c.first) && | |
6996 | (!n0_e.first && !n1_e.first); | |
6997 | } | |
6998 | ||
6999 | bool var_range() | |
7000 | { | |
7001 | return ( n0_e.first && n1_e.first) && | |
7002 | (!n0_c.first && !n1_c.first); | |
7003 | } | |
7004 | ||
7005 | bool operator() (std::size_t& r0, std::size_t& r1, | |
7006 | const std::size_t& size = std::numeric_limits<std::size_t>::max()) const | |
7007 | { | |
7008 | if (n0_c.first) | |
7009 | r0 = n0_c.second; | |
7010 | else if (n0_e.first) | |
7011 | { | |
7012 | const T r0_value = n0_e.second->value(); | |
7013 | ||
7014 | if (r0_value < 0) | |
7015 | return false; | |
7016 | else | |
7017 | r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); | |
7018 | } | |
7019 | else | |
7020 | return false; | |
7021 | ||
7022 | if (n1_c.first) | |
7023 | r1 = n1_c.second; | |
7024 | else if (n1_e.first) | |
7025 | { | |
7026 | const T r1_value = n1_e.second->value(); | |
7027 | ||
7028 | if (r1_value < 0) | |
7029 | return false; | |
7030 | else | |
7031 | r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); | |
7032 | } | |
7033 | else | |
7034 | return false; | |
7035 | ||
7036 | if ( | |
7037 | (std::numeric_limits<std::size_t>::max() != size) && | |
7038 | (std::numeric_limits<std::size_t>::max() == r1 ) | |
7039 | ) | |
7040 | { | |
7041 | r1 = size - 1; | |
7042 | } | |
7043 | ||
7044 | cache.first = r0; | |
7045 | cache.second = r1; | |
7046 | ||
7047 | return (r0 <= r1); | |
7048 | } | |
7049 | ||
7050 | inline std::size_t const_size() const | |
7051 | { | |
7052 | return (n1_c.second - n0_c.second + 1); | |
7053 | } | |
7054 | ||
7055 | inline std::size_t cache_size() const | |
7056 | { | |
7057 | return (cache.second - cache.first + 1); | |
7058 | } | |
7059 | ||
7060 | std::pair<bool,expression_node_ptr> n0_e; | |
7061 | std::pair<bool,expression_node_ptr> n1_e; | |
7062 | std::pair<bool,std::size_t > n0_c; | |
7063 | std::pair<bool,std::size_t > n1_c; | |
7064 | mutable cached_range_t cache; | |
7065 | }; | |
7066 | ||
7067 | template <typename T> | |
7068 | class string_base_node; | |
7069 | ||
7070 | template <typename T> | |
7071 | struct range_data_type | |
7072 | { | |
7073 | typedef range_pack<T> range_t; | |
7074 | typedef string_base_node<T>* strbase_ptr_t; | |
7075 | ||
7076 | range_data_type() | |
7077 | : range(0), | |
7078 | data (0), | |
7079 | size (0), | |
7080 | type_size(0), | |
7081 | str_node (0) | |
7082 | {} | |
7083 | ||
7084 | range_t* range; | |
7085 | void* data; | |
7086 | std::size_t size; | |
7087 | std::size_t type_size; | |
7088 | strbase_ptr_t str_node; | |
7089 | }; | |
7090 | ||
7091 | template <typename T> class vector_node; | |
7092 | ||
7093 | template <typename T> | |
7094 | class vector_interface | |
7095 | { | |
7096 | public: | |
7097 | ||
7098 | typedef vector_node<T>* vector_node_ptr; | |
7099 | typedef vec_data_store<T> vds_t; | |
7100 | ||
7101 | virtual ~vector_interface() | |
7102 | {} | |
7103 | ||
7104 | virtual std::size_t size () const = 0; | |
7105 | ||
7106 | virtual vector_node_ptr vec() const = 0; | |
7107 | ||
7108 | virtual vector_node_ptr vec() = 0; | |
7109 | ||
7110 | virtual vds_t& vds () = 0; | |
7111 | ||
7112 | virtual const vds_t& vds () const = 0; | |
7113 | ||
7114 | virtual bool side_effect () const { return false; } | |
7115 | }; | |
7116 | ||
7117 | template <typename T> | |
7118 | class vector_node : public expression_node <T>, | |
7119 | public vector_interface<T> | |
7120 | { | |
7121 | public: | |
7122 | ||
7123 | typedef expression_node<T>* expression_ptr; | |
7124 | typedef vector_holder<T> vector_holder_t; | |
7125 | typedef vector_node<T>* vector_node_ptr; | |
7126 | typedef vec_data_store<T> vds_t; | |
7127 | ||
7128 | explicit vector_node(vector_holder_t* vh) | |
7129 | : vector_holder_(vh), | |
7130 | vds_((*vector_holder_).size(),(*vector_holder_)[0]) | |
7131 | { | |
7132 | vector_holder_->set_ref(&vds_.ref()); | |
7133 | } | |
7134 | ||
7135 | vector_node(const vds_t& vds, vector_holder_t* vh) | |
7136 | : vector_holder_(vh), | |
7137 | vds_(vds) | |
7138 | {} | |
7139 | ||
7140 | inline T value() const | |
7141 | { | |
7142 | return vds().data()[0]; | |
7143 | } | |
7144 | ||
7145 | vector_node_ptr vec() const | |
7146 | { | |
7147 | return const_cast<vector_node_ptr>(this); | |
7148 | } | |
7149 | ||
7150 | vector_node_ptr vec() | |
7151 | { | |
7152 | return this; | |
7153 | } | |
7154 | ||
7155 | inline typename expression_node<T>::node_type type() const | |
7156 | { | |
7157 | return expression_node<T>::e_vector; | |
7158 | } | |
7159 | ||
7160 | std::size_t size() const | |
7161 | { | |
7162 | return vds().size(); | |
7163 | } | |
7164 | ||
7165 | vds_t& vds() | |
7166 | { | |
7167 | return vds_; | |
7168 | } | |
7169 | ||
7170 | const vds_t& vds() const | |
7171 | { | |
7172 | return vds_; | |
7173 | } | |
7174 | ||
7175 | inline vector_holder_t& vec_holder() | |
7176 | { | |
7177 | return (*vector_holder_); | |
7178 | } | |
7179 | ||
7180 | private: | |
7181 | ||
7182 | vector_holder_t* vector_holder_; | |
7183 | vds_t vds_; | |
7184 | }; | |
7185 | ||
7186 | template <typename T> | |
7187 | class vector_elem_node : public expression_node<T>, | |
7188 | public ivariable <T> | |
7189 | { | |
7190 | public: | |
7191 | ||
7192 | typedef expression_node<T>* expression_ptr; | |
7193 | typedef vector_holder<T> vector_holder_t; | |
7194 | typedef vector_holder_t* vector_holder_ptr; | |
7195 | ||
7196 | vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) | |
7197 | : index_(index), | |
7198 | vec_holder_(vec_holder), | |
7199 | vector_base_((*vec_holder)[0]), | |
7200 | index_deletable_(branch_deletable(index_)) | |
7201 | {} | |
7202 | ||
7203 | ~vector_elem_node() | |
7204 | { | |
7205 | if (index_ && index_deletable_) | |
7206 | { | |
7207 | destroy_node(index_); | |
7208 | } | |
7209 | } | |
7210 | ||
7211 | inline T value() const | |
7212 | { | |
7213 | return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7214 | } | |
7215 | ||
7216 | inline T& ref() | |
7217 | { | |
7218 | return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7219 | } | |
7220 | ||
7221 | inline const T& ref() const | |
7222 | { | |
7223 | return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7224 | } | |
7225 | ||
7226 | inline typename expression_node<T>::node_type type() const | |
7227 | { | |
7228 | return expression_node<T>::e_vecelem; | |
7229 | } | |
7230 | ||
7231 | inline vector_holder_t& vec_holder() | |
7232 | { | |
7233 | return (*vec_holder_); | |
7234 | } | |
7235 | ||
7236 | private: | |
7237 | ||
7238 | expression_ptr index_; | |
7239 | vector_holder_ptr vec_holder_; | |
7240 | T* vector_base_; | |
7241 | const bool index_deletable_; | |
7242 | }; | |
7243 | ||
7244 | template <typename T> | |
7245 | class rebasevector_elem_node : public expression_node<T>, | |
7246 | public ivariable <T> | |
7247 | { | |
7248 | public: | |
7249 | ||
7250 | typedef expression_node<T>* expression_ptr; | |
7251 | typedef vector_holder<T> vector_holder_t; | |
7252 | typedef vector_holder_t* vector_holder_ptr; | |
7253 | typedef vec_data_store<T> vds_t; | |
7254 | ||
7255 | rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) | |
7256 | : index_(index), | |
7257 | index_deletable_(branch_deletable(index_)), | |
7258 | vector_holder_(vec_holder), | |
7259 | vds_((*vector_holder_).size(),(*vector_holder_)[0]) | |
7260 | { | |
7261 | vector_holder_->set_ref(&vds_.ref()); | |
7262 | } | |
7263 | ||
7264 | ~rebasevector_elem_node() | |
7265 | { | |
7266 | if (index_ && index_deletable_) | |
7267 | { | |
7268 | destroy_node(index_); | |
7269 | } | |
7270 | } | |
7271 | ||
7272 | inline T value() const | |
7273 | { | |
7274 | return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7275 | } | |
7276 | ||
7277 | inline T& ref() | |
7278 | { | |
7279 | return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7280 | } | |
7281 | ||
7282 | inline const T& ref() const | |
7283 | { | |
7284 | return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); | |
7285 | } | |
7286 | ||
7287 | inline typename expression_node<T>::node_type type() const | |
7288 | { | |
7289 | return expression_node<T>::e_rbvecelem; | |
7290 | } | |
7291 | ||
7292 | inline vector_holder_t& vec_holder() | |
7293 | { | |
7294 | return (*vector_holder_); | |
7295 | } | |
7296 | ||
7297 | private: | |
7298 | ||
7299 | expression_ptr index_; | |
7300 | const bool index_deletable_; | |
7301 | vector_holder_ptr vector_holder_; | |
7302 | vds_t vds_; | |
7303 | }; | |
7304 | ||
7305 | template <typename T> | |
7306 | class rebasevector_celem_node : public expression_node<T>, | |
7307 | public ivariable <T> | |
7308 | { | |
7309 | public: | |
7310 | ||
7311 | typedef expression_node<T>* expression_ptr; | |
7312 | typedef vector_holder<T> vector_holder_t; | |
7313 | typedef vector_holder_t* vector_holder_ptr; | |
7314 | typedef vec_data_store<T> vds_t; | |
7315 | ||
7316 | rebasevector_celem_node(const std::size_t index, vector_holder_ptr vec_holder) | |
7317 | : index_(index), | |
7318 | vector_holder_(vec_holder), | |
7319 | vds_((*vector_holder_).size(),(*vector_holder_)[0]) | |
7320 | { | |
7321 | vector_holder_->set_ref(&vds_.ref()); | |
7322 | } | |
7323 | ||
7324 | inline T value() const | |
7325 | { | |
7326 | return *(vds_.data() + index_); | |
7327 | } | |
7328 | ||
7329 | inline T& ref() | |
7330 | { | |
7331 | return *(vds_.data() + index_); | |
7332 | } | |
7333 | ||
7334 | inline const T& ref() const | |
7335 | { | |
7336 | return *(vds_.data() + index_); | |
7337 | } | |
7338 | ||
7339 | inline typename expression_node<T>::node_type type() const | |
7340 | { | |
7341 | return expression_node<T>::e_rbveccelem; | |
7342 | } | |
7343 | ||
7344 | inline vector_holder_t& vec_holder() | |
7345 | { | |
7346 | return (*vector_holder_); | |
7347 | } | |
7348 | ||
7349 | private: | |
7350 | ||
7351 | const std::size_t index_; | |
7352 | vector_holder_ptr vector_holder_; | |
7353 | vds_t vds_; | |
7354 | }; | |
7355 | ||
7356 | template <typename T> | |
7357 | class vector_assignment_node : public expression_node<T> | |
7358 | { | |
7359 | public: | |
7360 | ||
7361 | typedef expression_node<T>* expression_ptr; | |
7362 | ||
7363 | vector_assignment_node(T* vector_base, | |
7364 | const std::size_t& size, | |
7365 | const std::vector<expression_ptr>& initialiser_list, | |
7366 | const bool single_value_initialse) | |
7367 | : vector_base_(vector_base), | |
7368 | initialiser_list_(initialiser_list), | |
7369 | size_(size), | |
7370 | single_value_initialse_(single_value_initialse) | |
7371 | {} | |
7372 | ||
7373 | ~vector_assignment_node() | |
7374 | { | |
7375 | for (std::size_t i = 0; i < initialiser_list_.size(); ++i) | |
7376 | { | |
7377 | if (branch_deletable(initialiser_list_[i])) | |
7378 | { | |
7379 | destroy_node(initialiser_list_[i]); | |
7380 | } | |
7381 | } | |
7382 | } | |
7383 | ||
7384 | inline T value() const | |
7385 | { | |
7386 | if (single_value_initialse_) | |
7387 | { | |
7388 | for (std::size_t i = 0; i < size_; ++i) | |
7389 | { | |
7390 | *(vector_base_ + i) = initialiser_list_[0]->value(); | |
7391 | } | |
7392 | } | |
7393 | else | |
7394 | { | |
7395 | std::size_t il_size = initialiser_list_.size(); | |
7396 | ||
7397 | for (std::size_t i = 0; i < il_size; ++i) | |
7398 | { | |
7399 | *(vector_base_ + i) = initialiser_list_[i]->value(); | |
7400 | } | |
7401 | ||
7402 | if (il_size < size_) | |
7403 | { | |
7404 | for (std::size_t i = il_size; i < size_; ++i) | |
7405 | { | |
7406 | *(vector_base_ + i) = T(0); | |
7407 | } | |
7408 | } | |
7409 | } | |
7410 | ||
7411 | return *(vector_base_); | |
7412 | } | |
7413 | ||
7414 | inline typename expression_node<T>::node_type type() const | |
7415 | { | |
7416 | return expression_node<T>::e_vecdefass; | |
7417 | } | |
7418 | ||
7419 | private: | |
7420 | ||
7421 | vector_assignment_node<T>& operator=(const vector_assignment_node<T>&); | |
7422 | ||
7423 | mutable T* vector_base_; | |
7424 | std::vector<expression_ptr> initialiser_list_; | |
7425 | const std::size_t size_; | |
7426 | const bool single_value_initialse_; | |
7427 | }; | |
7428 | ||
7429 | template <typename T> | |
7430 | class swap_node : public expression_node<T> | |
7431 | { | |
7432 | public: | |
7433 | ||
7434 | typedef expression_node<T>* expression_ptr; | |
7435 | typedef variable_node<T>* variable_node_ptr; | |
7436 | ||
7437 | swap_node(variable_node_ptr var0, variable_node_ptr var1) | |
7438 | : var0_(var0), | |
7439 | var1_(var1) | |
7440 | {} | |
7441 | ||
7442 | inline T value() const | |
7443 | { | |
7444 | std::swap(var0_->ref(),var1_->ref()); | |
7445 | return var1_->ref(); | |
7446 | } | |
7447 | ||
7448 | inline typename expression_node<T>::node_type type() const | |
7449 | { | |
7450 | return expression_node<T>::e_swap; | |
7451 | } | |
7452 | ||
7453 | private: | |
7454 | ||
7455 | variable_node_ptr var0_; | |
7456 | variable_node_ptr var1_; | |
7457 | }; | |
7458 | ||
7459 | template <typename T> | |
7460 | class swap_generic_node : public binary_node<T> | |
7461 | { | |
7462 | public: | |
7463 | ||
7464 | typedef expression_node<T>* expression_ptr; | |
7465 | typedef ivariable<T>* ivariable_ptr; | |
7466 | ||
7467 | swap_generic_node(expression_ptr var0, expression_ptr var1) | |
7468 | : binary_node<T>(details::e_swap, var0, var1), | |
7469 | var0_(dynamic_cast<ivariable_ptr>(var0)), | |
7470 | var1_(dynamic_cast<ivariable_ptr>(var1)) | |
7471 | {} | |
7472 | ||
7473 | inline T value() const | |
7474 | { | |
7475 | std::swap(var0_->ref(),var1_->ref()); | |
7476 | return var1_->ref(); | |
7477 | } | |
7478 | ||
7479 | inline typename expression_node<T>::node_type type() const | |
7480 | { | |
7481 | return expression_node<T>::e_swap; | |
7482 | } | |
7483 | ||
7484 | private: | |
7485 | ||
7486 | ivariable_ptr var0_; | |
7487 | ivariable_ptr var1_; | |
7488 | }; | |
7489 | ||
7490 | template <typename T> | |
7491 | class swap_vecvec_node : public binary_node <T>, | |
7492 | public vector_interface<T> | |
7493 | { | |
7494 | public: | |
7495 | ||
7496 | typedef expression_node<T>* expression_ptr; | |
7497 | typedef vector_node<T>* vector_node_ptr; | |
7498 | typedef vec_data_store<T> vds_t; | |
7499 | ||
7500 | swap_vecvec_node(expression_ptr branch0, | |
7501 | expression_ptr branch1) | |
7502 | : binary_node<T>(details::e_swap, branch0, branch1), | |
7503 | vec0_node_ptr_(0), | |
7504 | vec1_node_ptr_(0), | |
7505 | vec_size_ (0), | |
7506 | initialised_ (false) | |
7507 | { | |
7508 | if (is_ivector_node(binary_node<T>::branch_[0].first)) | |
7509 | { | |
7510 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
7511 | ||
7512 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) | |
7513 | { | |
7514 | vec0_node_ptr_ = vi->vec(); | |
7515 | vds() = vi->vds(); | |
7516 | } | |
7517 | } | |
7518 | ||
7519 | if (is_ivector_node(binary_node<T>::branch_[1].first)) | |
7520 | { | |
7521 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
7522 | ||
7523 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) | |
7524 | { | |
7525 | vec1_node_ptr_ = vi->vec(); | |
7526 | } | |
7527 | } | |
7528 | ||
7529 | if (vec0_node_ptr_ && vec1_node_ptr_) | |
7530 | { | |
7531 | vec_size_ = std::min(vec0_node_ptr_->vds().size(), | |
7532 | vec1_node_ptr_->vds().size()); | |
7533 | ||
7534 | initialised_ = true; | |
7535 | } | |
7536 | } | |
7537 | ||
7538 | inline T value() const | |
7539 | { | |
7540 | if (initialised_) | |
7541 | { | |
7542 | binary_node<T>::branch_[0].first->value(); | |
7543 | binary_node<T>::branch_[1].first->value(); | |
7544 | ||
7545 | T* vec0 = vec0_node_ptr_->vds().data(); | |
7546 | T* vec1 = vec1_node_ptr_->vds().data(); | |
7547 | ||
7548 | for (std::size_t i = 0; i < vec_size_; ++i) | |
7549 | { | |
7550 | std::swap(vec0[i],vec1[i]); | |
7551 | } | |
7552 | ||
7553 | return vec1_node_ptr_->value(); | |
7554 | } | |
7555 | else | |
7556 | return std::numeric_limits<T>::quiet_NaN(); | |
7557 | } | |
7558 | ||
7559 | vector_node_ptr vec() const | |
7560 | { | |
7561 | return vec0_node_ptr_; | |
7562 | } | |
7563 | ||
7564 | vector_node_ptr vec() | |
7565 | { | |
7566 | return vec0_node_ptr_; | |
7567 | } | |
7568 | ||
7569 | inline typename expression_node<T>::node_type type() const | |
7570 | { | |
7571 | return expression_node<T>::e_vecvecswap; | |
7572 | } | |
7573 | ||
7574 | std::size_t size() const | |
7575 | { | |
7576 | return vec_size_; | |
7577 | } | |
7578 | ||
7579 | vds_t& vds() | |
7580 | { | |
7581 | return vds_; | |
7582 | } | |
7583 | ||
7584 | const vds_t& vds() const | |
7585 | { | |
7586 | return vds_; | |
7587 | } | |
7588 | ||
7589 | private: | |
7590 | ||
7591 | vector_node<T>* vec0_node_ptr_; | |
7592 | vector_node<T>* vec1_node_ptr_; | |
7593 | std::size_t vec_size_; | |
7594 | bool initialised_; | |
7595 | vds_t vds_; | |
7596 | }; | |
7597 | ||
7598 | #ifndef exprtk_disable_string_capabilities | |
7599 | template <typename T> | |
7600 | class stringvar_node : public expression_node <T>, | |
7601 | public string_base_node<T>, | |
7602 | public range_interface <T> | |
7603 | { | |
7604 | public: | |
7605 | ||
7606 | typedef range_pack<T> range_t; | |
7607 | ||
7608 | static std::string null_value; | |
7609 | ||
7610 | explicit stringvar_node() | |
7611 | : value_(&null_value) | |
7612 | {} | |
7613 | ||
7614 | explicit stringvar_node(std::string& v) | |
7615 | : value_(&v) | |
7616 | { | |
7617 | rp_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
7618 | rp_.n1_c = std::make_pair<bool,std::size_t>(true,v.size() - 1); | |
7619 | rp_.cache.first = rp_.n0_c.second; | |
7620 | rp_.cache.second = rp_.n1_c.second; | |
7621 | } | |
7622 | ||
7623 | inline bool operator <(const stringvar_node<T>& v) const | |
7624 | { | |
7625 | return this < (&v); | |
7626 | } | |
7627 | ||
7628 | inline T value() const | |
7629 | { | |
7630 | rp_.n1_c.second = (*value_).size() - 1; | |
7631 | rp_.cache.second = rp_.n1_c.second; | |
7632 | ||
7633 | return std::numeric_limits<T>::quiet_NaN(); | |
7634 | } | |
7635 | ||
7636 | std::string str() const | |
7637 | { | |
7638 | return ref(); | |
7639 | } | |
7640 | ||
7641 | char_cptr base() const | |
7642 | { | |
7643 | return &(*value_)[0]; | |
7644 | } | |
7645 | ||
7646 | std::size_t size() const | |
7647 | { | |
7648 | return ref().size(); | |
7649 | } | |
7650 | ||
7651 | std::string& ref() | |
7652 | { | |
7653 | return (*value_); | |
7654 | } | |
7655 | ||
7656 | const std::string& ref() const | |
7657 | { | |
7658 | return (*value_); | |
7659 | } | |
7660 | ||
7661 | range_t& range_ref() | |
7662 | { | |
7663 | return rp_; | |
7664 | } | |
7665 | ||
7666 | const range_t& range_ref() const | |
7667 | { | |
7668 | return rp_; | |
7669 | } | |
7670 | ||
7671 | inline typename expression_node<T>::node_type type() const | |
7672 | { | |
7673 | return expression_node<T>::e_stringvar; | |
7674 | } | |
7675 | ||
7676 | private: | |
7677 | ||
7678 | std::string* value_; | |
7679 | mutable range_t rp_; | |
7680 | }; | |
7681 | ||
7682 | template <typename T> | |
7683 | std::string stringvar_node<T>::null_value = std::string(""); | |
7684 | ||
7685 | template <typename T> | |
7686 | class string_range_node : public expression_node <T>, | |
7687 | public string_base_node<T>, | |
7688 | public range_interface <T> | |
7689 | { | |
7690 | public: | |
7691 | ||
7692 | typedef range_pack<T> range_t; | |
7693 | ||
7694 | static std::string null_value; | |
7695 | ||
7696 | explicit string_range_node(std::string& v, const range_t& rp) | |
7697 | : value_(&v), | |
7698 | rp_(rp) | |
7699 | {} | |
7700 | ||
7701 | virtual ~string_range_node() | |
7702 | { | |
7703 | rp_.free(); | |
7704 | } | |
7705 | ||
7706 | inline bool operator <(const string_range_node<T>& v) const | |
7707 | { | |
7708 | return this < (&v); | |
7709 | } | |
7710 | ||
7711 | inline T value() const | |
7712 | { | |
7713 | return std::numeric_limits<T>::quiet_NaN(); | |
7714 | } | |
7715 | ||
7716 | inline std::string str() const | |
7717 | { | |
7718 | return (*value_); | |
7719 | } | |
7720 | ||
7721 | char_cptr base() const | |
7722 | { | |
7723 | return &(*value_)[0]; | |
7724 | } | |
7725 | ||
7726 | std::size_t size() const | |
7727 | { | |
7728 | return ref().size(); | |
7729 | } | |
7730 | ||
7731 | inline range_t range() const | |
7732 | { | |
7733 | return rp_; | |
7734 | } | |
7735 | ||
7736 | inline virtual std::string& ref() | |
7737 | { | |
7738 | return (*value_); | |
7739 | } | |
7740 | ||
7741 | inline virtual const std::string& ref() const | |
7742 | { | |
7743 | return (*value_); | |
7744 | } | |
7745 | ||
7746 | inline range_t& range_ref() | |
7747 | { | |
7748 | return rp_; | |
7749 | } | |
7750 | ||
7751 | inline const range_t& range_ref() const | |
7752 | { | |
7753 | return rp_; | |
7754 | } | |
7755 | ||
7756 | inline typename expression_node<T>::node_type type() const | |
7757 | { | |
7758 | return expression_node<T>::e_stringvarrng; | |
7759 | } | |
7760 | ||
7761 | private: | |
7762 | ||
7763 | std::string* value_; | |
7764 | range_t rp_; | |
7765 | }; | |
7766 | ||
7767 | template <typename T> | |
7768 | std::string string_range_node<T>::null_value = std::string(""); | |
7769 | ||
7770 | template <typename T> | |
7771 | class const_string_range_node : public expression_node <T>, | |
7772 | public string_base_node<T>, | |
7773 | public range_interface <T> | |
7774 | { | |
7775 | public: | |
7776 | ||
7777 | typedef range_pack<T> range_t; | |
7778 | ||
7779 | explicit const_string_range_node(const std::string& v, const range_t& rp) | |
7780 | : value_(v), | |
7781 | rp_(rp) | |
7782 | {} | |
7783 | ||
7784 | ~const_string_range_node() | |
7785 | { | |
7786 | rp_.free(); | |
7787 | } | |
7788 | ||
7789 | inline T value() const | |
7790 | { | |
7791 | return std::numeric_limits<T>::quiet_NaN(); | |
7792 | } | |
7793 | ||
7794 | std::string str() const | |
7795 | { | |
7796 | return value_; | |
7797 | } | |
7798 | ||
7799 | char_cptr base() const | |
7800 | { | |
7801 | return value_.data(); | |
7802 | } | |
7803 | ||
7804 | std::size_t size() const | |
7805 | { | |
7806 | return value_.size(); | |
7807 | } | |
7808 | ||
7809 | range_t range() const | |
7810 | { | |
7811 | return rp_; | |
7812 | } | |
7813 | ||
7814 | range_t& range_ref() | |
7815 | { | |
7816 | return rp_; | |
7817 | } | |
7818 | ||
7819 | const range_t& range_ref() const | |
7820 | { | |
7821 | return rp_; | |
7822 | } | |
7823 | ||
7824 | inline typename expression_node<T>::node_type type() const | |
7825 | { | |
7826 | return expression_node<T>::e_cstringvarrng; | |
7827 | } | |
7828 | ||
7829 | private: | |
7830 | ||
7831 | const_string_range_node<T>& operator=(const const_string_range_node<T>&); | |
7832 | ||
7833 | const std::string value_; | |
7834 | range_t rp_; | |
7835 | }; | |
7836 | ||
7837 | template <typename T> | |
7838 | class generic_string_range_node : public expression_node <T>, | |
7839 | public string_base_node<T>, | |
7840 | public range_interface <T> | |
7841 | { | |
7842 | public: | |
7843 | ||
7844 | typedef expression_node <T>* expression_ptr; | |
7845 | typedef stringvar_node <T>* strvar_node_ptr; | |
7846 | typedef string_base_node<T>* str_base_ptr; | |
7847 | typedef range_pack <T> range_t; | |
7848 | typedef range_t* range_ptr; | |
7849 | typedef range_interface<T> irange_t; | |
7850 | typedef irange_t* irange_ptr; | |
7851 | ||
7852 | generic_string_range_node(expression_ptr str_branch, const range_t& brange) | |
7853 | : initialised_(false), | |
7854 | branch_(str_branch), | |
7855 | branch_deletable_(branch_deletable(branch_)), | |
7856 | str_base_ptr_ (0), | |
7857 | str_range_ptr_(0), | |
7858 | base_range_(brange) | |
7859 | { | |
7860 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
7861 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); | |
7862 | range_.cache.first = range_.n0_c.second; | |
7863 | range_.cache.second = range_.n1_c.second; | |
7864 | ||
7865 | if (is_generally_string_node(branch_)) | |
7866 | { | |
7867 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); | |
7868 | ||
7869 | if (0 == str_base_ptr_) | |
7870 | return; | |
7871 | ||
7872 | str_range_ptr_ = dynamic_cast<irange_ptr>(branch_); | |
7873 | ||
7874 | if (0 == str_range_ptr_) | |
7875 | return; | |
7876 | } | |
7877 | ||
7878 | initialised_ = (str_base_ptr_ && str_range_ptr_); | |
7879 | } | |
7880 | ||
7881 | ~generic_string_range_node() | |
7882 | { | |
7883 | base_range_.free(); | |
7884 | ||
7885 | if (branch_ && branch_deletable_) | |
7886 | { | |
7887 | destroy_node(branch_); | |
7888 | } | |
7889 | } | |
7890 | ||
7891 | inline T value() const | |
7892 | { | |
7893 | if (initialised_) | |
7894 | { | |
7895 | branch_->value(); | |
7896 | ||
7897 | std::size_t str_r0 = 0; | |
7898 | std::size_t str_r1 = 0; | |
7899 | ||
7900 | std::size_t r0 = 0; | |
7901 | std::size_t r1 = 0; | |
7902 | ||
7903 | range_t& range = str_range_ptr_->range_ref(); | |
7904 | ||
7905 | const std::size_t base_str_size = str_base_ptr_->size(); | |
7906 | ||
7907 | if ( | |
7908 | range (str_r0, str_r1, base_str_size) && | |
7909 | base_range_( r0, r1, base_str_size) | |
7910 | ) | |
7911 | { | |
7912 | const std::size_t size = (r1 - r0) + 1; | |
7913 | ||
7914 | range_.n1_c.second = size - 1; | |
7915 | range_.cache.second = range_.n1_c.second; | |
7916 | ||
7917 | value_.assign(str_base_ptr_->base() + str_r0 + r0, size); | |
7918 | } | |
7919 | } | |
7920 | ||
7921 | return std::numeric_limits<T>::quiet_NaN(); | |
7922 | } | |
7923 | ||
7924 | std::string str() const | |
7925 | { | |
7926 | return value_; | |
7927 | } | |
7928 | ||
7929 | char_cptr base() const | |
7930 | { | |
7931 | return &value_[0]; | |
7932 | } | |
7933 | ||
7934 | std::size_t size() const | |
7935 | { | |
7936 | return value_.size(); | |
7937 | } | |
7938 | ||
7939 | range_t& range_ref() | |
7940 | { | |
7941 | return range_; | |
7942 | } | |
7943 | ||
7944 | const range_t& range_ref() const | |
7945 | { | |
7946 | return range_; | |
7947 | } | |
7948 | ||
7949 | inline typename expression_node<T>::node_type type() const | |
7950 | { | |
7951 | return expression_node<T>::e_strgenrange; | |
7952 | } | |
7953 | ||
7954 | private: | |
7955 | ||
7956 | bool initialised_; | |
7957 | expression_ptr branch_; | |
7958 | const bool branch_deletable_; | |
7959 | str_base_ptr str_base_ptr_; | |
7960 | irange_ptr str_range_ptr_; | |
7961 | mutable range_t base_range_; | |
7962 | mutable range_t range_; | |
7963 | mutable std::string value_; | |
7964 | }; | |
7965 | ||
7966 | template <typename T> | |
7967 | class string_concat_node : public binary_node <T>, | |
7968 | public string_base_node<T>, | |
7969 | public range_interface <T> | |
7970 | { | |
7971 | public: | |
7972 | ||
7973 | typedef expression_node <T>* expression_ptr; | |
7974 | typedef string_base_node<T>* str_base_ptr; | |
7975 | typedef range_pack <T> range_t; | |
7976 | typedef range_t* range_ptr; | |
7977 | typedef range_interface<T> irange_t; | |
7978 | typedef irange_t* irange_ptr; | |
7979 | ||
7980 | string_concat_node(const operator_type& opr, | |
7981 | expression_ptr branch0, | |
7982 | expression_ptr branch1) | |
7983 | : binary_node<T>(opr, branch0, branch1), | |
7984 | initialised_(false), | |
7985 | str0_base_ptr_ (0), | |
7986 | str1_base_ptr_ (0), | |
7987 | str0_range_ptr_(0), | |
7988 | str1_range_ptr_(0) | |
7989 | { | |
7990 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
7991 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); | |
7992 | ||
7993 | range_.cache.first = range_.n0_c.second; | |
7994 | range_.cache.second = range_.n1_c.second; | |
7995 | ||
7996 | if (is_generally_string_node(binary_node<T>::branch_[0].first)) | |
7997 | { | |
7998 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
7999 | ||
8000 | if (0 == str0_base_ptr_) | |
8001 | return; | |
8002 | ||
8003 | str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first); | |
8004 | ||
8005 | if (0 == str0_range_ptr_) | |
8006 | return; | |
8007 | } | |
8008 | ||
8009 | if (is_generally_string_node(binary_node<T>::branch_[1].first)) | |
8010 | { | |
8011 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first); | |
8012 | ||
8013 | if (0 == str1_base_ptr_) | |
8014 | return; | |
8015 | ||
8016 | str1_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first); | |
8017 | ||
8018 | if (0 == str1_range_ptr_) | |
8019 | return; | |
8020 | } | |
8021 | ||
8022 | initialised_ = str0_base_ptr_ && | |
8023 | str1_base_ptr_ && | |
8024 | str0_range_ptr_ && | |
8025 | str1_range_ptr_ ; | |
8026 | } | |
8027 | ||
8028 | inline T value() const | |
8029 | { | |
8030 | if (initialised_) | |
8031 | { | |
8032 | binary_node<T>::branch_[0].first->value(); | |
8033 | binary_node<T>::branch_[1].first->value(); | |
8034 | ||
8035 | std::size_t str0_r0 = 0; | |
8036 | std::size_t str0_r1 = 0; | |
8037 | ||
8038 | std::size_t str1_r0 = 0; | |
8039 | std::size_t str1_r1 = 0; | |
8040 | ||
8041 | range_t& range0 = str0_range_ptr_->range_ref(); | |
8042 | range_t& range1 = str1_range_ptr_->range_ref(); | |
8043 | ||
8044 | if ( | |
8045 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && | |
8046 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) | |
8047 | ) | |
8048 | { | |
8049 | const std::size_t size0 = (str0_r1 - str0_r0) + 1; | |
8050 | const std::size_t size1 = (str1_r1 - str1_r0) + 1; | |
8051 | ||
8052 | value_.assign(str0_base_ptr_->base() + str0_r0, size0); | |
8053 | value_.append(str1_base_ptr_->base() + str1_r0, size1); | |
8054 | ||
8055 | range_.n1_c.second = value_.size() - 1; | |
8056 | range_.cache.second = range_.n1_c.second; | |
8057 | } | |
8058 | } | |
8059 | ||
8060 | return std::numeric_limits<T>::quiet_NaN(); | |
8061 | } | |
8062 | ||
8063 | std::string str() const | |
8064 | { | |
8065 | return value_; | |
8066 | } | |
8067 | ||
8068 | char_cptr base() const | |
8069 | { | |
8070 | return &value_[0]; | |
8071 | } | |
8072 | ||
8073 | std::size_t size() const | |
8074 | { | |
8075 | return value_.size(); | |
8076 | } | |
8077 | ||
8078 | range_t& range_ref() | |
8079 | { | |
8080 | return range_; | |
8081 | } | |
8082 | ||
8083 | const range_t& range_ref() const | |
8084 | { | |
8085 | return range_; | |
8086 | } | |
8087 | ||
8088 | inline typename expression_node<T>::node_type type() const | |
8089 | { | |
8090 | return expression_node<T>::e_strconcat; | |
8091 | } | |
8092 | ||
8093 | private: | |
8094 | ||
8095 | bool initialised_; | |
8096 | str_base_ptr str0_base_ptr_; | |
8097 | str_base_ptr str1_base_ptr_; | |
8098 | irange_ptr str0_range_ptr_; | |
8099 | irange_ptr str1_range_ptr_; | |
8100 | mutable range_t range_; | |
8101 | mutable std::string value_; | |
8102 | }; | |
8103 | ||
8104 | template <typename T> | |
8105 | class swap_string_node : public binary_node <T>, | |
8106 | public string_base_node<T>, | |
8107 | public range_interface <T> | |
8108 | { | |
8109 | public: | |
8110 | ||
8111 | typedef expression_node <T>* expression_ptr; | |
8112 | typedef stringvar_node <T>* strvar_node_ptr; | |
8113 | typedef string_base_node<T>* str_base_ptr; | |
8114 | typedef range_pack <T> range_t; | |
8115 | typedef range_t* range_ptr; | |
8116 | typedef range_interface<T> irange_t; | |
8117 | typedef irange_t* irange_ptr; | |
8118 | ||
8119 | swap_string_node(expression_ptr branch0, expression_ptr branch1) | |
8120 | : binary_node<T>(details::e_swap, branch0, branch1), | |
8121 | initialised_(false), | |
8122 | str0_node_ptr_(0), | |
8123 | str1_node_ptr_(0) | |
8124 | { | |
8125 | if (is_string_node(binary_node<T>::branch_[0].first)) | |
8126 | { | |
8127 | str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first); | |
8128 | } | |
8129 | ||
8130 | if (is_string_node(binary_node<T>::branch_[1].first)) | |
8131 | { | |
8132 | str1_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[1].first); | |
8133 | } | |
8134 | ||
8135 | initialised_ = (str0_node_ptr_ && str1_node_ptr_); | |
8136 | } | |
8137 | ||
8138 | inline T value() const | |
8139 | { | |
8140 | if (initialised_) | |
8141 | { | |
8142 | binary_node<T>::branch_[0].first->value(); | |
8143 | binary_node<T>::branch_[1].first->value(); | |
8144 | ||
8145 | std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); | |
8146 | } | |
8147 | ||
8148 | return std::numeric_limits<T>::quiet_NaN(); | |
8149 | } | |
8150 | ||
8151 | std::string str() const | |
8152 | { | |
8153 | return str0_node_ptr_->str(); | |
8154 | } | |
8155 | ||
8156 | char_cptr base() const | |
8157 | { | |
8158 | return str0_node_ptr_->base(); | |
8159 | } | |
8160 | ||
8161 | std::size_t size() const | |
8162 | { | |
8163 | return str0_node_ptr_->size(); | |
8164 | } | |
8165 | ||
8166 | range_t& range_ref() | |
8167 | { | |
8168 | return str0_node_ptr_->range_ref(); | |
8169 | } | |
8170 | ||
8171 | const range_t& range_ref() const | |
8172 | { | |
8173 | return str0_node_ptr_->range_ref(); | |
8174 | } | |
8175 | ||
8176 | inline typename expression_node<T>::node_type type() const | |
8177 | { | |
8178 | return expression_node<T>::e_strswap; | |
8179 | } | |
8180 | ||
8181 | private: | |
8182 | ||
8183 | bool initialised_; | |
8184 | strvar_node_ptr str0_node_ptr_; | |
8185 | strvar_node_ptr str1_node_ptr_; | |
8186 | }; | |
8187 | ||
8188 | template <typename T> | |
8189 | class swap_genstrings_node : public binary_node<T> | |
8190 | { | |
8191 | public: | |
8192 | ||
8193 | typedef expression_node <T>* expression_ptr; | |
8194 | typedef string_base_node<T>* str_base_ptr; | |
8195 | typedef range_pack <T> range_t; | |
8196 | typedef range_t* range_ptr; | |
8197 | typedef range_interface<T> irange_t; | |
8198 | typedef irange_t* irange_ptr; | |
8199 | ||
8200 | swap_genstrings_node(expression_ptr branch0, | |
8201 | expression_ptr branch1) | |
8202 | : binary_node<T>(details::e_default, branch0, branch1), | |
8203 | str0_base_ptr_ (0), | |
8204 | str1_base_ptr_ (0), | |
8205 | str0_range_ptr_(0), | |
8206 | str1_range_ptr_(0), | |
8207 | initialised_(false) | |
8208 | { | |
8209 | if (is_generally_string_node(binary_node<T>::branch_[0].first)) | |
8210 | { | |
8211 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
8212 | ||
8213 | if (0 == str0_base_ptr_) | |
8214 | return; | |
8215 | ||
8216 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first); | |
8217 | ||
8218 | if (0 == range) | |
8219 | return; | |
8220 | ||
8221 | str0_range_ptr_ = &(range->range_ref()); | |
8222 | } | |
8223 | ||
8224 | if (is_generally_string_node(binary_node<T>::branch_[1].first)) | |
8225 | { | |
8226 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first); | |
8227 | ||
8228 | if (0 == str1_base_ptr_) | |
8229 | return; | |
8230 | ||
8231 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first); | |
8232 | ||
8233 | if (0 == range) | |
8234 | return; | |
8235 | ||
8236 | str1_range_ptr_ = &(range->range_ref()); | |
8237 | } | |
8238 | ||
8239 | initialised_ = str0_base_ptr_ && | |
8240 | str1_base_ptr_ && | |
8241 | str0_range_ptr_ && | |
8242 | str1_range_ptr_ ; | |
8243 | } | |
8244 | ||
8245 | inline T value() const | |
8246 | { | |
8247 | if (initialised_) | |
8248 | { | |
8249 | binary_node<T>::branch_[0].first->value(); | |
8250 | binary_node<T>::branch_[1].first->value(); | |
8251 | ||
8252 | std::size_t str0_r0 = 0; | |
8253 | std::size_t str0_r1 = 0; | |
8254 | ||
8255 | std::size_t str1_r0 = 0; | |
8256 | std::size_t str1_r1 = 0; | |
8257 | ||
8258 | range_t& range0 = (*str0_range_ptr_); | |
8259 | range_t& range1 = (*str1_range_ptr_); | |
8260 | ||
8261 | if ( | |
8262 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && | |
8263 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) | |
8264 | ) | |
8265 | { | |
8266 | const std::size_t size0 = range0.cache_size(); | |
8267 | const std::size_t size1 = range1.cache_size(); | |
8268 | const std::size_t max_size = std::min(size0,size1); | |
8269 | ||
8270 | char_ptr s0 = const_cast<char_ptr>(str0_base_ptr_->base() + str0_r0); | |
8271 | char_ptr s1 = const_cast<char_ptr>(str1_base_ptr_->base() + str1_r0); | |
8272 | ||
8273 | loop_unroll::details lud(max_size); | |
8274 | char_cptr upper_bound = s0 + lud.upper_bound; | |
8275 | ||
8276 | while (s0 < upper_bound) | |
8277 | { | |
8278 | #define exprtk_loop(N) \ | |
8279 | std::swap(s0[N], s1[N]); \ | |
8280 | ||
8281 | exprtk_loop( 0) exprtk_loop( 1) | |
8282 | exprtk_loop( 2) exprtk_loop( 3) | |
8283 | #ifndef exprtk_disable_superscalar_unroll | |
8284 | exprtk_loop( 4) exprtk_loop( 5) | |
8285 | exprtk_loop( 6) exprtk_loop( 7) | |
8286 | exprtk_loop( 8) exprtk_loop( 9) | |
8287 | exprtk_loop(10) exprtk_loop(11) | |
8288 | exprtk_loop(12) exprtk_loop(13) | |
8289 | exprtk_loop(14) exprtk_loop(15) | |
8290 | #endif | |
8291 | ||
8292 | s0 += lud.batch_size; | |
8293 | s1 += lud.batch_size; | |
8294 | } | |
8295 | ||
8296 | int i = 0; | |
8297 | ||
8298 | exprtk_disable_fallthrough_begin | |
8299 | switch (lud.remainder) | |
8300 | { | |
8301 | #define case_stmt(N) \ | |
8302 | case N : { std::swap(s0[i], s1[i]); ++i; } \ | |
8303 | ||
8304 | #ifndef exprtk_disable_superscalar_unroll | |
8305 | case_stmt(15) case_stmt(14) | |
8306 | case_stmt(13) case_stmt(12) | |
8307 | case_stmt(11) case_stmt(10) | |
8308 | case_stmt( 9) case_stmt( 8) | |
8309 | case_stmt( 7) case_stmt( 6) | |
8310 | case_stmt( 5) case_stmt( 4) | |
8311 | #endif | |
8312 | case_stmt( 3) case_stmt( 2) | |
8313 | case_stmt( 1) | |
8314 | } | |
8315 | exprtk_disable_fallthrough_end | |
8316 | ||
8317 | #undef exprtk_loop | |
8318 | #undef case_stmt | |
8319 | } | |
8320 | } | |
8321 | ||
8322 | return std::numeric_limits<T>::quiet_NaN(); | |
8323 | } | |
8324 | ||
8325 | inline typename expression_node<T>::node_type type() const | |
8326 | { | |
8327 | return expression_node<T>::e_strswap; | |
8328 | } | |
8329 | ||
8330 | private: | |
8331 | ||
8332 | swap_genstrings_node(swap_genstrings_node<T>&); | |
8333 | swap_genstrings_node<T>& operator=(swap_genstrings_node<T>&); | |
8334 | ||
8335 | str_base_ptr str0_base_ptr_; | |
8336 | str_base_ptr str1_base_ptr_; | |
8337 | range_ptr str0_range_ptr_; | |
8338 | range_ptr str1_range_ptr_; | |
8339 | bool initialised_; | |
8340 | }; | |
8341 | ||
8342 | template <typename T> | |
8343 | class stringvar_size_node : public expression_node<T> | |
8344 | { | |
8345 | public: | |
8346 | ||
8347 | static std::string null_value; | |
8348 | ||
8349 | explicit stringvar_size_node() | |
8350 | : value_(&null_value) | |
8351 | {} | |
8352 | ||
8353 | explicit stringvar_size_node(std::string& v) | |
8354 | : value_(&v) | |
8355 | {} | |
8356 | ||
8357 | inline T value() const | |
8358 | { | |
8359 | return T((*value_).size()); | |
8360 | } | |
8361 | ||
8362 | inline typename expression_node<T>::node_type type() const | |
8363 | { | |
8364 | return expression_node<T>::e_stringvarsize; | |
8365 | } | |
8366 | ||
8367 | private: | |
8368 | ||
8369 | std::string* value_; | |
8370 | }; | |
8371 | ||
8372 | template <typename T> | |
8373 | std::string stringvar_size_node<T>::null_value = std::string(""); | |
8374 | ||
8375 | template <typename T> | |
8376 | class string_size_node : public expression_node<T> | |
8377 | { | |
8378 | public: | |
8379 | ||
8380 | typedef expression_node <T>* expression_ptr; | |
8381 | typedef string_base_node<T>* str_base_ptr; | |
8382 | ||
8383 | explicit string_size_node(expression_ptr brnch) | |
8384 | : branch_(brnch), | |
8385 | branch_deletable_(branch_deletable(branch_)), | |
8386 | str_base_ptr_(0) | |
8387 | { | |
8388 | if (is_generally_string_node(branch_)) | |
8389 | { | |
8390 | str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); | |
8391 | ||
8392 | if (0 == str_base_ptr_) | |
8393 | return; | |
8394 | } | |
8395 | } | |
8396 | ||
8397 | ~string_size_node() | |
8398 | { | |
8399 | if (branch_ && branch_deletable_) | |
8400 | { | |
8401 | destroy_node(branch_); | |
8402 | } | |
8403 | } | |
8404 | ||
8405 | inline T value() const | |
8406 | { | |
8407 | T result = std::numeric_limits<T>::quiet_NaN(); | |
8408 | ||
8409 | if (str_base_ptr_) | |
8410 | { | |
8411 | branch_->value(); | |
8412 | result = T(str_base_ptr_->size()); | |
8413 | } | |
8414 | ||
8415 | return result; | |
8416 | } | |
8417 | ||
8418 | inline typename expression_node<T>::node_type type() const | |
8419 | { | |
8420 | return expression_node<T>::e_stringsize; | |
8421 | } | |
8422 | ||
8423 | private: | |
8424 | ||
8425 | expression_ptr branch_; | |
8426 | const bool branch_deletable_; | |
8427 | str_base_ptr str_base_ptr_; | |
8428 | }; | |
8429 | ||
8430 | struct asn_assignment | |
8431 | { | |
8432 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) | |
8433 | { s.assign(data,size); } | |
8434 | }; | |
8435 | ||
8436 | struct asn_addassignment | |
8437 | { | |
8438 | static inline void execute(std::string& s, char_cptr data, const std::size_t size) | |
8439 | { s.append(data,size); } | |
8440 | }; | |
8441 | ||
8442 | template <typename T, typename AssignmentProcess = asn_assignment> | |
8443 | class assignment_string_node : public binary_node <T>, | |
8444 | public string_base_node<T>, | |
8445 | public range_interface <T> | |
8446 | { | |
8447 | public: | |
8448 | ||
8449 | typedef expression_node <T>* expression_ptr; | |
8450 | typedef stringvar_node <T>* strvar_node_ptr; | |
8451 | typedef string_base_node<T>* str_base_ptr; | |
8452 | typedef range_pack <T> range_t; | |
8453 | typedef range_t* range_ptr; | |
8454 | typedef range_interface<T> irange_t; | |
8455 | typedef irange_t* irange_ptr; | |
8456 | ||
8457 | assignment_string_node(const operator_type& opr, | |
8458 | expression_ptr branch0, | |
8459 | expression_ptr branch1) | |
8460 | : binary_node<T>(opr, branch0, branch1), | |
8461 | initialised_(false), | |
8462 | str0_base_ptr_ (0), | |
8463 | str1_base_ptr_ (0), | |
8464 | str0_node_ptr_ (0), | |
8465 | str1_range_ptr_(0) | |
8466 | { | |
8467 | if (is_string_node(binary_node<T>::branch_[0].first)) | |
8468 | { | |
8469 | str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first); | |
8470 | ||
8471 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
8472 | } | |
8473 | ||
8474 | if (is_generally_string_node(binary_node<T>::branch_[1].first)) | |
8475 | { | |
8476 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first); | |
8477 | ||
8478 | if (0 == str1_base_ptr_) | |
8479 | return; | |
8480 | ||
8481 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first); | |
8482 | ||
8483 | if (0 == range) | |
8484 | return; | |
8485 | ||
8486 | str1_range_ptr_ = &(range->range_ref()); | |
8487 | } | |
8488 | ||
8489 | initialised_ = str0_base_ptr_ && | |
8490 | str1_base_ptr_ && | |
8491 | str0_node_ptr_ && | |
8492 | str1_range_ptr_ ; | |
8493 | } | |
8494 | ||
8495 | inline T value() const | |
8496 | { | |
8497 | if (initialised_) | |
8498 | { | |
8499 | binary_node<T>::branch_[1].first->value(); | |
8500 | ||
8501 | std::size_t r0 = 0; | |
8502 | std::size_t r1 = 0; | |
8503 | ||
8504 | range_t& range = (*str1_range_ptr_); | |
8505 | ||
8506 | if (range(r0, r1, str1_base_ptr_->size())) | |
8507 | { | |
8508 | AssignmentProcess::execute(str0_node_ptr_->ref(), | |
8509 | str1_base_ptr_->base() + r0, | |
8510 | (r1 - r0) + 1); | |
8511 | ||
8512 | binary_node<T>::branch_[0].first->value(); | |
8513 | } | |
8514 | } | |
8515 | ||
8516 | return std::numeric_limits<T>::quiet_NaN(); | |
8517 | } | |
8518 | ||
8519 | std::string str() const | |
8520 | { | |
8521 | return str0_node_ptr_->str(); | |
8522 | } | |
8523 | ||
8524 | char_cptr base() const | |
8525 | { | |
8526 | return str0_node_ptr_->base(); | |
8527 | } | |
8528 | ||
8529 | std::size_t size() const | |
8530 | { | |
8531 | return str0_node_ptr_->size(); | |
8532 | } | |
8533 | ||
8534 | range_t& range_ref() | |
8535 | { | |
8536 | return str0_node_ptr_->range_ref(); | |
8537 | } | |
8538 | ||
8539 | const range_t& range_ref() const | |
8540 | { | |
8541 | return str0_node_ptr_->range_ref(); | |
8542 | } | |
8543 | ||
8544 | inline typename expression_node<T>::node_type type() const | |
8545 | { | |
8546 | return expression_node<T>::e_strass; | |
8547 | } | |
8548 | ||
8549 | private: | |
8550 | ||
8551 | bool initialised_; | |
8552 | str_base_ptr str0_base_ptr_; | |
8553 | str_base_ptr str1_base_ptr_; | |
8554 | strvar_node_ptr str0_node_ptr_; | |
8555 | range_ptr str1_range_ptr_; | |
8556 | }; | |
8557 | ||
8558 | template <typename T, typename AssignmentProcess = asn_assignment> | |
8559 | class assignment_string_range_node : public binary_node <T>, | |
8560 | public string_base_node<T>, | |
8561 | public range_interface <T> | |
8562 | { | |
8563 | public: | |
8564 | ||
8565 | typedef expression_node <T>* expression_ptr; | |
8566 | typedef stringvar_node <T>* strvar_node_ptr; | |
8567 | typedef string_base_node<T>* str_base_ptr; | |
8568 | typedef range_pack <T> range_t; | |
8569 | typedef range_t* range_ptr; | |
8570 | typedef range_interface<T> irange_t; | |
8571 | typedef irange_t* irange_ptr; | |
8572 | ||
8573 | assignment_string_range_node(const operator_type& opr, | |
8574 | expression_ptr branch0, | |
8575 | expression_ptr branch1) | |
8576 | : binary_node<T>(opr, branch0, branch1), | |
8577 | initialised_(false), | |
8578 | str0_base_ptr_ (0), | |
8579 | str1_base_ptr_ (0), | |
8580 | str0_node_ptr_ (0), | |
8581 | str0_range_ptr_(0), | |
8582 | str1_range_ptr_(0) | |
8583 | { | |
8584 | if (is_string_range_node(binary_node<T>::branch_[0].first)) | |
8585 | { | |
8586 | str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first); | |
8587 | ||
8588 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
8589 | ||
8590 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first); | |
8591 | ||
8592 | if (0 == range) | |
8593 | return; | |
8594 | ||
8595 | str0_range_ptr_ = &(range->range_ref()); | |
8596 | } | |
8597 | ||
8598 | if (is_generally_string_node(binary_node<T>::branch_[1].first)) | |
8599 | { | |
8600 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first); | |
8601 | ||
8602 | if (0 == str1_base_ptr_) | |
8603 | return; | |
8604 | ||
8605 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first); | |
8606 | ||
8607 | if (0 == range) | |
8608 | return; | |
8609 | ||
8610 | str1_range_ptr_ = &(range->range_ref()); | |
8611 | } | |
8612 | ||
8613 | initialised_ = str0_base_ptr_ && | |
8614 | str1_base_ptr_ && | |
8615 | str0_node_ptr_ && | |
8616 | str0_range_ptr_ && | |
8617 | str1_range_ptr_ ; | |
8618 | } | |
8619 | ||
8620 | inline T value() const | |
8621 | { | |
8622 | if (initialised_) | |
8623 | { | |
8624 | binary_node<T>::branch_[0].first->value(); | |
8625 | binary_node<T>::branch_[1].first->value(); | |
8626 | ||
8627 | std::size_t s0_r0 = 0; | |
8628 | std::size_t s0_r1 = 0; | |
8629 | ||
8630 | std::size_t s1_r0 = 0; | |
8631 | std::size_t s1_r1 = 0; | |
8632 | ||
8633 | range_t& range0 = (*str0_range_ptr_); | |
8634 | range_t& range1 = (*str1_range_ptr_); | |
8635 | ||
8636 | if ( | |
8637 | range0(s0_r0, s0_r1, str0_base_ptr_->size()) && | |
8638 | range1(s1_r0, s1_r1, str1_base_ptr_->size()) | |
8639 | ) | |
8640 | { | |
8641 | std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; | |
8642 | ||
8643 | std::copy(str1_base_ptr_->base() + s1_r0, | |
8644 | str1_base_ptr_->base() + s1_r0 + size, | |
8645 | const_cast<char_ptr>(base() + s0_r0)); | |
8646 | } | |
8647 | } | |
8648 | ||
8649 | return std::numeric_limits<T>::quiet_NaN(); | |
8650 | } | |
8651 | ||
8652 | std::string str() const | |
8653 | { | |
8654 | return str0_node_ptr_->str(); | |
8655 | } | |
8656 | ||
8657 | char_cptr base() const | |
8658 | { | |
8659 | return str0_node_ptr_->base(); | |
8660 | } | |
8661 | ||
8662 | std::size_t size() const | |
8663 | { | |
8664 | return str0_node_ptr_->size(); | |
8665 | } | |
8666 | ||
8667 | range_t& range_ref() | |
8668 | { | |
8669 | return str0_node_ptr_->range_ref(); | |
8670 | } | |
8671 | ||
8672 | const range_t& range_ref() const | |
8673 | { | |
8674 | return str0_node_ptr_->range_ref(); | |
8675 | } | |
8676 | ||
8677 | inline typename expression_node<T>::node_type type() const | |
8678 | { | |
8679 | return expression_node<T>::e_strass; | |
8680 | } | |
8681 | ||
8682 | private: | |
8683 | ||
8684 | bool initialised_; | |
8685 | str_base_ptr str0_base_ptr_; | |
8686 | str_base_ptr str1_base_ptr_; | |
8687 | strvar_node_ptr str0_node_ptr_; | |
8688 | range_ptr str0_range_ptr_; | |
8689 | range_ptr str1_range_ptr_; | |
8690 | }; | |
8691 | ||
8692 | template <typename T> | |
8693 | class conditional_string_node : public trinary_node <T>, | |
8694 | public string_base_node<T>, | |
8695 | public range_interface <T> | |
8696 | { | |
8697 | public: | |
8698 | ||
8699 | typedef expression_node <T>* expression_ptr; | |
8700 | typedef string_base_node<T>* str_base_ptr; | |
8701 | typedef range_pack <T> range_t; | |
8702 | typedef range_t* range_ptr; | |
8703 | typedef range_interface<T> irange_t; | |
8704 | typedef irange_t* irange_ptr; | |
8705 | ||
8706 | conditional_string_node(expression_ptr test, | |
8707 | expression_ptr consequent, | |
8708 | expression_ptr alternative) | |
8709 | : trinary_node<T>(details::e_default,consequent,alternative,test), | |
8710 | initialised_(false), | |
8711 | str0_base_ptr_ (0), | |
8712 | str1_base_ptr_ (0), | |
8713 | str0_range_ptr_(0), | |
8714 | str1_range_ptr_(0), | |
8715 | test_ (test), | |
8716 | consequent_ (consequent), | |
8717 | alternative_(alternative) | |
8718 | { | |
8719 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
8720 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); | |
8721 | ||
8722 | range_.cache.first = range_.n0_c.second; | |
8723 | range_.cache.second = range_.n1_c.second; | |
8724 | ||
8725 | if (is_generally_string_node(trinary_node<T>::branch_[0].first)) | |
8726 | { | |
8727 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[0].first); | |
8728 | ||
8729 | if (0 == str0_base_ptr_) | |
8730 | return; | |
8731 | ||
8732 | str0_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[0].first); | |
8733 | ||
8734 | if (0 == str0_range_ptr_) | |
8735 | return; | |
8736 | } | |
8737 | ||
8738 | if (is_generally_string_node(trinary_node<T>::branch_[1].first)) | |
8739 | { | |
8740 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(trinary_node<T>::branch_[1].first); | |
8741 | ||
8742 | if (0 == str1_base_ptr_) | |
8743 | return; | |
8744 | ||
8745 | str1_range_ptr_ = dynamic_cast<irange_ptr>(trinary_node<T>::branch_[1].first); | |
8746 | ||
8747 | if (0 == str1_range_ptr_) | |
8748 | return; | |
8749 | } | |
8750 | ||
8751 | initialised_ = str0_base_ptr_ && | |
8752 | str1_base_ptr_ && | |
8753 | str0_range_ptr_ && | |
8754 | str1_range_ptr_ ; | |
8755 | ||
8756 | } | |
8757 | ||
8758 | inline T value() const | |
8759 | { | |
8760 | if (initialised_) | |
8761 | { | |
8762 | std::size_t r0 = 0; | |
8763 | std::size_t r1 = 0; | |
8764 | ||
8765 | if (is_true(test_)) | |
8766 | { | |
8767 | consequent_->value(); | |
8768 | ||
8769 | range_t& range = str0_range_ptr_->range_ref(); | |
8770 | ||
8771 | if (range(r0, r1, str0_base_ptr_->size())) | |
8772 | { | |
8773 | const std::size_t size = (r1 - r0) + 1; | |
8774 | ||
8775 | value_.assign(str0_base_ptr_->base() + r0, size); | |
8776 | ||
8777 | range_.n1_c.second = value_.size() - 1; | |
8778 | range_.cache.second = range_.n1_c.second; | |
8779 | ||
8780 | return T(1); | |
8781 | } | |
8782 | } | |
8783 | else | |
8784 | { | |
8785 | alternative_->value(); | |
8786 | ||
8787 | range_t& range = str1_range_ptr_->range_ref(); | |
8788 | ||
8789 | if (range(r0, r1, str1_base_ptr_->size())) | |
8790 | { | |
8791 | const std::size_t size = (r1 - r0) + 1; | |
8792 | ||
8793 | value_.assign(str1_base_ptr_->base() + r0, size); | |
8794 | ||
8795 | range_.n1_c.second = value_.size() - 1; | |
8796 | range_.cache.second = range_.n1_c.second; | |
8797 | ||
8798 | return T(0); | |
8799 | } | |
8800 | } | |
8801 | } | |
8802 | ||
8803 | return std::numeric_limits<T>::quiet_NaN(); | |
8804 | } | |
8805 | ||
8806 | std::string str() const | |
8807 | { | |
8808 | return value_; | |
8809 | } | |
8810 | ||
8811 | char_cptr base() const | |
8812 | { | |
8813 | return &value_[0]; | |
8814 | } | |
8815 | ||
8816 | std::size_t size() const | |
8817 | { | |
8818 | return value_.size(); | |
8819 | } | |
8820 | ||
8821 | range_t& range_ref() | |
8822 | { | |
8823 | return range_; | |
8824 | } | |
8825 | ||
8826 | const range_t& range_ref() const | |
8827 | { | |
8828 | return range_; | |
8829 | } | |
8830 | ||
8831 | inline typename expression_node<T>::node_type type() const | |
8832 | { | |
8833 | return expression_node<T>::e_strcondition; | |
8834 | } | |
8835 | ||
8836 | private: | |
8837 | ||
8838 | bool initialised_; | |
8839 | str_base_ptr str0_base_ptr_; | |
8840 | str_base_ptr str1_base_ptr_; | |
8841 | irange_ptr str0_range_ptr_; | |
8842 | irange_ptr str1_range_ptr_; | |
8843 | mutable range_t range_; | |
8844 | mutable std::string value_; | |
8845 | ||
8846 | expression_ptr test_; | |
8847 | expression_ptr consequent_; | |
8848 | expression_ptr alternative_; | |
8849 | }; | |
8850 | ||
8851 | template <typename T> | |
8852 | class cons_conditional_str_node : public binary_node <T>, | |
8853 | public string_base_node<T>, | |
8854 | public range_interface <T> | |
8855 | { | |
8856 | public: | |
8857 | ||
8858 | typedef expression_node <T>* expression_ptr; | |
8859 | typedef string_base_node<T>* str_base_ptr; | |
8860 | typedef range_pack <T> range_t; | |
8861 | typedef range_t* range_ptr; | |
8862 | typedef range_interface<T> irange_t; | |
8863 | typedef irange_t* irange_ptr; | |
8864 | ||
8865 | cons_conditional_str_node(expression_ptr test, | |
8866 | expression_ptr consequent) | |
8867 | : binary_node<T>(details::e_default, consequent, test), | |
8868 | initialised_(false), | |
8869 | str0_base_ptr_ (0), | |
8870 | str0_range_ptr_(0), | |
8871 | test_ (test), | |
8872 | consequent_(consequent) | |
8873 | { | |
8874 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
8875 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); | |
8876 | ||
8877 | range_.cache.first = range_.n0_c.second; | |
8878 | range_.cache.second = range_.n1_c.second; | |
8879 | ||
8880 | if (is_generally_string_node(binary_node<T>::branch_[0].first)) | |
8881 | { | |
8882 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
8883 | ||
8884 | if (0 == str0_base_ptr_) | |
8885 | return; | |
8886 | ||
8887 | str0_range_ptr_ = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first); | |
8888 | ||
8889 | if (0 == str0_range_ptr_) | |
8890 | return; | |
8891 | } | |
8892 | ||
8893 | initialised_ = str0_base_ptr_ && str0_range_ptr_ ; | |
8894 | } | |
8895 | ||
8896 | inline T value() const | |
8897 | { | |
8898 | if (initialised_) | |
8899 | { | |
8900 | if (is_true(test_)) | |
8901 | { | |
8902 | consequent_->value(); | |
8903 | ||
8904 | range_t& range = str0_range_ptr_->range_ref(); | |
8905 | ||
8906 | std::size_t r0 = 0; | |
8907 | std::size_t r1 = 0; | |
8908 | ||
8909 | if (range(r0, r1, str0_base_ptr_->size())) | |
8910 | { | |
8911 | const std::size_t size = (r1 - r0) + 1; | |
8912 | ||
8913 | value_.assign(str0_base_ptr_->base() + r0, size); | |
8914 | ||
8915 | range_.n1_c.second = value_.size() - 1; | |
8916 | range_.cache.second = range_.n1_c.second; | |
8917 | ||
8918 | return T(1); | |
8919 | } | |
8920 | } | |
8921 | } | |
8922 | ||
8923 | return std::numeric_limits<T>::quiet_NaN(); | |
8924 | } | |
8925 | ||
8926 | std::string str() const | |
8927 | { | |
8928 | return value_; | |
8929 | } | |
8930 | ||
8931 | char_cptr base() const | |
8932 | { | |
8933 | return &value_[0]; | |
8934 | } | |
8935 | ||
8936 | std::size_t size() const | |
8937 | { | |
8938 | return value_.size(); | |
8939 | } | |
8940 | ||
8941 | range_t& range_ref() | |
8942 | { | |
8943 | return range_; | |
8944 | } | |
8945 | ||
8946 | const range_t& range_ref() const | |
8947 | { | |
8948 | return range_; | |
8949 | } | |
8950 | ||
8951 | inline typename expression_node<T>::node_type type() const | |
8952 | { | |
8953 | return expression_node<T>::e_strccondition; | |
8954 | } | |
8955 | ||
8956 | private: | |
8957 | ||
8958 | bool initialised_; | |
8959 | str_base_ptr str0_base_ptr_; | |
8960 | irange_ptr str0_range_ptr_; | |
8961 | mutable range_t range_; | |
8962 | mutable std::string value_; | |
8963 | ||
8964 | expression_ptr test_; | |
8965 | expression_ptr consequent_; | |
8966 | }; | |
8967 | ||
8968 | template <typename T, typename VarArgFunction> | |
8969 | class str_vararg_node : public expression_node <T>, | |
8970 | public string_base_node<T>, | |
8971 | public range_interface <T> | |
8972 | { | |
8973 | public: | |
8974 | ||
8975 | typedef expression_node <T>* expression_ptr; | |
8976 | typedef string_base_node<T>* str_base_ptr; | |
8977 | typedef range_pack <T> range_t; | |
8978 | typedef range_t* range_ptr; | |
8979 | typedef range_interface<T> irange_t; | |
8980 | typedef irange_t* irange_ptr; | |
8981 | ||
8982 | template <typename Allocator, | |
8983 | template <typename, typename> class Sequence> | |
8984 | explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) | |
8985 | : final_node_(arg_list.back()), | |
8986 | final_deletable_(branch_deletable(final_node_)), | |
8987 | initialised_(false), | |
8988 | str_base_ptr_ (0), | |
8989 | str_range_ptr_(0) | |
8990 | { | |
8991 | if (0 == final_node_) | |
8992 | return; | |
8993 | else if (!is_generally_string_node(final_node_)) | |
8994 | return; | |
8995 | ||
8996 | str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_); | |
8997 | ||
8998 | if (0 == str_base_ptr_) | |
8999 | return; | |
9000 | ||
9001 | str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_); | |
9002 | ||
9003 | if (0 == str_range_ptr_) | |
9004 | return; | |
9005 | ||
9006 | initialised_ = str_base_ptr_ && str_range_ptr_; | |
9007 | ||
9008 | if (arg_list.size() > 1) | |
9009 | { | |
9010 | const std::size_t arg_list_size = arg_list.size() - 1; | |
9011 | ||
9012 | arg_list_.resize(arg_list_size); | |
9013 | delete_branch_.resize(arg_list_size); | |
9014 | ||
9015 | for (std::size_t i = 0; i < arg_list_size; ++i) | |
9016 | { | |
9017 | if (arg_list[i]) | |
9018 | { | |
9019 | arg_list_[i] = arg_list[i]; | |
9020 | delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); | |
9021 | } | |
9022 | else | |
9023 | { | |
9024 | arg_list_ .clear(); | |
9025 | delete_branch_.clear(); | |
9026 | return; | |
9027 | } | |
9028 | } | |
9029 | } | |
9030 | } | |
9031 | ||
9032 | ~str_vararg_node() | |
9033 | { | |
9034 | if (final_node_ && final_deletable_) | |
9035 | { | |
9036 | destroy_node(final_node_); | |
9037 | } | |
9038 | ||
9039 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
9040 | { | |
9041 | if (arg_list_[i] && delete_branch_[i]) | |
9042 | { | |
9043 | destroy_node(arg_list_[i]); | |
9044 | } | |
9045 | } | |
9046 | } | |
9047 | ||
9048 | inline T value() const | |
9049 | { | |
9050 | if (!arg_list_.empty()) | |
9051 | { | |
9052 | VarArgFunction::process(arg_list_); | |
9053 | } | |
9054 | ||
9055 | final_node_->value(); | |
9056 | ||
9057 | return std::numeric_limits<T>::quiet_NaN(); | |
9058 | } | |
9059 | ||
9060 | std::string str() const | |
9061 | { | |
9062 | return str_base_ptr_->str(); | |
9063 | } | |
9064 | ||
9065 | char_cptr base() const | |
9066 | { | |
9067 | return str_base_ptr_->base(); | |
9068 | } | |
9069 | ||
9070 | std::size_t size() const | |
9071 | { | |
9072 | return str_base_ptr_->size(); | |
9073 | } | |
9074 | ||
9075 | range_t& range_ref() | |
9076 | { | |
9077 | return str_range_ptr_->range_ref(); | |
9078 | } | |
9079 | ||
9080 | const range_t& range_ref() const | |
9081 | { | |
9082 | return str_range_ptr_->range_ref(); | |
9083 | } | |
9084 | ||
9085 | inline typename expression_node<T>::node_type type() const | |
9086 | { | |
9087 | return expression_node<T>::e_stringvararg; | |
9088 | } | |
9089 | ||
9090 | private: | |
9091 | ||
9092 | expression_ptr final_node_; | |
9093 | bool final_deletable_; | |
9094 | bool initialised_; | |
9095 | str_base_ptr str_base_ptr_; | |
9096 | irange_ptr str_range_ptr_; | |
9097 | std::vector<expression_ptr> arg_list_; | |
9098 | std::vector<unsigned char> delete_branch_; | |
9099 | }; | |
9100 | #endif | |
9101 | ||
9102 | template <typename T, std::size_t N> | |
9103 | inline T axn(T a, T x) | |
9104 | { | |
9105 | // a*x^n | |
9106 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x); | |
9107 | } | |
9108 | ||
9109 | template <typename T, std::size_t N> | |
9110 | inline T axnb(T a, T x, T b) | |
9111 | { | |
9112 | // a*x^n+b | |
9113 | return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; | |
9114 | } | |
9115 | ||
9116 | template <typename T> | |
9117 | struct sf_base | |
9118 | { | |
9119 | typedef typename details::functor_t<T>::Type Type; | |
9120 | typedef typename details::functor_t<T> functor_t; | |
9121 | typedef typename functor_t::qfunc_t quaternary_functor_t; | |
9122 | typedef typename functor_t::tfunc_t trinary_functor_t; | |
9123 | typedef typename functor_t::bfunc_t binary_functor_t; | |
9124 | typedef typename functor_t::ufunc_t unary_functor_t; | |
9125 | }; | |
9126 | ||
9127 | #define define_sfop3(NN,OP0,OP1) \ | |
9128 | template <typename T> \ | |
9129 | struct sf##NN##_op : public sf_base<T> \ | |
9130 | { \ | |
9131 | typedef typename sf_base<T>::Type const Type; \ | |
9132 | static inline T process(Type x, Type y, Type z) \ | |
9133 | { \ | |
9134 | return (OP0); \ | |
9135 | } \ | |
9136 | static inline std::string id() \ | |
9137 | { \ | |
9138 | return OP1; \ | |
9139 | } \ | |
9140 | }; \ | |
9141 | ||
9142 | define_sfop3(00,(x + y) / z ,"(t+t)/t") | |
9143 | define_sfop3(01,(x + y) * z ,"(t+t)*t") | |
9144 | define_sfop3(02,(x + y) - z ,"(t+t)-t") | |
9145 | define_sfop3(03,(x + y) + z ,"(t+t)+t") | |
9146 | define_sfop3(04,(x - y) + z ,"(t-t)+t") | |
9147 | define_sfop3(05,(x - y) / z ,"(t-t)/t") | |
9148 | define_sfop3(06,(x - y) * z ,"(t-t)*t") | |
9149 | define_sfop3(07,(x * y) + z ,"(t*t)+t") | |
9150 | define_sfop3(08,(x * y) - z ,"(t*t)-t") | |
9151 | define_sfop3(09,(x * y) / z ,"(t*t)/t") | |
9152 | define_sfop3(10,(x * y) * z ,"(t*t)*t") | |
9153 | define_sfop3(11,(x / y) + z ,"(t/t)+t") | |
9154 | define_sfop3(12,(x / y) - z ,"(t/t)-t") | |
9155 | define_sfop3(13,(x / y) / z ,"(t/t)/t") | |
9156 | define_sfop3(14,(x / y) * z ,"(t/t)*t") | |
9157 | define_sfop3(15,x / (y + z) ,"t/(t+t)") | |
9158 | define_sfop3(16,x / (y - z) ,"t/(t-t)") | |
9159 | define_sfop3(17,x / (y * z) ,"t/(t*t)") | |
9160 | define_sfop3(18,x / (y / z) ,"t/(t/t)") | |
9161 | define_sfop3(19,x * (y + z) ,"t*(t+t)") | |
9162 | define_sfop3(20,x * (y - z) ,"t*(t-t)") | |
9163 | define_sfop3(21,x * (y * z) ,"t*(t*t)") | |
9164 | define_sfop3(22,x * (y / z) ,"t*(t/t)") | |
9165 | define_sfop3(23,x - (y + z) ,"t-(t+t)") | |
9166 | define_sfop3(24,x - (y - z) ,"t-(t-t)") | |
9167 | define_sfop3(25,x - (y / z) ,"t-(t/t)") | |
9168 | define_sfop3(26,x - (y * z) ,"t-(t*t)") | |
9169 | define_sfop3(27,x + (y * z) ,"t+(t*t)") | |
9170 | define_sfop3(28,x + (y / z) ,"t+(t/t)") | |
9171 | define_sfop3(29,x + (y + z) ,"t+(t+t)") | |
9172 | define_sfop3(30,x + (y - z) ,"t+(t-t)") | |
9173 | define_sfop3(31,(axnb<T,2>(x,y,z))," ") | |
9174 | define_sfop3(32,(axnb<T,3>(x,y,z))," ") | |
9175 | define_sfop3(33,(axnb<T,4>(x,y,z))," ") | |
9176 | define_sfop3(34,(axnb<T,5>(x,y,z))," ") | |
9177 | define_sfop3(35,(axnb<T,6>(x,y,z))," ") | |
9178 | define_sfop3(36,(axnb<T,7>(x,y,z))," ") | |
9179 | define_sfop3(37,(axnb<T,8>(x,y,z))," ") | |
9180 | define_sfop3(38,(axnb<T,9>(x,y,z))," ") | |
9181 | define_sfop3(39,x * numeric::log(y) + z,"") | |
9182 | define_sfop3(40,x * numeric::log(y) - z,"") | |
9183 | define_sfop3(41,x * numeric::log10(y) + z,"") | |
9184 | define_sfop3(42,x * numeric::log10(y) - z,"") | |
9185 | define_sfop3(43,x * numeric::sin(y) + z ,"") | |
9186 | define_sfop3(44,x * numeric::sin(y) - z ,"") | |
9187 | define_sfop3(45,x * numeric::cos(y) + z ,"") | |
9188 | define_sfop3(46,x * numeric::cos(y) - z ,"") | |
9189 | define_sfop3(47,details::is_true(x) ? y : z,"") | |
9190 | ||
9191 | #define define_sfop4(NN,OP0,OP1) \ | |
9192 | template <typename T> \ | |
9193 | struct sf##NN##_op : public sf_base<T> \ | |
9194 | { \ | |
9195 | typedef typename sf_base<T>::Type const Type; \ | |
9196 | static inline T process(Type x, Type y, Type z, Type w) \ | |
9197 | { \ | |
9198 | return (OP0); \ | |
9199 | } \ | |
9200 | static inline std::string id() { return OP1; } \ | |
9201 | }; \ | |
9202 | ||
9203 | define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") | |
9204 | define_sfop4(49,(x + ((y + z) * w)),"t+((t+t)*t)") | |
9205 | define_sfop4(50,(x + ((y - z) / w)),"t+((t-t)/t)") | |
9206 | define_sfop4(51,(x + ((y - z) * w)),"t+((t-t)*t)") | |
9207 | define_sfop4(52,(x + ((y * z) / w)),"t+((t*t)/t)") | |
9208 | define_sfop4(53,(x + ((y * z) * w)),"t+((t*t)*t)") | |
9209 | define_sfop4(54,(x + ((y / z) + w)),"t+((t/t)+t)") | |
9210 | define_sfop4(55,(x + ((y / z) / w)),"t+((t/t)/t)") | |
9211 | define_sfop4(56,(x + ((y / z) * w)),"t+((t/t)*t)") | |
9212 | define_sfop4(57,(x - ((y + z) / w)),"t-((t+t)/t)") | |
9213 | define_sfop4(58,(x - ((y + z) * w)),"t-((t+t)*t)") | |
9214 | define_sfop4(59,(x - ((y - z) / w)),"t-((t-t)/t)") | |
9215 | define_sfop4(60,(x - ((y - z) * w)),"t-((t-t)*t)") | |
9216 | define_sfop4(61,(x - ((y * z) / w)),"t-((t*t)/t)") | |
9217 | define_sfop4(62,(x - ((y * z) * w)),"t-((t*t)*t)") | |
9218 | define_sfop4(63,(x - ((y / z) / w)),"t-((t/t)/t)") | |
9219 | define_sfop4(64,(x - ((y / z) * w)),"t-((t/t)*t)") | |
9220 | define_sfop4(65,(((x + y) * z) - w),"((t+t)*t)-t") | |
9221 | define_sfop4(66,(((x - y) * z) - w),"((t-t)*t)-t") | |
9222 | define_sfop4(67,(((x * y) * z) - w),"((t*t)*t)-t") | |
9223 | define_sfop4(68,(((x / y) * z) - w),"((t/t)*t)-t") | |
9224 | define_sfop4(69,(((x + y) / z) - w),"((t+t)/t)-t") | |
9225 | define_sfop4(70,(((x - y) / z) - w),"((t-t)/t)-t") | |
9226 | define_sfop4(71,(((x * y) / z) - w),"((t*t)/t)-t") | |
9227 | define_sfop4(72,(((x / y) / z) - w),"((t/t)/t)-t") | |
9228 | define_sfop4(73,((x * y) + (z * w)),"(t*t)+(t*t)") | |
9229 | define_sfop4(74,((x * y) - (z * w)),"(t*t)-(t*t)") | |
9230 | define_sfop4(75,((x * y) + (z / w)),"(t*t)+(t/t)") | |
9231 | define_sfop4(76,((x * y) - (z / w)),"(t*t)-(t/t)") | |
9232 | define_sfop4(77,((x / y) + (z / w)),"(t/t)+(t/t)") | |
9233 | define_sfop4(78,((x / y) - (z / w)),"(t/t)-(t/t)") | |
9234 | define_sfop4(79,((x / y) - (z * w)),"(t/t)-(t*t)") | |
9235 | define_sfop4(80,(x / (y + (z * w))),"t/(t+(t*t))") | |
9236 | define_sfop4(81,(x / (y - (z * w))),"t/(t-(t*t))") | |
9237 | define_sfop4(82,(x * (y + (z * w))),"t*(t+(t*t))") | |
9238 | define_sfop4(83,(x * (y - (z * w))),"t*(t-(t*t))") | |
9239 | ||
9240 | define_sfop4(84,(axn<T,2>(x,y) + axn<T,2>(z,w)),"") | |
9241 | define_sfop4(85,(axn<T,3>(x,y) + axn<T,3>(z,w)),"") | |
9242 | define_sfop4(86,(axn<T,4>(x,y) + axn<T,4>(z,w)),"") | |
9243 | define_sfop4(87,(axn<T,5>(x,y) + axn<T,5>(z,w)),"") | |
9244 | define_sfop4(88,(axn<T,6>(x,y) + axn<T,6>(z,w)),"") | |
9245 | define_sfop4(89,(axn<T,7>(x,y) + axn<T,7>(z,w)),"") | |
9246 | define_sfop4(90,(axn<T,8>(x,y) + axn<T,8>(z,w)),"") | |
9247 | define_sfop4(91,(axn<T,9>(x,y) + axn<T,9>(z,w)),"") | |
9248 | define_sfop4(92,((details::is_true(x) && details::is_true(y)) ? z : w),"") | |
9249 | define_sfop4(93,((details::is_true(x) || details::is_true(y)) ? z : w),"") | |
9250 | define_sfop4(94,((x < y) ? z : w),"") | |
9251 | define_sfop4(95,((x <= y) ? z : w),"") | |
9252 | define_sfop4(96,((x > y) ? z : w),"") | |
9253 | define_sfop4(97,((x >= y) ? z : w),"") | |
9254 | define_sfop4(98,(details::is_true(numeric::equal(x,y)) ? z : w),"") | |
9255 | define_sfop4(99,(x * numeric::sin(y) + z * numeric::cos(w)),"") | |
9256 | ||
9257 | define_sfop4(ext00,((x + y) - (z * w)),"(t+t)-(t*t)") | |
9258 | define_sfop4(ext01,((x + y) - (z / w)),"(t+t)-(t/t)") | |
9259 | define_sfop4(ext02,((x + y) + (z * w)),"(t+t)+(t*t)") | |
9260 | define_sfop4(ext03,((x + y) + (z / w)),"(t+t)+(t/t)") | |
9261 | define_sfop4(ext04,((x - y) + (z * w)),"(t-t)+(t*t)") | |
9262 | define_sfop4(ext05,((x - y) + (z / w)),"(t-t)+(t/t)") | |
9263 | define_sfop4(ext06,((x - y) - (z * w)),"(t-t)-(t*t)") | |
9264 | define_sfop4(ext07,((x - y) - (z / w)),"(t-t)-(t/t)") | |
9265 | define_sfop4(ext08,((x + y) - (z - w)),"(t+t)-(t-t)") | |
9266 | define_sfop4(ext09,((x + y) + (z - w)),"(t+t)+(t-t)") | |
9267 | define_sfop4(ext10,((x + y) + (z + w)),"(t+t)+(t+t)") | |
9268 | define_sfop4(ext11,((x + y) * (z - w)),"(t+t)*(t-t)") | |
9269 | define_sfop4(ext12,((x + y) / (z - w)),"(t+t)/(t-t)") | |
9270 | define_sfop4(ext13,((x - y) - (z + w)),"(t-t)-(t+t)") | |
9271 | define_sfop4(ext14,((x - y) + (z + w)),"(t-t)+(t+t)") | |
9272 | define_sfop4(ext15,((x - y) * (z + w)),"(t-t)*(t+t)") | |
9273 | define_sfop4(ext16,((x - y) / (z + w)),"(t-t)/(t+t)") | |
9274 | define_sfop4(ext17,((x * y) - (z + w)),"(t*t)-(t+t)") | |
9275 | define_sfop4(ext18,((x / y) - (z + w)),"(t/t)-(t+t)") | |
9276 | define_sfop4(ext19,((x * y) + (z + w)),"(t*t)+(t+t)") | |
9277 | define_sfop4(ext20,((x / y) + (z + w)),"(t/t)+(t+t)") | |
9278 | define_sfop4(ext21,((x * y) + (z - w)),"(t*t)+(t-t)") | |
9279 | define_sfop4(ext22,((x / y) + (z - w)),"(t/t)+(t-t)") | |
9280 | define_sfop4(ext23,((x * y) - (z - w)),"(t*t)-(t-t)") | |
9281 | define_sfop4(ext24,((x / y) - (z - w)),"(t/t)-(t-t)") | |
9282 | define_sfop4(ext25,((x + y) * (z * w)),"(t+t)*(t*t)") | |
9283 | define_sfop4(ext26,((x + y) * (z / w)),"(t+t)*(t/t)") | |
9284 | define_sfop4(ext27,((x + y) / (z * w)),"(t+t)/(t*t)") | |
9285 | define_sfop4(ext28,((x + y) / (z / w)),"(t+t)/(t/t)") | |
9286 | define_sfop4(ext29,((x - y) / (z * w)),"(t-t)/(t*t)") | |
9287 | define_sfop4(ext30,((x - y) / (z / w)),"(t-t)/(t/t)") | |
9288 | define_sfop4(ext31,((x - y) * (z * w)),"(t-t)*(t*t)") | |
9289 | define_sfop4(ext32,((x - y) * (z / w)),"(t-t)*(t/t)") | |
9290 | define_sfop4(ext33,((x * y) * (z + w)),"(t*t)*(t+t)") | |
9291 | define_sfop4(ext34,((x / y) * (z + w)),"(t/t)*(t+t)") | |
9292 | define_sfop4(ext35,((x * y) / (z + w)),"(t*t)/(t+t)") | |
9293 | define_sfop4(ext36,((x / y) / (z + w)),"(t/t)/(t+t)") | |
9294 | define_sfop4(ext37,((x * y) / (z - w)),"(t*t)/(t-t)") | |
9295 | define_sfop4(ext38,((x / y) / (z - w)),"(t/t)/(t-t)") | |
9296 | define_sfop4(ext39,((x * y) * (z - w)),"(t*t)*(t-t)") | |
9297 | define_sfop4(ext40,((x * y) / (z * w)),"(t*t)/(t*t)") | |
9298 | define_sfop4(ext41,((x / y) * (z / w)),"(t/t)*(t/t)") | |
9299 | define_sfop4(ext42,((x / y) * (z - w)),"(t/t)*(t-t)") | |
9300 | define_sfop4(ext43,((x * y) * (z * w)),"(t*t)*(t*t)") | |
9301 | define_sfop4(ext44,(x + (y * (z / w))),"t+(t*(t/t))") | |
9302 | define_sfop4(ext45,(x - (y * (z / w))),"t-(t*(t/t))") | |
9303 | define_sfop4(ext46,(x + (y / (z * w))),"t+(t/(t*t))") | |
9304 | define_sfop4(ext47,(x - (y / (z * w))),"t-(t/(t*t))") | |
9305 | define_sfop4(ext48,(((x - y) - z) * w),"((t-t)-t)*t") | |
9306 | define_sfop4(ext49,(((x - y) - z) / w),"((t-t)-t)/t") | |
9307 | define_sfop4(ext50,(((x - y) + z) * w),"((t-t)+t)*t") | |
9308 | define_sfop4(ext51,(((x - y) + z) / w),"((t-t)+t)/t") | |
9309 | define_sfop4(ext52,((x + (y - z)) * w),"(t+(t-t))*t") | |
9310 | define_sfop4(ext53,((x + (y - z)) / w),"(t+(t-t))/t") | |
9311 | define_sfop4(ext54,((x + y) / (z + w)),"(t+t)/(t+t)") | |
9312 | define_sfop4(ext55,((x - y) / (z - w)),"(t-t)/(t-t)") | |
9313 | define_sfop4(ext56,((x + y) * (z + w)),"(t+t)*(t+t)") | |
9314 | define_sfop4(ext57,((x - y) * (z - w)),"(t-t)*(t-t)") | |
9315 | define_sfop4(ext58,((x - y) + (z - w)),"(t-t)+(t-t)") | |
9316 | define_sfop4(ext59,((x - y) - (z - w)),"(t-t)-(t-t)") | |
9317 | define_sfop4(ext60,((x / y) + (z * w)),"(t/t)+(t*t)") | |
9318 | define_sfop4(ext61,(((x * y) * z) / w),"((t*t)*t)/t") | |
9319 | ||
9320 | #undef define_sfop3 | |
9321 | #undef define_sfop4 | |
9322 | ||
9323 | template <typename T, typename SpecialFunction> | |
9324 | class sf3_node : public trinary_node<T> | |
9325 | { | |
9326 | public: | |
9327 | ||
9328 | typedef expression_node<T>* expression_ptr; | |
9329 | ||
9330 | sf3_node(const operator_type& opr, | |
9331 | expression_ptr branch0, | |
9332 | expression_ptr branch1, | |
9333 | expression_ptr branch2) | |
9334 | : trinary_node<T>(opr, branch0, branch1, branch2) | |
9335 | {} | |
9336 | ||
9337 | inline T value() const | |
9338 | { | |
9339 | const T x = trinary_node<T>::branch_[0].first->value(); | |
9340 | const T y = trinary_node<T>::branch_[1].first->value(); | |
9341 | const T z = trinary_node<T>::branch_[2].first->value(); | |
9342 | ||
9343 | return SpecialFunction::process(x, y, z); | |
9344 | } | |
9345 | }; | |
9346 | ||
9347 | template <typename T, typename SpecialFunction> | |
9348 | class sf4_node : public quaternary_node<T> | |
9349 | { | |
9350 | public: | |
9351 | ||
9352 | typedef expression_node<T>* expression_ptr; | |
9353 | ||
9354 | sf4_node(const operator_type& opr, | |
9355 | expression_ptr branch0, | |
9356 | expression_ptr branch1, | |
9357 | expression_ptr branch2, | |
9358 | expression_ptr branch3) | |
9359 | : quaternary_node<T>(opr, branch0, branch1, branch2, branch3) | |
9360 | {} | |
9361 | ||
9362 | inline T value() const | |
9363 | { | |
9364 | const T x = quaternary_node<T>::branch_[0].first->value(); | |
9365 | const T y = quaternary_node<T>::branch_[1].first->value(); | |
9366 | const T z = quaternary_node<T>::branch_[2].first->value(); | |
9367 | const T w = quaternary_node<T>::branch_[3].first->value(); | |
9368 | ||
9369 | return SpecialFunction::process(x, y, z, w); | |
9370 | } | |
9371 | }; | |
9372 | ||
9373 | template <typename T, typename SpecialFunction> | |
9374 | class sf3_var_node : public expression_node<T> | |
9375 | { | |
9376 | public: | |
9377 | ||
9378 | typedef expression_node<T>* expression_ptr; | |
9379 | ||
9380 | sf3_var_node(const T& v0, const T& v1, const T& v2) | |
9381 | : v0_(v0), | |
9382 | v1_(v1), | |
9383 | v2_(v2) | |
9384 | {} | |
9385 | ||
9386 | inline T value() const | |
9387 | { | |
9388 | return SpecialFunction::process(v0_, v1_, v2_); | |
9389 | } | |
9390 | ||
9391 | inline typename expression_node<T>::node_type type() const | |
9392 | { | |
9393 | return expression_node<T>::e_trinary; | |
9394 | } | |
9395 | ||
9396 | private: | |
9397 | ||
9398 | sf3_var_node(sf3_var_node<T,SpecialFunction>&); | |
9399 | sf3_var_node<T,SpecialFunction>& operator=(sf3_var_node<T,SpecialFunction>&); | |
9400 | ||
9401 | const T& v0_; | |
9402 | const T& v1_; | |
9403 | const T& v2_; | |
9404 | }; | |
9405 | ||
9406 | template <typename T, typename SpecialFunction> | |
9407 | class sf4_var_node : public expression_node<T> | |
9408 | { | |
9409 | public: | |
9410 | ||
9411 | typedef expression_node<T>* expression_ptr; | |
9412 | ||
9413 | sf4_var_node(const T& v0, const T& v1, const T& v2, const T& v3) | |
9414 | : v0_(v0), | |
9415 | v1_(v1), | |
9416 | v2_(v2), | |
9417 | v3_(v3) | |
9418 | {} | |
9419 | ||
9420 | inline T value() const | |
9421 | { | |
9422 | return SpecialFunction::process(v0_, v1_, v2_, v3_); | |
9423 | } | |
9424 | ||
9425 | inline typename expression_node<T>::node_type type() const | |
9426 | { | |
9427 | return expression_node<T>::e_trinary; | |
9428 | } | |
9429 | ||
9430 | private: | |
9431 | ||
9432 | sf4_var_node(sf4_var_node<T,SpecialFunction>&); | |
9433 | sf4_var_node<T,SpecialFunction>& operator=(sf4_var_node<T,SpecialFunction>&); | |
9434 | ||
9435 | const T& v0_; | |
9436 | const T& v1_; | |
9437 | const T& v2_; | |
9438 | const T& v3_; | |
9439 | }; | |
9440 | ||
9441 | template <typename T, typename VarArgFunction> | |
9442 | class vararg_node : public expression_node<T> | |
9443 | { | |
9444 | public: | |
9445 | ||
9446 | typedef expression_node<T>* expression_ptr; | |
9447 | ||
9448 | template <typename Allocator, | |
9449 | template <typename, typename> class Sequence> | |
9450 | explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) | |
9451 | { | |
9452 | arg_list_ .resize(arg_list.size()); | |
9453 | delete_branch_.resize(arg_list.size()); | |
9454 | ||
9455 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
9456 | { | |
9457 | if (arg_list[i]) | |
9458 | { | |
9459 | arg_list_[i] = arg_list[i]; | |
9460 | delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); | |
9461 | } | |
9462 | else | |
9463 | { | |
9464 | arg_list_.clear(); | |
9465 | delete_branch_.clear(); | |
9466 | return; | |
9467 | } | |
9468 | } | |
9469 | } | |
9470 | ||
9471 | ~vararg_node() | |
9472 | { | |
9473 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
9474 | { | |
9475 | if (arg_list_[i] && delete_branch_[i]) | |
9476 | { | |
9477 | destroy_node(arg_list_[i]); | |
9478 | } | |
9479 | } | |
9480 | } | |
9481 | ||
9482 | inline T value() const | |
9483 | { | |
9484 | return VarArgFunction::process(arg_list_); | |
9485 | } | |
9486 | ||
9487 | inline typename expression_node<T>::node_type type() const | |
9488 | { | |
9489 | return expression_node<T>::e_vararg; | |
9490 | } | |
9491 | ||
9492 | private: | |
9493 | ||
9494 | std::vector<expression_ptr> arg_list_; | |
9495 | std::vector<unsigned char> delete_branch_; | |
9496 | }; | |
9497 | ||
9498 | template <typename T, typename VarArgFunction> | |
9499 | class vararg_varnode : public expression_node<T> | |
9500 | { | |
9501 | public: | |
9502 | ||
9503 | typedef expression_node<T>* expression_ptr; | |
9504 | ||
9505 | template <typename Allocator, | |
9506 | template <typename, typename> class Sequence> | |
9507 | explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) | |
9508 | { | |
9509 | arg_list_.resize(arg_list.size()); | |
9510 | ||
9511 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
9512 | { | |
9513 | if (arg_list[i] && is_variable_node(arg_list[i])) | |
9514 | { | |
9515 | variable_node<T>* var_node_ptr = static_cast<variable_node<T>*>(arg_list[i]); | |
9516 | arg_list_[i] = (&var_node_ptr->ref()); | |
9517 | } | |
9518 | else | |
9519 | { | |
9520 | arg_list_.clear(); | |
9521 | return; | |
9522 | } | |
9523 | } | |
9524 | } | |
9525 | ||
9526 | inline T value() const | |
9527 | { | |
9528 | if (!arg_list_.empty()) | |
9529 | return VarArgFunction::process(arg_list_); | |
9530 | else | |
9531 | return std::numeric_limits<T>::quiet_NaN(); | |
9532 | } | |
9533 | ||
9534 | inline typename expression_node<T>::node_type type() const | |
9535 | { | |
9536 | return expression_node<T>::e_vararg; | |
9537 | } | |
9538 | ||
9539 | private: | |
9540 | ||
9541 | std::vector<const T*> arg_list_; | |
9542 | }; | |
9543 | ||
9544 | template <typename T, typename VecFunction> | |
9545 | class vectorize_node : public expression_node<T> | |
9546 | { | |
9547 | public: | |
9548 | ||
9549 | typedef expression_node<T>* expression_ptr; | |
9550 | ||
9551 | explicit vectorize_node(const expression_ptr v) | |
9552 | : ivec_ptr_(0), | |
9553 | v_(v), | |
9554 | v_deletable_(branch_deletable(v_)) | |
9555 | { | |
9556 | if (is_ivector_node(v)) | |
9557 | { | |
9558 | ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v); | |
9559 | } | |
9560 | else | |
9561 | ivec_ptr_ = 0; | |
9562 | } | |
9563 | ||
9564 | ~vectorize_node() | |
9565 | { | |
9566 | if (v_ && v_deletable_) | |
9567 | { | |
9568 | destroy_node(v_); | |
9569 | } | |
9570 | } | |
9571 | ||
9572 | inline T value() const | |
9573 | { | |
9574 | if (ivec_ptr_) | |
9575 | { | |
9576 | v_->value(); | |
9577 | return VecFunction::process(ivec_ptr_); | |
9578 | } | |
9579 | else | |
9580 | return std::numeric_limits<T>::quiet_NaN(); | |
9581 | } | |
9582 | ||
9583 | inline typename expression_node<T>::node_type type() const | |
9584 | { | |
9585 | return expression_node<T>::e_vecfunc; | |
9586 | } | |
9587 | ||
9588 | private: | |
9589 | ||
9590 | vector_interface<T>* ivec_ptr_; | |
9591 | expression_ptr v_; | |
9592 | const bool v_deletable_; | |
9593 | }; | |
9594 | ||
9595 | template <typename T> | |
9596 | class assignment_node : public binary_node<T> | |
9597 | { | |
9598 | public: | |
9599 | ||
9600 | typedef expression_node<T>* expression_ptr; | |
9601 | ||
9602 | assignment_node(const operator_type& opr, | |
9603 | expression_ptr branch0, | |
9604 | expression_ptr branch1) | |
9605 | : binary_node<T>(opr, branch0, branch1), | |
9606 | var_node_ptr_(0) | |
9607 | { | |
9608 | if (is_variable_node(binary_node<T>::branch_[0].first)) | |
9609 | { | |
9610 | var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first); | |
9611 | } | |
9612 | } | |
9613 | ||
9614 | inline T value() const | |
9615 | { | |
9616 | if (var_node_ptr_) | |
9617 | { | |
9618 | T& result = var_node_ptr_->ref(); | |
9619 | ||
9620 | result = binary_node<T>::branch_[1].first->value(); | |
9621 | ||
9622 | return result; | |
9623 | } | |
9624 | else | |
9625 | return std::numeric_limits<T>::quiet_NaN(); | |
9626 | } | |
9627 | ||
9628 | private: | |
9629 | ||
9630 | variable_node<T>* var_node_ptr_; | |
9631 | }; | |
9632 | ||
9633 | template <typename T> | |
9634 | class assignment_vec_elem_node : public binary_node<T> | |
9635 | { | |
9636 | public: | |
9637 | ||
9638 | typedef expression_node<T>* expression_ptr; | |
9639 | ||
9640 | assignment_vec_elem_node(const operator_type& opr, | |
9641 | expression_ptr branch0, | |
9642 | expression_ptr branch1) | |
9643 | : binary_node<T>(opr, branch0, branch1), | |
9644 | vec_node_ptr_(0) | |
9645 | { | |
9646 | if (is_vector_elem_node(binary_node<T>::branch_[0].first)) | |
9647 | { | |
9648 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first); | |
9649 | } | |
9650 | } | |
9651 | ||
9652 | inline T value() const | |
9653 | { | |
9654 | if (vec_node_ptr_) | |
9655 | { | |
9656 | T& result = vec_node_ptr_->ref(); | |
9657 | ||
9658 | result = binary_node<T>::branch_[1].first->value(); | |
9659 | ||
9660 | return result; | |
9661 | } | |
9662 | else | |
9663 | return std::numeric_limits<T>::quiet_NaN(); | |
9664 | } | |
9665 | ||
9666 | private: | |
9667 | ||
9668 | vector_elem_node<T>* vec_node_ptr_; | |
9669 | }; | |
9670 | ||
9671 | template <typename T> | |
9672 | class assignment_rebasevec_elem_node : public binary_node<T> | |
9673 | { | |
9674 | public: | |
9675 | ||
9676 | typedef expression_node<T>* expression_ptr; | |
9677 | ||
9678 | assignment_rebasevec_elem_node(const operator_type& opr, | |
9679 | expression_ptr branch0, | |
9680 | expression_ptr branch1) | |
9681 | : binary_node<T>(opr, branch0, branch1), | |
9682 | rbvec_node_ptr_(0) | |
9683 | { | |
9684 | if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first)) | |
9685 | { | |
9686 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first); | |
9687 | } | |
9688 | } | |
9689 | ||
9690 | inline T value() const | |
9691 | { | |
9692 | if (rbvec_node_ptr_) | |
9693 | { | |
9694 | T& result = rbvec_node_ptr_->ref(); | |
9695 | ||
9696 | result = binary_node<T>::branch_[1].first->value(); | |
9697 | ||
9698 | return result; | |
9699 | } | |
9700 | else | |
9701 | return std::numeric_limits<T>::quiet_NaN(); | |
9702 | } | |
9703 | ||
9704 | private: | |
9705 | ||
9706 | rebasevector_elem_node<T>* rbvec_node_ptr_; | |
9707 | }; | |
9708 | ||
9709 | template <typename T> | |
9710 | class assignment_rebasevec_celem_node : public binary_node<T> | |
9711 | { | |
9712 | public: | |
9713 | ||
9714 | typedef expression_node<T>* expression_ptr; | |
9715 | ||
9716 | assignment_rebasevec_celem_node(const operator_type& opr, | |
9717 | expression_ptr branch0, | |
9718 | expression_ptr branch1) | |
9719 | : binary_node<T>(opr, branch0, branch1), | |
9720 | rbvec_node_ptr_(0) | |
9721 | { | |
9722 | if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first)) | |
9723 | { | |
9724 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first); | |
9725 | } | |
9726 | } | |
9727 | ||
9728 | inline T value() const | |
9729 | { | |
9730 | if (rbvec_node_ptr_) | |
9731 | { | |
9732 | T& result = rbvec_node_ptr_->ref(); | |
9733 | ||
9734 | result = binary_node<T>::branch_[1].first->value(); | |
9735 | ||
9736 | return result; | |
9737 | } | |
9738 | else | |
9739 | return std::numeric_limits<T>::quiet_NaN(); | |
9740 | } | |
9741 | ||
9742 | private: | |
9743 | ||
9744 | rebasevector_celem_node<T>* rbvec_node_ptr_; | |
9745 | }; | |
9746 | ||
9747 | template <typename T> | |
9748 | class assignment_vec_node : public binary_node <T>, | |
9749 | public vector_interface<T> | |
9750 | { | |
9751 | public: | |
9752 | ||
9753 | typedef expression_node<T>* expression_ptr; | |
9754 | typedef vector_node<T>* vector_node_ptr; | |
9755 | typedef vec_data_store<T> vds_t; | |
9756 | ||
9757 | assignment_vec_node(const operator_type& opr, | |
9758 | expression_ptr branch0, | |
9759 | expression_ptr branch1) | |
9760 | : binary_node<T>(opr, branch0, branch1), | |
9761 | vec_node_ptr_(0) | |
9762 | { | |
9763 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
9764 | { | |
9765 | vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); | |
9766 | vds() = vec_node_ptr_->vds(); | |
9767 | } | |
9768 | } | |
9769 | ||
9770 | inline T value() const | |
9771 | { | |
9772 | if (vec_node_ptr_) | |
9773 | { | |
9774 | const T v = binary_node<T>::branch_[1].first->value(); | |
9775 | ||
9776 | T* vec = vds().data(); | |
9777 | ||
9778 | loop_unroll::details lud(size()); | |
9779 | const T* upper_bound = vec + lud.upper_bound; | |
9780 | ||
9781 | while (vec < upper_bound) | |
9782 | { | |
9783 | #define exprtk_loop(N) \ | |
9784 | vec[N] = v; \ | |
9785 | ||
9786 | exprtk_loop( 0) exprtk_loop( 1) | |
9787 | exprtk_loop( 2) exprtk_loop( 3) | |
9788 | #ifndef exprtk_disable_superscalar_unroll | |
9789 | exprtk_loop( 4) exprtk_loop( 5) | |
9790 | exprtk_loop( 6) exprtk_loop( 7) | |
9791 | exprtk_loop( 8) exprtk_loop( 9) | |
9792 | exprtk_loop(10) exprtk_loop(11) | |
9793 | exprtk_loop(12) exprtk_loop(13) | |
9794 | exprtk_loop(14) exprtk_loop(15) | |
9795 | #endif | |
9796 | ||
9797 | vec += lud.batch_size; | |
9798 | } | |
9799 | ||
9800 | exprtk_disable_fallthrough_begin | |
9801 | switch (lud.remainder) | |
9802 | { | |
9803 | #define case_stmt(N) \ | |
9804 | case N : *vec++ = v; \ | |
9805 | ||
9806 | #ifndef exprtk_disable_superscalar_unroll | |
9807 | case_stmt(15) case_stmt(14) | |
9808 | case_stmt(13) case_stmt(12) | |
9809 | case_stmt(11) case_stmt(10) | |
9810 | case_stmt( 9) case_stmt( 8) | |
9811 | case_stmt( 7) case_stmt( 6) | |
9812 | case_stmt( 5) case_stmt( 4) | |
9813 | #endif | |
9814 | case_stmt( 3) case_stmt( 2) | |
9815 | case_stmt( 1) | |
9816 | } | |
9817 | exprtk_disable_fallthrough_end | |
9818 | ||
9819 | #undef exprtk_loop | |
9820 | #undef case_stmt | |
9821 | ||
9822 | return vec_node_ptr_->value(); | |
9823 | } | |
9824 | else | |
9825 | return std::numeric_limits<T>::quiet_NaN(); | |
9826 | } | |
9827 | ||
9828 | vector_node_ptr vec() const | |
9829 | { | |
9830 | return vec_node_ptr_; | |
9831 | } | |
9832 | ||
9833 | vector_node_ptr vec() | |
9834 | { | |
9835 | return vec_node_ptr_; | |
9836 | } | |
9837 | ||
9838 | inline typename expression_node<T>::node_type type() const | |
9839 | { | |
9840 | return expression_node<T>::e_vecvalass; | |
9841 | } | |
9842 | ||
9843 | std::size_t size() const | |
9844 | { | |
9845 | return vds().size(); | |
9846 | } | |
9847 | ||
9848 | vds_t& vds() | |
9849 | { | |
9850 | return vds_; | |
9851 | } | |
9852 | ||
9853 | const vds_t& vds() const | |
9854 | { | |
9855 | return vds_; | |
9856 | } | |
9857 | ||
9858 | private: | |
9859 | ||
9860 | vector_node<T>* vec_node_ptr_; | |
9861 | vds_t vds_; | |
9862 | }; | |
9863 | ||
9864 | template <typename T> | |
9865 | class assignment_vecvec_node : public binary_node <T>, | |
9866 | public vector_interface<T> | |
9867 | { | |
9868 | public: | |
9869 | ||
9870 | typedef expression_node<T>* expression_ptr; | |
9871 | typedef vector_node<T>* vector_node_ptr; | |
9872 | typedef vec_data_store<T> vds_t; | |
9873 | ||
9874 | assignment_vecvec_node(const operator_type& opr, | |
9875 | expression_ptr branch0, | |
9876 | expression_ptr branch1) | |
9877 | : binary_node<T>(opr, branch0, branch1), | |
9878 | vec0_node_ptr_(0), | |
9879 | vec1_node_ptr_(0), | |
9880 | initialised_(false), | |
9881 | src_is_ivec_(false) | |
9882 | { | |
9883 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
9884 | { | |
9885 | vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); | |
9886 | vds() = vec0_node_ptr_->vds(); | |
9887 | } | |
9888 | ||
9889 | if (is_vector_node(binary_node<T>::branch_[1].first)) | |
9890 | { | |
9891 | vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); | |
9892 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); | |
9893 | } | |
9894 | else if (is_ivector_node(binary_node<T>::branch_[1].first)) | |
9895 | { | |
9896 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
9897 | ||
9898 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) | |
9899 | { | |
9900 | vec1_node_ptr_ = vi->vec(); | |
9901 | ||
9902 | if (!vi->side_effect()) | |
9903 | { | |
9904 | vi->vds() = vds(); | |
9905 | src_is_ivec_ = true; | |
9906 | } | |
9907 | else | |
9908 | vds_t::match_sizes(vds(),vi->vds()); | |
9909 | } | |
9910 | } | |
9911 | ||
9912 | initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); | |
9913 | } | |
9914 | ||
9915 | inline T value() const | |
9916 | { | |
9917 | if (initialised_) | |
9918 | { | |
9919 | binary_node<T>::branch_[1].first->value(); | |
9920 | ||
9921 | if (src_is_ivec_) | |
9922 | return vec0_node_ptr_->value(); | |
9923 | ||
9924 | T* vec0 = vec0_node_ptr_->vds().data(); | |
9925 | T* vec1 = vec1_node_ptr_->vds().data(); | |
9926 | ||
9927 | loop_unroll::details lud(size()); | |
9928 | const T* upper_bound = vec0 + lud.upper_bound; | |
9929 | ||
9930 | while (vec0 < upper_bound) | |
9931 | { | |
9932 | #define exprtk_loop(N) \ | |
9933 | vec0[N] = vec1[N]; \ | |
9934 | ||
9935 | exprtk_loop( 0) exprtk_loop( 1) | |
9936 | exprtk_loop( 2) exprtk_loop( 3) | |
9937 | #ifndef exprtk_disable_superscalar_unroll | |
9938 | exprtk_loop( 4) exprtk_loop( 5) | |
9939 | exprtk_loop( 6) exprtk_loop( 7) | |
9940 | exprtk_loop( 8) exprtk_loop( 9) | |
9941 | exprtk_loop(10) exprtk_loop(11) | |
9942 | exprtk_loop(12) exprtk_loop(13) | |
9943 | exprtk_loop(14) exprtk_loop(15) | |
9944 | #endif | |
9945 | ||
9946 | vec0 += lud.batch_size; | |
9947 | vec1 += lud.batch_size; | |
9948 | } | |
9949 | ||
9950 | exprtk_disable_fallthrough_begin | |
9951 | switch (lud.remainder) | |
9952 | { | |
9953 | #define case_stmt(N) \ | |
9954 | case N : *vec0++ = *vec1++; \ | |
9955 | ||
9956 | #ifndef exprtk_disable_superscalar_unroll | |
9957 | case_stmt(15) case_stmt(14) | |
9958 | case_stmt(13) case_stmt(12) | |
9959 | case_stmt(11) case_stmt(10) | |
9960 | case_stmt( 9) case_stmt( 8) | |
9961 | case_stmt( 7) case_stmt( 6) | |
9962 | case_stmt( 5) case_stmt( 4) | |
9963 | #endif | |
9964 | case_stmt( 3) case_stmt( 2) | |
9965 | case_stmt( 1) | |
9966 | } | |
9967 | exprtk_disable_fallthrough_end | |
9968 | ||
9969 | #undef exprtk_loop | |
9970 | #undef case_stmt | |
9971 | ||
9972 | return vec0_node_ptr_->value(); | |
9973 | } | |
9974 | else | |
9975 | return std::numeric_limits<T>::quiet_NaN(); | |
9976 | } | |
9977 | ||
9978 | vector_node_ptr vec() const | |
9979 | { | |
9980 | return vec0_node_ptr_; | |
9981 | } | |
9982 | ||
9983 | vector_node_ptr vec() | |
9984 | { | |
9985 | return vec0_node_ptr_; | |
9986 | } | |
9987 | ||
9988 | inline typename expression_node<T>::node_type type() const | |
9989 | { | |
9990 | return expression_node<T>::e_vecvecass; | |
9991 | } | |
9992 | ||
9993 | std::size_t size() const | |
9994 | { | |
9995 | return vds().size(); | |
9996 | } | |
9997 | ||
9998 | vds_t& vds() | |
9999 | { | |
10000 | return vds_; | |
10001 | } | |
10002 | ||
10003 | const vds_t& vds() const | |
10004 | { | |
10005 | return vds_; | |
10006 | } | |
10007 | ||
10008 | private: | |
10009 | ||
10010 | vector_node<T>* vec0_node_ptr_; | |
10011 | vector_node<T>* vec1_node_ptr_; | |
10012 | bool initialised_; | |
10013 | bool src_is_ivec_; | |
10014 | vds_t vds_; | |
10015 | }; | |
10016 | ||
10017 | template <typename T, typename Operation> | |
10018 | class assignment_op_node : public binary_node<T> | |
10019 | { | |
10020 | public: | |
10021 | ||
10022 | typedef expression_node<T>* expression_ptr; | |
10023 | ||
10024 | assignment_op_node(const operator_type& opr, | |
10025 | expression_ptr branch0, | |
10026 | expression_ptr branch1) | |
10027 | : binary_node<T>(opr, branch0, branch1), | |
10028 | var_node_ptr_(0) | |
10029 | { | |
10030 | if (is_variable_node(binary_node<T>::branch_[0].first)) | |
10031 | { | |
10032 | var_node_ptr_ = static_cast<variable_node<T>*>(binary_node<T>::branch_[0].first); | |
10033 | } | |
10034 | } | |
10035 | ||
10036 | inline T value() const | |
10037 | { | |
10038 | if (var_node_ptr_) | |
10039 | { | |
10040 | T& v = var_node_ptr_->ref(); | |
10041 | v = Operation::process(v,binary_node<T>::branch_[1].first->value()); | |
10042 | ||
10043 | return v; | |
10044 | } | |
10045 | else | |
10046 | return std::numeric_limits<T>::quiet_NaN(); | |
10047 | } | |
10048 | ||
10049 | private: | |
10050 | ||
10051 | variable_node<T>* var_node_ptr_; | |
10052 | }; | |
10053 | ||
10054 | template <typename T, typename Operation> | |
10055 | class assignment_vec_elem_op_node : public binary_node<T> | |
10056 | { | |
10057 | public: | |
10058 | ||
10059 | typedef expression_node<T>* expression_ptr; | |
10060 | ||
10061 | assignment_vec_elem_op_node(const operator_type& opr, | |
10062 | expression_ptr branch0, | |
10063 | expression_ptr branch1) | |
10064 | : binary_node<T>(opr, branch0, branch1), | |
10065 | vec_node_ptr_(0) | |
10066 | { | |
10067 | if (is_vector_elem_node(binary_node<T>::branch_[0].first)) | |
10068 | { | |
10069 | vec_node_ptr_ = static_cast<vector_elem_node<T>*>(binary_node<T>::branch_[0].first); | |
10070 | } | |
10071 | } | |
10072 | ||
10073 | inline T value() const | |
10074 | { | |
10075 | if (vec_node_ptr_) | |
10076 | { | |
10077 | T& v = vec_node_ptr_->ref(); | |
10078 | v = Operation::process(v,binary_node<T>::branch_[1].first->value()); | |
10079 | ||
10080 | return v; | |
10081 | } | |
10082 | else | |
10083 | return std::numeric_limits<T>::quiet_NaN(); | |
10084 | } | |
10085 | ||
10086 | private: | |
10087 | ||
10088 | vector_elem_node<T>* vec_node_ptr_; | |
10089 | }; | |
10090 | ||
10091 | template <typename T, typename Operation> | |
10092 | class assignment_rebasevec_elem_op_node : public binary_node<T> | |
10093 | { | |
10094 | public: | |
10095 | ||
10096 | typedef expression_node<T>* expression_ptr; | |
10097 | ||
10098 | assignment_rebasevec_elem_op_node(const operator_type& opr, | |
10099 | expression_ptr branch0, | |
10100 | expression_ptr branch1) | |
10101 | : binary_node<T>(opr, branch0, branch1), | |
10102 | rbvec_node_ptr_(0) | |
10103 | { | |
10104 | if (is_rebasevector_elem_node(binary_node<T>::branch_[0].first)) | |
10105 | { | |
10106 | rbvec_node_ptr_ = static_cast<rebasevector_elem_node<T>*>(binary_node<T>::branch_[0].first); | |
10107 | } | |
10108 | } | |
10109 | ||
10110 | inline T value() const | |
10111 | { | |
10112 | if (rbvec_node_ptr_) | |
10113 | { | |
10114 | T& v = rbvec_node_ptr_->ref(); | |
10115 | v = Operation::process(v,binary_node<T>::branch_[1].first->value()); | |
10116 | ||
10117 | return v; | |
10118 | } | |
10119 | else | |
10120 | return std::numeric_limits<T>::quiet_NaN(); | |
10121 | } | |
10122 | ||
10123 | private: | |
10124 | ||
10125 | rebasevector_elem_node<T>* rbvec_node_ptr_; | |
10126 | }; | |
10127 | ||
10128 | template <typename T, typename Operation> | |
10129 | class assignment_rebasevec_celem_op_node : public binary_node<T> | |
10130 | { | |
10131 | public: | |
10132 | ||
10133 | typedef expression_node<T>* expression_ptr; | |
10134 | ||
10135 | assignment_rebasevec_celem_op_node(const operator_type& opr, | |
10136 | expression_ptr branch0, | |
10137 | expression_ptr branch1) | |
10138 | : binary_node<T>(opr, branch0, branch1), | |
10139 | rbvec_node_ptr_(0) | |
10140 | { | |
10141 | if (is_rebasevector_celem_node(binary_node<T>::branch_[0].first)) | |
10142 | { | |
10143 | rbvec_node_ptr_ = static_cast<rebasevector_celem_node<T>*>(binary_node<T>::branch_[0].first); | |
10144 | } | |
10145 | } | |
10146 | ||
10147 | inline T value() const | |
10148 | { | |
10149 | if (rbvec_node_ptr_) | |
10150 | { | |
10151 | T& v = rbvec_node_ptr_->ref(); | |
10152 | v = Operation::process(v,binary_node<T>::branch_[1].first->value()); | |
10153 | ||
10154 | return v; | |
10155 | } | |
10156 | else | |
10157 | return std::numeric_limits<T>::quiet_NaN(); | |
10158 | } | |
10159 | ||
10160 | private: | |
10161 | ||
10162 | rebasevector_celem_node<T>* rbvec_node_ptr_; | |
10163 | }; | |
10164 | ||
10165 | template <typename T, typename Operation> | |
10166 | class assignment_vec_op_node : public binary_node <T>, | |
10167 | public vector_interface<T> | |
10168 | { | |
10169 | public: | |
10170 | ||
10171 | typedef expression_node<T>* expression_ptr; | |
10172 | typedef vector_node<T>* vector_node_ptr; | |
10173 | typedef vec_data_store<T> vds_t; | |
10174 | ||
10175 | assignment_vec_op_node(const operator_type& opr, | |
10176 | expression_ptr branch0, | |
10177 | expression_ptr branch1) | |
10178 | : binary_node<T>(opr, branch0, branch1), | |
10179 | vec_node_ptr_(0) | |
10180 | { | |
10181 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
10182 | { | |
10183 | vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); | |
10184 | vds() = vec_node_ptr_->vds(); | |
10185 | } | |
10186 | } | |
10187 | ||
10188 | inline T value() const | |
10189 | { | |
10190 | if (vec_node_ptr_) | |
10191 | { | |
10192 | const T v = binary_node<T>::branch_[1].first->value(); | |
10193 | ||
10194 | T* vec = vds().data(); | |
10195 | ||
10196 | loop_unroll::details lud(size()); | |
10197 | const T* upper_bound = vec + lud.upper_bound; | |
10198 | ||
10199 | while (vec < upper_bound) | |
10200 | { | |
10201 | #define exprtk_loop(N) \ | |
10202 | Operation::assign(vec[N],v); \ | |
10203 | ||
10204 | exprtk_loop( 0) exprtk_loop( 1) | |
10205 | exprtk_loop( 2) exprtk_loop( 3) | |
10206 | #ifndef exprtk_disable_superscalar_unroll | |
10207 | exprtk_loop( 4) exprtk_loop( 5) | |
10208 | exprtk_loop( 6) exprtk_loop( 7) | |
10209 | exprtk_loop( 8) exprtk_loop( 9) | |
10210 | exprtk_loop(10) exprtk_loop(11) | |
10211 | exprtk_loop(12) exprtk_loop(13) | |
10212 | exprtk_loop(14) exprtk_loop(15) | |
10213 | #endif | |
10214 | ||
10215 | vec += lud.batch_size; | |
10216 | } | |
10217 | ||
10218 | exprtk_disable_fallthrough_begin | |
10219 | switch (lud.remainder) | |
10220 | { | |
10221 | #define case_stmt(N) \ | |
10222 | case N : Operation::assign(*vec++,v); \ | |
10223 | ||
10224 | #ifndef exprtk_disable_superscalar_unroll | |
10225 | case_stmt(15) case_stmt(14) | |
10226 | case_stmt(13) case_stmt(12) | |
10227 | case_stmt(11) case_stmt(10) | |
10228 | case_stmt( 9) case_stmt( 8) | |
10229 | case_stmt( 7) case_stmt( 6) | |
10230 | case_stmt( 5) case_stmt( 4) | |
10231 | #endif | |
10232 | case_stmt( 3) case_stmt( 2) | |
10233 | case_stmt( 1) | |
10234 | } | |
10235 | exprtk_disable_fallthrough_end | |
10236 | ||
10237 | ||
10238 | #undef exprtk_loop | |
10239 | #undef case_stmt | |
10240 | ||
10241 | return vec_node_ptr_->value(); | |
10242 | } | |
10243 | else | |
10244 | return std::numeric_limits<T>::quiet_NaN(); | |
10245 | } | |
10246 | ||
10247 | vector_node_ptr vec() const | |
10248 | { | |
10249 | return vec_node_ptr_; | |
10250 | } | |
10251 | ||
10252 | vector_node_ptr vec() | |
10253 | { | |
10254 | return vec_node_ptr_; | |
10255 | } | |
10256 | ||
10257 | inline typename expression_node<T>::node_type type() const | |
10258 | { | |
10259 | return expression_node<T>::e_vecopvalass; | |
10260 | } | |
10261 | ||
10262 | std::size_t size() const | |
10263 | { | |
10264 | return vds().size(); | |
10265 | } | |
10266 | ||
10267 | vds_t& vds() | |
10268 | { | |
10269 | return vds_; | |
10270 | } | |
10271 | ||
10272 | const vds_t& vds() const | |
10273 | { | |
10274 | return vds_; | |
10275 | } | |
10276 | ||
10277 | bool side_effect() const | |
10278 | { | |
10279 | return true; | |
10280 | } | |
10281 | ||
10282 | private: | |
10283 | ||
10284 | vector_node<T>* vec_node_ptr_; | |
10285 | vds_t vds_; | |
10286 | }; | |
10287 | ||
10288 | template <typename T, typename Operation> | |
10289 | class assignment_vecvec_op_node : public binary_node <T>, | |
10290 | public vector_interface<T> | |
10291 | { | |
10292 | public: | |
10293 | ||
10294 | typedef expression_node<T>* expression_ptr; | |
10295 | typedef vector_node<T>* vector_node_ptr; | |
10296 | typedef vec_data_store<T> vds_t; | |
10297 | ||
10298 | assignment_vecvec_op_node(const operator_type& opr, | |
10299 | expression_ptr branch0, | |
10300 | expression_ptr branch1) | |
10301 | : binary_node<T>(opr, branch0, branch1), | |
10302 | vec0_node_ptr_(0), | |
10303 | vec1_node_ptr_(0), | |
10304 | initialised_(false) | |
10305 | { | |
10306 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
10307 | { | |
10308 | vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first); | |
10309 | vds() = vec0_node_ptr_->vds(); | |
10310 | } | |
10311 | ||
10312 | if (is_vector_node(binary_node<T>::branch_[1].first)) | |
10313 | { | |
10314 | vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first); | |
10315 | vec1_node_ptr_->vds() = vds(); | |
10316 | } | |
10317 | else if (is_ivector_node(binary_node<T>::branch_[1].first)) | |
10318 | { | |
10319 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10320 | ||
10321 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) | |
10322 | { | |
10323 | vec1_node_ptr_ = vi->vec(); | |
10324 | vec1_node_ptr_->vds() = vds(); | |
10325 | } | |
10326 | else | |
10327 | vds_t::match_sizes(vds(),vec1_node_ptr_->vds()); | |
10328 | } | |
10329 | ||
10330 | initialised_ = (vec0_node_ptr_ && vec1_node_ptr_); | |
10331 | } | |
10332 | ||
10333 | inline T value() const | |
10334 | { | |
10335 | if (initialised_) | |
10336 | { | |
10337 | binary_node<T>::branch_[0].first->value(); | |
10338 | binary_node<T>::branch_[1].first->value(); | |
10339 | ||
10340 | T* vec0 = vec0_node_ptr_->vds().data(); | |
10341 | const T* vec1 = vec1_node_ptr_->vds().data(); | |
10342 | ||
10343 | loop_unroll::details lud(size()); | |
10344 | const T* upper_bound = vec0 + lud.upper_bound; | |
10345 | ||
10346 | while (vec0 < upper_bound) | |
10347 | { | |
10348 | #define exprtk_loop(N) \ | |
10349 | vec0[N] = Operation::process(vec0[N], vec1[N]); \ | |
10350 | ||
10351 | exprtk_loop( 0) exprtk_loop( 1) | |
10352 | exprtk_loop( 2) exprtk_loop( 3) | |
10353 | #ifndef exprtk_disable_superscalar_unroll | |
10354 | exprtk_loop( 4) exprtk_loop( 5) | |
10355 | exprtk_loop( 6) exprtk_loop( 7) | |
10356 | exprtk_loop( 8) exprtk_loop( 9) | |
10357 | exprtk_loop(10) exprtk_loop(11) | |
10358 | exprtk_loop(12) exprtk_loop(13) | |
10359 | exprtk_loop(14) exprtk_loop(15) | |
10360 | #endif | |
10361 | ||
10362 | vec0 += lud.batch_size; | |
10363 | vec1 += lud.batch_size; | |
10364 | } | |
10365 | ||
10366 | int i = 0; | |
10367 | ||
10368 | exprtk_disable_fallthrough_begin | |
10369 | switch (lud.remainder) | |
10370 | { | |
10371 | #define case_stmt(N) \ | |
10372 | case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ | |
10373 | ||
10374 | #ifndef exprtk_disable_superscalar_unroll | |
10375 | case_stmt(15) case_stmt(14) | |
10376 | case_stmt(13) case_stmt(12) | |
10377 | case_stmt(11) case_stmt(10) | |
10378 | case_stmt( 9) case_stmt( 8) | |
10379 | case_stmt( 7) case_stmt( 6) | |
10380 | case_stmt( 5) case_stmt( 4) | |
10381 | #endif | |
10382 | case_stmt( 3) case_stmt( 2) | |
10383 | case_stmt( 1) | |
10384 | } | |
10385 | exprtk_disable_fallthrough_end | |
10386 | ||
10387 | #undef exprtk_loop | |
10388 | #undef case_stmt | |
10389 | ||
10390 | return vec0_node_ptr_->value(); | |
10391 | } | |
10392 | else | |
10393 | return std::numeric_limits<T>::quiet_NaN(); | |
10394 | } | |
10395 | ||
10396 | vector_node_ptr vec() const | |
10397 | { | |
10398 | return vec0_node_ptr_; | |
10399 | } | |
10400 | ||
10401 | vector_node_ptr vec() | |
10402 | { | |
10403 | return vec0_node_ptr_; | |
10404 | } | |
10405 | ||
10406 | inline typename expression_node<T>::node_type type() const | |
10407 | { | |
10408 | return expression_node<T>::e_vecopvecass; | |
10409 | } | |
10410 | ||
10411 | std::size_t size() const | |
10412 | { | |
10413 | return vds().size(); | |
10414 | } | |
10415 | ||
10416 | vds_t& vds() | |
10417 | { | |
10418 | return vds_; | |
10419 | } | |
10420 | ||
10421 | const vds_t& vds() const | |
10422 | { | |
10423 | return vds_; | |
10424 | } | |
10425 | ||
10426 | bool side_effect() const | |
10427 | { | |
10428 | return true; | |
10429 | } | |
10430 | ||
10431 | private: | |
10432 | ||
10433 | vector_node<T>* vec0_node_ptr_; | |
10434 | vector_node<T>* vec1_node_ptr_; | |
10435 | bool initialised_; | |
10436 | vds_t vds_; | |
10437 | }; | |
10438 | ||
10439 | template <typename T, typename Operation> | |
10440 | class vec_binop_vecvec_node : public binary_node <T>, | |
10441 | public vector_interface<T> | |
10442 | { | |
10443 | public: | |
10444 | ||
10445 | typedef expression_node<T>* expression_ptr; | |
10446 | typedef vector_node<T>* vector_node_ptr; | |
10447 | typedef vector_holder<T>* vector_holder_ptr; | |
10448 | typedef vec_data_store<T> vds_t; | |
10449 | ||
10450 | vec_binop_vecvec_node(const operator_type& opr, | |
10451 | expression_ptr branch0, | |
10452 | expression_ptr branch1) | |
10453 | : binary_node<T>(opr, branch0, branch1), | |
10454 | vec0_node_ptr_(0), | |
10455 | vec1_node_ptr_(0), | |
10456 | temp_ (0), | |
10457 | temp_vec_node_(0), | |
10458 | initialised_(false) | |
10459 | { | |
10460 | bool v0_is_ivec = false; | |
10461 | bool v1_is_ivec = false; | |
10462 | ||
10463 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
10464 | { | |
10465 | vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first); | |
10466 | } | |
10467 | else if (is_ivector_node(binary_node<T>::branch_[0].first)) | |
10468 | { | |
10469 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10470 | ||
10471 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) | |
10472 | { | |
10473 | vec0_node_ptr_ = vi->vec(); | |
10474 | v0_is_ivec = true; | |
10475 | } | |
10476 | } | |
10477 | ||
10478 | if (is_vector_node(binary_node<T>::branch_[1].first)) | |
10479 | { | |
10480 | vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first); | |
10481 | } | |
10482 | else if (is_ivector_node(binary_node<T>::branch_[1].first)) | |
10483 | { | |
10484 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10485 | ||
10486 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) | |
10487 | { | |
10488 | vec1_node_ptr_ = vi->vec(); | |
10489 | v1_is_ivec = true; | |
10490 | } | |
10491 | } | |
10492 | ||
10493 | if (vec0_node_ptr_ && vec1_node_ptr_) | |
10494 | { | |
10495 | vector_holder<T>& vec0 = vec0_node_ptr_->vec_holder(); | |
10496 | vector_holder<T>& vec1 = vec1_node_ptr_->vec_holder(); | |
10497 | ||
10498 | if (v0_is_ivec && (vec0.size() <= vec1.size())) | |
10499 | vds_ = vds_t(vec0_node_ptr_->vds()); | |
10500 | else if (v1_is_ivec && (vec1.size() <= vec0.size())) | |
10501 | vds_ = vds_t(vec1_node_ptr_->vds()); | |
10502 | else | |
10503 | vds_ = vds_t(std::min(vec0.size(),vec1.size())); | |
10504 | ||
10505 | temp_ = new vector_holder<T>(vds().data(),vds().size()); | |
10506 | temp_vec_node_ = new vector_node<T> (vds(),temp_); | |
10507 | ||
10508 | initialised_ = true; | |
10509 | } | |
10510 | } | |
10511 | ||
10512 | ~vec_binop_vecvec_node() | |
10513 | { | |
10514 | delete temp_; | |
10515 | delete temp_vec_node_; | |
10516 | } | |
10517 | ||
10518 | inline T value() const | |
10519 | { | |
10520 | if (initialised_) | |
10521 | { | |
10522 | binary_node<T>::branch_[0].first->value(); | |
10523 | binary_node<T>::branch_[1].first->value(); | |
10524 | ||
10525 | const T* vec0 = vec0_node_ptr_->vds().data(); | |
10526 | const T* vec1 = vec1_node_ptr_->vds().data(); | |
10527 | T* vec2 = vds().data(); | |
10528 | ||
10529 | loop_unroll::details lud(size()); | |
10530 | const T* upper_bound = vec2 + lud.upper_bound; | |
10531 | ||
10532 | while (vec2 < upper_bound) | |
10533 | { | |
10534 | #define exprtk_loop(N) \ | |
10535 | vec2[N] = Operation::process(vec0[N], vec1[N]); \ | |
10536 | ||
10537 | exprtk_loop( 0) exprtk_loop( 1) | |
10538 | exprtk_loop( 2) exprtk_loop( 3) | |
10539 | #ifndef exprtk_disable_superscalar_unroll | |
10540 | exprtk_loop( 4) exprtk_loop( 5) | |
10541 | exprtk_loop( 6) exprtk_loop( 7) | |
10542 | exprtk_loop( 8) exprtk_loop( 9) | |
10543 | exprtk_loop(10) exprtk_loop(11) | |
10544 | exprtk_loop(12) exprtk_loop(13) | |
10545 | exprtk_loop(14) exprtk_loop(15) | |
10546 | #endif | |
10547 | ||
10548 | vec0 += lud.batch_size; | |
10549 | vec1 += lud.batch_size; | |
10550 | vec2 += lud.batch_size; | |
10551 | } | |
10552 | ||
10553 | int i = 0; | |
10554 | ||
10555 | exprtk_disable_fallthrough_begin | |
10556 | switch (lud.remainder) | |
10557 | { | |
10558 | #define case_stmt(N) \ | |
10559 | case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ | |
10560 | ||
10561 | #ifndef exprtk_disable_superscalar_unroll | |
10562 | case_stmt(15) case_stmt(14) | |
10563 | case_stmt(13) case_stmt(12) | |
10564 | case_stmt(11) case_stmt(10) | |
10565 | case_stmt( 9) case_stmt( 8) | |
10566 | case_stmt( 7) case_stmt( 6) | |
10567 | case_stmt( 5) case_stmt( 4) | |
10568 | #endif | |
10569 | case_stmt( 3) case_stmt( 2) | |
10570 | case_stmt( 1) | |
10571 | } | |
10572 | exprtk_disable_fallthrough_end | |
10573 | ||
10574 | #undef exprtk_loop | |
10575 | #undef case_stmt | |
10576 | ||
10577 | return (vds().data())[0]; | |
10578 | } | |
10579 | else | |
10580 | return std::numeric_limits<T>::quiet_NaN(); | |
10581 | } | |
10582 | ||
10583 | vector_node_ptr vec() const | |
10584 | { | |
10585 | return temp_vec_node_; | |
10586 | } | |
10587 | ||
10588 | vector_node_ptr vec() | |
10589 | { | |
10590 | return temp_vec_node_; | |
10591 | } | |
10592 | ||
10593 | inline typename expression_node<T>::node_type type() const | |
10594 | { | |
10595 | return expression_node<T>::e_vecvecarith; | |
10596 | } | |
10597 | ||
10598 | std::size_t size() const | |
10599 | { | |
10600 | return vds_.size(); | |
10601 | } | |
10602 | ||
10603 | vds_t& vds() | |
10604 | { | |
10605 | return vds_; | |
10606 | } | |
10607 | ||
10608 | const vds_t& vds() const | |
10609 | { | |
10610 | return vds_; | |
10611 | } | |
10612 | ||
10613 | private: | |
10614 | ||
10615 | vector_node_ptr vec0_node_ptr_; | |
10616 | vector_node_ptr vec1_node_ptr_; | |
10617 | vector_holder_ptr temp_; | |
10618 | vector_node_ptr temp_vec_node_; | |
10619 | bool initialised_; | |
10620 | vds_t vds_; | |
10621 | }; | |
10622 | ||
10623 | template <typename T, typename Operation> | |
10624 | class vec_binop_vecval_node : public binary_node <T>, | |
10625 | public vector_interface<T> | |
10626 | { | |
10627 | public: | |
10628 | ||
10629 | typedef expression_node<T>* expression_ptr; | |
10630 | typedef vector_node<T>* vector_node_ptr; | |
10631 | typedef vector_holder<T>* vector_holder_ptr; | |
10632 | typedef vec_data_store<T> vds_t; | |
10633 | ||
10634 | vec_binop_vecval_node(const operator_type& opr, | |
10635 | expression_ptr branch0, | |
10636 | expression_ptr branch1) | |
10637 | : binary_node<T>(opr, branch0, branch1), | |
10638 | vec0_node_ptr_(0), | |
10639 | temp_ (0), | |
10640 | temp_vec_node_(0) | |
10641 | { | |
10642 | bool v0_is_ivec = false; | |
10643 | ||
10644 | if (is_vector_node(binary_node<T>::branch_[0].first)) | |
10645 | { | |
10646 | vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first); | |
10647 | } | |
10648 | else if (is_ivector_node(binary_node<T>::branch_[0].first)) | |
10649 | { | |
10650 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10651 | ||
10652 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first))) | |
10653 | { | |
10654 | vec0_node_ptr_ = vi->vec(); | |
10655 | v0_is_ivec = true; | |
10656 | } | |
10657 | } | |
10658 | ||
10659 | if (vec0_node_ptr_) | |
10660 | { | |
10661 | if (v0_is_ivec) | |
10662 | vds() = vec0_node_ptr_->vds(); | |
10663 | else | |
10664 | vds() = vds_t(vec0_node_ptr_->size()); | |
10665 | ||
10666 | temp_ = new vector_holder<T>(vds()); | |
10667 | temp_vec_node_ = new vector_node<T> (vds(),temp_); | |
10668 | } | |
10669 | } | |
10670 | ||
10671 | ~vec_binop_vecval_node() | |
10672 | { | |
10673 | delete temp_; | |
10674 | delete temp_vec_node_; | |
10675 | } | |
10676 | ||
10677 | inline T value() const | |
10678 | { | |
10679 | if (vec0_node_ptr_) | |
10680 | { | |
10681 | binary_node<T>::branch_[0].first->value(); | |
10682 | const T v = binary_node<T>::branch_[1].first->value(); | |
10683 | ||
10684 | const T* vec0 = vec0_node_ptr_->vds().data(); | |
10685 | T* vec1 = vds().data(); | |
10686 | ||
10687 | loop_unroll::details lud(size()); | |
10688 | const T* upper_bound = vec0 + lud.upper_bound; | |
10689 | ||
10690 | while (vec0 < upper_bound) | |
10691 | { | |
10692 | #define exprtk_loop(N) \ | |
10693 | vec1[N] = Operation::process(vec0[N], v); \ | |
10694 | ||
10695 | exprtk_loop( 0) exprtk_loop( 1) | |
10696 | exprtk_loop( 2) exprtk_loop( 3) | |
10697 | #ifndef exprtk_disable_superscalar_unroll | |
10698 | exprtk_loop( 4) exprtk_loop( 5) | |
10699 | exprtk_loop( 6) exprtk_loop( 7) | |
10700 | exprtk_loop( 8) exprtk_loop( 9) | |
10701 | exprtk_loop(10) exprtk_loop(11) | |
10702 | exprtk_loop(12) exprtk_loop(13) | |
10703 | exprtk_loop(14) exprtk_loop(15) | |
10704 | #endif | |
10705 | ||
10706 | vec0 += lud.batch_size; | |
10707 | vec1 += lud.batch_size; | |
10708 | } | |
10709 | ||
10710 | int i = 0; | |
10711 | ||
10712 | exprtk_disable_fallthrough_begin | |
10713 | switch (lud.remainder) | |
10714 | { | |
10715 | #define case_stmt(N) \ | |
10716 | case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ | |
10717 | ||
10718 | #ifndef exprtk_disable_superscalar_unroll | |
10719 | case_stmt(15) case_stmt(14) | |
10720 | case_stmt(13) case_stmt(12) | |
10721 | case_stmt(11) case_stmt(10) | |
10722 | case_stmt( 9) case_stmt( 8) | |
10723 | case_stmt( 7) case_stmt( 6) | |
10724 | case_stmt( 5) case_stmt( 4) | |
10725 | #endif | |
10726 | case_stmt( 3) case_stmt( 2) | |
10727 | case_stmt( 1) | |
10728 | } | |
10729 | exprtk_disable_fallthrough_end | |
10730 | ||
10731 | #undef exprtk_loop | |
10732 | #undef case_stmt | |
10733 | ||
10734 | return (vds().data())[0]; | |
10735 | } | |
10736 | else | |
10737 | return std::numeric_limits<T>::quiet_NaN(); | |
10738 | } | |
10739 | ||
10740 | vector_node_ptr vec() const | |
10741 | { | |
10742 | return temp_vec_node_; | |
10743 | } | |
10744 | ||
10745 | vector_node_ptr vec() | |
10746 | { | |
10747 | return temp_vec_node_; | |
10748 | } | |
10749 | ||
10750 | inline typename expression_node<T>::node_type type() const | |
10751 | { | |
10752 | return expression_node<T>::e_vecvalarith; | |
10753 | } | |
10754 | ||
10755 | std::size_t size() const | |
10756 | { | |
10757 | return vds().size(); | |
10758 | } | |
10759 | ||
10760 | vds_t& vds() | |
10761 | { | |
10762 | return vds_; | |
10763 | } | |
10764 | ||
10765 | const vds_t& vds() const | |
10766 | { | |
10767 | return vds_; | |
10768 | } | |
10769 | ||
10770 | private: | |
10771 | ||
10772 | vector_node_ptr vec0_node_ptr_; | |
10773 | vector_holder_ptr temp_; | |
10774 | vector_node_ptr temp_vec_node_; | |
10775 | vds_t vds_; | |
10776 | }; | |
10777 | ||
10778 | template <typename T, typename Operation> | |
10779 | class vec_binop_valvec_node : public binary_node <T>, | |
10780 | public vector_interface<T> | |
10781 | { | |
10782 | public: | |
10783 | ||
10784 | typedef expression_node<T>* expression_ptr; | |
10785 | typedef vector_node<T>* vector_node_ptr; | |
10786 | typedef vector_holder<T>* vector_holder_ptr; | |
10787 | typedef vec_data_store<T> vds_t; | |
10788 | ||
10789 | vec_binop_valvec_node(const operator_type& opr, | |
10790 | expression_ptr branch0, | |
10791 | expression_ptr branch1) | |
10792 | : binary_node<T>(opr, branch0, branch1), | |
10793 | vec1_node_ptr_(0), | |
10794 | temp_ (0), | |
10795 | temp_vec_node_(0) | |
10796 | { | |
10797 | bool v1_is_ivec = false; | |
10798 | ||
10799 | if (is_vector_node(binary_node<T>::branch_[1].first)) | |
10800 | { | |
10801 | vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first); | |
10802 | } | |
10803 | else if (is_ivector_node(binary_node<T>::branch_[1].first)) | |
10804 | { | |
10805 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10806 | ||
10807 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first))) | |
10808 | { | |
10809 | vec1_node_ptr_ = vi->vec(); | |
10810 | v1_is_ivec = true; | |
10811 | } | |
10812 | } | |
10813 | ||
10814 | if (vec1_node_ptr_) | |
10815 | { | |
10816 | if (v1_is_ivec) | |
10817 | vds() = vec1_node_ptr_->vds(); | |
10818 | else | |
10819 | vds() = vds_t(vec1_node_ptr_->size()); | |
10820 | ||
10821 | temp_ = new vector_holder<T>(vds()); | |
10822 | temp_vec_node_ = new vector_node<T> (vds(),temp_); | |
10823 | } | |
10824 | } | |
10825 | ||
10826 | ~vec_binop_valvec_node() | |
10827 | { | |
10828 | delete temp_; | |
10829 | delete temp_vec_node_; | |
10830 | } | |
10831 | ||
10832 | inline T value() const | |
10833 | { | |
10834 | if (vec1_node_ptr_) | |
10835 | { | |
10836 | const T v = binary_node<T>::branch_[0].first->value(); | |
10837 | binary_node<T>::branch_[1].first->value(); | |
10838 | ||
10839 | T* vec0 = vds().data(); | |
10840 | const T* vec1 = vec1_node_ptr_->vds().data(); | |
10841 | ||
10842 | loop_unroll::details lud(size()); | |
10843 | const T* upper_bound = vec0 + lud.upper_bound; | |
10844 | ||
10845 | while (vec0 < upper_bound) | |
10846 | { | |
10847 | #define exprtk_loop(N) \ | |
10848 | vec0[N] = Operation::process(v, vec1[N]); \ | |
10849 | ||
10850 | exprtk_loop( 0) exprtk_loop( 1) | |
10851 | exprtk_loop( 2) exprtk_loop( 3) | |
10852 | #ifndef exprtk_disable_superscalar_unroll | |
10853 | exprtk_loop( 4) exprtk_loop( 5) | |
10854 | exprtk_loop( 6) exprtk_loop( 7) | |
10855 | exprtk_loop( 8) exprtk_loop( 9) | |
10856 | exprtk_loop(10) exprtk_loop(11) | |
10857 | exprtk_loop(12) exprtk_loop(13) | |
10858 | exprtk_loop(14) exprtk_loop(15) | |
10859 | #endif | |
10860 | ||
10861 | vec0 += lud.batch_size; | |
10862 | vec1 += lud.batch_size; | |
10863 | } | |
10864 | ||
10865 | int i = 0; | |
10866 | ||
10867 | exprtk_disable_fallthrough_begin | |
10868 | switch (lud.remainder) | |
10869 | { | |
10870 | #define case_stmt(N) \ | |
10871 | case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ | |
10872 | ||
10873 | #ifndef exprtk_disable_superscalar_unroll | |
10874 | case_stmt(15) case_stmt(14) | |
10875 | case_stmt(13) case_stmt(12) | |
10876 | case_stmt(11) case_stmt(10) | |
10877 | case_stmt( 9) case_stmt( 8) | |
10878 | case_stmt( 7) case_stmt( 6) | |
10879 | case_stmt( 5) case_stmt( 4) | |
10880 | #endif | |
10881 | case_stmt( 3) case_stmt( 2) | |
10882 | case_stmt( 1) | |
10883 | } | |
10884 | exprtk_disable_fallthrough_end | |
10885 | ||
10886 | #undef exprtk_loop | |
10887 | #undef case_stmt | |
10888 | ||
10889 | return (vds().data())[0]; | |
10890 | } | |
10891 | else | |
10892 | return std::numeric_limits<T>::quiet_NaN(); | |
10893 | } | |
10894 | ||
10895 | vector_node_ptr vec() const | |
10896 | { | |
10897 | return temp_vec_node_; | |
10898 | } | |
10899 | ||
10900 | vector_node_ptr vec() | |
10901 | { | |
10902 | return temp_vec_node_; | |
10903 | } | |
10904 | ||
10905 | inline typename expression_node<T>::node_type type() const | |
10906 | { | |
10907 | return expression_node<T>::e_vecvalarith; | |
10908 | } | |
10909 | ||
10910 | std::size_t size() const | |
10911 | { | |
10912 | return vds().size(); | |
10913 | } | |
10914 | ||
10915 | vds_t& vds() | |
10916 | { | |
10917 | return vds_; | |
10918 | } | |
10919 | ||
10920 | const vds_t& vds() const | |
10921 | { | |
10922 | return vds_; | |
10923 | } | |
10924 | ||
10925 | private: | |
10926 | ||
10927 | vector_node_ptr vec1_node_ptr_; | |
10928 | vector_holder_ptr temp_; | |
10929 | vector_node_ptr temp_vec_node_; | |
10930 | vds_t vds_; | |
10931 | }; | |
10932 | ||
10933 | template <typename T, typename Operation> | |
10934 | class unary_vector_node : public unary_node <T>, | |
10935 | public vector_interface<T> | |
10936 | { | |
10937 | public: | |
10938 | ||
10939 | typedef expression_node<T>* expression_ptr; | |
10940 | typedef vector_node<T>* vector_node_ptr; | |
10941 | typedef vector_holder<T>* vector_holder_ptr; | |
10942 | typedef vec_data_store<T> vds_t; | |
10943 | ||
10944 | unary_vector_node(const operator_type& opr, expression_ptr branch0) | |
10945 | : unary_node<T>(opr, branch0), | |
10946 | vec0_node_ptr_(0), | |
10947 | temp_ (0), | |
10948 | temp_vec_node_(0) | |
10949 | { | |
10950 | bool vec0_is_ivec = false; | |
10951 | ||
10952 | if (is_vector_node(unary_node<T>::branch_)) | |
10953 | { | |
10954 | vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_); | |
10955 | } | |
10956 | else if (is_ivector_node(unary_node<T>::branch_)) | |
10957 | { | |
10958 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
10959 | ||
10960 | if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_))) | |
10961 | { | |
10962 | vec0_node_ptr_ = vi->vec(); | |
10963 | vec0_is_ivec = true; | |
10964 | } | |
10965 | } | |
10966 | ||
10967 | if (vec0_node_ptr_) | |
10968 | { | |
10969 | if (vec0_is_ivec) | |
10970 | vds_ = vec0_node_ptr_->vds(); | |
10971 | else | |
10972 | vds_ = vds_t(vec0_node_ptr_->size()); | |
10973 | ||
10974 | temp_ = new vector_holder<T>(vds()); | |
10975 | temp_vec_node_ = new vector_node<T> (vds(),temp_); | |
10976 | } | |
10977 | } | |
10978 | ||
10979 | ~unary_vector_node() | |
10980 | { | |
10981 | delete temp_; | |
10982 | delete temp_vec_node_; | |
10983 | } | |
10984 | ||
10985 | inline T value() const | |
10986 | { | |
10987 | unary_node<T>::branch_->value(); | |
10988 | ||
10989 | if (vec0_node_ptr_) | |
10990 | { | |
10991 | const T* vec0 = vec0_node_ptr_->vds().data(); | |
10992 | T* vec1 = vds().data(); | |
10993 | ||
10994 | loop_unroll::details lud(size()); | |
10995 | const T* upper_bound = vec0 + lud.upper_bound; | |
10996 | ||
10997 | while (vec0 < upper_bound) | |
10998 | { | |
10999 | #define exprtk_loop(N) \ | |
11000 | vec1[N] = Operation::process(vec0[N]); \ | |
11001 | ||
11002 | exprtk_loop( 0) exprtk_loop( 1) | |
11003 | exprtk_loop( 2) exprtk_loop( 3) | |
11004 | #ifndef exprtk_disable_superscalar_unroll | |
11005 | exprtk_loop( 4) exprtk_loop( 5) | |
11006 | exprtk_loop( 6) exprtk_loop( 7) | |
11007 | exprtk_loop( 8) exprtk_loop( 9) | |
11008 | exprtk_loop(10) exprtk_loop(11) | |
11009 | exprtk_loop(12) exprtk_loop(13) | |
11010 | exprtk_loop(14) exprtk_loop(15) | |
11011 | #endif | |
11012 | ||
11013 | vec0 += lud.batch_size; | |
11014 | vec1 += lud.batch_size; | |
11015 | } | |
11016 | ||
11017 | int i = 0; | |
11018 | ||
11019 | exprtk_disable_fallthrough_begin | |
11020 | switch (lud.remainder) | |
11021 | { | |
11022 | #define case_stmt(N) \ | |
11023 | case N : { vec1[i] = Operation::process(vec0[i]); ++i; } \ | |
11024 | ||
11025 | #ifndef exprtk_disable_superscalar_unroll | |
11026 | case_stmt(15) case_stmt(14) | |
11027 | case_stmt(13) case_stmt(12) | |
11028 | case_stmt(11) case_stmt(10) | |
11029 | case_stmt( 9) case_stmt( 8) | |
11030 | case_stmt( 7) case_stmt( 6) | |
11031 | case_stmt( 5) case_stmt( 4) | |
11032 | #endif | |
11033 | case_stmt( 3) case_stmt( 2) | |
11034 | case_stmt( 1) | |
11035 | } | |
11036 | exprtk_disable_fallthrough_end | |
11037 | ||
11038 | #undef exprtk_loop | |
11039 | #undef case_stmt | |
11040 | ||
11041 | return (vds().data())[0]; | |
11042 | } | |
11043 | else | |
11044 | return std::numeric_limits<T>::quiet_NaN(); | |
11045 | } | |
11046 | ||
11047 | vector_node_ptr vec() const | |
11048 | { | |
11049 | return temp_vec_node_; | |
11050 | } | |
11051 | ||
11052 | vector_node_ptr vec() | |
11053 | { | |
11054 | return temp_vec_node_; | |
11055 | } | |
11056 | ||
11057 | inline typename expression_node<T>::node_type type() const | |
11058 | { | |
11059 | return expression_node<T>::e_vecunaryop; | |
11060 | } | |
11061 | ||
11062 | std::size_t size() const | |
11063 | { | |
11064 | return vds().size(); | |
11065 | } | |
11066 | ||
11067 | vds_t& vds() | |
11068 | { | |
11069 | return vds_; | |
11070 | } | |
11071 | ||
11072 | const vds_t& vds() const | |
11073 | { | |
11074 | return vds_; | |
11075 | } | |
11076 | ||
11077 | private: | |
11078 | ||
11079 | vector_node_ptr vec0_node_ptr_; | |
11080 | vector_holder_ptr temp_; | |
11081 | vector_node_ptr temp_vec_node_; | |
11082 | vds_t vds_; | |
11083 | }; | |
11084 | ||
11085 | template <typename T> | |
11086 | class scand_node : public binary_node<T> | |
11087 | { | |
11088 | public: | |
11089 | ||
11090 | typedef expression_node<T>* expression_ptr; | |
11091 | ||
11092 | scand_node(const operator_type& opr, | |
11093 | expression_ptr branch0, | |
11094 | expression_ptr branch1) | |
11095 | : binary_node<T>(opr, branch0, branch1) | |
11096 | {} | |
11097 | ||
11098 | inline T value() const | |
11099 | { | |
11100 | return ( | |
11101 | std::not_equal_to<T>() | |
11102 | (T(0),binary_node<T>::branch_[0].first->value()) && | |
11103 | std::not_equal_to<T>() | |
11104 | (T(0),binary_node<T>::branch_[1].first->value()) | |
11105 | ) ? T(1) : T(0); | |
11106 | } | |
11107 | }; | |
11108 | ||
11109 | template <typename T> | |
11110 | class scor_node : public binary_node<T> | |
11111 | { | |
11112 | public: | |
11113 | ||
11114 | typedef expression_node<T>* expression_ptr; | |
11115 | ||
11116 | scor_node(const operator_type& opr, | |
11117 | expression_ptr branch0, | |
11118 | expression_ptr branch1) | |
11119 | : binary_node<T>(opr, branch0, branch1) | |
11120 | {} | |
11121 | ||
11122 | inline T value() const | |
11123 | { | |
11124 | return ( | |
11125 | std::not_equal_to<T>() | |
11126 | (T(0),binary_node<T>::branch_[0].first->value()) || | |
11127 | std::not_equal_to<T>() | |
11128 | (T(0),binary_node<T>::branch_[1].first->value()) | |
11129 | ) ? T(1) : T(0); | |
11130 | } | |
11131 | }; | |
11132 | ||
11133 | template <typename T, typename IFunction, std::size_t N> | |
11134 | class function_N_node : public expression_node<T> | |
11135 | { | |
11136 | public: | |
11137 | ||
11138 | // Function of N paramters. | |
11139 | typedef expression_node<T>* expression_ptr; | |
11140 | typedef std::pair<expression_ptr,bool> branch_t; | |
11141 | typedef IFunction ifunction; | |
11142 | ||
11143 | explicit function_N_node(ifunction* func) | |
11144 | : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)), | |
11145 | parameter_count_(func->param_count) | |
11146 | {} | |
11147 | ||
11148 | ~function_N_node() | |
11149 | { | |
11150 | cleanup_branches::execute<T,N>(branch_); | |
11151 | } | |
11152 | ||
11153 | template <std::size_t NumBranches> | |
11154 | bool init_branches(expression_ptr (&b)[NumBranches]) | |
11155 | { | |
11156 | // Needed for incompetent and broken msvc compiler versions | |
11157 | #ifdef _MSC_VER | |
11158 | #pragma warning(push) | |
11159 | #pragma warning(disable: 4127) | |
11160 | #endif | |
11161 | if (N != NumBranches) | |
11162 | return false; | |
11163 | else | |
11164 | { | |
11165 | for (std::size_t i = 0; i < NumBranches; ++i) | |
11166 | { | |
11167 | if (b[i]) | |
11168 | branch_[i] = std::make_pair(b[i],branch_deletable(b[i])); | |
11169 | else | |
11170 | return false; | |
11171 | } | |
11172 | return true; | |
11173 | } | |
11174 | #ifdef _MSC_VER | |
11175 | #pragma warning(pop) | |
11176 | #endif | |
11177 | } | |
11178 | ||
11179 | inline bool operator <(const function_N_node<T,IFunction,N>& fn) const | |
11180 | { | |
11181 | return this < (&fn); | |
11182 | } | |
11183 | ||
11184 | inline T value() const | |
11185 | { | |
11186 | // Needed for incompetent and broken msvc compiler versions | |
11187 | #ifdef _MSC_VER | |
11188 | #pragma warning(push) | |
11189 | #pragma warning(disable: 4127) | |
11190 | #endif | |
11191 | if ((0 == function_) || (0 == N)) | |
11192 | return std::numeric_limits<T>::quiet_NaN(); | |
11193 | else | |
11194 | { | |
11195 | T v[N]; | |
11196 | evaluate_branches<T,N>::execute(v,branch_); | |
11197 | return invoke<T,N>::execute(*function_,v); | |
11198 | } | |
11199 | #ifdef _MSC_VER | |
11200 | #pragma warning(pop) | |
11201 | #endif | |
11202 | } | |
11203 | ||
11204 | template <typename T_, std::size_t BranchCount> | |
11205 | struct evaluate_branches | |
11206 | { | |
11207 | static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount]) | |
11208 | { | |
11209 | for (std::size_t i = 0; i < BranchCount; ++i) | |
11210 | { | |
11211 | v[i] = b[i].first->value(); | |
11212 | } | |
11213 | } | |
11214 | }; | |
11215 | ||
11216 | template <typename T_> | |
11217 | struct evaluate_branches <T_,5> | |
11218 | { | |
11219 | static inline void execute(T_ (&v)[5], const branch_t (&b)[5]) | |
11220 | { | |
11221 | v[0] = b[0].first->value(); | |
11222 | v[1] = b[1].first->value(); | |
11223 | v[2] = b[2].first->value(); | |
11224 | v[3] = b[3].first->value(); | |
11225 | v[4] = b[4].first->value(); | |
11226 | } | |
11227 | }; | |
11228 | ||
11229 | template <typename T_> | |
11230 | struct evaluate_branches <T_,4> | |
11231 | { | |
11232 | static inline void execute(T_ (&v)[4], const branch_t (&b)[4]) | |
11233 | { | |
11234 | v[0] = b[0].first->value(); | |
11235 | v[1] = b[1].first->value(); | |
11236 | v[2] = b[2].first->value(); | |
11237 | v[3] = b[3].first->value(); | |
11238 | } | |
11239 | }; | |
11240 | ||
11241 | template <typename T_> | |
11242 | struct evaluate_branches <T_,3> | |
11243 | { | |
11244 | static inline void execute(T_ (&v)[3], const branch_t (&b)[3]) | |
11245 | { | |
11246 | v[0] = b[0].first->value(); | |
11247 | v[1] = b[1].first->value(); | |
11248 | v[2] = b[2].first->value(); | |
11249 | } | |
11250 | }; | |
11251 | ||
11252 | template <typename T_> | |
11253 | struct evaluate_branches <T_,2> | |
11254 | { | |
11255 | static inline void execute(T_ (&v)[2], const branch_t (&b)[2]) | |
11256 | { | |
11257 | v[0] = b[0].first->value(); | |
11258 | v[1] = b[1].first->value(); | |
11259 | } | |
11260 | }; | |
11261 | ||
11262 | template <typename T_> | |
11263 | struct evaluate_branches <T_,1> | |
11264 | { | |
11265 | static inline void execute(T_ (&v)[1], const branch_t (&b)[1]) | |
11266 | { | |
11267 | v[0] = b[0].first->value(); | |
11268 | } | |
11269 | }; | |
11270 | ||
11271 | template <typename T_, std::size_t ParamCount> | |
11272 | struct invoke { static inline T execute(ifunction&, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } }; | |
11273 | ||
11274 | template <typename T_> | |
11275 | struct invoke<T_,20> | |
11276 | { | |
11277 | static inline T_ execute(ifunction& f, T_ (&v)[20]) | |
11278 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19]); } | |
11279 | }; | |
11280 | ||
11281 | template <typename T_> | |
11282 | struct invoke<T_,19> | |
11283 | { | |
11284 | static inline T_ execute(ifunction& f, T_ (&v)[19]) | |
11285 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18]); } | |
11286 | }; | |
11287 | ||
11288 | template <typename T_> | |
11289 | struct invoke<T_,18> | |
11290 | { | |
11291 | static inline T_ execute(ifunction& f, T_ (&v)[18]) | |
11292 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16],v[17]); } | |
11293 | }; | |
11294 | ||
11295 | template <typename T_> | |
11296 | struct invoke<T_,17> | |
11297 | { | |
11298 | static inline T_ execute(ifunction& f, T_ (&v)[17]) | |
11299 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15],v[16]); } | |
11300 | }; | |
11301 | ||
11302 | template <typename T_> | |
11303 | struct invoke<T_,16> | |
11304 | { | |
11305 | static inline T_ execute(ifunction& f, T_ (&v)[16]) | |
11306 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14],v[15]); } | |
11307 | }; | |
11308 | ||
11309 | template <typename T_> | |
11310 | struct invoke<T_,15> | |
11311 | { | |
11312 | static inline T_ execute(ifunction& f, T_ (&v)[15]) | |
11313 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13],v[14]); } | |
11314 | }; | |
11315 | ||
11316 | template <typename T_> | |
11317 | struct invoke<T_,14> | |
11318 | { | |
11319 | static inline T_ execute(ifunction& f, T_ (&v)[14]) | |
11320 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12],v[13]); } | |
11321 | }; | |
11322 | ||
11323 | template <typename T_> | |
11324 | struct invoke<T_,13> | |
11325 | { | |
11326 | static inline T_ execute(ifunction& f, T_ (&v)[13]) | |
11327 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11],v[12]); } | |
11328 | }; | |
11329 | ||
11330 | template <typename T_> | |
11331 | struct invoke<T_,12> | |
11332 | { | |
11333 | static inline T_ execute(ifunction& f, T_ (&v)[12]) | |
11334 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10],v[11]); } | |
11335 | }; | |
11336 | ||
11337 | template <typename T_> | |
11338 | struct invoke<T_,11> | |
11339 | { | |
11340 | static inline T_ execute(ifunction& f, T_ (&v)[11]) | |
11341 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10]); } | |
11342 | }; | |
11343 | ||
11344 | template <typename T_> | |
11345 | struct invoke<T_,10> | |
11346 | { | |
11347 | static inline T_ execute(ifunction& f, T_ (&v)[10]) | |
11348 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } | |
11349 | }; | |
11350 | ||
11351 | template <typename T_> | |
11352 | struct invoke<T_,9> | |
11353 | { | |
11354 | static inline T_ execute(ifunction& f, T_ (&v)[9]) | |
11355 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } | |
11356 | }; | |
11357 | ||
11358 | template <typename T_> | |
11359 | struct invoke<T_,8> | |
11360 | { | |
11361 | static inline T_ execute(ifunction& f, T_ (&v)[8]) | |
11362 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } | |
11363 | }; | |
11364 | ||
11365 | template <typename T_> | |
11366 | struct invoke<T_,7> | |
11367 | { | |
11368 | static inline T_ execute(ifunction& f, T_ (&v)[7]) | |
11369 | { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } | |
11370 | }; | |
11371 | ||
11372 | template <typename T_> | |
11373 | struct invoke<T_,6> | |
11374 | { | |
11375 | static inline T_ execute(ifunction& f, T_ (&v)[6]) | |
11376 | { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } | |
11377 | }; | |
11378 | ||
11379 | template <typename T_> | |
11380 | struct invoke<T_,5> | |
11381 | { | |
11382 | static inline T_ execute(ifunction& f, T_ (&v)[5]) | |
11383 | { return f(v[0],v[1],v[2],v[3],v[4]); } | |
11384 | }; | |
11385 | ||
11386 | template <typename T_> | |
11387 | struct invoke<T_,4> | |
11388 | { | |
11389 | static inline T_ execute(ifunction& f, T_ (&v)[4]) | |
11390 | { return f(v[0],v[1],v[2],v[3]); } | |
11391 | }; | |
11392 | ||
11393 | template <typename T_> | |
11394 | struct invoke<T_,3> | |
11395 | { | |
11396 | static inline T_ execute(ifunction& f, T_ (&v)[3]) | |
11397 | { return f(v[0],v[1],v[2]); } | |
11398 | }; | |
11399 | ||
11400 | template <typename T_> | |
11401 | struct invoke<T_,2> | |
11402 | { | |
11403 | static inline T_ execute(ifunction& f, T_ (&v)[2]) | |
11404 | { return f(v[0],v[1]); } | |
11405 | }; | |
11406 | ||
11407 | template <typename T_> | |
11408 | struct invoke<T_,1> | |
11409 | { | |
11410 | static inline T_ execute(ifunction& f, T_ (&v)[1]) | |
11411 | { return f(v[0]); } | |
11412 | }; | |
11413 | ||
11414 | inline typename expression_node<T>::node_type type() const | |
11415 | { | |
11416 | return expression_node<T>::e_function; | |
11417 | } | |
11418 | ||
11419 | private: | |
11420 | ||
11421 | ifunction* function_; | |
11422 | std::size_t parameter_count_; | |
11423 | branch_t branch_[N]; | |
11424 | }; | |
11425 | ||
11426 | template <typename T, typename IFunction> | |
11427 | class function_N_node<T,IFunction,0> : public expression_node<T> | |
11428 | { | |
11429 | public: | |
11430 | ||
11431 | typedef expression_node<T>* expression_ptr; | |
11432 | typedef IFunction ifunction; | |
11433 | ||
11434 | explicit function_N_node(ifunction* func) | |
11435 | : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) | |
11436 | {} | |
11437 | ||
11438 | inline bool operator <(const function_N_node<T,IFunction,0>& fn) const | |
11439 | { | |
11440 | return this < (&fn); | |
11441 | } | |
11442 | ||
11443 | inline T value() const | |
11444 | { | |
11445 | if (function_) | |
11446 | return (*function_)(); | |
11447 | else | |
11448 | return std::numeric_limits<T>::quiet_NaN(); | |
11449 | } | |
11450 | ||
11451 | inline typename expression_node<T>::node_type type() const | |
11452 | { | |
11453 | return expression_node<T>::e_function; | |
11454 | } | |
11455 | ||
11456 | private: | |
11457 | ||
11458 | ifunction* function_; | |
11459 | }; | |
11460 | ||
11461 | template <typename T, typename VarArgFunction> | |
11462 | class vararg_function_node : public expression_node<T> | |
11463 | { | |
11464 | public: | |
11465 | ||
11466 | typedef expression_node<T>* expression_ptr; | |
11467 | ||
11468 | vararg_function_node(VarArgFunction* func, | |
11469 | const std::vector<expression_ptr>& arg_list) | |
11470 | : function_(func), | |
11471 | arg_list_(arg_list) | |
11472 | { | |
11473 | value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); | |
11474 | } | |
11475 | ||
11476 | ~vararg_function_node() | |
11477 | { | |
11478 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
11479 | { | |
11480 | if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) | |
11481 | { | |
11482 | destroy_node(arg_list_[i]); | |
11483 | } | |
11484 | } | |
11485 | } | |
11486 | ||
11487 | inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const | |
11488 | { | |
11489 | return this < (&fn); | |
11490 | } | |
11491 | ||
11492 | inline T value() const | |
11493 | { | |
11494 | if (function_) | |
11495 | { | |
11496 | populate_value_list(); | |
11497 | return (*function_)(value_list_); | |
11498 | } | |
11499 | else | |
11500 | return std::numeric_limits<T>::quiet_NaN(); | |
11501 | } | |
11502 | ||
11503 | inline typename expression_node<T>::node_type type() const | |
11504 | { | |
11505 | return expression_node<T>::e_vafunction; | |
11506 | } | |
11507 | ||
11508 | private: | |
11509 | ||
11510 | inline void populate_value_list() const | |
11511 | { | |
11512 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
11513 | { | |
11514 | value_list_[i] = arg_list_[i]->value(); | |
11515 | } | |
11516 | } | |
11517 | ||
11518 | VarArgFunction* function_; | |
11519 | std::vector<expression_ptr> arg_list_; | |
11520 | mutable std::vector<T> value_list_; | |
11521 | }; | |
11522 | ||
11523 | template <typename T, typename GenericFunction> | |
11524 | class generic_function_node : public expression_node<T> | |
11525 | { | |
11526 | public: | |
11527 | ||
11528 | typedef type_store<T> type_store_t; | |
11529 | typedef expression_node<T>* expression_ptr; | |
11530 | typedef variable_node<T> variable_node_t; | |
11531 | typedef vector_node<T> vector_node_t; | |
11532 | typedef variable_node_t* variable_node_ptr_t; | |
11533 | typedef vector_node_t* vector_node_ptr_t; | |
11534 | typedef range_interface<T> range_interface_t; | |
11535 | typedef range_data_type<T> range_data_type_t; | |
11536 | typedef range_pack<T> range_t; | |
11537 | typedef std::pair<expression_ptr,bool> branch_t; | |
11538 | typedef std::pair<void*,std::size_t> void_t; | |
11539 | typedef std::vector<T> tmp_vs_t; | |
11540 | typedef std::vector<type_store_t> typestore_list_t; | |
11541 | typedef std::vector<range_data_type_t> range_list_t; | |
11542 | ||
11543 | generic_function_node(const std::vector<expression_ptr>& arg_list, | |
11544 | GenericFunction* func = (GenericFunction*)(0)) | |
11545 | : function_(func), | |
11546 | arg_list_(arg_list) | |
11547 | {} | |
11548 | ||
11549 | virtual ~generic_function_node() | |
11550 | { | |
11551 | cleanup_branches::execute(branch_); | |
11552 | } | |
11553 | ||
11554 | virtual bool init_branches() | |
11555 | { | |
11556 | expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); | |
11557 | typestore_list_ .resize(arg_list_.size(),type_store_t() ); | |
11558 | range_list_ .resize(arg_list_.size(),range_data_type_t()); | |
11559 | branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false)); | |
11560 | ||
11561 | for (std::size_t i = 0; i < arg_list_.size(); ++i) | |
11562 | { | |
11563 | type_store_t& ts = typestore_list_[i]; | |
11564 | ||
11565 | if (0 == arg_list_[i]) | |
11566 | return false; | |
11567 | else if (is_ivector_node(arg_list_[i])) | |
11568 | { | |
11569 | vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); | |
11570 | ||
11571 | if (0 == (vi = dynamic_cast<vector_interface<T>*>(arg_list_[i]))) | |
11572 | return false; | |
11573 | ||
11574 | ts.size = vi->size(); | |
11575 | ts.data = vi->vds().data(); | |
11576 | ts.type = type_store_t::e_vector; | |
11577 | vi->vec()->vec_holder().set_ref(&ts.vec_data); | |
11578 | } | |
11579 | #ifndef exprtk_disable_string_capabilities | |
11580 | else if (is_generally_string_node(arg_list_[i])) | |
11581 | { | |
11582 | string_base_node<T>* sbn = reinterpret_cast<string_base_node<T>*>(0); | |
11583 | ||
11584 | if (0 == (sbn = dynamic_cast<string_base_node<T>*>(arg_list_[i]))) | |
11585 | return false; | |
11586 | ||
11587 | ts.size = sbn->size(); | |
11588 | ts.data = reinterpret_cast<void*>(const_cast<char_ptr>(sbn->base())); | |
11589 | ts.type = type_store_t::e_string; | |
11590 | ||
11591 | range_list_[i].data = ts.data; | |
11592 | range_list_[i].size = ts.size; | |
11593 | range_list_[i].type_size = sizeof(char); | |
11594 | range_list_[i].str_node = sbn; | |
11595 | ||
11596 | range_interface_t* ri = reinterpret_cast<range_interface_t*>(0); | |
11597 | ||
11598 | if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) | |
11599 | return false; | |
11600 | ||
11601 | range_t& rp = ri->range_ref(); | |
11602 | ||
11603 | if ( | |
11604 | rp.const_range() && | |
11605 | is_const_string_range_node(arg_list_[i]) | |
11606 | ) | |
11607 | { | |
11608 | ts.size = rp.const_size(); | |
11609 | ts.data = static_cast<char_ptr>(ts.data) + rp.n0_c.second; | |
11610 | range_list_[i].range = reinterpret_cast<range_t*>(0); | |
11611 | } | |
11612 | else | |
11613 | range_list_[i].range = &(ri->range_ref()); | |
11614 | } | |
11615 | #endif | |
11616 | else if (is_variable_node(arg_list_[i])) | |
11617 | { | |
11618 | variable_node_ptr_t var = variable_node_ptr_t(0); | |
11619 | ||
11620 | if (0 == (var = dynamic_cast<variable_node_ptr_t>(arg_list_[i]))) | |
11621 | return false; | |
11622 | ||
11623 | ts.size = 1; | |
11624 | ts.data = &var->ref(); | |
11625 | ts.type = type_store_t::e_scalar; | |
11626 | } | |
11627 | else | |
11628 | { | |
11629 | ts.size = 1; | |
11630 | ts.data = reinterpret_cast<void*>(&expr_as_vec1_store_[i]); | |
11631 | ts.type = type_store_t::e_scalar; | |
11632 | } | |
11633 | ||
11634 | branch_[i] = std::make_pair(arg_list_[i],branch_deletable(arg_list_[i])); | |
11635 | } | |
11636 | ||
11637 | return true; | |
11638 | } | |
11639 | ||
11640 | inline bool operator <(const generic_function_node<T,GenericFunction>& fn) const | |
11641 | { | |
11642 | return this < (&fn); | |
11643 | } | |
11644 | ||
11645 | inline T value() const | |
11646 | { | |
11647 | if (function_) | |
11648 | { | |
11649 | if (populate_value_list()) | |
11650 | { | |
11651 | typedef typename GenericFunction::parameter_list_t parameter_list_t; | |
11652 | ||
11653 | return (*function_)(parameter_list_t(typestore_list_)); | |
11654 | } | |
11655 | } | |
11656 | ||
11657 | return std::numeric_limits<T>::quiet_NaN(); | |
11658 | } | |
11659 | ||
11660 | inline typename expression_node<T>::node_type type() const | |
11661 | { | |
11662 | return expression_node<T>::e_genfunction; | |
11663 | } | |
11664 | ||
11665 | protected: | |
11666 | ||
11667 | inline virtual bool populate_value_list() const | |
11668 | { | |
11669 | for (std::size_t i = 0; i < branch_.size(); ++i) | |
11670 | { | |
11671 | expr_as_vec1_store_[i] = branch_[i].first->value(); | |
11672 | } | |
11673 | ||
11674 | for (std::size_t i = 0; i < branch_.size(); ++i) | |
11675 | { | |
11676 | range_data_type_t& rdt = range_list_[i]; | |
11677 | ||
11678 | if (rdt.range) | |
11679 | { | |
11680 | range_t& rp = (*rdt.range); | |
11681 | std::size_t r0 = 0; | |
11682 | std::size_t r1 = 0; | |
11683 | ||
11684 | if (rp(r0,r1,rdt.size)) | |
11685 | { | |
11686 | type_store_t& ts = typestore_list_[i]; | |
11687 | ||
11688 | ts.size = rp.cache_size(); | |
11689 | #ifndef exprtk_disable_string_capabilities | |
11690 | if (ts.type == type_store_t::e_string) | |
11691 | ts.data = const_cast<char_ptr>(rdt.str_node->base()) + rp.cache.first; | |
11692 | else | |
11693 | #endif | |
11694 | ts.data = static_cast<char_ptr>(rdt.data) + (rp.cache.first * rdt.type_size); | |
11695 | } | |
11696 | else | |
11697 | return false; | |
11698 | } | |
11699 | } | |
11700 | ||
11701 | return true; | |
11702 | } | |
11703 | ||
11704 | GenericFunction* function_; | |
11705 | mutable typestore_list_t typestore_list_; | |
11706 | ||
11707 | private: | |
11708 | ||
11709 | std::vector<expression_ptr> arg_list_; | |
11710 | std::vector<branch_t> branch_; | |
11711 | mutable tmp_vs_t expr_as_vec1_store_; | |
11712 | mutable range_list_t range_list_; | |
11713 | }; | |
11714 | ||
11715 | #ifndef exprtk_disable_string_capabilities | |
11716 | template <typename T, typename StringFunction> | |
11717 | class string_function_node : public generic_function_node<T,StringFunction>, | |
11718 | public string_base_node<T>, | |
11719 | public range_interface <T> | |
11720 | { | |
11721 | public: | |
11722 | ||
11723 | typedef generic_function_node<T,StringFunction> gen_function_t; | |
11724 | typedef range_pack<T> range_t; | |
11725 | ||
11726 | string_function_node(StringFunction* func, | |
11727 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) | |
11728 | : gen_function_t(arg_list,func) | |
11729 | { | |
11730 | range_.n0_c = std::make_pair<bool,std::size_t>(true,0); | |
11731 | range_.n1_c = std::make_pair<bool,std::size_t>(true,0); | |
11732 | range_.cache.first = range_.n0_c.second; | |
11733 | range_.cache.second = range_.n1_c.second; | |
11734 | } | |
11735 | ||
11736 | inline bool operator <(const string_function_node<T,StringFunction>& fn) const | |
11737 | { | |
11738 | return this < (&fn); | |
11739 | } | |
11740 | ||
11741 | inline T value() const | |
11742 | { | |
11743 | if (gen_function_t::function_) | |
11744 | { | |
11745 | if (gen_function_t::populate_value_list()) | |
11746 | { | |
11747 | typedef typename StringFunction::parameter_list_t parameter_list_t; | |
11748 | ||
11749 | const T result = (*gen_function_t::function_) | |
11750 | ( | |
11751 | ret_string_, | |
11752 | parameter_list_t(gen_function_t::typestore_list_) | |
11753 | ); | |
11754 | ||
11755 | range_.n1_c.second = ret_string_.size() - 1; | |
11756 | range_.cache.second = range_.n1_c.second; | |
11757 | ||
11758 | return result; | |
11759 | } | |
11760 | } | |
11761 | ||
11762 | return std::numeric_limits<T>::quiet_NaN(); | |
11763 | } | |
11764 | ||
11765 | inline typename expression_node<T>::node_type type() const | |
11766 | { | |
11767 | return expression_node<T>::e_strfunction; | |
11768 | } | |
11769 | ||
11770 | std::string str() const | |
11771 | { | |
11772 | return ret_string_; | |
11773 | } | |
11774 | ||
11775 | char_cptr base() const | |
11776 | { | |
11777 | return &ret_string_[0]; | |
11778 | } | |
11779 | ||
11780 | std::size_t size() const | |
11781 | { | |
11782 | return ret_string_.size(); | |
11783 | } | |
11784 | ||
11785 | range_t& range_ref() | |
11786 | { | |
11787 | return range_; | |
11788 | } | |
11789 | ||
11790 | const range_t& range_ref() const | |
11791 | { | |
11792 | return range_; | |
11793 | } | |
11794 | ||
11795 | protected: | |
11796 | ||
11797 | mutable range_t range_; | |
11798 | mutable std::string ret_string_; | |
11799 | }; | |
11800 | #endif | |
11801 | ||
11802 | template <typename T, typename GenericFunction> | |
11803 | class multimode_genfunction_node : public generic_function_node<T,GenericFunction> | |
11804 | { | |
11805 | public: | |
11806 | ||
11807 | typedef generic_function_node<T,GenericFunction> gen_function_t; | |
11808 | typedef range_pack<T> range_t; | |
11809 | ||
11810 | multimode_genfunction_node(GenericFunction* func, | |
11811 | const std::size_t& param_seq_index, | |
11812 | const std::vector<typename gen_function_t::expression_ptr>& arg_list) | |
11813 | : gen_function_t(arg_list,func), | |
11814 | param_seq_index_(param_seq_index) | |
11815 | {} | |
11816 | ||
11817 | inline T value() const | |
11818 | { | |
11819 | if (gen_function_t::function_) | |
11820 | { | |
11821 | if (gen_function_t::populate_value_list()) | |
11822 | { | |
11823 | typedef typename GenericFunction::parameter_list_t parameter_list_t; | |
11824 | ||
11825 | return (*gen_function_t::function_) | |
11826 | ( | |
11827 | param_seq_index_, | |
11828 | parameter_list_t(gen_function_t::typestore_list_) | |
11829 | ); | |
11830 | } | |
11831 | } | |
11832 | ||
11833 | return std::numeric_limits<T>::quiet_NaN(); | |
11834 | } | |
11835 | ||
11836 | inline typename expression_node<T>::node_type type() const | |
11837 | { | |
11838 | return expression_node<T>::e_genfunction; | |
11839 | } | |
11840 | ||
11841 | private: | |
11842 | ||
11843 | std::size_t param_seq_index_; | |
11844 | }; | |
11845 | ||
11846 | #ifndef exprtk_disable_string_capabilities | |
11847 | template <typename T, typename StringFunction> | |
11848 | class multimode_strfunction_node : public string_function_node<T,StringFunction> | |
11849 | { | |
11850 | public: | |
11851 | ||
11852 | typedef string_function_node<T,StringFunction> str_function_t; | |
11853 | typedef range_pack<T> range_t; | |
11854 | ||
11855 | multimode_strfunction_node(StringFunction* func, | |
11856 | const std::size_t& param_seq_index, | |
11857 | const std::vector<typename str_function_t::expression_ptr>& arg_list) | |
11858 | : str_function_t(func,arg_list), | |
11859 | param_seq_index_(param_seq_index) | |
11860 | {} | |
11861 | ||
11862 | inline T value() const | |
11863 | { | |
11864 | if (str_function_t::function_) | |
11865 | { | |
11866 | if (str_function_t::populate_value_list()) | |
11867 | { | |
11868 | typedef typename StringFunction::parameter_list_t parameter_list_t; | |
11869 | ||
11870 | const T result = (*str_function_t::function_) | |
11871 | ( | |
11872 | param_seq_index_, | |
11873 | str_function_t::ret_string_, | |
11874 | parameter_list_t(str_function_t::typestore_list_) | |
11875 | ); | |
11876 | ||
11877 | str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; | |
11878 | str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; | |
11879 | ||
11880 | return result; | |
11881 | } | |
11882 | } | |
11883 | ||
11884 | return std::numeric_limits<T>::quiet_NaN(); | |
11885 | } | |
11886 | ||
11887 | inline typename expression_node<T>::node_type type() const | |
11888 | { | |
11889 | return expression_node<T>::e_strfunction; | |
11890 | } | |
11891 | ||
11892 | private: | |
11893 | ||
11894 | const std::size_t param_seq_index_; | |
11895 | }; | |
11896 | #endif | |
11897 | ||
11898 | class return_exception | |
11899 | {}; | |
11900 | ||
11901 | template <typename T> | |
11902 | class null_igenfunc | |
11903 | { | |
11904 | public: | |
11905 | ||
11906 | virtual ~null_igenfunc() | |
11907 | {} | |
11908 | ||
11909 | typedef type_store<T> generic_type; | |
11910 | typedef typename generic_type::parameter_list parameter_list_t; | |
11911 | ||
11912 | inline virtual T operator() (parameter_list_t) | |
11913 | { | |
11914 | return std::numeric_limits<T>::quiet_NaN(); | |
11915 | } | |
11916 | }; | |
11917 | ||
11918 | #ifndef exprtk_disable_return_statement | |
11919 | template <typename T> | |
11920 | class return_node : public generic_function_node<T,null_igenfunc<T> > | |
11921 | { | |
11922 | public: | |
11923 | ||
11924 | typedef null_igenfunc<T> igeneric_function_t; | |
11925 | typedef igeneric_function_t* igeneric_function_ptr; | |
11926 | typedef generic_function_node<T,igeneric_function_t> gen_function_t; | |
11927 | typedef results_context<T> results_context_t; | |
11928 | ||
11929 | return_node(const std::vector<typename gen_function_t::expression_ptr>& arg_list, | |
11930 | results_context_t& rc) | |
11931 | : gen_function_t (arg_list), | |
11932 | results_context_(&rc) | |
11933 | {} | |
11934 | ||
11935 | inline T value() const | |
11936 | { | |
11937 | if ( | |
11938 | (0 != results_context_) && | |
11939 | gen_function_t::populate_value_list() | |
11940 | ) | |
11941 | { | |
11942 | typedef typename type_store<T>::parameter_list parameter_list_t; | |
11943 | ||
11944 | results_context_-> | |
11945 | assign(parameter_list_t(gen_function_t::typestore_list_)); | |
11946 | ||
11947 | throw return_exception(); | |
11948 | } | |
11949 | ||
11950 | return std::numeric_limits<T>::quiet_NaN(); | |
11951 | } | |
11952 | ||
11953 | inline typename expression_node<T>::node_type type() const | |
11954 | { | |
11955 | return expression_node<T>::e_return; | |
11956 | } | |
11957 | ||
11958 | private: | |
11959 | ||
11960 | results_context_t* results_context_; | |
11961 | }; | |
11962 | ||
11963 | template <typename T> | |
11964 | class return_envelope_node : public expression_node<T> | |
11965 | { | |
11966 | public: | |
11967 | ||
11968 | typedef expression_node<T>* expression_ptr; | |
11969 | typedef results_context<T> results_context_t; | |
11970 | ||
11971 | return_envelope_node(expression_ptr body, results_context_t& rc) | |
11972 | : results_context_(&rc ), | |
11973 | return_invoked_ (false), | |
11974 | body_ (body ), | |
11975 | body_deletable_ (branch_deletable(body_)) | |
11976 | {} | |
11977 | ||
11978 | ~return_envelope_node() | |
11979 | { | |
11980 | if (body_ && body_deletable_) | |
11981 | { | |
11982 | destroy_node(body_); | |
11983 | } | |
11984 | } | |
11985 | ||
11986 | inline T value() const | |
11987 | { | |
11988 | try | |
11989 | { | |
11990 | return_invoked_ = false; | |
11991 | results_context_->clear(); | |
11992 | ||
11993 | return body_->value(); | |
11994 | } | |
11995 | catch(const return_exception&) | |
11996 | { | |
11997 | return_invoked_ = true; | |
11998 | return std::numeric_limits<T>::quiet_NaN(); | |
11999 | } | |
12000 | } | |
12001 | ||
12002 | inline typename expression_node<T>::node_type type() const | |
12003 | { | |
12004 | return expression_node<T>::e_retenv; | |
12005 | } | |
12006 | ||
12007 | inline bool* retinvk_ptr() | |
12008 | { | |
12009 | return &return_invoked_; | |
12010 | } | |
12011 | ||
12012 | private: | |
12013 | ||
12014 | results_context_t* results_context_; | |
12015 | mutable bool return_invoked_; | |
12016 | expression_ptr body_; | |
12017 | const bool body_deletable_; | |
12018 | }; | |
12019 | #endif | |
12020 | ||
12021 | #define exprtk_define_unary_op(OpName) \ | |
12022 | template <typename T> \ | |
12023 | struct OpName##_op \ | |
12024 | { \ | |
12025 | typedef typename functor_t<T>::Type Type; \ | |
12026 | typedef typename expression_node<T>::node_type node_t; \ | |
12027 | \ | |
12028 | static inline T process(Type v) \ | |
12029 | { \ | |
12030 | return numeric:: OpName (v); \ | |
12031 | } \ | |
12032 | \ | |
12033 | static inline node_t type() \ | |
12034 | { \ | |
12035 | return expression_node<T>::e_##OpName; \ | |
12036 | } \ | |
12037 | \ | |
12038 | static inline details::operator_type operation() \ | |
12039 | { \ | |
12040 | return details::e_##OpName; \ | |
12041 | } \ | |
12042 | }; \ | |
12043 | ||
12044 | exprtk_define_unary_op(abs ) | |
12045 | exprtk_define_unary_op(acos ) | |
12046 | exprtk_define_unary_op(acosh) | |
12047 | exprtk_define_unary_op(asin ) | |
12048 | exprtk_define_unary_op(asinh) | |
12049 | exprtk_define_unary_op(atan ) | |
12050 | exprtk_define_unary_op(atanh) | |
12051 | exprtk_define_unary_op(ceil ) | |
12052 | exprtk_define_unary_op(cos ) | |
12053 | exprtk_define_unary_op(cosh ) | |
12054 | exprtk_define_unary_op(cot ) | |
12055 | exprtk_define_unary_op(csc ) | |
12056 | exprtk_define_unary_op(d2g ) | |
12057 | exprtk_define_unary_op(d2r ) | |
12058 | exprtk_define_unary_op(erf ) | |
12059 | exprtk_define_unary_op(erfc ) | |
12060 | exprtk_define_unary_op(exp ) | |
12061 | exprtk_define_unary_op(expm1) | |
12062 | exprtk_define_unary_op(floor) | |
12063 | exprtk_define_unary_op(frac ) | |
12064 | exprtk_define_unary_op(g2d ) | |
12065 | exprtk_define_unary_op(log ) | |
12066 | exprtk_define_unary_op(log10) | |
12067 | exprtk_define_unary_op(log2 ) | |
12068 | exprtk_define_unary_op(log1p) | |
12069 | exprtk_define_unary_op(ncdf ) | |
12070 | exprtk_define_unary_op(neg ) | |
12071 | exprtk_define_unary_op(notl ) | |
12072 | exprtk_define_unary_op(pos ) | |
12073 | exprtk_define_unary_op(r2d ) | |
12074 | exprtk_define_unary_op(round) | |
12075 | exprtk_define_unary_op(sec ) | |
12076 | exprtk_define_unary_op(sgn ) | |
12077 | exprtk_define_unary_op(sin ) | |
12078 | exprtk_define_unary_op(sinc ) | |
12079 | exprtk_define_unary_op(sinh ) | |
12080 | exprtk_define_unary_op(sqrt ) | |
12081 | exprtk_define_unary_op(tan ) | |
12082 | exprtk_define_unary_op(tanh ) | |
12083 | exprtk_define_unary_op(trunc) | |
12084 | #undef exprtk_define_unary_op | |
12085 | ||
12086 | template <typename T> | |
12087 | struct opr_base | |
12088 | { | |
12089 | typedef typename details::functor_t<T>::Type Type; | |
12090 | typedef typename details::functor_t<T>::RefType RefType; | |
12091 | typedef typename details::functor_t<T> functor_t; | |
12092 | typedef typename functor_t::qfunc_t quaternary_functor_t; | |
12093 | typedef typename functor_t::tfunc_t trinary_functor_t; | |
12094 | typedef typename functor_t::bfunc_t binary_functor_t; | |
12095 | typedef typename functor_t::ufunc_t unary_functor_t; | |
12096 | }; | |
12097 | ||
12098 | template <typename T> | |
12099 | struct add_op : public opr_base<T> | |
12100 | { | |
12101 | typedef typename opr_base<T>::Type Type; | |
12102 | typedef typename opr_base<T>::RefType RefType; | |
12103 | ||
12104 | static inline T process(Type t1, Type t2) { return t1 + t2; } | |
12105 | static inline T process(Type t1, Type t2, Type t3) { return t1 + t2 + t3; } | |
12106 | static inline void assign(RefType t1, Type t2) { t1 += t2; } | |
12107 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; } | |
12108 | static inline details::operator_type operation() { return details::e_add; } | |
12109 | }; | |
12110 | ||
12111 | template <typename T> | |
12112 | struct mul_op : public opr_base<T> | |
12113 | { | |
12114 | typedef typename opr_base<T>::Type Type; | |
12115 | typedef typename opr_base<T>::RefType RefType; | |
12116 | ||
12117 | static inline T process(Type t1, Type t2) { return t1 * t2; } | |
12118 | static inline T process(Type t1, Type t2, Type t3) { return t1 * t2 * t3; } | |
12119 | static inline void assign(RefType t1, Type t2) { t1 *= t2; } | |
12120 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; } | |
12121 | static inline details::operator_type operation() { return details::e_mul; } | |
12122 | }; | |
12123 | ||
12124 | template <typename T> | |
12125 | struct sub_op : public opr_base<T> | |
12126 | { | |
12127 | typedef typename opr_base<T>::Type Type; | |
12128 | typedef typename opr_base<T>::RefType RefType; | |
12129 | ||
12130 | static inline T process(Type t1, Type t2) { return t1 - t2; } | |
12131 | static inline T process(Type t1, Type t2, Type t3) { return t1 - t2 - t3; } | |
12132 | static inline void assign(RefType t1, Type t2) { t1 -= t2; } | |
12133 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; } | |
12134 | static inline details::operator_type operation() { return details::e_sub; } | |
12135 | }; | |
12136 | ||
12137 | template <typename T> | |
12138 | struct div_op : public opr_base<T> | |
12139 | { | |
12140 | typedef typename opr_base<T>::Type Type; | |
12141 | typedef typename opr_base<T>::RefType RefType; | |
12142 | ||
12143 | static inline T process(Type t1, Type t2) { return t1 / t2; } | |
12144 | static inline T process(Type t1, Type t2, Type t3) { return t1 / t2 / t3; } | |
12145 | static inline void assign(RefType t1, Type t2) { t1 /= t2; } | |
12146 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; } | |
12147 | static inline details::operator_type operation() { return details::e_div; } | |
12148 | }; | |
12149 | ||
12150 | template <typename T> | |
12151 | struct mod_op : public opr_base<T> | |
12152 | { | |
12153 | typedef typename opr_base<T>::Type Type; | |
12154 | typedef typename opr_base<T>::RefType RefType; | |
12155 | ||
12156 | static inline T process(Type t1, Type t2) { return numeric::modulus<T>(t1,t2); } | |
12157 | static inline void assign(RefType t1, Type t2) { t1 = numeric::modulus<T>(t1,t2); } | |
12158 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; } | |
12159 | static inline details::operator_type operation() { return details::e_mod; } | |
12160 | }; | |
12161 | ||
12162 | template <typename T> | |
12163 | struct pow_op : public opr_base<T> | |
12164 | { | |
12165 | typedef typename opr_base<T>::Type Type; | |
12166 | typedef typename opr_base<T>::RefType RefType; | |
12167 | ||
12168 | static inline T process(Type t1, Type t2) { return numeric::pow<T>(t1,t2); } | |
12169 | static inline void assign(RefType t1, Type t2) { t1 = numeric::pow<T>(t1,t2); } | |
12170 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; } | |
12171 | static inline details::operator_type operation() { return details::e_pow; } | |
12172 | }; | |
12173 | ||
12174 | template <typename T> | |
12175 | struct lt_op : public opr_base<T> | |
12176 | { | |
12177 | typedef typename opr_base<T>::Type Type; | |
12178 | ||
12179 | static inline T process(Type t1, Type t2) { return ((t1 < t2) ? T(1) : T(0)); } | |
12180 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); } | |
12181 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; } | |
12182 | static inline details::operator_type operation() { return details::e_lt; } | |
12183 | }; | |
12184 | ||
12185 | template <typename T> | |
12186 | struct lte_op : public opr_base<T> | |
12187 | { | |
12188 | typedef typename opr_base<T>::Type Type; | |
12189 | ||
12190 | static inline T process(Type t1, Type t2) { return ((t1 <= t2) ? T(1) : T(0)); } | |
12191 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); } | |
12192 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; } | |
12193 | static inline details::operator_type operation() { return details::e_lte; } | |
12194 | }; | |
12195 | ||
12196 | template <typename T> | |
12197 | struct gt_op : public opr_base<T> | |
12198 | { | |
12199 | typedef typename opr_base<T>::Type Type; | |
12200 | ||
12201 | static inline T process(Type t1, Type t2) { return ((t1 > t2) ? T(1) : T(0)); } | |
12202 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); } | |
12203 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; } | |
12204 | static inline details::operator_type operation() { return details::e_gt; } | |
12205 | }; | |
12206 | ||
12207 | template <typename T> | |
12208 | struct gte_op : public opr_base<T> | |
12209 | { | |
12210 | typedef typename opr_base<T>::Type Type; | |
12211 | ||
12212 | static inline T process(Type t1, Type t2) { return ((t1 >= t2) ? T(1) : T(0)); } | |
12213 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); } | |
12214 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; } | |
12215 | static inline details::operator_type operation() { return details::e_gte; } | |
12216 | }; | |
12217 | ||
12218 | template <typename T> | |
12219 | struct eq_op : public opr_base<T> | |
12220 | { | |
12221 | typedef typename opr_base<T>::Type Type; | |
12222 | static inline T process(Type t1, Type t2) { return (std::equal_to<T>()(t1,t2) ? T(1) : T(0)); } | |
12223 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } | |
12224 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } | |
12225 | static inline details::operator_type operation() { return details::e_eq; } | |
12226 | }; | |
12227 | ||
12228 | template <typename T> | |
12229 | struct equal_op : public opr_base<T> | |
12230 | { | |
12231 | typedef typename opr_base<T>::Type Type; | |
12232 | ||
12233 | static inline T process(Type t1, Type t2) { return numeric::equal(t1,t2); } | |
12234 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); } | |
12235 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; } | |
12236 | static inline details::operator_type operation() { return details::e_equal; } | |
12237 | }; | |
12238 | ||
12239 | template <typename T> | |
12240 | struct ne_op : public opr_base<T> | |
12241 | { | |
12242 | typedef typename opr_base<T>::Type Type; | |
12243 | ||
12244 | static inline T process(Type t1, Type t2) { return (std::not_equal_to<T>()(t1,t2) ? T(1) : T(0)); } | |
12245 | static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); } | |
12246 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; } | |
12247 | static inline details::operator_type operation() { return details::e_ne; } | |
12248 | }; | |
12249 | ||
12250 | template <typename T> | |
12251 | struct and_op : public opr_base<T> | |
12252 | { | |
12253 | typedef typename opr_base<T>::Type Type; | |
12254 | ||
12255 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(1) : T(0); } | |
12256 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; } | |
12257 | static inline details::operator_type operation() { return details::e_and; } | |
12258 | }; | |
12259 | ||
12260 | template <typename T> | |
12261 | struct nand_op : public opr_base<T> | |
12262 | { | |
12263 | typedef typename opr_base<T>::Type Type; | |
12264 | ||
12265 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) && details::is_true(t2)) ? T(0) : T(1); } | |
12266 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; } | |
12267 | static inline details::operator_type operation() { return details::e_nand; } | |
12268 | }; | |
12269 | ||
12270 | template <typename T> | |
12271 | struct or_op : public opr_base<T> | |
12272 | { | |
12273 | typedef typename opr_base<T>::Type Type; | |
12274 | ||
12275 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(1) : T(0); } | |
12276 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; } | |
12277 | static inline details::operator_type operation() { return details::e_or; } | |
12278 | }; | |
12279 | ||
12280 | template <typename T> | |
12281 | struct nor_op : public opr_base<T> | |
12282 | { | |
12283 | typedef typename opr_base<T>::Type Type; | |
12284 | ||
12285 | static inline T process(Type t1, Type t2) { return (details::is_true(t1) || details::is_true(t2)) ? T(0) : T(1); } | |
12286 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } | |
12287 | static inline details::operator_type operation() { return details::e_nor; } | |
12288 | }; | |
12289 | ||
12290 | template <typename T> | |
12291 | struct xor_op : public opr_base<T> | |
12292 | { | |
12293 | typedef typename opr_base<T>::Type Type; | |
12294 | ||
12295 | static inline T process(Type t1, Type t2) { return numeric::xor_opr<T>(t1,t2); } | |
12296 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } | |
12297 | static inline details::operator_type operation() { return details::e_xor; } | |
12298 | }; | |
12299 | ||
12300 | template <typename T> | |
12301 | struct xnor_op : public opr_base<T> | |
12302 | { | |
12303 | typedef typename opr_base<T>::Type Type; | |
12304 | ||
12305 | static inline T process(Type t1, Type t2) { return numeric::xnor_opr<T>(t1,t2); } | |
12306 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; } | |
12307 | static inline details::operator_type operation() { return details::e_xnor; } | |
12308 | }; | |
12309 | ||
12310 | template <typename T> | |
12311 | struct in_op : public opr_base<T> | |
12312 | { | |
12313 | typedef typename opr_base<T>::Type Type; | |
12314 | ||
12315 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } | |
12316 | static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); } | |
12317 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; } | |
12318 | static inline details::operator_type operation() { return details::e_in; } | |
12319 | }; | |
12320 | ||
12321 | template <typename T> | |
12322 | struct like_op : public opr_base<T> | |
12323 | { | |
12324 | typedef typename opr_base<T>::Type Type; | |
12325 | ||
12326 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } | |
12327 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); } | |
12328 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; } | |
12329 | static inline details::operator_type operation() { return details::e_like; } | |
12330 | }; | |
12331 | ||
12332 | template <typename T> | |
12333 | struct ilike_op : public opr_base<T> | |
12334 | { | |
12335 | typedef typename opr_base<T>::Type Type; | |
12336 | ||
12337 | static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); } | |
12338 | static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); } | |
12339 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; } | |
12340 | static inline details::operator_type operation() { return details::e_ilike; } | |
12341 | }; | |
12342 | ||
12343 | template <typename T> | |
12344 | struct inrange_op : public opr_base<T> | |
12345 | { | |
12346 | typedef typename opr_base<T>::Type Type; | |
12347 | ||
12348 | static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); } | |
12349 | static inline T process(const std::string& t0, const std::string& t1, const std::string& t2) | |
12350 | { | |
12351 | return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); | |
12352 | } | |
12353 | static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; } | |
12354 | static inline details::operator_type operation() { return details::e_inrange; } | |
12355 | }; | |
12356 | ||
12357 | template <typename T> | |
12358 | inline T value(details::expression_node<T>* n) | |
12359 | { | |
12360 | return n->value(); | |
12361 | } | |
12362 | ||
12363 | template <typename T> | |
12364 | inline T value(T* t) | |
12365 | { | |
12366 | return (*t); | |
12367 | } | |
12368 | ||
12369 | template <typename T> | |
12370 | struct vararg_add_op : public opr_base<T> | |
12371 | { | |
12372 | typedef typename opr_base<T>::Type Type; | |
12373 | ||
12374 | template <typename Type, | |
12375 | typename Allocator, | |
12376 | template <typename, typename> class Sequence> | |
12377 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12378 | { | |
12379 | switch (arg_list.size()) | |
12380 | { | |
12381 | case 0 : return T(0); | |
12382 | case 1 : return process_1(arg_list); | |
12383 | case 2 : return process_2(arg_list); | |
12384 | case 3 : return process_3(arg_list); | |
12385 | case 4 : return process_4(arg_list); | |
12386 | case 5 : return process_5(arg_list); | |
12387 | default : | |
12388 | { | |
12389 | T result = T(0); | |
12390 | ||
12391 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
12392 | { | |
12393 | result += value(arg_list[i]); | |
12394 | } | |
12395 | ||
12396 | return result; | |
12397 | } | |
12398 | } | |
12399 | } | |
12400 | ||
12401 | template <typename Sequence> | |
12402 | static inline T process_1(const Sequence& arg_list) | |
12403 | { | |
12404 | return value(arg_list[0]); | |
12405 | } | |
12406 | ||
12407 | template <typename Sequence> | |
12408 | static inline T process_2(const Sequence& arg_list) | |
12409 | { | |
12410 | return value(arg_list[0]) + value(arg_list[1]); | |
12411 | } | |
12412 | ||
12413 | template <typename Sequence> | |
12414 | static inline T process_3(const Sequence& arg_list) | |
12415 | { | |
12416 | return value(arg_list[0]) + value(arg_list[1]) + | |
12417 | value(arg_list[2]) ; | |
12418 | } | |
12419 | ||
12420 | template <typename Sequence> | |
12421 | static inline T process_4(const Sequence& arg_list) | |
12422 | { | |
12423 | return value(arg_list[0]) + value(arg_list[1]) + | |
12424 | value(arg_list[2]) + value(arg_list[3]) ; | |
12425 | } | |
12426 | ||
12427 | template <typename Sequence> | |
12428 | static inline T process_5(const Sequence& arg_list) | |
12429 | { | |
12430 | return value(arg_list[0]) + value(arg_list[1]) + | |
12431 | value(arg_list[2]) + value(arg_list[3]) + | |
12432 | value(arg_list[4]) ; | |
12433 | } | |
12434 | }; | |
12435 | ||
12436 | template <typename T> | |
12437 | struct vararg_mul_op : public opr_base<T> | |
12438 | { | |
12439 | typedef typename opr_base<T>::Type Type; | |
12440 | ||
12441 | template <typename Type, | |
12442 | typename Allocator, | |
12443 | template <typename, typename> class Sequence> | |
12444 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12445 | { | |
12446 | switch (arg_list.size()) | |
12447 | { | |
12448 | case 0 : return T(0); | |
12449 | case 1 : return process_1(arg_list); | |
12450 | case 2 : return process_2(arg_list); | |
12451 | case 3 : return process_3(arg_list); | |
12452 | case 4 : return process_4(arg_list); | |
12453 | case 5 : return process_5(arg_list); | |
12454 | default : | |
12455 | { | |
12456 | T result = T(value(arg_list[0])); | |
12457 | ||
12458 | for (std::size_t i = 1; i < arg_list.size(); ++i) | |
12459 | { | |
12460 | result *= value(arg_list[i]); | |
12461 | } | |
12462 | ||
12463 | return result; | |
12464 | } | |
12465 | } | |
12466 | } | |
12467 | ||
12468 | template <typename Sequence> | |
12469 | static inline T process_1(const Sequence& arg_list) | |
12470 | { | |
12471 | return value(arg_list[0]); | |
12472 | } | |
12473 | ||
12474 | template <typename Sequence> | |
12475 | static inline T process_2(const Sequence& arg_list) | |
12476 | { | |
12477 | return value(arg_list[0]) * value(arg_list[1]); | |
12478 | } | |
12479 | ||
12480 | template <typename Sequence> | |
12481 | static inline T process_3(const Sequence& arg_list) | |
12482 | { | |
12483 | return value(arg_list[0]) * value(arg_list[1]) * | |
12484 | value(arg_list[2]) ; | |
12485 | } | |
12486 | ||
12487 | template <typename Sequence> | |
12488 | static inline T process_4(const Sequence& arg_list) | |
12489 | { | |
12490 | return value(arg_list[0]) * value(arg_list[1]) * | |
12491 | value(arg_list[2]) * value(arg_list[3]) ; | |
12492 | } | |
12493 | ||
12494 | template <typename Sequence> | |
12495 | static inline T process_5(const Sequence& arg_list) | |
12496 | { | |
12497 | return value(arg_list[0]) * value(arg_list[1]) * | |
12498 | value(arg_list[2]) * value(arg_list[3]) * | |
12499 | value(arg_list[4]) ; | |
12500 | } | |
12501 | }; | |
12502 | ||
12503 | template <typename T> | |
12504 | struct vararg_avg_op : public opr_base<T> | |
12505 | { | |
12506 | typedef typename opr_base<T>::Type Type; | |
12507 | ||
12508 | template <typename Type, | |
12509 | typename Allocator, | |
12510 | template <typename, typename> class Sequence> | |
12511 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12512 | { | |
12513 | switch (arg_list.size()) | |
12514 | { | |
12515 | case 0 : return T(0); | |
12516 | case 1 : return process_1(arg_list); | |
12517 | case 2 : return process_2(arg_list); | |
12518 | case 3 : return process_3(arg_list); | |
12519 | case 4 : return process_4(arg_list); | |
12520 | case 5 : return process_5(arg_list); | |
12521 | default : return vararg_add_op<T>::process(arg_list) / arg_list.size(); | |
12522 | } | |
12523 | } | |
12524 | ||
12525 | template <typename Sequence> | |
12526 | static inline T process_1(const Sequence& arg_list) | |
12527 | { | |
12528 | return value(arg_list[0]); | |
12529 | } | |
12530 | ||
12531 | template <typename Sequence> | |
12532 | static inline T process_2(const Sequence& arg_list) | |
12533 | { | |
12534 | return (value(arg_list[0]) + value(arg_list[1])) / T(2); | |
12535 | } | |
12536 | ||
12537 | template <typename Sequence> | |
12538 | static inline T process_3(const Sequence& arg_list) | |
12539 | { | |
12540 | return (value(arg_list[0]) + value(arg_list[1]) + value(arg_list[2])) / T(3); | |
12541 | } | |
12542 | ||
12543 | template <typename Sequence> | |
12544 | static inline T process_4(const Sequence& arg_list) | |
12545 | { | |
12546 | return (value(arg_list[0]) + value(arg_list[1]) + | |
12547 | value(arg_list[2]) + value(arg_list[3])) / T(4); | |
12548 | } | |
12549 | ||
12550 | template <typename Sequence> | |
12551 | static inline T process_5(const Sequence& arg_list) | |
12552 | { | |
12553 | return (value(arg_list[0]) + value(arg_list[1]) + | |
12554 | value(arg_list[2]) + value(arg_list[3]) + | |
12555 | value(arg_list[4])) / T(5); | |
12556 | } | |
12557 | }; | |
12558 | ||
12559 | template <typename T> | |
12560 | struct vararg_min_op : public opr_base<T> | |
12561 | { | |
12562 | typedef typename opr_base<T>::Type Type; | |
12563 | ||
12564 | template <typename Type, | |
12565 | typename Allocator, | |
12566 | template <typename, typename> class Sequence> | |
12567 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12568 | { | |
12569 | switch (arg_list.size()) | |
12570 | { | |
12571 | case 0 : return T(0); | |
12572 | case 1 : return process_1(arg_list); | |
12573 | case 2 : return process_2(arg_list); | |
12574 | case 3 : return process_3(arg_list); | |
12575 | case 4 : return process_4(arg_list); | |
12576 | case 5 : return process_5(arg_list); | |
12577 | default : | |
12578 | { | |
12579 | T result = T(value(arg_list[0])); | |
12580 | ||
12581 | for (std::size_t i = 1; i < arg_list.size(); ++i) | |
12582 | { | |
12583 | const T v = value(arg_list[i]); | |
12584 | ||
12585 | if (v < result) | |
12586 | result = v; | |
12587 | } | |
12588 | ||
12589 | return result; | |
12590 | } | |
12591 | } | |
12592 | } | |
12593 | ||
12594 | template <typename Sequence> | |
12595 | static inline T process_1(const Sequence& arg_list) | |
12596 | { | |
12597 | return value(arg_list[0]); | |
12598 | } | |
12599 | ||
12600 | template <typename Sequence> | |
12601 | static inline T process_2(const Sequence& arg_list) | |
12602 | { | |
12603 | return std::min<T>(value(arg_list[0]),value(arg_list[1])); | |
12604 | } | |
12605 | ||
12606 | template <typename Sequence> | |
12607 | static inline T process_3(const Sequence& arg_list) | |
12608 | { | |
12609 | return std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); | |
12610 | } | |
12611 | ||
12612 | template <typename Sequence> | |
12613 | static inline T process_4(const Sequence& arg_list) | |
12614 | { | |
12615 | return std::min<T>( | |
12616 | std::min<T>(value(arg_list[0]), value(arg_list[1])), | |
12617 | std::min<T>(value(arg_list[2]), value(arg_list[3]))); | |
12618 | } | |
12619 | ||
12620 | template <typename Sequence> | |
12621 | static inline T process_5(const Sequence& arg_list) | |
12622 | { | |
12623 | return std::min<T>( | |
12624 | std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), | |
12625 | std::min<T>(value(arg_list[2]), value(arg_list[3]))), | |
12626 | value(arg_list[4])); | |
12627 | } | |
12628 | }; | |
12629 | ||
12630 | template <typename T> | |
12631 | struct vararg_max_op : public opr_base<T> | |
12632 | { | |
12633 | typedef typename opr_base<T>::Type Type; | |
12634 | ||
12635 | template <typename Type, | |
12636 | typename Allocator, | |
12637 | template <typename, typename> class Sequence> | |
12638 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12639 | { | |
12640 | switch (arg_list.size()) | |
12641 | { | |
12642 | case 0 : return T(0); | |
12643 | case 1 : return process_1(arg_list); | |
12644 | case 2 : return process_2(arg_list); | |
12645 | case 3 : return process_3(arg_list); | |
12646 | case 4 : return process_4(arg_list); | |
12647 | case 5 : return process_5(arg_list); | |
12648 | default : | |
12649 | { | |
12650 | T result = T(value(arg_list[0])); | |
12651 | ||
12652 | for (std::size_t i = 1; i < arg_list.size(); ++i) | |
12653 | { | |
12654 | const T v = value(arg_list[i]); | |
12655 | ||
12656 | if (v > result) | |
12657 | result = v; | |
12658 | } | |
12659 | ||
12660 | return result; | |
12661 | } | |
12662 | } | |
12663 | } | |
12664 | ||
12665 | template <typename Sequence> | |
12666 | static inline T process_1(const Sequence& arg_list) | |
12667 | { | |
12668 | return value(arg_list[0]); | |
12669 | } | |
12670 | ||
12671 | template <typename Sequence> | |
12672 | static inline T process_2(const Sequence& arg_list) | |
12673 | { | |
12674 | return std::max<T>(value(arg_list[0]),value(arg_list[1])); | |
12675 | } | |
12676 | ||
12677 | template <typename Sequence> | |
12678 | static inline T process_3(const Sequence& arg_list) | |
12679 | { | |
12680 | return std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])),value(arg_list[2])); | |
12681 | } | |
12682 | ||
12683 | template <typename Sequence> | |
12684 | static inline T process_4(const Sequence& arg_list) | |
12685 | { | |
12686 | return std::max<T>( | |
12687 | std::max<T>(value(arg_list[0]), value(arg_list[1])), | |
12688 | std::max<T>(value(arg_list[2]), value(arg_list[3]))); | |
12689 | } | |
12690 | ||
12691 | template <typename Sequence> | |
12692 | static inline T process_5(const Sequence& arg_list) | |
12693 | { | |
12694 | return std::max<T>( | |
12695 | std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), | |
12696 | std::max<T>(value(arg_list[2]), value(arg_list[3]))), | |
12697 | value(arg_list[4])); | |
12698 | } | |
12699 | }; | |
12700 | ||
12701 | template <typename T> | |
12702 | struct vararg_mand_op : public opr_base<T> | |
12703 | { | |
12704 | typedef typename opr_base<T>::Type Type; | |
12705 | ||
12706 | template <typename Type, | |
12707 | typename Allocator, | |
12708 | template <typename, typename> class Sequence> | |
12709 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12710 | { | |
12711 | switch (arg_list.size()) | |
12712 | { | |
12713 | case 1 : return process_1(arg_list); | |
12714 | case 2 : return process_2(arg_list); | |
12715 | case 3 : return process_3(arg_list); | |
12716 | case 4 : return process_4(arg_list); | |
12717 | case 5 : return process_5(arg_list); | |
12718 | default : | |
12719 | { | |
12720 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
12721 | { | |
12722 | if (std::equal_to<T>()(T(0), value(arg_list[i]))) | |
12723 | return T(0); | |
12724 | } | |
12725 | ||
12726 | return T(1); | |
12727 | } | |
12728 | } | |
12729 | } | |
12730 | ||
12731 | template <typename Sequence> | |
12732 | static inline T process_1(const Sequence& arg_list) | |
12733 | { | |
12734 | return std::not_equal_to<T>() | |
12735 | (T(0), value(arg_list[0])) ? T(1) : T(0); | |
12736 | } | |
12737 | ||
12738 | template <typename Sequence> | |
12739 | static inline T process_2(const Sequence& arg_list) | |
12740 | { | |
12741 | return ( | |
12742 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && | |
12743 | std::not_equal_to<T>()(T(0), value(arg_list[1])) | |
12744 | ) ? T(1) : T(0); | |
12745 | } | |
12746 | ||
12747 | template <typename Sequence> | |
12748 | static inline T process_3(const Sequence& arg_list) | |
12749 | { | |
12750 | return ( | |
12751 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && | |
12752 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && | |
12753 | std::not_equal_to<T>()(T(0), value(arg_list[2])) | |
12754 | ) ? T(1) : T(0); | |
12755 | } | |
12756 | ||
12757 | template <typename Sequence> | |
12758 | static inline T process_4(const Sequence& arg_list) | |
12759 | { | |
12760 | return ( | |
12761 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && | |
12762 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && | |
12763 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && | |
12764 | std::not_equal_to<T>()(T(0), value(arg_list[3])) | |
12765 | ) ? T(1) : T(0); | |
12766 | } | |
12767 | ||
12768 | template <typename Sequence> | |
12769 | static inline T process_5(const Sequence& arg_list) | |
12770 | { | |
12771 | return ( | |
12772 | std::not_equal_to<T>()(T(0), value(arg_list[0])) && | |
12773 | std::not_equal_to<T>()(T(0), value(arg_list[1])) && | |
12774 | std::not_equal_to<T>()(T(0), value(arg_list[2])) && | |
12775 | std::not_equal_to<T>()(T(0), value(arg_list[3])) && | |
12776 | std::not_equal_to<T>()(T(0), value(arg_list[4])) | |
12777 | ) ? T(1) : T(0); | |
12778 | } | |
12779 | }; | |
12780 | ||
12781 | template <typename T> | |
12782 | struct vararg_mor_op : public opr_base<T> | |
12783 | { | |
12784 | typedef typename opr_base<T>::Type Type; | |
12785 | ||
12786 | template <typename Type, | |
12787 | typename Allocator, | |
12788 | template <typename, typename> class Sequence> | |
12789 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12790 | { | |
12791 | switch (arg_list.size()) | |
12792 | { | |
12793 | case 1 : return process_1(arg_list); | |
12794 | case 2 : return process_2(arg_list); | |
12795 | case 3 : return process_3(arg_list); | |
12796 | case 4 : return process_4(arg_list); | |
12797 | case 5 : return process_5(arg_list); | |
12798 | default : | |
12799 | { | |
12800 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
12801 | { | |
12802 | if (std::not_equal_to<T>()(T(0), value(arg_list[i]))) | |
12803 | return T(1); | |
12804 | } | |
12805 | ||
12806 | return T(0); | |
12807 | } | |
12808 | } | |
12809 | } | |
12810 | ||
12811 | template <typename Sequence> | |
12812 | static inline T process_1(const Sequence& arg_list) | |
12813 | { | |
12814 | return std::not_equal_to<T>() | |
12815 | (T(0), value(arg_list[0])) ? T(1) : T(0); | |
12816 | } | |
12817 | ||
12818 | template <typename Sequence> | |
12819 | static inline T process_2(const Sequence& arg_list) | |
12820 | { | |
12821 | return ( | |
12822 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || | |
12823 | std::not_equal_to<T>()(T(0), value(arg_list[1])) | |
12824 | ) ? T(1) : T(0); | |
12825 | } | |
12826 | ||
12827 | template <typename Sequence> | |
12828 | static inline T process_3(const Sequence& arg_list) | |
12829 | { | |
12830 | return ( | |
12831 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || | |
12832 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || | |
12833 | std::not_equal_to<T>()(T(0), value(arg_list[2])) | |
12834 | ) ? T(1) : T(0); | |
12835 | } | |
12836 | ||
12837 | template <typename Sequence> | |
12838 | static inline T process_4(const Sequence& arg_list) | |
12839 | { | |
12840 | return ( | |
12841 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || | |
12842 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || | |
12843 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || | |
12844 | std::not_equal_to<T>()(T(0), value(arg_list[3])) | |
12845 | ) ? T(1) : T(0); | |
12846 | } | |
12847 | ||
12848 | template <typename Sequence> | |
12849 | static inline T process_5(const Sequence& arg_list) | |
12850 | { | |
12851 | return ( | |
12852 | std::not_equal_to<T>()(T(0), value(arg_list[0])) || | |
12853 | std::not_equal_to<T>()(T(0), value(arg_list[1])) || | |
12854 | std::not_equal_to<T>()(T(0), value(arg_list[2])) || | |
12855 | std::not_equal_to<T>()(T(0), value(arg_list[3])) || | |
12856 | std::not_equal_to<T>()(T(0), value(arg_list[4])) | |
12857 | ) ? T(1) : T(0); | |
12858 | } | |
12859 | }; | |
12860 | ||
12861 | template <typename T> | |
12862 | struct vararg_multi_op : public opr_base<T> | |
12863 | { | |
12864 | typedef typename opr_base<T>::Type Type; | |
12865 | ||
12866 | template <typename Type, | |
12867 | typename Allocator, | |
12868 | template <typename, typename> class Sequence> | |
12869 | static inline T process(const Sequence<Type,Allocator>& arg_list) | |
12870 | { | |
12871 | switch (arg_list.size()) | |
12872 | { | |
12873 | case 0 : return std::numeric_limits<T>::quiet_NaN(); | |
12874 | case 1 : return process_1(arg_list); | |
12875 | case 2 : return process_2(arg_list); | |
12876 | case 3 : return process_3(arg_list); | |
12877 | case 4 : return process_4(arg_list); | |
12878 | case 5 : return process_5(arg_list); | |
12879 | case 6 : return process_6(arg_list); | |
12880 | case 7 : return process_7(arg_list); | |
12881 | case 8 : return process_8(arg_list); | |
12882 | default : | |
12883 | { | |
12884 | for (std::size_t i = 0; i < (arg_list.size() - 1); ++i) | |
12885 | { | |
12886 | value(arg_list[i]); | |
12887 | } | |
12888 | ||
12889 | return value(arg_list.back()); | |
12890 | } | |
12891 | } | |
12892 | } | |
12893 | ||
12894 | template <typename Sequence> | |
12895 | static inline T process_1(const Sequence& arg_list) | |
12896 | { | |
12897 | return value(arg_list[0]); | |
12898 | } | |
12899 | ||
12900 | template <typename Sequence> | |
12901 | static inline T process_2(const Sequence& arg_list) | |
12902 | { | |
12903 | value(arg_list[0]); | |
12904 | return value(arg_list[1]); | |
12905 | } | |
12906 | ||
12907 | template <typename Sequence> | |
12908 | static inline T process_3(const Sequence& arg_list) | |
12909 | { | |
12910 | value(arg_list[0]); | |
12911 | value(arg_list[1]); | |
12912 | return value(arg_list[2]); | |
12913 | } | |
12914 | ||
12915 | template <typename Sequence> | |
12916 | static inline T process_4(const Sequence& arg_list) | |
12917 | { | |
12918 | value(arg_list[0]); | |
12919 | value(arg_list[1]); | |
12920 | value(arg_list[2]); | |
12921 | return value(arg_list[3]); | |
12922 | } | |
12923 | ||
12924 | template <typename Sequence> | |
12925 | static inline T process_5(const Sequence& arg_list) | |
12926 | { | |
12927 | value(arg_list[0]); | |
12928 | value(arg_list[1]); | |
12929 | value(arg_list[2]); | |
12930 | value(arg_list[3]); | |
12931 | return value(arg_list[4]); | |
12932 | } | |
12933 | ||
12934 | template <typename Sequence> | |
12935 | static inline T process_6(const Sequence& arg_list) | |
12936 | { | |
12937 | value(arg_list[0]); | |
12938 | value(arg_list[1]); | |
12939 | value(arg_list[2]); | |
12940 | value(arg_list[3]); | |
12941 | value(arg_list[4]); | |
12942 | return value(arg_list[5]); | |
12943 | } | |
12944 | ||
12945 | template <typename Sequence> | |
12946 | static inline T process_7(const Sequence& arg_list) | |
12947 | { | |
12948 | value(arg_list[0]); | |
12949 | value(arg_list[1]); | |
12950 | value(arg_list[2]); | |
12951 | value(arg_list[3]); | |
12952 | value(arg_list[4]); | |
12953 | value(arg_list[5]); | |
12954 | return value(arg_list[6]); | |
12955 | } | |
12956 | ||
12957 | template <typename Sequence> | |
12958 | static inline T process_8(const Sequence& arg_list) | |
12959 | { | |
12960 | value(arg_list[0]); | |
12961 | value(arg_list[1]); | |
12962 | value(arg_list[2]); | |
12963 | value(arg_list[3]); | |
12964 | value(arg_list[4]); | |
12965 | value(arg_list[5]); | |
12966 | value(arg_list[6]); | |
12967 | return value(arg_list[7]); | |
12968 | } | |
12969 | }; | |
12970 | ||
12971 | template <typename T> | |
12972 | struct vec_add_op | |
12973 | { | |
12974 | typedef vector_interface<T>* ivector_ptr; | |
12975 | ||
12976 | static inline T process(const ivector_ptr v) | |
12977 | { | |
12978 | const T* vec = v->vec()->vds().data(); | |
12979 | const std::size_t vec_size = v->vec()->vds().size(); | |
12980 | ||
12981 | loop_unroll::details lud(vec_size); | |
12982 | ||
12983 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) | |
12984 | { | |
12985 | T result = T(0); | |
12986 | int i = 0; | |
12987 | ||
12988 | exprtk_disable_fallthrough_begin | |
12989 | switch (vec_size) | |
12990 | { | |
12991 | #define case_stmt(N) \ | |
12992 | case N : result += vec[i++]; \ | |
12993 | ||
12994 | #ifndef exprtk_disable_superscalar_unroll | |
12995 | case_stmt(16) case_stmt(15) | |
12996 | case_stmt(14) case_stmt(13) | |
12997 | case_stmt(12) case_stmt(11) | |
12998 | case_stmt(10) case_stmt( 9) | |
12999 | case_stmt( 8) case_stmt( 7) | |
13000 | case_stmt( 6) case_stmt( 5) | |
13001 | #endif | |
13002 | case_stmt( 4) case_stmt( 3) | |
13003 | case_stmt( 2) case_stmt( 1) | |
13004 | } | |
13005 | exprtk_disable_fallthrough_end | |
13006 | ||
13007 | #undef case_stmt | |
13008 | ||
13009 | return result; | |
13010 | } | |
13011 | ||
13012 | T r[] = { | |
13013 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0), | |
13014 | T(0), T(0), T(0), T(0), T(0), T(0), T(0), T(0) | |
13015 | }; | |
13016 | ||
13017 | const T* upper_bound = vec + lud.upper_bound; | |
13018 | ||
13019 | while (vec < upper_bound) | |
13020 | { | |
13021 | #define exprtk_loop(N) \ | |
13022 | r[N] += vec[N]; \ | |
13023 | ||
13024 | exprtk_loop( 0) exprtk_loop( 1) | |
13025 | exprtk_loop( 2) exprtk_loop( 3) | |
13026 | #ifndef exprtk_disable_superscalar_unroll | |
13027 | exprtk_loop( 4) exprtk_loop( 5) | |
13028 | exprtk_loop( 6) exprtk_loop( 7) | |
13029 | exprtk_loop( 8) exprtk_loop( 9) | |
13030 | exprtk_loop(10) exprtk_loop(11) | |
13031 | exprtk_loop(12) exprtk_loop(13) | |
13032 | exprtk_loop(14) exprtk_loop(15) | |
13033 | #endif | |
13034 | ||
13035 | vec += lud.batch_size; | |
13036 | } | |
13037 | ||
13038 | int i = 0; | |
13039 | ||
13040 | exprtk_disable_fallthrough_begin | |
13041 | switch (lud.remainder) | |
13042 | { | |
13043 | #define case_stmt(N) \ | |
13044 | case N : r[0] += vec[i++]; \ | |
13045 | ||
13046 | #ifndef exprtk_disable_superscalar_unroll | |
13047 | case_stmt(15) case_stmt(14) | |
13048 | case_stmt(13) case_stmt(12) | |
13049 | case_stmt(11) case_stmt(10) | |
13050 | case_stmt( 9) case_stmt( 8) | |
13051 | case_stmt( 7) case_stmt( 6) | |
13052 | case_stmt( 5) case_stmt( 4) | |
13053 | #endif | |
13054 | case_stmt( 3) case_stmt( 2) | |
13055 | case_stmt( 1) | |
13056 | } | |
13057 | exprtk_disable_fallthrough_end | |
13058 | ||
13059 | #undef exprtk_loop | |
13060 | #undef case_stmt | |
13061 | ||
13062 | return (r[ 0] + r[ 1] + r[ 2] + r[ 3]) | |
13063 | #ifndef exprtk_disable_superscalar_unroll | |
13064 | + (r[ 4] + r[ 5] + r[ 6] + r[ 7]) | |
13065 | + (r[ 8] + r[ 9] + r[10] + r[11]) | |
13066 | + (r[12] + r[13] + r[14] + r[15]) | |
13067 | #endif | |
13068 | ; | |
13069 | } | |
13070 | }; | |
13071 | ||
13072 | template <typename T> | |
13073 | struct vec_mul_op | |
13074 | { | |
13075 | typedef vector_interface<T>* ivector_ptr; | |
13076 | ||
13077 | static inline T process(const ivector_ptr v) | |
13078 | { | |
13079 | const T* vec = v->vec()->vds().data(); | |
13080 | const std::size_t vec_size = v->vec()->vds().size(); | |
13081 | ||
13082 | loop_unroll::details lud(vec_size); | |
13083 | ||
13084 | if (vec_size <= static_cast<std::size_t>(lud.batch_size)) | |
13085 | { | |
13086 | T result = T(1); | |
13087 | int i = 0; | |
13088 | ||
13089 | exprtk_disable_fallthrough_begin | |
13090 | switch (vec_size) | |
13091 | { | |
13092 | #define case_stmt(N) \ | |
13093 | case N : result *= vec[i++]; \ | |
13094 | ||
13095 | #ifndef exprtk_disable_superscalar_unroll | |
13096 | case_stmt(16) case_stmt(15) | |
13097 | case_stmt(14) case_stmt(13) | |
13098 | case_stmt(12) case_stmt(11) | |
13099 | case_stmt(10) case_stmt( 9) | |
13100 | case_stmt( 8) case_stmt( 7) | |
13101 | case_stmt( 6) case_stmt( 5) | |
13102 | #endif | |
13103 | case_stmt( 4) case_stmt( 3) | |
13104 | case_stmt( 2) case_stmt( 1) | |
13105 | } | |
13106 | exprtk_disable_fallthrough_end | |
13107 | ||
13108 | #undef case_stmt | |
13109 | ||
13110 | return result; | |
13111 | } | |
13112 | ||
13113 | T r[] = { | |
13114 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1), | |
13115 | T(1), T(1), T(1), T(1), T(1), T(1), T(1), T(1) | |
13116 | }; | |
13117 | ||
13118 | const T* upper_bound = vec + lud.upper_bound; | |
13119 | ||
13120 | while (vec < upper_bound) | |
13121 | { | |
13122 | #define exprtk_loop(N) \ | |
13123 | r[N] *= vec[N]; \ | |
13124 | ||
13125 | exprtk_loop( 0) exprtk_loop( 1) | |
13126 | exprtk_loop( 2) exprtk_loop( 3) | |
13127 | #ifndef exprtk_disable_superscalar_unroll | |
13128 | exprtk_loop( 4) exprtk_loop( 5) | |
13129 | exprtk_loop( 6) exprtk_loop( 7) | |
13130 | exprtk_loop( 8) exprtk_loop( 9) | |
13131 | exprtk_loop(10) exprtk_loop(11) | |
13132 | exprtk_loop(12) exprtk_loop(13) | |
13133 | exprtk_loop(14) exprtk_loop(15) | |
13134 | #endif | |
13135 | ||
13136 | vec += lud.batch_size; | |
13137 | } | |
13138 | ||
13139 | int i = 0; | |
13140 | ||
13141 | exprtk_disable_fallthrough_begin | |
13142 | switch (lud.remainder) | |
13143 | { | |
13144 | #define case_stmt(N) \ | |
13145 | case N : r[0] *= vec[i++]; \ | |
13146 | ||
13147 | #ifndef exprtk_disable_superscalar_unroll | |
13148 | case_stmt(15) case_stmt(14) | |
13149 | case_stmt(13) case_stmt(12) | |
13150 | case_stmt(11) case_stmt(10) | |
13151 | case_stmt( 9) case_stmt( 8) | |
13152 | case_stmt( 7) case_stmt( 6) | |
13153 | case_stmt( 5) case_stmt( 4) | |
13154 | #endif | |
13155 | case_stmt( 3) case_stmt( 2) | |
13156 | case_stmt( 1) | |
13157 | } | |
13158 | exprtk_disable_fallthrough_end | |
13159 | ||
13160 | #undef exprtk_loop | |
13161 | #undef case_stmt | |
13162 | ||
13163 | return (r[ 0] * r[ 1] * r[ 2] * r[ 3]) | |
13164 | #ifndef exprtk_disable_superscalar_unroll | |
13165 | + (r[ 4] * r[ 5] * r[ 6] * r[ 7]) | |
13166 | + (r[ 8] * r[ 9] * r[10] * r[11]) | |
13167 | + (r[12] * r[13] * r[14] * r[15]) | |
13168 | #endif | |
13169 | ; | |
13170 | } | |
13171 | }; | |
13172 | ||
13173 | template <typename T> | |
13174 | struct vec_avg_op | |
13175 | { | |
13176 | typedef vector_interface<T>* ivector_ptr; | |
13177 | ||
13178 | static inline T process(const ivector_ptr v) | |
13179 | { | |
13180 | const std::size_t vec_size = v->vec()->vds().size(); | |
13181 | ||
13182 | return vec_add_op<T>::process(v) / vec_size; | |
13183 | } | |
13184 | }; | |
13185 | ||
13186 | template <typename T> | |
13187 | struct vec_min_op | |
13188 | { | |
13189 | typedef vector_interface<T>* ivector_ptr; | |
13190 | ||
13191 | static inline T process(const ivector_ptr v) | |
13192 | { | |
13193 | const T* vec = v->vec()->vds().data(); | |
13194 | const std::size_t vec_size = v->vec()->vds().size(); | |
13195 | ||
13196 | T result = vec[0]; | |
13197 | ||
13198 | for (std::size_t i = 1; i < vec_size; ++i) | |
13199 | { | |
13200 | T v_i = vec[i]; | |
13201 | ||
13202 | if (v_i < result) | |
13203 | result = v_i; | |
13204 | } | |
13205 | ||
13206 | return result; | |
13207 | } | |
13208 | }; | |
13209 | ||
13210 | template <typename T> | |
13211 | struct vec_max_op | |
13212 | { | |
13213 | typedef vector_interface<T>* ivector_ptr; | |
13214 | ||
13215 | static inline T process(const ivector_ptr v) | |
13216 | { | |
13217 | const T* vec = v->vec()->vds().data(); | |
13218 | const std::size_t vec_size = v->vec()->vds().size(); | |
13219 | ||
13220 | T result = vec[0]; | |
13221 | ||
13222 | for (std::size_t i = 1; i < vec_size; ++i) | |
13223 | { | |
13224 | T v_i = vec[i]; | |
13225 | ||
13226 | if (v_i > result) | |
13227 | result = v_i; | |
13228 | } | |
13229 | ||
13230 | return result; | |
13231 | } | |
13232 | }; | |
13233 | ||
13234 | template <typename T> | |
13235 | class vov_base_node : public expression_node<T> | |
13236 | { | |
13237 | public: | |
13238 | ||
13239 | virtual ~vov_base_node() | |
13240 | {} | |
13241 | ||
13242 | inline virtual operator_type operation() const | |
13243 | { | |
13244 | return details::e_default; | |
13245 | } | |
13246 | ||
13247 | virtual const T& v0() const = 0; | |
13248 | ||
13249 | virtual const T& v1() const = 0; | |
13250 | }; | |
13251 | ||
13252 | template <typename T> | |
13253 | class cov_base_node : public expression_node<T> | |
13254 | { | |
13255 | public: | |
13256 | ||
13257 | virtual ~cov_base_node() | |
13258 | {} | |
13259 | ||
13260 | inline virtual operator_type operation() const | |
13261 | { | |
13262 | return details::e_default; | |
13263 | } | |
13264 | ||
13265 | virtual const T c() const = 0; | |
13266 | ||
13267 | virtual const T& v() const = 0; | |
13268 | }; | |
13269 | ||
13270 | template <typename T> | |
13271 | class voc_base_node : public expression_node<T> | |
13272 | { | |
13273 | public: | |
13274 | ||
13275 | virtual ~voc_base_node() | |
13276 | {} | |
13277 | ||
13278 | inline virtual operator_type operation() const | |
13279 | { | |
13280 | return details::e_default; | |
13281 | } | |
13282 | ||
13283 | virtual const T c() const = 0; | |
13284 | ||
13285 | virtual const T& v() const = 0; | |
13286 | }; | |
13287 | ||
13288 | template <typename T> | |
13289 | class vob_base_node : public expression_node<T> | |
13290 | { | |
13291 | public: | |
13292 | ||
13293 | virtual ~vob_base_node() | |
13294 | {} | |
13295 | ||
13296 | virtual const T& v() const = 0; | |
13297 | }; | |
13298 | ||
13299 | template <typename T> | |
13300 | class bov_base_node : public expression_node<T> | |
13301 | { | |
13302 | public: | |
13303 | ||
13304 | virtual ~bov_base_node() | |
13305 | {} | |
13306 | ||
13307 | virtual const T& v() const = 0; | |
13308 | }; | |
13309 | ||
13310 | template <typename T> | |
13311 | class cob_base_node : public expression_node<T> | |
13312 | { | |
13313 | public: | |
13314 | ||
13315 | virtual ~cob_base_node() | |
13316 | {} | |
13317 | ||
13318 | inline virtual operator_type operation() const | |
13319 | { | |
13320 | return details::e_default; | |
13321 | } | |
13322 | ||
13323 | virtual const T c() const = 0; | |
13324 | ||
13325 | virtual void set_c(const T) = 0; | |
13326 | ||
13327 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; | |
13328 | }; | |
13329 | ||
13330 | template <typename T> | |
13331 | class boc_base_node : public expression_node<T> | |
13332 | { | |
13333 | public: | |
13334 | ||
13335 | virtual ~boc_base_node() | |
13336 | {} | |
13337 | ||
13338 | inline virtual operator_type operation() const | |
13339 | { | |
13340 | return details::e_default; | |
13341 | } | |
13342 | ||
13343 | virtual const T c() const = 0; | |
13344 | ||
13345 | virtual void set_c(const T) = 0; | |
13346 | ||
13347 | virtual expression_node<T>* move_branch(const std::size_t& index) = 0; | |
13348 | }; | |
13349 | ||
13350 | template <typename T> | |
13351 | class uv_base_node : public expression_node<T> | |
13352 | { | |
13353 | public: | |
13354 | ||
13355 | virtual ~uv_base_node() | |
13356 | {} | |
13357 | ||
13358 | inline virtual operator_type operation() const | |
13359 | { | |
13360 | return details::e_default; | |
13361 | } | |
13362 | ||
13363 | virtual const T& v() const = 0; | |
13364 | }; | |
13365 | ||
13366 | template <typename T> | |
13367 | class sos_base_node : public expression_node<T> | |
13368 | { | |
13369 | public: | |
13370 | ||
13371 | virtual ~sos_base_node() | |
13372 | {} | |
13373 | ||
13374 | inline virtual operator_type operation() const | |
13375 | { | |
13376 | return details::e_default; | |
13377 | } | |
13378 | }; | |
13379 | ||
13380 | template <typename T> | |
13381 | class sosos_base_node : public expression_node<T> | |
13382 | { | |
13383 | public: | |
13384 | ||
13385 | virtual ~sosos_base_node() | |
13386 | {} | |
13387 | ||
13388 | inline virtual operator_type operation() const | |
13389 | { | |
13390 | return details::e_default; | |
13391 | } | |
13392 | }; | |
13393 | ||
13394 | template <typename T> | |
13395 | class T0oT1oT2_base_node : public expression_node<T> | |
13396 | { | |
13397 | public: | |
13398 | ||
13399 | virtual ~T0oT1oT2_base_node() | |
13400 | {} | |
13401 | ||
13402 | virtual std::string type_id() const = 0; | |
13403 | }; | |
13404 | ||
13405 | template <typename T> | |
13406 | class T0oT1oT2oT3_base_node : public expression_node<T> | |
13407 | { | |
13408 | public: | |
13409 | ||
13410 | virtual ~T0oT1oT2oT3_base_node() | |
13411 | {} | |
13412 | ||
13413 | virtual std::string type_id() const = 0; | |
13414 | }; | |
13415 | ||
13416 | template <typename T, typename Operation> | |
13417 | class unary_variable_node : public uv_base_node<T> | |
13418 | { | |
13419 | public: | |
13420 | ||
13421 | typedef expression_node<T>* expression_ptr; | |
13422 | typedef Operation operation_t; | |
13423 | ||
13424 | explicit unary_variable_node(const T& var) | |
13425 | : v_(var) | |
13426 | {} | |
13427 | ||
13428 | inline T value() const | |
13429 | { | |
13430 | return Operation::process(v_); | |
13431 | } | |
13432 | ||
13433 | inline typename expression_node<T>::node_type type() const | |
13434 | { | |
13435 | return Operation::type(); | |
13436 | } | |
13437 | ||
13438 | inline operator_type operation() const | |
13439 | { | |
13440 | return Operation::operation(); | |
13441 | } | |
13442 | ||
13443 | inline const T& v() const | |
13444 | { | |
13445 | return v_; | |
13446 | } | |
13447 | ||
13448 | private: | |
13449 | ||
13450 | unary_variable_node(unary_variable_node<T,Operation>&); | |
13451 | unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&); | |
13452 | ||
13453 | const T& v_; | |
13454 | }; | |
13455 | ||
13456 | template <typename T> | |
13457 | class uvouv_node : public expression_node<T> | |
13458 | { | |
13459 | public: | |
13460 | ||
13461 | // UOpr1(v0) Op UOpr2(v1) | |
13462 | ||
13463 | typedef expression_node<T>* expression_ptr; | |
13464 | typedef typename details::functor_t<T> functor_t; | |
13465 | typedef typename functor_t::bfunc_t bfunc_t; | |
13466 | typedef typename functor_t::ufunc_t ufunc_t; | |
13467 | ||
13468 | explicit uvouv_node(const T& var0,const T& var1, | |
13469 | ufunc_t uf0, ufunc_t uf1, bfunc_t bf) | |
13470 | : v0_(var0), | |
13471 | v1_(var1), | |
13472 | u0_(uf0 ), | |
13473 | u1_(uf1 ), | |
13474 | f_ (bf ) | |
13475 | {} | |
13476 | ||
13477 | inline T value() const | |
13478 | { | |
13479 | return f_(u0_(v0_),u1_(v1_)); | |
13480 | } | |
13481 | ||
13482 | inline typename expression_node<T>::node_type type() const | |
13483 | { | |
13484 | return expression_node<T>::e_uvouv; | |
13485 | } | |
13486 | ||
13487 | inline operator_type operation() const | |
13488 | { | |
13489 | return details::e_default; | |
13490 | } | |
13491 | ||
13492 | inline const T& v0() | |
13493 | { | |
13494 | return v0_; | |
13495 | } | |
13496 | ||
13497 | inline const T& v1() | |
13498 | { | |
13499 | return v1_; | |
13500 | } | |
13501 | ||
13502 | inline ufunc_t u0() | |
13503 | { | |
13504 | return u0_; | |
13505 | } | |
13506 | ||
13507 | inline ufunc_t u1() | |
13508 | { | |
13509 | return u1_; | |
13510 | } | |
13511 | ||
13512 | inline ufunc_t f() | |
13513 | { | |
13514 | return f_; | |
13515 | } | |
13516 | ||
13517 | private: | |
13518 | ||
13519 | uvouv_node(uvouv_node<T>&); | |
13520 | uvouv_node<T>& operator=(uvouv_node<T>&); | |
13521 | ||
13522 | const T& v0_; | |
13523 | const T& v1_; | |
13524 | const ufunc_t u0_; | |
13525 | const ufunc_t u1_; | |
13526 | const bfunc_t f_; | |
13527 | }; | |
13528 | ||
13529 | template <typename T, typename Operation> | |
13530 | class unary_branch_node : public expression_node<T> | |
13531 | { | |
13532 | public: | |
13533 | ||
13534 | typedef expression_node<T>* expression_ptr; | |
13535 | typedef Operation operation_t; | |
13536 | ||
13537 | explicit unary_branch_node(expression_ptr brnch) | |
13538 | : branch_(brnch), | |
13539 | branch_deletable_(branch_deletable(branch_)) | |
13540 | {} | |
13541 | ||
13542 | ~unary_branch_node() | |
13543 | { | |
13544 | if (branch_ && branch_deletable_) | |
13545 | { | |
13546 | destroy_node(branch_); | |
13547 | } | |
13548 | } | |
13549 | ||
13550 | inline T value() const | |
13551 | { | |
13552 | return Operation::process(branch_->value()); | |
13553 | } | |
13554 | ||
13555 | inline typename expression_node<T>::node_type type() const | |
13556 | { | |
13557 | return Operation::type(); | |
13558 | } | |
13559 | ||
13560 | inline operator_type operation() const | |
13561 | { | |
13562 | return Operation::operation(); | |
13563 | } | |
13564 | ||
13565 | inline expression_node<T>* branch(const std::size_t&) const | |
13566 | { | |
13567 | return branch_; | |
13568 | } | |
13569 | ||
13570 | inline void release() | |
13571 | { | |
13572 | branch_deletable_ = false; | |
13573 | } | |
13574 | ||
13575 | private: | |
13576 | ||
13577 | unary_branch_node(unary_branch_node<T,Operation>&); | |
13578 | unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&); | |
13579 | ||
13580 | expression_ptr branch_; | |
13581 | bool branch_deletable_; | |
13582 | }; | |
13583 | ||
13584 | template <typename T> struct is_const { enum {result = 0}; }; | |
13585 | template <typename T> struct is_const <const T> { enum {result = 1}; }; | |
13586 | template <typename T> struct is_const_ref { enum {result = 0}; }; | |
13587 | template <typename T> struct is_const_ref <const T&> { enum {result = 1}; }; | |
13588 | template <typename T> struct is_ref { enum {result = 0}; }; | |
13589 | template <typename T> struct is_ref<T&> { enum {result = 1}; }; | |
13590 | template <typename T> struct is_ref<const T&> { enum {result = 0}; }; | |
13591 | ||
13592 | template <std::size_t State> | |
13593 | struct param_to_str { static std::string result() { static const std::string r("v"); return r; } }; | |
13594 | ||
13595 | template <> | |
13596 | struct param_to_str<0> { static std::string result() { static const std::string r("c"); return r; } }; | |
13597 | ||
13598 | #define exprtk_crtype(Type) \ | |
13599 | param_to_str<is_const_ref< Type >::result>::result() \ | |
13600 | ||
13601 | template <typename T> | |
13602 | struct T0oT1oT2process | |
13603 | { | |
13604 | typedef typename details::functor_t<T> functor_t; | |
13605 | typedef typename functor_t::bfunc_t bfunc_t; | |
13606 | ||
13607 | struct mode0 | |
13608 | { | |
13609 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) | |
13610 | { | |
13611 | // (T0 o0 T1) o1 T2 | |
13612 | return bf1(bf0(t0,t1),t2); | |
13613 | } | |
13614 | ||
13615 | template <typename T0, typename T1, typename T2> | |
13616 | static inline std::string id() | |
13617 | { | |
13618 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + | |
13619 | exprtk_crtype(T1) + ")o(" + | |
13620 | exprtk_crtype(T2) + ")" ; | |
13621 | return result; | |
13622 | } | |
13623 | }; | |
13624 | ||
13625 | struct mode1 | |
13626 | { | |
13627 | static inline T process(const T& t0, const T& t1, const T& t2, const bfunc_t bf0, const bfunc_t bf1) | |
13628 | { | |
13629 | // T0 o0 (T1 o1 T2) | |
13630 | return bf0(t0,bf1(t1,t2)); | |
13631 | } | |
13632 | ||
13633 | template <typename T0, typename T1, typename T2> | |
13634 | static inline std::string id() | |
13635 | { | |
13636 | static const std::string result = "(" + exprtk_crtype(T0) + ")o(" + | |
13637 | exprtk_crtype(T1) + "o" + | |
13638 | exprtk_crtype(T2) + ")" ; | |
13639 | return result; | |
13640 | } | |
13641 | }; | |
13642 | }; | |
13643 | ||
13644 | template <typename T> | |
13645 | struct T0oT1oT20T3process | |
13646 | { | |
13647 | typedef typename details::functor_t<T> functor_t; | |
13648 | typedef typename functor_t::bfunc_t bfunc_t; | |
13649 | ||
13650 | struct mode0 | |
13651 | { | |
13652 | static inline T process(const T& t0, const T& t1, | |
13653 | const T& t2, const T& t3, | |
13654 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) | |
13655 | { | |
13656 | // (T0 o0 T1) o1 (T2 o2 T3) | |
13657 | return bf1(bf0(t0,t1),bf2(t2,t3)); | |
13658 | } | |
13659 | ||
13660 | template <typename T0, typename T1, typename T2, typename T3> | |
13661 | static inline std::string id() | |
13662 | { | |
13663 | static const std::string result = "(" + exprtk_crtype(T0) + "o" + | |
13664 | exprtk_crtype(T1) + ")o" + | |
13665 | "(" + exprtk_crtype(T2) + "o" + | |
13666 | exprtk_crtype(T3) + ")" ; | |
13667 | return result; | |
13668 | } | |
13669 | }; | |
13670 | ||
13671 | struct mode1 | |
13672 | { | |
13673 | static inline T process(const T& t0, const T& t1, | |
13674 | const T& t2, const T& t3, | |
13675 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) | |
13676 | { | |
13677 | // (T0 o0 (T1 o1 (T2 o2 T3)) | |
13678 | return bf0(t0,bf1(t1,bf2(t2,t3))); | |
13679 | } | |
13680 | template <typename T0, typename T1, typename T2, typename T3> | |
13681 | static inline std::string id() | |
13682 | { | |
13683 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + | |
13684 | exprtk_crtype(T1) + ")o(" + | |
13685 | exprtk_crtype(T2) + "o" + | |
13686 | exprtk_crtype(T3) + "))" ; | |
13687 | return result; | |
13688 | } | |
13689 | }; | |
13690 | ||
13691 | struct mode2 | |
13692 | { | |
13693 | static inline T process(const T& t0, const T& t1, | |
13694 | const T& t2, const T& t3, | |
13695 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) | |
13696 | { | |
13697 | // (T0 o0 ((T1 o1 T2) o2 T3) | |
13698 | return bf0(t0,bf2(bf1(t1,t2),t3)); | |
13699 | } | |
13700 | ||
13701 | template <typename T0, typename T1, typename T2, typename T3> | |
13702 | static inline std::string id() | |
13703 | { | |
13704 | static const std::string result = "(" + exprtk_crtype(T0) + ")o((" + | |
13705 | exprtk_crtype(T1) + "o" + | |
13706 | exprtk_crtype(T2) + ")o(" + | |
13707 | exprtk_crtype(T3) + "))" ; | |
13708 | return result; | |
13709 | } | |
13710 | }; | |
13711 | ||
13712 | struct mode3 | |
13713 | { | |
13714 | static inline T process(const T& t0, const T& t1, | |
13715 | const T& t2, const T& t3, | |
13716 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) | |
13717 | { | |
13718 | // (((T0 o0 T1) o1 T2) o2 T3) | |
13719 | return bf2(bf1(bf0(t0,t1),t2),t3); | |
13720 | } | |
13721 | ||
13722 | template <typename T0, typename T1, typename T2, typename T3> | |
13723 | static inline std::string id() | |
13724 | { | |
13725 | static const std::string result = "((" + exprtk_crtype(T0) + "o" + | |
13726 | exprtk_crtype(T1) + ")o(" + | |
13727 | exprtk_crtype(T2) + "))o(" + | |
13728 | exprtk_crtype(T3) + ")"; | |
13729 | return result; | |
13730 | } | |
13731 | }; | |
13732 | ||
13733 | struct mode4 | |
13734 | { | |
13735 | static inline T process(const T& t0, const T& t1, | |
13736 | const T& t2, const T& t3, | |
13737 | const bfunc_t bf0, const bfunc_t bf1, const bfunc_t bf2) | |
13738 | { | |
13739 | // ((T0 o0 (T1 o1 T2)) o2 T3 | |
13740 | return bf2(bf0(t0,bf1(t1,t2)),t3); | |
13741 | } | |
13742 | ||
13743 | template <typename T0, typename T1, typename T2, typename T3> | |
13744 | static inline std::string id() | |
13745 | { | |
13746 | static const std::string result = "((" + exprtk_crtype(T0) + ")o(" + | |
13747 | exprtk_crtype(T1) + "o" + | |
13748 | exprtk_crtype(T2) + "))o(" + | |
13749 | exprtk_crtype(T3) + ")" ; | |
13750 | return result; | |
13751 | } | |
13752 | }; | |
13753 | }; | |
13754 | ||
13755 | #undef exprtk_crtype | |
13756 | ||
13757 | template <typename T, typename T0, typename T1> | |
13758 | struct nodetype_T0oT1 { static const typename expression_node<T>::node_type result; }; | |
13759 | template <typename T, typename T0, typename T1> | |
13760 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0,T1>::result = expression_node<T>::e_none; | |
13761 | ||
13762 | #define synthesis_node_type_define(T0_,T1_,v_) \ | |
13763 | template <typename T, typename T0, typename T1> \ | |
13764 | struct nodetype_T0oT1<T,T0_,T1_> { static const typename expression_node<T>::node_type result; }; \ | |
13765 | template <typename T, typename T0, typename T1> \ | |
13766 | const typename expression_node<T>::node_type nodetype_T0oT1<T,T0_,T1_>::result = expression_node<T>:: v_; \ | |
13767 | ||
13768 | synthesis_node_type_define(const T0&, const T1&, e_vov) | |
13769 | synthesis_node_type_define(const T0&, const T1 , e_voc) | |
13770 | synthesis_node_type_define(const T0 , const T1&, e_cov) | |
13771 | synthesis_node_type_define( T0&, T1&, e_none) | |
13772 | synthesis_node_type_define(const T0 , const T1 , e_none) | |
13773 | synthesis_node_type_define( T0&, const T1 , e_none) | |
13774 | synthesis_node_type_define(const T0 , T1&, e_none) | |
13775 | synthesis_node_type_define(const T0&, T1&, e_none) | |
13776 | synthesis_node_type_define( T0&, const T1&, e_none) | |
13777 | #undef synthesis_node_type_define | |
13778 | ||
13779 | template <typename T, typename T0, typename T1, typename T2> | |
13780 | struct nodetype_T0oT1oT2 { static const typename expression_node<T>::node_type result; }; | |
13781 | template <typename T, typename T0, typename T1, typename T2> | |
13782 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0,T1,T2>::result = expression_node<T>::e_none; | |
13783 | ||
13784 | #define synthesis_node_type_define(T0_,T1_,T2_,v_) \ | |
13785 | template <typename T, typename T0, typename T1, typename T2> \ | |
13786 | struct nodetype_T0oT1oT2<T,T0_,T1_,T2_> { static const typename expression_node<T>::node_type result; }; \ | |
13787 | template <typename T, typename T0, typename T1, typename T2> \ | |
13788 | const typename expression_node<T>::node_type nodetype_T0oT1oT2<T,T0_,T1_,T2_>::result = expression_node<T>:: v_; \ | |
13789 | ||
13790 | synthesis_node_type_define(const T0&, const T1&, const T2&, e_vovov) | |
13791 | synthesis_node_type_define(const T0&, const T1&, const T2 , e_vovoc) | |
13792 | synthesis_node_type_define(const T0&, const T1 , const T2&, e_vocov) | |
13793 | synthesis_node_type_define(const T0 , const T1&, const T2&, e_covov) | |
13794 | synthesis_node_type_define(const T0 , const T1&, const T2 , e_covoc) | |
13795 | synthesis_node_type_define(const T0 , const T1 , const T2 , e_none ) | |
13796 | synthesis_node_type_define(const T0 , const T1 , const T2&, e_none ) | |
13797 | synthesis_node_type_define(const T0&, const T1 , const T2 , e_none ) | |
13798 | synthesis_node_type_define( T0&, T1&, T2&, e_none ) | |
13799 | #undef synthesis_node_type_define | |
13800 | ||
13801 | template <typename T, typename T0, typename T1, typename T2, typename T3> | |
13802 | struct nodetype_T0oT1oT2oT3 { static const typename expression_node<T>::node_type result; }; | |
13803 | template <typename T, typename T0, typename T1, typename T2, typename T3> | |
13804 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result = expression_node<T>::e_none; | |
13805 | ||
13806 | #define synthesis_node_type_define(T0_,T1_,T2_,T3_,v_) \ | |
13807 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ | |
13808 | struct nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_> { static const typename expression_node<T>::node_type result; }; \ | |
13809 | template <typename T, typename T0, typename T1, typename T2, typename T3> \ | |
13810 | const typename expression_node<T>::node_type nodetype_T0oT1oT2oT3<T,T0_,T1_,T2_,T3_>::result = expression_node<T>:: v_; \ | |
13811 | ||
13812 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3&, e_vovovov) | |
13813 | synthesis_node_type_define(const T0&, const T1&, const T2&, const T3 , e_vovovoc) | |
13814 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3&, e_vovocov) | |
13815 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3&, e_vocovov) | |
13816 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3&, e_covovov) | |
13817 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3&, e_covocov) | |
13818 | synthesis_node_type_define(const T0&, const T1 , const T2&, const T3 , e_vocovoc) | |
13819 | synthesis_node_type_define(const T0 , const T1&, const T2&, const T3 , e_covovoc) | |
13820 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3&, e_vococov) | |
13821 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3 , e_none ) | |
13822 | synthesis_node_type_define(const T0 , const T1 , const T2 , const T3&, e_none ) | |
13823 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3 , e_none ) | |
13824 | synthesis_node_type_define(const T0 , const T1&, const T2 , const T3 , e_none ) | |
13825 | synthesis_node_type_define(const T0&, const T1 , const T2 , const T3 , e_none ) | |
13826 | synthesis_node_type_define(const T0 , const T1 , const T2&, const T3&, e_none ) | |
13827 | synthesis_node_type_define(const T0&, const T1&, const T2 , const T3 , e_none ) | |
13828 | #undef synthesis_node_type_define | |
13829 | ||
13830 | template <typename T, typename T0, typename T1> | |
13831 | class T0oT1 : public expression_node<T> | |
13832 | { | |
13833 | public: | |
13834 | ||
13835 | typedef typename details::functor_t<T> functor_t; | |
13836 | typedef typename functor_t::bfunc_t bfunc_t; | |
13837 | typedef T value_type; | |
13838 | typedef T0oT1<T,T0,T1> node_type; | |
13839 | ||
13840 | T0oT1(T0 p0, T1 p1, const bfunc_t p2) | |
13841 | : t0_(p0), | |
13842 | t1_(p1), | |
13843 | f_ (p2) | |
13844 | {} | |
13845 | ||
13846 | inline typename expression_node<T>::node_type type() const | |
13847 | { | |
13848 | static const typename expression_node<T>::node_type result = nodetype_T0oT1<T,T0,T1>::result; | |
13849 | return result; | |
13850 | } | |
13851 | ||
13852 | inline operator_type operation() const | |
13853 | { | |
13854 | return e_default; | |
13855 | } | |
13856 | ||
13857 | inline T value() const | |
13858 | { | |
13859 | return f_(t0_,t1_); | |
13860 | } | |
13861 | ||
13862 | inline T0 t0() const | |
13863 | { | |
13864 | return t0_; | |
13865 | } | |
13866 | ||
13867 | inline T1 t1() const | |
13868 | { | |
13869 | return t1_; | |
13870 | } | |
13871 | ||
13872 | inline bfunc_t f() const | |
13873 | { | |
13874 | return f_; | |
13875 | } | |
13876 | ||
13877 | template <typename Allocator> | |
13878 | static inline expression_node<T>* allocate(Allocator& allocator, | |
13879 | T0 p0, T1 p1, | |
13880 | bfunc_t p2) | |
13881 | { | |
13882 | return allocator | |
13883 | .template allocate_type<node_type, T0, T1, bfunc_t&> | |
13884 | (p0, p1, p2); | |
13885 | } | |
13886 | ||
13887 | private: | |
13888 | ||
13889 | T0oT1(T0oT1<T,T0,T1>&) {} | |
13890 | T0oT1<T,T0,T1>& operator=(T0oT1<T,T0,T1>&) { return (*this); } | |
13891 | ||
13892 | T0 t0_; | |
13893 | T1 t1_; | |
13894 | const bfunc_t f_; | |
13895 | }; | |
13896 | ||
13897 | template <typename T, typename T0, typename T1, typename T2, typename ProcessMode> | |
13898 | class T0oT1oT2 : public T0oT1oT2_base_node<T> | |
13899 | { | |
13900 | public: | |
13901 | ||
13902 | typedef typename details::functor_t<T> functor_t; | |
13903 | typedef typename functor_t::bfunc_t bfunc_t; | |
13904 | typedef T value_type; | |
13905 | typedef T0oT1oT2<T,T0,T1,T2,ProcessMode> node_type; | |
13906 | typedef ProcessMode process_mode_t; | |
13907 | ||
13908 | T0oT1oT2(T0 p0, T1 p1, T2 p2, const bfunc_t p3, const bfunc_t p4) | |
13909 | : t0_(p0), | |
13910 | t1_(p1), | |
13911 | t2_(p2), | |
13912 | f0_(p3), | |
13913 | f1_(p4) | |
13914 | {} | |
13915 | ||
13916 | inline typename expression_node<T>::node_type type() const | |
13917 | { | |
13918 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; | |
13919 | return result; | |
13920 | } | |
13921 | ||
13922 | inline operator_type operation() const | |
13923 | { | |
13924 | return e_default; | |
13925 | } | |
13926 | ||
13927 | inline T value() const | |
13928 | { | |
13929 | return ProcessMode::process(t0_, t1_, t2_, f0_, f1_); | |
13930 | } | |
13931 | ||
13932 | inline T0 t0() const | |
13933 | { | |
13934 | return t0_; | |
13935 | } | |
13936 | ||
13937 | inline T1 t1() const | |
13938 | { | |
13939 | return t1_; | |
13940 | } | |
13941 | ||
13942 | inline T2 t2() const | |
13943 | { | |
13944 | return t2_; | |
13945 | } | |
13946 | ||
13947 | bfunc_t f0() const | |
13948 | { | |
13949 | return f0_; | |
13950 | } | |
13951 | ||
13952 | bfunc_t f1() const | |
13953 | { | |
13954 | return f1_; | |
13955 | } | |
13956 | ||
13957 | std::string type_id() const | |
13958 | { | |
13959 | return id(); | |
13960 | } | |
13961 | ||
13962 | static inline std::string id() | |
13963 | { | |
13964 | return process_mode_t::template id<T0,T1,T2>(); | |
13965 | } | |
13966 | ||
13967 | template <typename Allocator> | |
13968 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, bfunc_t p3, bfunc_t p4) | |
13969 | { | |
13970 | return allocator | |
13971 | .template allocate_type<node_type, T0, T1, T2, bfunc_t, bfunc_t> | |
13972 | (p0, p1, p2, p3, p4); | |
13973 | } | |
13974 | ||
13975 | private: | |
13976 | ||
13977 | T0oT1oT2(node_type&) {} | |
13978 | node_type& operator=(node_type&) { return (*this); } | |
13979 | ||
13980 | T0 t0_; | |
13981 | T1 t1_; | |
13982 | T2 t2_; | |
13983 | const bfunc_t f0_; | |
13984 | const bfunc_t f1_; | |
13985 | }; | |
13986 | ||
13987 | template <typename T, typename T0_, typename T1_, typename T2_, typename T3_, typename ProcessMode> | |
13988 | class T0oT1oT2oT3 : public T0oT1oT2oT3_base_node<T> | |
13989 | { | |
13990 | public: | |
13991 | ||
13992 | typedef typename details::functor_t<T> functor_t; | |
13993 | typedef typename functor_t::bfunc_t bfunc_t; | |
13994 | typedef T value_type; | |
13995 | typedef T0_ T0; | |
13996 | typedef T1_ T1; | |
13997 | typedef T2_ T2; | |
13998 | typedef T3_ T3; | |
13999 | typedef T0oT1oT2oT3<T,T0,T1,T2,T3,ProcessMode> node_type; | |
14000 | typedef ProcessMode process_mode_t; | |
14001 | ||
14002 | T0oT1oT2oT3(T0 p0, T1 p1, T2 p2, T3 p3, bfunc_t p4, bfunc_t p5, bfunc_t p6) | |
14003 | : t0_(p0), | |
14004 | t1_(p1), | |
14005 | t2_(p2), | |
14006 | t3_(p3), | |
14007 | f0_(p4), | |
14008 | f1_(p5), | |
14009 | f2_(p6) | |
14010 | {} | |
14011 | ||
14012 | inline T value() const | |
14013 | { | |
14014 | return ProcessMode::process(t0_, t1_, t2_, t3_, f0_, f1_, f2_); | |
14015 | } | |
14016 | ||
14017 | inline T0 t0() const | |
14018 | { | |
14019 | return t0_; | |
14020 | } | |
14021 | ||
14022 | inline T1 t1() const | |
14023 | { | |
14024 | return t1_; | |
14025 | } | |
14026 | ||
14027 | inline T2 t2() const | |
14028 | { | |
14029 | return t2_; | |
14030 | } | |
14031 | ||
14032 | inline T3 t3() const | |
14033 | { | |
14034 | return t3_; | |
14035 | } | |
14036 | ||
14037 | inline bfunc_t f0() const | |
14038 | { | |
14039 | return f0_; | |
14040 | } | |
14041 | ||
14042 | inline bfunc_t f1() const | |
14043 | { | |
14044 | return f1_; | |
14045 | } | |
14046 | ||
14047 | inline bfunc_t f2() const | |
14048 | { | |
14049 | return f2_; | |
14050 | } | |
14051 | ||
14052 | inline std::string type_id() const | |
14053 | { | |
14054 | return id(); | |
14055 | } | |
14056 | ||
14057 | static inline std::string id() | |
14058 | { | |
14059 | return process_mode_t::template id<T0, T1, T2, T3>(); | |
14060 | } | |
14061 | ||
14062 | template <typename Allocator> | |
14063 | static inline expression_node<T>* allocate(Allocator& allocator, | |
14064 | T0 p0, T1 p1, T2 p2, T3 p3, | |
14065 | bfunc_t p4, bfunc_t p5, bfunc_t p6) | |
14066 | { | |
14067 | return allocator | |
14068 | .template allocate_type<node_type, T0, T1, T2, T3, bfunc_t, bfunc_t> | |
14069 | (p0, p1, p2, p3, p4, p5, p6); | |
14070 | } | |
14071 | ||
14072 | private: | |
14073 | ||
14074 | T0oT1oT2oT3(node_type&) {} | |
14075 | node_type& operator=(node_type&) { return (*this); } | |
14076 | ||
14077 | T0 t0_; | |
14078 | T1 t1_; | |
14079 | T2 t2_; | |
14080 | T3 t3_; | |
14081 | const bfunc_t f0_; | |
14082 | const bfunc_t f1_; | |
14083 | const bfunc_t f2_; | |
14084 | }; | |
14085 | ||
14086 | template <typename T, typename T0, typename T1, typename T2> | |
14087 | class T0oT1oT2_sf3 : public T0oT1oT2_base_node<T> | |
14088 | { | |
14089 | public: | |
14090 | ||
14091 | typedef typename details::functor_t<T> functor_t; | |
14092 | typedef typename functor_t::tfunc_t tfunc_t; | |
14093 | typedef T value_type; | |
14094 | typedef T0oT1oT2_sf3<T,T0,T1,T2> node_type; | |
14095 | ||
14096 | T0oT1oT2_sf3(T0 p0, T1 p1, T2 p2, const tfunc_t p3) | |
14097 | : t0_(p0), | |
14098 | t1_(p1), | |
14099 | t2_(p2), | |
14100 | f_ (p3) | |
14101 | {} | |
14102 | ||
14103 | inline typename expression_node<T>::node_type type() const | |
14104 | { | |
14105 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; | |
14106 | return result; | |
14107 | } | |
14108 | ||
14109 | inline operator_type operation() const | |
14110 | { | |
14111 | return e_default; | |
14112 | } | |
14113 | ||
14114 | inline T value() const | |
14115 | { | |
14116 | return f_(t0_, t1_, t2_); | |
14117 | } | |
14118 | ||
14119 | inline T0 t0() const | |
14120 | { | |
14121 | return t0_; | |
14122 | } | |
14123 | ||
14124 | inline T1 t1() const | |
14125 | { | |
14126 | return t1_; | |
14127 | } | |
14128 | ||
14129 | inline T2 t2() const | |
14130 | { | |
14131 | return t2_; | |
14132 | } | |
14133 | ||
14134 | tfunc_t f() const | |
14135 | { | |
14136 | return f_; | |
14137 | } | |
14138 | ||
14139 | std::string type_id() const | |
14140 | { | |
14141 | return id(); | |
14142 | } | |
14143 | ||
14144 | static inline std::string id() | |
14145 | { | |
14146 | return "sf3"; | |
14147 | } | |
14148 | ||
14149 | template <typename Allocator> | |
14150 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, tfunc_t p3) | |
14151 | { | |
14152 | return allocator | |
14153 | .template allocate_type<node_type, T0, T1, T2, tfunc_t> | |
14154 | (p0, p1, p2, p3); | |
14155 | } | |
14156 | ||
14157 | private: | |
14158 | ||
14159 | T0oT1oT2_sf3(node_type&) {} | |
14160 | node_type& operator=(node_type&) { return (*this); } | |
14161 | ||
14162 | T0 t0_; | |
14163 | T1 t1_; | |
14164 | T2 t2_; | |
14165 | const tfunc_t f_; | |
14166 | }; | |
14167 | ||
14168 | template <typename T, typename T0, typename T1, typename T2> | |
14169 | class sf3ext_type_node : public T0oT1oT2_base_node<T> | |
14170 | { | |
14171 | public: | |
14172 | ||
14173 | virtual ~sf3ext_type_node() | |
14174 | {} | |
14175 | ||
14176 | virtual T0 t0() const = 0; | |
14177 | ||
14178 | virtual T1 t1() const = 0; | |
14179 | ||
14180 | virtual T2 t2() const = 0; | |
14181 | }; | |
14182 | ||
14183 | template <typename T, typename T0, typename T1, typename T2, typename SF3Operation> | |
14184 | class T0oT1oT2_sf3ext : public sf3ext_type_node<T,T0,T1,T2> | |
14185 | { | |
14186 | public: | |
14187 | ||
14188 | typedef typename details::functor_t<T> functor_t; | |
14189 | typedef typename functor_t::tfunc_t tfunc_t; | |
14190 | typedef T value_type; | |
14191 | typedef T0oT1oT2_sf3ext<T,T0,T1,T2,SF3Operation> node_type; | |
14192 | ||
14193 | T0oT1oT2_sf3ext(T0 p0, T1 p1, T2 p2) | |
14194 | : t0_(p0), | |
14195 | t1_(p1), | |
14196 | t2_(p2) | |
14197 | {} | |
14198 | ||
14199 | inline typename expression_node<T>::node_type type() const | |
14200 | { | |
14201 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2<T,T0,T1,T2>::result; | |
14202 | return result; | |
14203 | } | |
14204 | ||
14205 | inline operator_type operation() const | |
14206 | { | |
14207 | return e_default; | |
14208 | } | |
14209 | ||
14210 | inline T value() const | |
14211 | { | |
14212 | return SF3Operation::process(t0_, t1_, t2_); | |
14213 | } | |
14214 | ||
14215 | T0 t0() const | |
14216 | { | |
14217 | return t0_; | |
14218 | } | |
14219 | ||
14220 | T1 t1() const | |
14221 | { | |
14222 | return t1_; | |
14223 | } | |
14224 | ||
14225 | T2 t2() const | |
14226 | { | |
14227 | return t2_; | |
14228 | } | |
14229 | ||
14230 | std::string type_id() const | |
14231 | { | |
14232 | return id(); | |
14233 | } | |
14234 | ||
14235 | static inline std::string id() | |
14236 | { | |
14237 | return SF3Operation::id(); | |
14238 | } | |
14239 | ||
14240 | template <typename Allocator> | |
14241 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2) | |
14242 | { | |
14243 | return allocator | |
14244 | .template allocate_type<node_type, T0, T1, T2> | |
14245 | (p0, p1, p2); | |
14246 | } | |
14247 | ||
14248 | private: | |
14249 | ||
14250 | T0oT1oT2_sf3ext(node_type&) {} | |
14251 | node_type& operator=(node_type&) { return (*this); } | |
14252 | ||
14253 | T0 t0_; | |
14254 | T1 t1_; | |
14255 | T2 t2_; | |
14256 | }; | |
14257 | ||
14258 | template <typename T> | |
14259 | inline bool is_sf3ext_node(const expression_node<T>* n) | |
14260 | { | |
14261 | switch (n->type()) | |
14262 | { | |
14263 | case expression_node<T>::e_vovov : return true; | |
14264 | case expression_node<T>::e_vovoc : return true; | |
14265 | case expression_node<T>::e_vocov : return true; | |
14266 | case expression_node<T>::e_covov : return true; | |
14267 | case expression_node<T>::e_covoc : return true; | |
14268 | default : return false; | |
14269 | } | |
14270 | } | |
14271 | ||
14272 | template <typename T, typename T0, typename T1, typename T2, typename T3> | |
14273 | class T0oT1oT2oT3_sf4 : public T0oT1oT2_base_node<T> | |
14274 | { | |
14275 | public: | |
14276 | ||
14277 | typedef typename details::functor_t<T> functor_t; | |
14278 | typedef typename functor_t::qfunc_t qfunc_t; | |
14279 | typedef T value_type; | |
14280 | typedef T0oT1oT2oT3_sf4<T,T0,T1,T2,T3> node_type; | |
14281 | ||
14282 | T0oT1oT2oT3_sf4(T0 p0, T1 p1, T2 p2, T3 p3, const qfunc_t p4) | |
14283 | : t0_(p0), | |
14284 | t1_(p1), | |
14285 | t2_(p2), | |
14286 | t3_(p3), | |
14287 | f_ (p4) | |
14288 | {} | |
14289 | ||
14290 | inline typename expression_node<T>::node_type type() const | |
14291 | { | |
14292 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; | |
14293 | return result; | |
14294 | } | |
14295 | ||
14296 | inline operator_type operation() const | |
14297 | { | |
14298 | return e_default; | |
14299 | } | |
14300 | ||
14301 | inline T value() const | |
14302 | { | |
14303 | return f_(t0_, t1_, t2_, t3_); | |
14304 | } | |
14305 | ||
14306 | inline T0 t0() const | |
14307 | { | |
14308 | return t0_; | |
14309 | } | |
14310 | ||
14311 | inline T1 t1() const | |
14312 | { | |
14313 | return t1_; | |
14314 | } | |
14315 | ||
14316 | inline T2 t2() const | |
14317 | { | |
14318 | return t2_; | |
14319 | } | |
14320 | ||
14321 | inline T3 t3() const | |
14322 | { | |
14323 | return t3_; | |
14324 | } | |
14325 | ||
14326 | qfunc_t f() const | |
14327 | { | |
14328 | return f_; | |
14329 | } | |
14330 | ||
14331 | std::string type_id() const | |
14332 | { | |
14333 | return id(); | |
14334 | } | |
14335 | ||
14336 | static inline std::string id() | |
14337 | { | |
14338 | return "sf4"; | |
14339 | } | |
14340 | ||
14341 | template <typename Allocator> | |
14342 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3, qfunc_t p4) | |
14343 | { | |
14344 | return allocator | |
14345 | .template allocate_type<node_type, T0, T1, T2, T3, qfunc_t> | |
14346 | (p0, p1, p2, p3, p4); | |
14347 | } | |
14348 | ||
14349 | private: | |
14350 | ||
14351 | T0oT1oT2oT3_sf4(node_type&) {} | |
14352 | node_type& operator=(node_type&) { return (*this); } | |
14353 | ||
14354 | T0 t0_; | |
14355 | T1 t1_; | |
14356 | T2 t2_; | |
14357 | T3 t3_; | |
14358 | const qfunc_t f_; | |
14359 | }; | |
14360 | ||
14361 | template <typename T, typename T0, typename T1, typename T2, typename T3, typename SF4Operation> | |
14362 | class T0oT1oT2oT3_sf4ext : public T0oT1oT2oT3_base_node<T> | |
14363 | { | |
14364 | public: | |
14365 | ||
14366 | typedef typename details::functor_t<T> functor_t; | |
14367 | typedef typename functor_t::tfunc_t tfunc_t; | |
14368 | typedef T value_type; | |
14369 | typedef T0oT1oT2oT3_sf4ext<T,T0,T1,T2,T3,SF4Operation> node_type; | |
14370 | ||
14371 | T0oT1oT2oT3_sf4ext(T0 p0, T1 p1, T2 p2, T3 p3) | |
14372 | : t0_(p0), | |
14373 | t1_(p1), | |
14374 | t2_(p2), | |
14375 | t3_(p3) | |
14376 | {} | |
14377 | ||
14378 | inline typename expression_node<T>::node_type type() const | |
14379 | { | |
14380 | static const typename expression_node<T>::node_type result = nodetype_T0oT1oT2oT3<T,T0,T1,T2,T3>::result; | |
14381 | return result; | |
14382 | } | |
14383 | ||
14384 | inline operator_type operation() const | |
14385 | { | |
14386 | return e_default; | |
14387 | } | |
14388 | ||
14389 | inline T value() const | |
14390 | { | |
14391 | return SF4Operation::process(t0_, t1_, t2_, t3_); | |
14392 | } | |
14393 | ||
14394 | inline T0 t0() const | |
14395 | { | |
14396 | return t0_; | |
14397 | } | |
14398 | ||
14399 | inline T1 t1() const | |
14400 | { | |
14401 | return t1_; | |
14402 | } | |
14403 | ||
14404 | inline T2 t2() const | |
14405 | { | |
14406 | return t2_; | |
14407 | } | |
14408 | ||
14409 | inline T3 t3() const | |
14410 | { | |
14411 | return t3_; | |
14412 | } | |
14413 | ||
14414 | std::string type_id() const | |
14415 | { | |
14416 | return id(); | |
14417 | } | |
14418 | ||
14419 | static inline std::string id() | |
14420 | { | |
14421 | return SF4Operation::id(); | |
14422 | } | |
14423 | ||
14424 | template <typename Allocator> | |
14425 | static inline expression_node<T>* allocate(Allocator& allocator, T0 p0, T1 p1, T2 p2, T3 p3) | |
14426 | { | |
14427 | return allocator | |
14428 | .template allocate_type<node_type, T0, T1, T2, T3> | |
14429 | (p0, p1, p2, p3); | |
14430 | } | |
14431 | ||
14432 | private: | |
14433 | ||
14434 | T0oT1oT2oT3_sf4ext(node_type&) {} | |
14435 | node_type& operator=(node_type&) { return (*this); } | |
14436 | ||
14437 | T0 t0_; | |
14438 | T1 t1_; | |
14439 | T2 t2_; | |
14440 | T3 t3_; | |
14441 | }; | |
14442 | ||
14443 | template <typename T> | |
14444 | inline bool is_sf4ext_node(const expression_node<T>* n) | |
14445 | { | |
14446 | switch (n->type()) | |
14447 | { | |
14448 | case expression_node<T>::e_vovovov : return true; | |
14449 | case expression_node<T>::e_vovovoc : return true; | |
14450 | case expression_node<T>::e_vovocov : return true; | |
14451 | case expression_node<T>::e_vocovov : return true; | |
14452 | case expression_node<T>::e_covovov : return true; | |
14453 | case expression_node<T>::e_covocov : return true; | |
14454 | case expression_node<T>::e_vocovoc : return true; | |
14455 | case expression_node<T>::e_covovoc : return true; | |
14456 | case expression_node<T>::e_vococov : return true; | |
14457 | default : return false; | |
14458 | } | |
14459 | } | |
14460 | ||
14461 | template <typename T, typename T0, typename T1> | |
14462 | struct T0oT1_define | |
14463 | { | |
14464 | typedef details::T0oT1<T, T0, T1> type0; | |
14465 | }; | |
14466 | ||
14467 | template <typename T, typename T0, typename T1, typename T2> | |
14468 | struct T0oT1oT2_define | |
14469 | { | |
14470 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode0> type0; | |
14471 | typedef details::T0oT1oT2<T, T0, T1, T2, typename T0oT1oT2process<T>::mode1> type1; | |
14472 | typedef details::T0oT1oT2_sf3<T, T0, T1, T2> sf3_type; | |
14473 | typedef details::sf3ext_type_node<T, T0, T1, T2> sf3_type_node; | |
14474 | }; | |
14475 | ||
14476 | template <typename T, typename T0, typename T1, typename T2, typename T3> | |
14477 | struct T0oT1oT2oT3_define | |
14478 | { | |
14479 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode0> type0; | |
14480 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode1> type1; | |
14481 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode2> type2; | |
14482 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode3> type3; | |
14483 | typedef details::T0oT1oT2oT3<T, T0, T1, T2, T3, typename T0oT1oT20T3process<T>::mode4> type4; | |
14484 | typedef details::T0oT1oT2oT3_sf4<T, T0, T1, T2, T3> sf4_type; | |
14485 | }; | |
14486 | ||
14487 | template <typename T, typename Operation> | |
14488 | class vov_node : public vov_base_node<T> | |
14489 | { | |
14490 | public: | |
14491 | ||
14492 | typedef expression_node<T>* expression_ptr; | |
14493 | typedef Operation operation_t; | |
14494 | ||
14495 | // variable op variable node | |
14496 | explicit vov_node(const T& var0, const T& var1) | |
14497 | : v0_(var0), | |
14498 | v1_(var1) | |
14499 | {} | |
14500 | ||
14501 | inline T value() const | |
14502 | { | |
14503 | return Operation::process(v0_,v1_); | |
14504 | } | |
14505 | ||
14506 | inline typename expression_node<T>::node_type type() const | |
14507 | { | |
14508 | return Operation::type(); | |
14509 | } | |
14510 | ||
14511 | inline operator_type operation() const | |
14512 | { | |
14513 | return Operation::operation(); | |
14514 | } | |
14515 | ||
14516 | inline const T& v0() const | |
14517 | { | |
14518 | return v0_; | |
14519 | } | |
14520 | ||
14521 | inline const T& v1() const | |
14522 | { | |
14523 | return v1_; | |
14524 | } | |
14525 | ||
14526 | protected: | |
14527 | ||
14528 | const T& v0_; | |
14529 | const T& v1_; | |
14530 | ||
14531 | private: | |
14532 | ||
14533 | vov_node(vov_node<T,Operation>&); | |
14534 | vov_node<T,Operation>& operator=(vov_node<T,Operation>&); | |
14535 | }; | |
14536 | ||
14537 | template <typename T, typename Operation> | |
14538 | class cov_node : public cov_base_node<T> | |
14539 | { | |
14540 | public: | |
14541 | ||
14542 | typedef expression_node<T>* expression_ptr; | |
14543 | typedef Operation operation_t; | |
14544 | ||
14545 | // constant op variable node | |
14546 | explicit cov_node(const T& const_var, const T& var) | |
14547 | : c_(const_var), | |
14548 | v_(var) | |
14549 | {} | |
14550 | ||
14551 | inline T value() const | |
14552 | { | |
14553 | return Operation::process(c_,v_); | |
14554 | } | |
14555 | ||
14556 | inline typename expression_node<T>::node_type type() const | |
14557 | { | |
14558 | return Operation::type(); | |
14559 | } | |
14560 | ||
14561 | inline operator_type operation() const | |
14562 | { | |
14563 | return Operation::operation(); | |
14564 | } | |
14565 | ||
14566 | inline const T c() const | |
14567 | { | |
14568 | return c_; | |
14569 | } | |
14570 | ||
14571 | inline const T& v() const | |
14572 | { | |
14573 | return v_; | |
14574 | } | |
14575 | ||
14576 | protected: | |
14577 | ||
14578 | const T c_; | |
14579 | const T& v_; | |
14580 | ||
14581 | private: | |
14582 | ||
14583 | cov_node(const cov_node<T,Operation>&); | |
14584 | cov_node<T,Operation>& operator=(const cov_node<T,Operation>&); | |
14585 | }; | |
14586 | ||
14587 | template <typename T, typename Operation> | |
14588 | class voc_node : public voc_base_node<T> | |
14589 | { | |
14590 | public: | |
14591 | ||
14592 | typedef expression_node<T>* expression_ptr; | |
14593 | typedef Operation operation_t; | |
14594 | ||
14595 | // variable op constant node | |
14596 | explicit voc_node(const T& var, const T& const_var) | |
14597 | : v_(var), | |
14598 | c_(const_var) | |
14599 | {} | |
14600 | ||
14601 | inline T value() const | |
14602 | { | |
14603 | return Operation::process(v_,c_); | |
14604 | } | |
14605 | ||
14606 | inline operator_type operation() const | |
14607 | { | |
14608 | return Operation::operation(); | |
14609 | } | |
14610 | ||
14611 | inline const T c() const | |
14612 | { | |
14613 | return c_; | |
14614 | } | |
14615 | ||
14616 | inline const T& v() const | |
14617 | { | |
14618 | return v_; | |
14619 | } | |
14620 | ||
14621 | protected: | |
14622 | ||
14623 | const T& v_; | |
14624 | const T c_; | |
14625 | ||
14626 | private: | |
14627 | ||
14628 | voc_node(const voc_node<T,Operation>&); | |
14629 | voc_node<T,Operation>& operator=(const voc_node<T,Operation>&); | |
14630 | }; | |
14631 | ||
14632 | template <typename T, typename Operation> | |
14633 | class vob_node : public vob_base_node<T> | |
14634 | { | |
14635 | public: | |
14636 | ||
14637 | typedef expression_node<T>* expression_ptr; | |
14638 | typedef std::pair<expression_ptr,bool> branch_t; | |
14639 | typedef Operation operation_t; | |
14640 | ||
14641 | // variable op constant node | |
14642 | explicit vob_node(const T& var, const expression_ptr brnch) | |
14643 | : v_(var) | |
14644 | { | |
14645 | init_branches<1>(branch_,brnch); | |
14646 | } | |
14647 | ||
14648 | ~vob_node() | |
14649 | { | |
14650 | cleanup_branches::execute<T,1>(branch_); | |
14651 | } | |
14652 | ||
14653 | inline T value() const | |
14654 | { | |
14655 | return Operation::process(v_,branch_[0].first->value()); | |
14656 | } | |
14657 | ||
14658 | inline operator_type operation() const | |
14659 | { | |
14660 | return Operation::operation(); | |
14661 | } | |
14662 | ||
14663 | inline const T& v() const | |
14664 | { | |
14665 | return v_; | |
14666 | } | |
14667 | ||
14668 | inline expression_node<T>* branch(const std::size_t&) const | |
14669 | { | |
14670 | return branch_[0].first; | |
14671 | } | |
14672 | ||
14673 | private: | |
14674 | ||
14675 | vob_node(const vob_node<T,Operation>&); | |
14676 | vob_node<T,Operation>& operator=(const vob_node<T,Operation>&); | |
14677 | ||
14678 | const T& v_; | |
14679 | branch_t branch_[1]; | |
14680 | }; | |
14681 | ||
14682 | template <typename T, typename Operation> | |
14683 | class bov_node : public bov_base_node<T> | |
14684 | { | |
14685 | public: | |
14686 | ||
14687 | typedef expression_node<T>* expression_ptr; | |
14688 | typedef std::pair<expression_ptr,bool> branch_t; | |
14689 | typedef Operation operation_t; | |
14690 | ||
14691 | // variable op constant node | |
14692 | explicit bov_node(const expression_ptr brnch, const T& var) | |
14693 | : v_(var) | |
14694 | { | |
14695 | init_branches<1>(branch_,brnch); | |
14696 | } | |
14697 | ||
14698 | ~bov_node() | |
14699 | { | |
14700 | cleanup_branches::execute<T,1>(branch_); | |
14701 | } | |
14702 | ||
14703 | inline T value() const | |
14704 | { | |
14705 | return Operation::process(branch_[0].first->value(),v_); | |
14706 | } | |
14707 | ||
14708 | inline operator_type operation() const | |
14709 | { | |
14710 | return Operation::operation(); | |
14711 | } | |
14712 | ||
14713 | inline const T& v() const | |
14714 | { | |
14715 | return v_; | |
14716 | } | |
14717 | ||
14718 | inline expression_node<T>* branch(const std::size_t&) const | |
14719 | { | |
14720 | return branch_[0].first; | |
14721 | } | |
14722 | ||
14723 | private: | |
14724 | ||
14725 | bov_node(const bov_node<T,Operation>&); | |
14726 | bov_node<T,Operation>& operator=(const bov_node<T,Operation>&); | |
14727 | ||
14728 | const T& v_; | |
14729 | branch_t branch_[1]; | |
14730 | }; | |
14731 | ||
14732 | template <typename T, typename Operation> | |
14733 | class cob_node : public cob_base_node<T> | |
14734 | { | |
14735 | public: | |
14736 | ||
14737 | typedef expression_node<T>* expression_ptr; | |
14738 | typedef std::pair<expression_ptr,bool> branch_t; | |
14739 | typedef Operation operation_t; | |
14740 | ||
14741 | // variable op constant node | |
14742 | explicit cob_node(const T const_var, const expression_ptr brnch) | |
14743 | : c_(const_var) | |
14744 | { | |
14745 | init_branches<1>(branch_,brnch); | |
14746 | } | |
14747 | ||
14748 | ~cob_node() | |
14749 | { | |
14750 | cleanup_branches::execute<T,1>(branch_); | |
14751 | } | |
14752 | ||
14753 | inline T value() const | |
14754 | { | |
14755 | return Operation::process(c_,branch_[0].first->value()); | |
14756 | } | |
14757 | ||
14758 | inline operator_type operation() const | |
14759 | { | |
14760 | return Operation::operation(); | |
14761 | } | |
14762 | ||
14763 | inline const T c() const | |
14764 | { | |
14765 | return c_; | |
14766 | } | |
14767 | ||
14768 | inline void set_c(const T new_c) | |
14769 | { | |
14770 | (*const_cast<T*>(&c_)) = new_c; | |
14771 | } | |
14772 | ||
14773 | inline expression_node<T>* branch(const std::size_t&) const | |
14774 | { | |
14775 | return branch_[0].first; | |
14776 | } | |
14777 | ||
14778 | inline expression_node<T>* move_branch(const std::size_t&) | |
14779 | { | |
14780 | branch_[0].second = false; | |
14781 | return branch_[0].first; | |
14782 | } | |
14783 | ||
14784 | private: | |
14785 | ||
14786 | cob_node(const cob_node<T,Operation>&); | |
14787 | cob_node<T,Operation>& operator=(const cob_node<T,Operation>&); | |
14788 | ||
14789 | const T c_; | |
14790 | branch_t branch_[1]; | |
14791 | }; | |
14792 | ||
14793 | template <typename T, typename Operation> | |
14794 | class boc_node : public boc_base_node<T> | |
14795 | { | |
14796 | public: | |
14797 | ||
14798 | typedef expression_node<T>* expression_ptr; | |
14799 | typedef std::pair<expression_ptr,bool> branch_t; | |
14800 | typedef Operation operation_t; | |
14801 | ||
14802 | // variable op constant node | |
14803 | explicit boc_node(const expression_ptr brnch, const T const_var) | |
14804 | : c_(const_var) | |
14805 | { | |
14806 | init_branches<1>(branch_,brnch); | |
14807 | } | |
14808 | ||
14809 | ~boc_node() | |
14810 | { | |
14811 | cleanup_branches::execute<T,1>(branch_); | |
14812 | } | |
14813 | ||
14814 | inline T value() const | |
14815 | { | |
14816 | return Operation::process(branch_[0].first->value(),c_); | |
14817 | } | |
14818 | ||
14819 | inline operator_type operation() const | |
14820 | { | |
14821 | return Operation::operation(); | |
14822 | } | |
14823 | ||
14824 | inline const T c() const | |
14825 | { | |
14826 | return c_; | |
14827 | } | |
14828 | ||
14829 | inline void set_c(const T new_c) | |
14830 | { | |
14831 | (*const_cast<T*>(&c_)) = new_c; | |
14832 | } | |
14833 | ||
14834 | inline expression_node<T>* branch(const std::size_t&) const | |
14835 | { | |
14836 | return branch_[0].first; | |
14837 | } | |
14838 | ||
14839 | inline expression_node<T>* move_branch(const std::size_t&) | |
14840 | { | |
14841 | branch_[0].second = false; | |
14842 | return branch_[0].first; | |
14843 | } | |
14844 | ||
14845 | private: | |
14846 | ||
14847 | boc_node(const boc_node<T,Operation>&); | |
14848 | boc_node<T,Operation>& operator=(const boc_node<T,Operation>&); | |
14849 | ||
14850 | const T c_; | |
14851 | branch_t branch_[1]; | |
14852 | }; | |
14853 | ||
14854 | #ifndef exprtk_disable_string_capabilities | |
14855 | template <typename T, typename SType0, typename SType1, typename Operation> | |
14856 | class sos_node : public sos_base_node<T> | |
14857 | { | |
14858 | public: | |
14859 | ||
14860 | typedef expression_node<T>* expression_ptr; | |
14861 | typedef Operation operation_t; | |
14862 | ||
14863 | // string op string node | |
14864 | explicit sos_node(SType0 p0, SType1 p1) | |
14865 | : s0_(p0), | |
14866 | s1_(p1) | |
14867 | {} | |
14868 | ||
14869 | inline T value() const | |
14870 | { | |
14871 | return Operation::process(s0_,s1_); | |
14872 | } | |
14873 | ||
14874 | inline typename expression_node<T>::node_type type() const | |
14875 | { | |
14876 | return Operation::type(); | |
14877 | } | |
14878 | ||
14879 | inline operator_type operation() const | |
14880 | { | |
14881 | return Operation::operation(); | |
14882 | } | |
14883 | ||
14884 | inline std::string& s0() | |
14885 | { | |
14886 | return s0_; | |
14887 | } | |
14888 | ||
14889 | inline std::string& s1() | |
14890 | { | |
14891 | return s1_; | |
14892 | } | |
14893 | ||
14894 | protected: | |
14895 | ||
14896 | SType0 s0_; | |
14897 | SType1 s1_; | |
14898 | ||
14899 | private: | |
14900 | ||
14901 | sos_node(sos_node<T,SType0,SType1,Operation>&); | |
14902 | sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&); | |
14903 | }; | |
14904 | ||
14905 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> | |
14906 | class str_xrox_node : public sos_base_node<T> | |
14907 | { | |
14908 | public: | |
14909 | ||
14910 | typedef expression_node<T>* expression_ptr; | |
14911 | typedef Operation operation_t; | |
14912 | ||
14913 | // string-range op string node | |
14914 | explicit str_xrox_node(SType0 p0, SType1 p1, RangePack rp0) | |
14915 | : s0_ (p0 ), | |
14916 | s1_ (p1 ), | |
14917 | rp0_(rp0) | |
14918 | {} | |
14919 | ||
14920 | ~str_xrox_node() | |
14921 | { | |
14922 | rp0_.free(); | |
14923 | } | |
14924 | ||
14925 | inline T value() const | |
14926 | { | |
14927 | std::size_t r0 = 0; | |
14928 | std::size_t r1 = 0; | |
14929 | ||
14930 | if (rp0_(r0, r1, s0_.size())) | |
14931 | return Operation::process(s0_.substr(r0, (r1 - r0) + 1), s1_); | |
14932 | else | |
14933 | return T(0); | |
14934 | } | |
14935 | ||
14936 | inline typename expression_node<T>::node_type type() const | |
14937 | { | |
14938 | return Operation::type(); | |
14939 | } | |
14940 | ||
14941 | inline operator_type operation() const | |
14942 | { | |
14943 | return Operation::operation(); | |
14944 | } | |
14945 | ||
14946 | inline std::string& s0() | |
14947 | { | |
14948 | return s0_; | |
14949 | } | |
14950 | ||
14951 | inline std::string& s1() | |
14952 | { | |
14953 | return s1_; | |
14954 | } | |
14955 | ||
14956 | protected: | |
14957 | ||
14958 | SType0 s0_; | |
14959 | SType1 s1_; | |
14960 | RangePack rp0_; | |
14961 | ||
14962 | private: | |
14963 | ||
14964 | str_xrox_node(str_xrox_node<T,SType0,SType1,RangePack,Operation>&); | |
14965 | str_xrox_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xrox_node<T,SType0,SType1,RangePack,Operation>&); | |
14966 | }; | |
14967 | ||
14968 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> | |
14969 | class str_xoxr_node : public sos_base_node<T> | |
14970 | { | |
14971 | public: | |
14972 | ||
14973 | typedef expression_node<T>* expression_ptr; | |
14974 | typedef Operation operation_t; | |
14975 | ||
14976 | // string op string range node | |
14977 | explicit str_xoxr_node(SType0 p0, SType1 p1, RangePack rp1) | |
14978 | : s0_ (p0 ), | |
14979 | s1_ (p1 ), | |
14980 | rp1_(rp1) | |
14981 | {} | |
14982 | ||
14983 | ~str_xoxr_node() | |
14984 | { | |
14985 | rp1_.free(); | |
14986 | } | |
14987 | ||
14988 | inline T value() const | |
14989 | { | |
14990 | std::size_t r0 = 0; | |
14991 | std::size_t r1 = 0; | |
14992 | ||
14993 | if (rp1_(r0, r1, s1_.size())) | |
14994 | return Operation::process(s0_, s1_.substr(r0, (r1 - r0) + 1)); | |
14995 | else | |
14996 | return T(0); | |
14997 | } | |
14998 | ||
14999 | inline typename expression_node<T>::node_type type() const | |
15000 | { | |
15001 | return Operation::type(); | |
15002 | } | |
15003 | ||
15004 | inline operator_type operation() const | |
15005 | { | |
15006 | return Operation::operation(); | |
15007 | } | |
15008 | ||
15009 | inline std::string& s0() | |
15010 | { | |
15011 | return s0_; | |
15012 | } | |
15013 | ||
15014 | inline std::string& s1() | |
15015 | { | |
15016 | return s1_; | |
15017 | } | |
15018 | ||
15019 | protected: | |
15020 | ||
15021 | SType0 s0_; | |
15022 | SType1 s1_; | |
15023 | RangePack rp1_; | |
15024 | ||
15025 | private: | |
15026 | ||
15027 | str_xoxr_node(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&); | |
15028 | str_xoxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xoxr_node<T,SType0,SType1,RangePack,Operation>&); | |
15029 | }; | |
15030 | ||
15031 | template <typename T, typename SType0, typename SType1, typename RangePack, typename Operation> | |
15032 | class str_xroxr_node : public sos_base_node<T> | |
15033 | { | |
15034 | public: | |
15035 | ||
15036 | typedef expression_node<T>* expression_ptr; | |
15037 | typedef Operation operation_t; | |
15038 | ||
15039 | // string-range op string-range node | |
15040 | explicit str_xroxr_node(SType0 p0, SType1 p1, RangePack rp0, RangePack rp1) | |
15041 | : s0_ (p0 ), | |
15042 | s1_ (p1 ), | |
15043 | rp0_(rp0), | |
15044 | rp1_(rp1) | |
15045 | {} | |
15046 | ||
15047 | ~str_xroxr_node() | |
15048 | { | |
15049 | rp0_.free(); | |
15050 | rp1_.free(); | |
15051 | } | |
15052 | ||
15053 | inline T value() const | |
15054 | { | |
15055 | std::size_t r0_0 = 0; | |
15056 | std::size_t r0_1 = 0; | |
15057 | std::size_t r1_0 = 0; | |
15058 | std::size_t r1_1 = 0; | |
15059 | ||
15060 | if ( | |
15061 | rp0_(r0_0, r1_0, s0_.size()) && | |
15062 | rp1_(r0_1, r1_1, s1_.size()) | |
15063 | ) | |
15064 | { | |
15065 | return Operation::process( | |
15066 | s0_.substr(r0_0, (r1_0 - r0_0) + 1), | |
15067 | s1_.substr(r0_1, (r1_1 - r0_1) + 1) | |
15068 | ); | |
15069 | } | |
15070 | else | |
15071 | return T(0); | |
15072 | } | |
15073 | ||
15074 | inline typename expression_node<T>::node_type type() const | |
15075 | { | |
15076 | return Operation::type(); | |
15077 | } | |
15078 | ||
15079 | inline operator_type operation() const | |
15080 | { | |
15081 | return Operation::operation(); | |
15082 | } | |
15083 | ||
15084 | inline std::string& s0() | |
15085 | { | |
15086 | return s0_; | |
15087 | } | |
15088 | ||
15089 | inline std::string& s1() | |
15090 | { | |
15091 | return s1_; | |
15092 | } | |
15093 | ||
15094 | protected: | |
15095 | ||
15096 | SType0 s0_; | |
15097 | SType1 s1_; | |
15098 | RangePack rp0_; | |
15099 | RangePack rp1_; | |
15100 | ||
15101 | private: | |
15102 | ||
15103 | str_xroxr_node(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&); | |
15104 | str_xroxr_node<T,SType0,SType1,RangePack,Operation>& operator=(str_xroxr_node<T,SType0,SType1,RangePack,Operation>&); | |
15105 | }; | |
15106 | ||
15107 | template <typename T, typename Operation> | |
15108 | class str_sogens_node : public binary_node<T> | |
15109 | { | |
15110 | public: | |
15111 | ||
15112 | typedef expression_node <T>* expression_ptr; | |
15113 | typedef string_base_node<T>* str_base_ptr; | |
15114 | typedef range_pack <T> range_t; | |
15115 | typedef range_t* range_ptr; | |
15116 | typedef range_interface<T> irange_t; | |
15117 | typedef irange_t* irange_ptr; | |
15118 | ||
15119 | str_sogens_node(const operator_type& opr, | |
15120 | expression_ptr branch0, | |
15121 | expression_ptr branch1) | |
15122 | : binary_node<T>(opr, branch0, branch1), | |
15123 | str0_base_ptr_ (0), | |
15124 | str1_base_ptr_ (0), | |
15125 | str0_range_ptr_(0), | |
15126 | str1_range_ptr_(0) | |
15127 | { | |
15128 | if (is_generally_string_node(binary_node<T>::branch_[0].first)) | |
15129 | { | |
15130 | str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); | |
15131 | ||
15132 | if (0 == str0_base_ptr_) | |
15133 | return; | |
15134 | ||
15135 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[0].first); | |
15136 | ||
15137 | if (0 == range) | |
15138 | return; | |
15139 | ||
15140 | str0_range_ptr_ = &(range->range_ref()); | |
15141 | } | |
15142 | ||
15143 | if (is_generally_string_node(binary_node<T>::branch_[1].first)) | |
15144 | { | |
15145 | str1_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[1].first); | |
15146 | ||
15147 | if (0 == str1_base_ptr_) | |
15148 | return; | |
15149 | ||
15150 | irange_ptr range = dynamic_cast<irange_ptr>(binary_node<T>::branch_[1].first); | |
15151 | ||
15152 | if (0 == range) | |
15153 | return; | |
15154 | ||
15155 | str1_range_ptr_ = &(range->range_ref()); | |
15156 | } | |
15157 | } | |
15158 | ||
15159 | inline T value() const | |
15160 | { | |
15161 | if ( | |
15162 | str0_base_ptr_ && | |
15163 | str1_base_ptr_ && | |
15164 | str0_range_ptr_ && | |
15165 | str1_range_ptr_ | |
15166 | ) | |
15167 | { | |
15168 | binary_node<T>::branch_[0].first->value(); | |
15169 | binary_node<T>::branch_[1].first->value(); | |
15170 | ||
15171 | std::size_t str0_r0 = 0; | |
15172 | std::size_t str0_r1 = 0; | |
15173 | ||
15174 | std::size_t str1_r0 = 0; | |
15175 | std::size_t str1_r1 = 0; | |
15176 | ||
15177 | range_t& range0 = (*str0_range_ptr_); | |
15178 | range_t& range1 = (*str1_range_ptr_); | |
15179 | ||
15180 | if ( | |
15181 | range0(str0_r0, str0_r1, str0_base_ptr_->size()) && | |
15182 | range1(str1_r0, str1_r1, str1_base_ptr_->size()) | |
15183 | ) | |
15184 | { | |
15185 | return Operation::process( | |
15186 | str0_base_ptr_->str().substr(str0_r0,(str0_r1 - str0_r0) + 1), | |
15187 | str1_base_ptr_->str().substr(str1_r0,(str1_r1 - str1_r0) + 1) | |
15188 | ); | |
15189 | } | |
15190 | } | |
15191 | ||
15192 | return std::numeric_limits<T>::quiet_NaN(); | |
15193 | } | |
15194 | ||
15195 | inline typename expression_node<T>::node_type type() const | |
15196 | { | |
15197 | return Operation::type(); | |
15198 | } | |
15199 | ||
15200 | inline operator_type operation() const | |
15201 | { | |
15202 | return Operation::operation(); | |
15203 | } | |
15204 | ||
15205 | private: | |
15206 | ||
15207 | str_sogens_node(str_sogens_node<T,Operation>&); | |
15208 | str_sogens_node<T,Operation>& operator=(str_sogens_node<T,Operation>&); | |
15209 | ||
15210 | str_base_ptr str0_base_ptr_; | |
15211 | str_base_ptr str1_base_ptr_; | |
15212 | range_ptr str0_range_ptr_; | |
15213 | range_ptr str1_range_ptr_; | |
15214 | }; | |
15215 | ||
15216 | template <typename T, typename SType0, typename SType1, typename SType2, typename Operation> | |
15217 | class sosos_node : public sosos_base_node<T> | |
15218 | { | |
15219 | public: | |
15220 | ||
15221 | typedef expression_node<T>* expression_ptr; | |
15222 | typedef Operation operation_t; | |
15223 | ||
15224 | // variable op variable node | |
15225 | explicit sosos_node(SType0 p0, SType1 p1, SType2 p2) | |
15226 | : s0_(p0), | |
15227 | s1_(p1), | |
15228 | s2_(p2) | |
15229 | {} | |
15230 | ||
15231 | inline T value() const | |
15232 | { | |
15233 | return Operation::process(s0_,s1_,s2_); | |
15234 | } | |
15235 | ||
15236 | inline typename expression_node<T>::node_type type() const | |
15237 | { | |
15238 | return Operation::type(); | |
15239 | } | |
15240 | ||
15241 | inline operator_type operation() const | |
15242 | { | |
15243 | return Operation::operation(); | |
15244 | } | |
15245 | ||
15246 | inline std::string& s0() | |
15247 | { | |
15248 | return s0_; | |
15249 | } | |
15250 | ||
15251 | inline std::string& s1() | |
15252 | { | |
15253 | return s1_; | |
15254 | } | |
15255 | ||
15256 | inline std::string& s2() | |
15257 | { | |
15258 | return s2_; | |
15259 | } | |
15260 | ||
15261 | protected: | |
15262 | ||
15263 | SType0 s0_; | |
15264 | SType1 s1_; | |
15265 | SType2 s2_; | |
15266 | ||
15267 | private: | |
15268 | ||
15269 | sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&); | |
15270 | sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&); | |
15271 | }; | |
15272 | #endif | |
15273 | ||
15274 | template <typename T, typename PowOp> | |
15275 | class ipow_node : public expression_node<T> | |
15276 | { | |
15277 | public: | |
15278 | ||
15279 | typedef expression_node<T>* expression_ptr; | |
15280 | typedef PowOp operation_t; | |
15281 | ||
15282 | explicit ipow_node(const T& v) | |
15283 | : v_(v) | |
15284 | {} | |
15285 | ||
15286 | inline T value() const | |
15287 | { | |
15288 | return PowOp::result(v_); | |
15289 | } | |
15290 | ||
15291 | inline typename expression_node<T>::node_type type() const | |
15292 | { | |
15293 | return expression_node<T>::e_ipow; | |
15294 | } | |
15295 | ||
15296 | private: | |
15297 | ||
15298 | ipow_node(const ipow_node<T,PowOp>&); | |
15299 | ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&); | |
15300 | ||
15301 | const T& v_; | |
15302 | }; | |
15303 | ||
15304 | template <typename T, typename PowOp> | |
15305 | class bipow_node : public expression_node<T> | |
15306 | { | |
15307 | public: | |
15308 | ||
15309 | typedef expression_node<T>* expression_ptr; | |
15310 | typedef std::pair<expression_ptr, bool> branch_t; | |
15311 | typedef PowOp operation_t; | |
15312 | ||
15313 | explicit bipow_node(expression_ptr brnch) | |
15314 | { | |
15315 | init_branches<1>(branch_, brnch); | |
15316 | } | |
15317 | ||
15318 | ~bipow_node() | |
15319 | { | |
15320 | cleanup_branches::execute<T,1>(branch_); | |
15321 | } | |
15322 | ||
15323 | inline T value() const | |
15324 | { | |
15325 | return PowOp::result(branch_[0].first->value()); | |
15326 | } | |
15327 | ||
15328 | inline typename expression_node<T>::node_type type() const | |
15329 | { | |
15330 | return expression_node<T>::e_ipow; | |
15331 | } | |
15332 | ||
15333 | private: | |
15334 | ||
15335 | bipow_node(const bipow_node<T,PowOp>&); | |
15336 | bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&); | |
15337 | ||
15338 | branch_t branch_[1]; | |
15339 | }; | |
15340 | ||
15341 | template <typename T, typename PowOp> | |
15342 | class ipowinv_node : public expression_node<T> | |
15343 | { | |
15344 | public: | |
15345 | ||
15346 | typedef expression_node<T>* expression_ptr; | |
15347 | typedef PowOp operation_t; | |
15348 | ||
15349 | explicit ipowinv_node(const T& v) | |
15350 | : v_(v) | |
15351 | {} | |
15352 | ||
15353 | inline T value() const | |
15354 | { | |
15355 | return (T(1) / PowOp::result(v_)); | |
15356 | } | |
15357 | ||
15358 | inline typename expression_node<T>::node_type type() const | |
15359 | { | |
15360 | return expression_node<T>::e_ipowinv; | |
15361 | } | |
15362 | ||
15363 | private: | |
15364 | ||
15365 | ipowinv_node(const ipowinv_node<T,PowOp>&); | |
15366 | ipowinv_node<T,PowOp>& operator=(const ipowinv_node<T,PowOp>&); | |
15367 | ||
15368 | const T& v_; | |
15369 | }; | |
15370 | ||
15371 | template <typename T, typename PowOp> | |
15372 | class bipowninv_node : public expression_node<T> | |
15373 | { | |
15374 | public: | |
15375 | ||
15376 | typedef expression_node<T>* expression_ptr; | |
15377 | typedef std::pair<expression_ptr, bool> branch_t; | |
15378 | typedef PowOp operation_t; | |
15379 | ||
15380 | explicit bipowninv_node(expression_ptr brnch) | |
15381 | { | |
15382 | init_branches<1>(branch_, brnch); | |
15383 | } | |
15384 | ||
15385 | ~bipowninv_node() | |
15386 | { | |
15387 | cleanup_branches::execute<T,1>(branch_); | |
15388 | } | |
15389 | ||
15390 | inline T value() const | |
15391 | { | |
15392 | return (T(1) / PowOp::result(branch_[0].first->value())); | |
15393 | } | |
15394 | ||
15395 | inline typename expression_node<T>::node_type type() const | |
15396 | { | |
15397 | return expression_node<T>::e_ipowinv; | |
15398 | } | |
15399 | ||
15400 | private: | |
15401 | ||
15402 | bipowninv_node(const bipowninv_node<T,PowOp>&); | |
15403 | bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&); | |
15404 | ||
15405 | branch_t branch_[1]; | |
15406 | }; | |
15407 | ||
15408 | template <typename T> | |
15409 | inline bool is_vov_node(const expression_node<T>* node) | |
15410 | { | |
15411 | return (0 != dynamic_cast<const vov_base_node<T>*>(node)); | |
15412 | } | |
15413 | ||
15414 | template <typename T> | |
15415 | inline bool is_cov_node(const expression_node<T>* node) | |
15416 | { | |
15417 | return (0 != dynamic_cast<const cov_base_node<T>*>(node)); | |
15418 | } | |
15419 | ||
15420 | template <typename T> | |
15421 | inline bool is_voc_node(const expression_node<T>* node) | |
15422 | { | |
15423 | return (0 != dynamic_cast<const voc_base_node<T>*>(node)); | |
15424 | } | |
15425 | ||
15426 | template <typename T> | |
15427 | inline bool is_cob_node(const expression_node<T>* node) | |
15428 | { | |
15429 | return (0 != dynamic_cast<const cob_base_node<T>*>(node)); | |
15430 | } | |
15431 | ||
15432 | template <typename T> | |
15433 | inline bool is_boc_node(const expression_node<T>* node) | |
15434 | { | |
15435 | return (0 != dynamic_cast<const boc_base_node<T>*>(node)); | |
15436 | } | |
15437 | ||
15438 | template <typename T> | |
15439 | inline bool is_t0ot1ot2_node(const expression_node<T>* node) | |
15440 | { | |
15441 | return (0 != dynamic_cast<const T0oT1oT2_base_node<T>*>(node)); | |
15442 | } | |
15443 | ||
15444 | template <typename T> | |
15445 | inline bool is_t0ot1ot2ot3_node(const expression_node<T>* node) | |
15446 | { | |
15447 | return (0 != dynamic_cast<const T0oT1oT2oT3_base_node<T>*>(node)); | |
15448 | } | |
15449 | ||
15450 | template <typename T> | |
15451 | inline bool is_uv_node(const expression_node<T>* node) | |
15452 | { | |
15453 | return (0 != dynamic_cast<const uv_base_node<T>*>(node)); | |
15454 | } | |
15455 | ||
15456 | template <typename T> | |
15457 | inline bool is_string_node(const expression_node<T>* node) | |
15458 | { | |
15459 | return node && (expression_node<T>::e_stringvar == node->type()); | |
15460 | } | |
15461 | ||
15462 | template <typename T> | |
15463 | inline bool is_string_range_node(const expression_node<T>* node) | |
15464 | { | |
15465 | return node && (expression_node<T>::e_stringvarrng == node->type()); | |
15466 | } | |
15467 | ||
15468 | template <typename T> | |
15469 | inline bool is_const_string_node(const expression_node<T>* node) | |
15470 | { | |
15471 | return node && (expression_node<T>::e_stringconst == node->type()); | |
15472 | } | |
15473 | ||
15474 | template <typename T> | |
15475 | inline bool is_const_string_range_node(const expression_node<T>* node) | |
15476 | { | |
15477 | return node && (expression_node<T>::e_cstringvarrng == node->type()); | |
15478 | } | |
15479 | ||
15480 | template <typename T> | |
15481 | inline bool is_string_assignment_node(const expression_node<T>* node) | |
15482 | { | |
15483 | return node && (expression_node<T>::e_strass == node->type()); | |
15484 | } | |
15485 | ||
15486 | template <typename T> | |
15487 | inline bool is_string_concat_node(const expression_node<T>* node) | |
15488 | { | |
15489 | return node && (expression_node<T>::e_strconcat == node->type()); | |
15490 | } | |
15491 | ||
15492 | template <typename T> | |
15493 | inline bool is_string_function_node(const expression_node<T>* node) | |
15494 | { | |
15495 | return node && (expression_node<T>::e_strfunction == node->type()); | |
15496 | } | |
15497 | ||
15498 | template <typename T> | |
15499 | inline bool is_string_condition_node(const expression_node<T>* node) | |
15500 | { | |
15501 | return node && (expression_node<T>::e_strcondition == node->type()); | |
15502 | } | |
15503 | ||
15504 | template <typename T> | |
15505 | inline bool is_string_ccondition_node(const expression_node<T>* node) | |
15506 | { | |
15507 | return node && (expression_node<T>::e_strccondition == node->type()); | |
15508 | } | |
15509 | ||
15510 | template <typename T> | |
15511 | inline bool is_string_vararg_node(const expression_node<T>* node) | |
15512 | { | |
15513 | return node && (expression_node<T>::e_stringvararg == node->type()); | |
15514 | } | |
15515 | ||
15516 | template <typename T> | |
15517 | inline bool is_genricstring_range_node(const expression_node<T>* node) | |
15518 | { | |
15519 | return node && (expression_node<T>::e_strgenrange == node->type()); | |
15520 | } | |
15521 | ||
15522 | template <typename T> | |
15523 | inline bool is_generally_string_node(const expression_node<T>* node) | |
15524 | { | |
15525 | if (node) | |
15526 | { | |
15527 | switch (node->type()) | |
15528 | { | |
15529 | case expression_node<T>::e_stringvar : | |
15530 | case expression_node<T>::e_stringconst : | |
15531 | case expression_node<T>::e_stringvarrng : | |
15532 | case expression_node<T>::e_cstringvarrng : | |
15533 | case expression_node<T>::e_strgenrange : | |
15534 | case expression_node<T>::e_strass : | |
15535 | case expression_node<T>::e_strconcat : | |
15536 | case expression_node<T>::e_strfunction : | |
15537 | case expression_node<T>::e_strcondition : | |
15538 | case expression_node<T>::e_strccondition : | |
15539 | case expression_node<T>::e_stringvararg : return true; | |
15540 | default : return false; | |
15541 | } | |
15542 | } | |
15543 | ||
15544 | return false; | |
15545 | } | |
15546 | ||
15547 | class node_allocator | |
15548 | { | |
15549 | public: | |
15550 | ||
15551 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15552 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) | |
15553 | { | |
15554 | return allocate<ResultNode>(operation, branch[0]); | |
15555 | } | |
15556 | ||
15557 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15558 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) | |
15559 | { | |
15560 | return allocate<ResultNode>(operation, branch[0], branch[1]); | |
15561 | } | |
15562 | ||
15563 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15564 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) | |
15565 | { | |
15566 | return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); | |
15567 | } | |
15568 | ||
15569 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15570 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) | |
15571 | { | |
15572 | return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); | |
15573 | } | |
15574 | ||
15575 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15576 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) | |
15577 | { | |
15578 | return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); | |
15579 | } | |
15580 | ||
15581 | template <typename ResultNode, typename OpType, typename ExprNode> | |
15582 | inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) | |
15583 | { | |
15584 | return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); | |
15585 | } | |
15586 | ||
15587 | template <typename node_type> | |
15588 | inline expression_node<typename node_type::value_type>* allocate() const | |
15589 | { | |
15590 | return (new node_type()); | |
15591 | } | |
15592 | ||
15593 | template <typename node_type, | |
15594 | typename Type, | |
15595 | typename Allocator, | |
15596 | template <typename, typename> class Sequence> | |
15597 | inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const | |
15598 | { | |
15599 | return (new node_type(seq)); | |
15600 | } | |
15601 | ||
15602 | template <typename node_type, typename T1> | |
15603 | inline expression_node<typename node_type::value_type>* allocate(T1& t1) const | |
15604 | { | |
15605 | return (new node_type(t1)); | |
15606 | } | |
15607 | ||
15608 | template <typename node_type, typename T1> | |
15609 | inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const | |
15610 | { | |
15611 | return (new node_type(t1)); | |
15612 | } | |
15613 | ||
15614 | template <typename node_type, | |
15615 | typename T1, typename T2> | |
15616 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const | |
15617 | { | |
15618 | return (new node_type(t1, t2)); | |
15619 | } | |
15620 | ||
15621 | template <typename node_type, | |
15622 | typename T1, typename T2> | |
15623 | inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const | |
15624 | { | |
15625 | return (new node_type(t1, t2)); | |
15626 | } | |
15627 | ||
15628 | template <typename node_type, | |
15629 | typename T1, typename T2> | |
15630 | inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const | |
15631 | { | |
15632 | return (new node_type(t1, t2)); | |
15633 | } | |
15634 | ||
15635 | template <typename node_type, | |
15636 | typename T1, typename T2> | |
15637 | inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const | |
15638 | { | |
15639 | return (new node_type(t1, t2)); | |
15640 | } | |
15641 | ||
15642 | template <typename node_type, | |
15643 | typename T1, typename T2> | |
15644 | inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const | |
15645 | { | |
15646 | return (new node_type(t1, t2)); | |
15647 | } | |
15648 | ||
15649 | template <typename node_type, | |
15650 | typename T1, typename T2, typename T3> | |
15651 | inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const | |
15652 | { | |
15653 | return (new node_type(t1, t2, t3)); | |
15654 | } | |
15655 | ||
15656 | template <typename node_type, | |
15657 | typename T1, typename T2, typename T3, typename T4> | |
15658 | inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const | |
15659 | { | |
15660 | return (new node_type(t1, t2, t3, t4)); | |
15661 | } | |
15662 | ||
15663 | template <typename node_type, | |
15664 | typename T1, typename T2, typename T3> | |
15665 | inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const | |
15666 | { | |
15667 | return (new node_type(t1, t2, t3)); | |
15668 | } | |
15669 | ||
15670 | template <typename node_type, | |
15671 | typename T1, typename T2, typename T3, typename T4> | |
15672 | inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const | |
15673 | { | |
15674 | return (new node_type(t1, t2, t3, t4)); | |
15675 | } | |
15676 | ||
15677 | template <typename node_type, | |
15678 | typename T1, typename T2, typename T3, typename T4, typename T5> | |
15679 | inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const | |
15680 | { | |
15681 | return (new node_type(t1, t2, t3, t4, t5)); | |
15682 | } | |
15683 | ||
15684 | template <typename node_type, | |
15685 | typename T1, typename T2, typename T3> | |
15686 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15687 | const T3& t3) const | |
15688 | { | |
15689 | return (new node_type(t1, t2, t3)); | |
15690 | } | |
15691 | ||
15692 | template <typename node_type, | |
15693 | typename T1, typename T2, | |
15694 | typename T3, typename T4> | |
15695 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15696 | const T3& t3, const T4& t4) const | |
15697 | { | |
15698 | return (new node_type(t1, t2, t3, t4)); | |
15699 | } | |
15700 | ||
15701 | template <typename node_type, | |
15702 | typename T1, typename T2, | |
15703 | typename T3, typename T4, typename T5> | |
15704 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15705 | const T3& t3, const T4& t4, | |
15706 | const T5& t5) const | |
15707 | { | |
15708 | return (new node_type(t1, t2, t3, t4, t5)); | |
15709 | } | |
15710 | ||
15711 | template <typename node_type, | |
15712 | typename T1, typename T2, | |
15713 | typename T3, typename T4, typename T5, typename T6> | |
15714 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15715 | const T3& t3, const T4& t4, | |
15716 | const T5& t5, const T6& t6) const | |
15717 | { | |
15718 | return (new node_type(t1, t2, t3, t4, t5, t6)); | |
15719 | } | |
15720 | ||
15721 | template <typename node_type, | |
15722 | typename T1, typename T2, | |
15723 | typename T3, typename T4, | |
15724 | typename T5, typename T6, typename T7> | |
15725 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15726 | const T3& t3, const T4& t4, | |
15727 | const T5& t5, const T6& t6, | |
15728 | const T7& t7) const | |
15729 | { | |
15730 | return (new node_type(t1, t2, t3, t4, t5, t6, t7)); | |
15731 | } | |
15732 | ||
15733 | template <typename node_type, | |
15734 | typename T1, typename T2, | |
15735 | typename T3, typename T4, | |
15736 | typename T5, typename T6, | |
15737 | typename T7, typename T8> | |
15738 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15739 | const T3& t3, const T4& t4, | |
15740 | const T5& t5, const T6& t6, | |
15741 | const T7& t7, const T8& t8) const | |
15742 | { | |
15743 | return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); | |
15744 | } | |
15745 | ||
15746 | template <typename node_type, | |
15747 | typename T1, typename T2, | |
15748 | typename T3, typename T4, | |
15749 | typename T5, typename T6, | |
15750 | typename T7, typename T8, typename T9> | |
15751 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15752 | const T3& t3, const T4& t4, | |
15753 | const T5& t5, const T6& t6, | |
15754 | const T7& t7, const T8& t8, | |
15755 | const T9& t9) const | |
15756 | { | |
15757 | return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); | |
15758 | } | |
15759 | ||
15760 | template <typename node_type, | |
15761 | typename T1, typename T2, | |
15762 | typename T3, typename T4, | |
15763 | typename T5, typename T6, | |
15764 | typename T7, typename T8, | |
15765 | typename T9, typename T10> | |
15766 | inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, | |
15767 | const T3& t3, const T4& t4, | |
15768 | const T5& t5, const T6& t6, | |
15769 | const T7& t7, const T8& t8, | |
15770 | const T9& t9, const T10& t10) const | |
15771 | { | |
15772 | return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); | |
15773 | } | |
15774 | ||
15775 | template <typename node_type, | |
15776 | typename T1, typename T2, typename T3> | |
15777 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const | |
15778 | { | |
15779 | return (new node_type(t1, t2, t3)); | |
15780 | } | |
15781 | ||
15782 | template <typename node_type, | |
15783 | typename T1, typename T2, | |
15784 | typename T3, typename T4> | |
15785 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, | |
15786 | T3 t3, T4 t4) const | |
15787 | { | |
15788 | return (new node_type(t1, t2, t3, t4)); | |
15789 | } | |
15790 | ||
15791 | template <typename node_type, | |
15792 | typename T1, typename T2, | |
15793 | typename T3, typename T4, | |
15794 | typename T5> | |
15795 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, | |
15796 | T3 t3, T4 t4, | |
15797 | T5 t5) const | |
15798 | { | |
15799 | return (new node_type(t1, t2, t3, t4, t5)); | |
15800 | } | |
15801 | ||
15802 | template <typename node_type, | |
15803 | typename T1, typename T2, | |
15804 | typename T3, typename T4, | |
15805 | typename T5, typename T6> | |
15806 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, | |
15807 | T3 t3, T4 t4, | |
15808 | T5 t5, T6 t6) const | |
15809 | { | |
15810 | return (new node_type(t1, t2, t3, t4, t5, t6)); | |
15811 | } | |
15812 | ||
15813 | template <typename node_type, | |
15814 | typename T1, typename T2, | |
15815 | typename T3, typename T4, | |
15816 | typename T5, typename T6, typename T7> | |
15817 | inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, | |
15818 | T3 t3, T4 t4, | |
15819 | T5 t5, T6 t6, | |
15820 | T7 t7) const | |
15821 | { | |
15822 | return (new node_type(t1, t2, t3, t4, t5, t6, t7)); | |
15823 | } | |
15824 | ||
15825 | template <typename T> | |
15826 | void inline free(expression_node<T>*& e) const | |
15827 | { | |
15828 | delete e; | |
15829 | e = 0; | |
15830 | } | |
15831 | }; | |
15832 | ||
15833 | inline void load_operations_map(std::multimap<std::string,details::base_operation_t,details::ilesscompare>& m) | |
15834 | { | |
15835 | #define register_op(Symbol,Type,Args) \ | |
15836 | m.insert(std::make_pair(std::string(Symbol),details::base_operation_t(Type,Args))); \ | |
15837 | ||
15838 | register_op( "abs", e_abs , 1) | |
15839 | register_op( "acos", e_acos , 1) | |
15840 | register_op( "acosh", e_acosh , 1) | |
15841 | register_op( "asin", e_asin , 1) | |
15842 | register_op( "asinh", e_asinh , 1) | |
15843 | register_op( "atan", e_atan , 1) | |
15844 | register_op( "atanh", e_atanh , 1) | |
15845 | register_op( "ceil", e_ceil , 1) | |
15846 | register_op( "cos", e_cos , 1) | |
15847 | register_op( "cosh", e_cosh , 1) | |
15848 | register_op( "exp", e_exp , 1) | |
15849 | register_op( "expm1", e_expm1 , 1) | |
15850 | register_op( "floor", e_floor , 1) | |
15851 | register_op( "log", e_log , 1) | |
15852 | register_op( "log10", e_log10 , 1) | |
15853 | register_op( "log2", e_log2 , 1) | |
15854 | register_op( "log1p", e_log1p , 1) | |
15855 | register_op( "round", e_round , 1) | |
15856 | register_op( "sin", e_sin , 1) | |
15857 | register_op( "sinc", e_sinc , 1) | |
15858 | register_op( "sinh", e_sinh , 1) | |
15859 | register_op( "sec", e_sec , 1) | |
15860 | register_op( "csc", e_csc , 1) | |
15861 | register_op( "sqrt", e_sqrt , 1) | |
15862 | register_op( "tan", e_tan , 1) | |
15863 | register_op( "tanh", e_tanh , 1) | |
15864 | register_op( "cot", e_cot , 1) | |
15865 | register_op( "rad2deg", e_r2d , 1) | |
15866 | register_op( "deg2rad", e_d2r , 1) | |
15867 | register_op( "deg2grad", e_d2g , 1) | |
15868 | register_op( "grad2deg", e_g2d , 1) | |
15869 | register_op( "sgn", e_sgn , 1) | |
15870 | register_op( "not", e_notl , 1) | |
15871 | register_op( "erf", e_erf , 1) | |
15872 | register_op( "erfc", e_erfc , 1) | |
15873 | register_op( "ncdf", e_ncdf , 1) | |
15874 | register_op( "frac", e_frac , 1) | |
15875 | register_op( "trunc", e_trunc , 1) | |
15876 | register_op( "atan2", e_atan2 , 2) | |
15877 | register_op( "mod", e_mod , 2) | |
15878 | register_op( "logn", e_logn , 2) | |
15879 | register_op( "pow", e_pow , 2) | |
15880 | register_op( "root", e_root , 2) | |
15881 | register_op( "roundn", e_roundn , 2) | |
15882 | register_op( "equal", e_equal , 2) | |
15883 | register_op("not_equal", e_nequal , 2) | |
15884 | register_op( "hypot", e_hypot , 2) | |
15885 | register_op( "shr", e_shr , 2) | |
15886 | register_op( "shl", e_shl , 2) | |
15887 | register_op( "clamp", e_clamp , 3) | |
15888 | register_op( "iclamp", e_iclamp , 3) | |
15889 | register_op( "inrange", e_inrange , 3) | |
15890 | #undef register_op | |
15891 | } | |
15892 | ||
15893 | } // namespace details | |
15894 | ||
15895 | class function_traits | |
15896 | { | |
15897 | public: | |
15898 | ||
15899 | function_traits() | |
15900 | : allow_zero_parameters_(false), | |
15901 | has_side_effects_(true), | |
15902 | min_num_args_(0), | |
15903 | max_num_args_(std::numeric_limits<std::size_t>::max()) | |
15904 | {} | |
15905 | ||
15906 | inline bool& allow_zero_parameters() | |
15907 | { | |
15908 | return allow_zero_parameters_; | |
15909 | } | |
15910 | ||
15911 | inline bool& has_side_effects() | |
15912 | { | |
15913 | return has_side_effects_; | |
15914 | } | |
15915 | ||
15916 | std::size_t& min_num_args() | |
15917 | { | |
15918 | return min_num_args_; | |
15919 | } | |
15920 | ||
15921 | std::size_t& max_num_args() | |
15922 | { | |
15923 | return max_num_args_; | |
15924 | } | |
15925 | ||
15926 | private: | |
15927 | ||
15928 | bool allow_zero_parameters_; | |
15929 | bool has_side_effects_; | |
15930 | std::size_t min_num_args_; | |
15931 | std::size_t max_num_args_; | |
15932 | }; | |
15933 | ||
15934 | template <typename FunctionType> | |
15935 | void enable_zero_parameters(FunctionType& func) | |
15936 | { | |
15937 | func.allow_zero_parameters() = true; | |
15938 | ||
15939 | if (0 != func.min_num_args()) | |
15940 | { | |
15941 | func.min_num_args() = 0; | |
15942 | } | |
15943 | } | |
15944 | ||
15945 | template <typename FunctionType> | |
15946 | void disable_zero_parameters(FunctionType& func) | |
15947 | { | |
15948 | func.allow_zero_parameters() = false; | |
15949 | } | |
15950 | ||
15951 | template <typename FunctionType> | |
15952 | void enable_has_side_effects(FunctionType& func) | |
15953 | { | |
15954 | func.has_side_effects() = true; | |
15955 | } | |
15956 | ||
15957 | template <typename FunctionType> | |
15958 | void disable_has_side_effects(FunctionType& func) | |
15959 | { | |
15960 | func.has_side_effects() = false; | |
15961 | } | |
15962 | ||
15963 | template <typename FunctionType> | |
15964 | void set_min_num_args(FunctionType& func, const std::size_t& num_args) | |
15965 | { | |
15966 | func.min_num_args() = num_args; | |
15967 | ||
15968 | if ((0 != func.min_num_args()) && func.allow_zero_parameters()) | |
15969 | func.allow_zero_parameters() = false; | |
15970 | } | |
15971 | ||
15972 | template <typename FunctionType> | |
15973 | void set_max_num_args(FunctionType& func, const std::size_t& num_args) | |
15974 | { | |
15975 | func.max_num_args() = num_args; | |
15976 | } | |
15977 | ||
15978 | template <typename T> | |
15979 | class ifunction : public function_traits | |
15980 | { | |
15981 | public: | |
15982 | ||
15983 | explicit ifunction(const std::size_t& pc) | |
15984 | : param_count(pc) | |
15985 | {} | |
15986 | ||
15987 | virtual ~ifunction() | |
15988 | {} | |
15989 | ||
15990 | #define empty_method_body \ | |
15991 | { \ | |
15992 | return std::numeric_limits<T>::quiet_NaN(); \ | |
15993 | } \ | |
15994 | ||
15995 | inline virtual T operator() () | |
15996 | empty_method_body | |
15997 | ||
15998 | inline virtual T operator() (const T&) | |
15999 | empty_method_body | |
16000 | ||
16001 | inline virtual T operator() (const T&,const T&) | |
16002 | empty_method_body | |
16003 | ||
16004 | inline virtual T operator() (const T&, const T&, const T&) | |
16005 | empty_method_body | |
16006 | ||
16007 | inline virtual T operator() (const T&, const T&, const T&, const T&) | |
16008 | empty_method_body | |
16009 | ||
16010 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) | |
16011 | empty_method_body | |
16012 | ||
16013 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) | |
16014 | empty_method_body | |
16015 | ||
16016 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16017 | empty_method_body | |
16018 | ||
16019 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16020 | empty_method_body | |
16021 | ||
16022 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16023 | empty_method_body | |
16024 | ||
16025 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16026 | empty_method_body | |
16027 | ||
16028 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16029 | const T&) | |
16030 | empty_method_body | |
16031 | ||
16032 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16033 | const T&, const T&) | |
16034 | empty_method_body | |
16035 | ||
16036 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16037 | const T&, const T&, const T&) | |
16038 | empty_method_body | |
16039 | ||
16040 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16041 | const T&, const T&, const T&, const T&) | |
16042 | empty_method_body | |
16043 | ||
16044 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16045 | const T&, const T&, const T&, const T&, const T&) | |
16046 | empty_method_body | |
16047 | ||
16048 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16049 | const T&, const T&, const T&, const T&, const T&, const T&) | |
16050 | empty_method_body | |
16051 | ||
16052 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16053 | const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16054 | empty_method_body | |
16055 | ||
16056 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16057 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16058 | empty_method_body | |
16059 | ||
16060 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16061 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16062 | empty_method_body | |
16063 | ||
16064 | inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, | |
16065 | const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) | |
16066 | empty_method_body | |
16067 | ||
16068 | #undef empty_method_body | |
16069 | ||
16070 | std::size_t param_count; | |
16071 | }; | |
16072 | ||
16073 | template <typename T> | |
16074 | class ivararg_function : public function_traits | |
16075 | { | |
16076 | public: | |
16077 | ||
16078 | virtual ~ivararg_function() | |
16079 | {} | |
16080 | ||
16081 | inline virtual T operator() (const std::vector<T>&) | |
16082 | { | |
16083 | exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n")); | |
16084 | return std::numeric_limits<T>::quiet_NaN(); | |
16085 | } | |
16086 | }; | |
16087 | ||
16088 | template <typename T> | |
16089 | class igeneric_function : public function_traits | |
16090 | { | |
16091 | public: | |
16092 | ||
16093 | enum return_type | |
16094 | { | |
16095 | e_rtrn_scalar = 0, | |
16096 | e_rtrn_string = 1, | |
16097 | e_rtrn_overload = 2 | |
16098 | }; | |
16099 | ||
16100 | typedef T type; | |
16101 | typedef type_store<T> generic_type; | |
16102 | typedef typename generic_type::parameter_list parameter_list_t; | |
16103 | ||
16104 | igeneric_function(const std::string& param_seq = "", const return_type rtr_type = e_rtrn_scalar) | |
16105 | : parameter_sequence(param_seq), | |
16106 | rtrn_type(rtr_type) | |
16107 | {} | |
16108 | ||
16109 | virtual ~igeneric_function() | |
16110 | {} | |
16111 | ||
16112 | #define igeneric_function_empty_body(N) \ | |
16113 | { \ | |
16114 | exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \ | |
16115 | return std::numeric_limits<T>::quiet_NaN(); \ | |
16116 | } \ | |
16117 | ||
16118 | // f(i_0,i_1,....,i_N) --> Scalar | |
16119 | inline virtual T operator() (parameter_list_t) | |
16120 | igeneric_function_empty_body(1) | |
16121 | ||
16122 | // f(i_0,i_1,....,i_N) --> String | |
16123 | inline virtual T operator() (std::string&, parameter_list_t) | |
16124 | igeneric_function_empty_body(2) | |
16125 | ||
16126 | // f(psi,i_0,i_1,....,i_N) --> Scalar | |
16127 | inline virtual T operator() (const std::size_t&, parameter_list_t) | |
16128 | igeneric_function_empty_body(3) | |
16129 | ||
16130 | // f(psi,i_0,i_1,....,i_N) --> String | |
16131 | inline virtual T operator() (const std::size_t&, std::string&, parameter_list_t) | |
16132 | igeneric_function_empty_body(4) | |
16133 | ||
16134 | std::string parameter_sequence; | |
16135 | return_type rtrn_type; | |
16136 | }; | |
16137 | ||
16138 | template <typename T> class parser; | |
16139 | template <typename T> class expression_helper; | |
16140 | ||
16141 | template <typename T> | |
16142 | class symbol_table | |
16143 | { | |
16144 | public: | |
16145 | ||
16146 | typedef T (*ff00_functor)(); | |
16147 | typedef T (*ff01_functor)(T); | |
16148 | typedef T (*ff02_functor)(T, T); | |
16149 | typedef T (*ff03_functor)(T, T, T); | |
16150 | typedef T (*ff04_functor)(T, T, T, T); | |
16151 | typedef T (*ff05_functor)(T, T, T, T, T); | |
16152 | typedef T (*ff06_functor)(T, T, T, T, T, T); | |
16153 | typedef T (*ff07_functor)(T, T, T, T, T, T, T); | |
16154 | typedef T (*ff08_functor)(T, T, T, T, T, T, T, T); | |
16155 | typedef T (*ff09_functor)(T, T, T, T, T, T, T, T, T); | |
16156 | typedef T (*ff10_functor)(T, T, T, T, T, T, T, T, T, T); | |
16157 | typedef T (*ff11_functor)(T, T, T, T, T, T, T, T, T, T, T); | |
16158 | typedef T (*ff12_functor)(T, T, T, T, T, T, T, T, T, T, T, T); | |
16159 | typedef T (*ff13_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T); | |
16160 | typedef T (*ff14_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T); | |
16161 | typedef T (*ff15_functor)(T, T, T, T, T, T, T, T, T, T, T, T, T, T, T); | |
16162 | ||
16163 | protected: | |
16164 | ||
16165 | struct freefunc00 : public exprtk::ifunction<T> | |
16166 | { | |
16167 | using exprtk::ifunction<T>::operator(); | |
16168 | ||
16169 | explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} | |
16170 | inline T operator() () | |
16171 | { return f(); } | |
16172 | ff00_functor f; | |
16173 | }; | |
16174 | ||
16175 | struct freefunc01 : public exprtk::ifunction<T> | |
16176 | { | |
16177 | using exprtk::ifunction<T>::operator(); | |
16178 | ||
16179 | explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} | |
16180 | inline T operator() (const T& v0) | |
16181 | { return f(v0); } | |
16182 | ff01_functor f; | |
16183 | }; | |
16184 | ||
16185 | struct freefunc02 : public exprtk::ifunction<T> | |
16186 | { | |
16187 | using exprtk::ifunction<T>::operator(); | |
16188 | ||
16189 | explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} | |
16190 | inline T operator() (const T& v0, const T& v1) | |
16191 | { return f(v0, v1); } | |
16192 | ff02_functor f; | |
16193 | }; | |
16194 | ||
16195 | struct freefunc03 : public exprtk::ifunction<T> | |
16196 | { | |
16197 | using exprtk::ifunction<T>::operator(); | |
16198 | ||
16199 | explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} | |
16200 | inline T operator() (const T& v0, const T& v1, const T& v2) | |
16201 | { return f(v0, v1, v2); } | |
16202 | ff03_functor f; | |
16203 | }; | |
16204 | ||
16205 | struct freefunc04 : public exprtk::ifunction<T> | |
16206 | { | |
16207 | using exprtk::ifunction<T>::operator(); | |
16208 | ||
16209 | explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} | |
16210 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) | |
16211 | { return f(v0, v1, v2, v3); } | |
16212 | ff04_functor f; | |
16213 | }; | |
16214 | ||
16215 | struct freefunc05 : public exprtk::ifunction<T> | |
16216 | { | |
16217 | using exprtk::ifunction<T>::operator(); | |
16218 | ||
16219 | explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} | |
16220 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) | |
16221 | { return f(v0, v1, v2, v3, v4); } | |
16222 | ff05_functor f; | |
16223 | }; | |
16224 | ||
16225 | struct freefunc06 : public exprtk::ifunction<T> | |
16226 | { | |
16227 | using exprtk::ifunction<T>::operator(); | |
16228 | ||
16229 | explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} | |
16230 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) | |
16231 | { return f(v0, v1, v2, v3, v4, v5); } | |
16232 | ff06_functor f; | |
16233 | }; | |
16234 | ||
16235 | struct freefunc07 : public exprtk::ifunction<T> | |
16236 | { | |
16237 | using exprtk::ifunction<T>::operator(); | |
16238 | ||
16239 | explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} | |
16240 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, | |
16241 | const T& v5, const T& v6) | |
16242 | { return f(v0, v1, v2, v3, v4, v5, v6); } | |
16243 | ff07_functor f; | |
16244 | }; | |
16245 | ||
16246 | struct freefunc08 : public exprtk::ifunction<T> | |
16247 | { | |
16248 | using exprtk::ifunction<T>::operator(); | |
16249 | ||
16250 | explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} | |
16251 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, | |
16252 | const T& v5, const T& v6, const T& v7) | |
16253 | { return f(v0, v1, v2, v3, v4, v5, v6, v7); } | |
16254 | ff08_functor f; | |
16255 | }; | |
16256 | ||
16257 | struct freefunc09 : public exprtk::ifunction<T> | |
16258 | { | |
16259 | using exprtk::ifunction<T>::operator(); | |
16260 | ||
16261 | explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} | |
16262 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, | |
16263 | const T& v5, const T& v6, const T& v7, const T& v8) | |
16264 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } | |
16265 | ff09_functor f; | |
16266 | }; | |
16267 | ||
16268 | struct freefunc10 : public exprtk::ifunction<T> | |
16269 | { | |
16270 | using exprtk::ifunction<T>::operator(); | |
16271 | ||
16272 | explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} | |
16273 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, | |
16274 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) | |
16275 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } | |
16276 | ff10_functor f; | |
16277 | }; | |
16278 | ||
16279 | struct freefunc11 : public exprtk::ifunction<T> | |
16280 | { | |
16281 | using exprtk::ifunction<T>::operator(); | |
16282 | ||
16283 | explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} | |
16284 | inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, | |
16285 | const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) | |
16286 | { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } | |
16287 | ff11_functor f; | |
16288 | }; | |
16289 | ||
16290 | struct freefunc12 : public exprtk::ifunction<T> | |
16291 | { | |
16292 | using exprtk::ifunction<T>::operator(); | |
16293 | ||
16294 | explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} | |
16295 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, | |
16296 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, | |
16297 | const T& v10, const T& v11) | |
16298 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11); } | |
16299 | ff12_functor f; | |
16300 | }; | |
16301 | ||
16302 | struct freefunc13 : public exprtk::ifunction<T> | |
16303 | { | |
16304 | using exprtk::ifunction<T>::operator(); | |
16305 | ||
16306 | explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} | |
16307 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, | |
16308 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, | |
16309 | const T& v10, const T& v11, const T& v12) | |
16310 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12); } | |
16311 | ff13_functor f; | |
16312 | }; | |
16313 | ||
16314 | struct freefunc14 : public exprtk::ifunction<T> | |
16315 | { | |
16316 | using exprtk::ifunction<T>::operator(); | |
16317 | ||
16318 | explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} | |
16319 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, | |
16320 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, | |
16321 | const T& v10, const T& v11, const T& v12, const T& v13) | |
16322 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13); } | |
16323 | ff14_functor f; | |
16324 | }; | |
16325 | ||
16326 | struct freefunc15 : public exprtk::ifunction<T> | |
16327 | { | |
16328 | using exprtk::ifunction<T>::operator(); | |
16329 | ||
16330 | explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} | |
16331 | inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, | |
16332 | const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, | |
16333 | const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) | |
16334 | { return f(v00, v01, v02, v03, v04, v05, v06, v07, v08, v09, v10, v11, v12, v13, v14); } | |
16335 | ff15_functor f; | |
16336 | }; | |
16337 | ||
16338 | template <typename Type, typename RawType> | |
16339 | struct type_store | |
16340 | { | |
16341 | typedef details::expression_node<T>* expression_ptr; | |
16342 | typedef typename details::variable_node<T> variable_node_t; | |
16343 | typedef ifunction<T> ifunction_t; | |
16344 | typedef ivararg_function<T> ivararg_function_t; | |
16345 | typedef igeneric_function<T> igeneric_function_t; | |
16346 | typedef details::vector_holder<T> vector_t; | |
16347 | #ifndef exprtk_disable_string_capabilities | |
16348 | typedef typename details::stringvar_node<T> stringvar_node_t; | |
16349 | #endif | |
16350 | ||
16351 | typedef Type type_t; | |
16352 | typedef type_t* type_ptr; | |
16353 | typedef std::pair<bool,type_ptr> type_pair_t; | |
16354 | typedef std::map<std::string,type_pair_t,details::ilesscompare> type_map_t; | |
16355 | typedef typename type_map_t::iterator tm_itr_t; | |
16356 | typedef typename type_map_t::const_iterator tm_const_itr_t; | |
16357 | ||
16358 | enum { lut_size = 256 }; | |
16359 | ||
16360 | type_map_t map; | |
16361 | std::size_t size; | |
16362 | ||
16363 | type_store() | |
16364 | : size(0) | |
16365 | {} | |
16366 | ||
16367 | inline bool symbol_exists(const std::string& symbol_name) const | |
16368 | { | |
16369 | if (symbol_name.empty()) | |
16370 | return false; | |
16371 | else if (map.end() != map.find(symbol_name)) | |
16372 | return true; | |
16373 | else | |
16374 | return false; | |
16375 | } | |
16376 | ||
16377 | template <typename PtrType> | |
16378 | inline std::string entity_name(const PtrType& ptr) const | |
16379 | { | |
16380 | if (map.empty()) | |
16381 | return std::string(); | |
16382 | ||
16383 | tm_const_itr_t itr = map.begin(); | |
16384 | ||
16385 | while (map.end() != itr) | |
16386 | { | |
16387 | if (itr->second.second == ptr) | |
16388 | { | |
16389 | return itr->first; | |
16390 | } | |
16391 | else | |
16392 | ++itr; | |
16393 | } | |
16394 | ||
16395 | return std::string(); | |
16396 | } | |
16397 | ||
16398 | inline bool is_constant(const std::string& symbol_name) const | |
16399 | { | |
16400 | if (symbol_name.empty()) | |
16401 | return false; | |
16402 | else | |
16403 | { | |
16404 | const tm_const_itr_t itr = map.find(symbol_name); | |
16405 | ||
16406 | if (map.end() == itr) | |
16407 | return false; | |
16408 | else | |
16409 | return (*itr).second.first; | |
16410 | } | |
16411 | } | |
16412 | ||
16413 | template <typename Tie, typename RType> | |
16414 | inline bool add_impl(const std::string& symbol_name, RType t, const bool is_const) | |
16415 | { | |
16416 | if (symbol_name.size() > 1) | |
16417 | { | |
16418 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) | |
16419 | { | |
16420 | if (details::imatch(symbol_name, details::reserved_symbols[i])) | |
16421 | { | |
16422 | return false; | |
16423 | } | |
16424 | } | |
16425 | } | |
16426 | ||
16427 | const tm_itr_t itr = map.find(symbol_name); | |
16428 | ||
16429 | if (map.end() == itr) | |
16430 | { | |
16431 | map[symbol_name] = Tie::make(t,is_const); | |
16432 | ++size; | |
16433 | } | |
16434 | ||
16435 | return true; | |
16436 | } | |
16437 | ||
16438 | struct tie_array | |
16439 | { | |
16440 | static inline std::pair<bool,vector_t*> make(std::pair<T*,std::size_t> v, const bool is_const = false) | |
16441 | { | |
16442 | return std::make_pair(is_const, new vector_t(v.first, v.second)); | |
16443 | } | |
16444 | }; | |
16445 | ||
16446 | struct tie_stdvec | |
16447 | { | |
16448 | template <typename Allocator> | |
16449 | static inline std::pair<bool,vector_t*> make(std::vector<T,Allocator>& v, const bool is_const = false) | |
16450 | { | |
16451 | return std::make_pair(is_const, new vector_t(v)); | |
16452 | } | |
16453 | }; | |
16454 | ||
16455 | struct tie_vecview | |
16456 | { | |
16457 | static inline std::pair<bool,vector_t*> make(exprtk::vector_view<T>& v, const bool is_const = false) | |
16458 | { | |
16459 | return std::make_pair(is_const, new vector_t(v)); | |
16460 | } | |
16461 | }; | |
16462 | ||
16463 | struct tie_stddeq | |
16464 | { | |
16465 | template <typename Allocator> | |
16466 | static inline std::pair<bool,vector_t*> make(std::deque<T,Allocator>& v, const bool is_const = false) | |
16467 | { | |
16468 | return std::make_pair(is_const, new vector_t(v)); | |
16469 | } | |
16470 | }; | |
16471 | ||
16472 | template <std::size_t v_size> | |
16473 | inline bool add(const std::string& symbol_name, T (&v)[v_size], const bool is_const = false) | |
16474 | { | |
16475 | return add_impl<tie_array,std::pair<T*,std::size_t> > | |
16476 | (symbol_name, std::make_pair(v,v_size), is_const); | |
16477 | } | |
16478 | ||
16479 | inline bool add(const std::string& symbol_name, T* v, const std::size_t v_size, const bool is_const = false) | |
16480 | { | |
16481 | return add_impl<tie_array,std::pair<T*,std::size_t> > | |
16482 | (symbol_name, std::make_pair(v,v_size), is_const); | |
16483 | } | |
16484 | ||
16485 | template <typename Allocator> | |
16486 | inline bool add(const std::string& symbol_name, std::vector<T,Allocator>& v, const bool is_const = false) | |
16487 | { | |
16488 | return add_impl<tie_stdvec,std::vector<T,Allocator>&> | |
16489 | (symbol_name, v, is_const); | |
16490 | } | |
16491 | ||
16492 | inline bool add(const std::string& symbol_name, exprtk::vector_view<T>& v, const bool is_const = false) | |
16493 | { | |
16494 | return add_impl<tie_vecview,exprtk::vector_view<T>&> | |
16495 | (symbol_name, v, is_const); | |
16496 | } | |
16497 | ||
16498 | template <typename Allocator> | |
16499 | inline bool add(const std::string& symbol_name, std::deque<T,Allocator>& v, const bool is_const = false) | |
16500 | { | |
16501 | return add_impl<tie_stddeq,std::deque<T,Allocator>&> | |
16502 | (symbol_name, v, is_const); | |
16503 | } | |
16504 | ||
16505 | inline bool add(const std::string& symbol_name, RawType& t, const bool is_const = false) | |
16506 | { | |
16507 | struct tie | |
16508 | { | |
16509 | static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_const = false) | |
16510 | { | |
16511 | return std::make_pair(is_const, new variable_node_t(t)); | |
16512 | } | |
16513 | ||
16514 | #ifndef exprtk_disable_string_capabilities | |
16515 | static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_const = false) | |
16516 | { | |
16517 | return std::make_pair(is_const, new stringvar_node_t(t)); | |
16518 | } | |
16519 | #endif | |
16520 | ||
16521 | static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false) | |
16522 | { | |
16523 | return std::make_pair(is_constant,&t); | |
16524 | } | |
16525 | ||
16526 | static inline std::pair<bool,vararg_function_t*> make(vararg_function_t& t, const bool is_const = false) | |
16527 | { | |
16528 | return std::make_pair(is_const,&t); | |
16529 | } | |
16530 | ||
16531 | static inline std::pair<bool,generic_function_t*> make(generic_function_t& t, const bool is_constant = false) | |
16532 | { | |
16533 | return std::make_pair(is_constant,&t); | |
16534 | } | |
16535 | }; | |
16536 | ||
16537 | const tm_itr_t itr = map.find(symbol_name); | |
16538 | ||
16539 | if (map.end() == itr) | |
16540 | { | |
16541 | map[symbol_name] = tie::make(t,is_const); | |
16542 | ++size; | |
16543 | } | |
16544 | ||
16545 | return true; | |
16546 | } | |
16547 | ||
16548 | inline type_ptr get(const std::string& symbol_name) const | |
16549 | { | |
16550 | const tm_const_itr_t itr = map.find(symbol_name); | |
16551 | ||
16552 | if (map.end() == itr) | |
16553 | return reinterpret_cast<type_ptr>(0); | |
16554 | else | |
16555 | return itr->second.second; | |
16556 | } | |
16557 | ||
16558 | template <typename TType, typename TRawType, typename PtrType> | |
16559 | struct ptr_match | |
16560 | { | |
16561 | static inline bool test(const PtrType, const void*) | |
16562 | { | |
16563 | return false; | |
16564 | } | |
16565 | }; | |
16566 | ||
16567 | template <typename TType, typename TRawType> | |
16568 | struct ptr_match<TType,TRawType,variable_node_t*> | |
16569 | { | |
16570 | static inline bool test(const variable_node_t* p, const void* ptr) | |
16571 | { | |
16572 | exprtk_debug(("ptr_match::test() - %p <--> %p\n",(void*)(&(p->ref())),ptr)); | |
16573 | return (&(p->ref()) == ptr); | |
16574 | } | |
16575 | }; | |
16576 | ||
16577 | inline type_ptr get_from_varptr(const void* ptr) const | |
16578 | { | |
16579 | tm_const_itr_t itr = map.begin(); | |
16580 | ||
16581 | while (map.end() != itr) | |
16582 | { | |
16583 | type_ptr ret_ptr = itr->second.second; | |
16584 | ||
16585 | if (ptr_match<Type,RawType,type_ptr>::test(ret_ptr,ptr)) | |
16586 | { | |
16587 | return ret_ptr; | |
16588 | } | |
16589 | ||
16590 | ++itr; | |
16591 | } | |
16592 | ||
16593 | return type_ptr(0); | |
16594 | } | |
16595 | ||
16596 | inline bool remove(const std::string& symbol_name, const bool delete_node = true) | |
16597 | { | |
16598 | const tm_itr_t itr = map.find(symbol_name); | |
16599 | ||
16600 | if (map.end() != itr) | |
16601 | { | |
16602 | struct deleter | |
16603 | { | |
16604 | static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } | |
16605 | static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } | |
16606 | #ifndef exprtk_disable_string_capabilities | |
16607 | static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } | |
16608 | #endif | |
16609 | static inline void process(std::pair<bool,function_t*>&) { } | |
16610 | }; | |
16611 | ||
16612 | if (delete_node) | |
16613 | { | |
16614 | deleter::process((*itr).second); | |
16615 | } | |
16616 | ||
16617 | map.erase(itr); | |
16618 | --size; | |
16619 | ||
16620 | return true; | |
16621 | } | |
16622 | else | |
16623 | return false; | |
16624 | } | |
16625 | ||
16626 | inline RawType& type_ref(const std::string& symbol_name) | |
16627 | { | |
16628 | struct init_type | |
16629 | { | |
16630 | static inline double set(double) { return (0.0); } | |
16631 | static inline double set(long double) { return (0.0); } | |
16632 | static inline float set(float) { return (0.0f); } | |
16633 | static inline std::string set(std::string) { return std::string(""); } | |
16634 | }; | |
16635 | ||
16636 | static RawType null_type = init_type::set(RawType()); | |
16637 | ||
16638 | const tm_const_itr_t itr = map.find(symbol_name); | |
16639 | ||
16640 | if (map.end() == itr) | |
16641 | return null_type; | |
16642 | else | |
16643 | return itr->second.second->ref(); | |
16644 | } | |
16645 | ||
16646 | inline void clear(const bool delete_node = true) | |
16647 | { | |
16648 | struct deleter | |
16649 | { | |
16650 | static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } | |
16651 | static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } | |
16652 | static inline void process(std::pair<bool,function_t*>&) { } | |
16653 | #ifndef exprtk_disable_string_capabilities | |
16654 | static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } | |
16655 | #endif | |
16656 | }; | |
16657 | ||
16658 | if (!map.empty()) | |
16659 | { | |
16660 | if (delete_node) | |
16661 | { | |
16662 | tm_itr_t itr = map.begin(); | |
16663 | tm_itr_t end = map.end (); | |
16664 | ||
16665 | while (end != itr) | |
16666 | { | |
16667 | deleter::process((*itr).second); | |
16668 | ++itr; | |
16669 | } | |
16670 | } | |
16671 | ||
16672 | map.clear(); | |
16673 | } | |
16674 | ||
16675 | size = 0; | |
16676 | } | |
16677 | ||
16678 | template <typename Allocator, | |
16679 | template <typename, typename> class Sequence> | |
16680 | inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const | |
16681 | { | |
16682 | std::size_t count = 0; | |
16683 | ||
16684 | if (!map.empty()) | |
16685 | { | |
16686 | tm_const_itr_t itr = map.begin(); | |
16687 | tm_const_itr_t end = map.end (); | |
16688 | ||
16689 | while (end != itr) | |
16690 | { | |
16691 | list.push_back(std::make_pair((*itr).first,itr->second.second->ref())); | |
16692 | ++itr; | |
16693 | ++count; | |
16694 | } | |
16695 | } | |
16696 | ||
16697 | return count; | |
16698 | } | |
16699 | ||
16700 | template <typename Allocator, | |
16701 | template <typename, typename> class Sequence> | |
16702 | inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const | |
16703 | { | |
16704 | std::size_t count = 0; | |
16705 | ||
16706 | if (!map.empty()) | |
16707 | { | |
16708 | tm_const_itr_t itr = map.begin(); | |
16709 | tm_const_itr_t end = map.end (); | |
16710 | ||
16711 | while (end != itr) | |
16712 | { | |
16713 | vlist.push_back((*itr).first); | |
16714 | ++itr; | |
16715 | ++count; | |
16716 | } | |
16717 | } | |
16718 | ||
16719 | return count; | |
16720 | } | |
16721 | }; | |
16722 | ||
16723 | typedef details::expression_node<T>* expression_ptr; | |
16724 | typedef typename details::variable_node<T> variable_t; | |
16725 | typedef typename details::vector_holder<T> vector_holder_t; | |
16726 | typedef variable_t* variable_ptr; | |
16727 | #ifndef exprtk_disable_string_capabilities | |
16728 | typedef typename details::stringvar_node<T> stringvar_t; | |
16729 | typedef stringvar_t* stringvar_ptr; | |
16730 | #endif | |
16731 | typedef ifunction <T> function_t; | |
16732 | typedef ivararg_function <T> vararg_function_t; | |
16733 | typedef igeneric_function<T> generic_function_t; | |
16734 | typedef function_t* function_ptr; | |
16735 | typedef vararg_function_t* vararg_function_ptr; | |
16736 | typedef generic_function_t* generic_function_ptr; | |
16737 | ||
16738 | static const std::size_t lut_size = 256; | |
16739 | ||
16740 | // Symbol Table Holder | |
16741 | struct control_block | |
16742 | { | |
16743 | struct st_data | |
16744 | { | |
16745 | type_store<typename details::variable_node<T>,T> variable_store; | |
16746 | #ifndef exprtk_disable_string_capabilities | |
16747 | type_store<typename details::stringvar_node<T>,std::string> stringvar_store; | |
16748 | #endif | |
16749 | type_store<ifunction<T>,ifunction<T> > function_store; | |
16750 | type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store; | |
16751 | type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store; | |
16752 | type_store<igeneric_function<T>,igeneric_function<T> > string_function_store; | |
16753 | type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store; | |
16754 | type_store<vector_holder_t,vector_holder_t> vector_store; | |
16755 | ||
16756 | st_data() | |
16757 | { | |
16758 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) | |
16759 | { | |
16760 | reserved_symbol_table_.insert(details::reserved_words[i]); | |
16761 | } | |
16762 | ||
16763 | for (std::size_t i = 0; i < details::reserved_symbols_size; ++i) | |
16764 | { | |
16765 | reserved_symbol_table_.insert(details::reserved_symbols[i]); | |
16766 | } | |
16767 | } | |
16768 | ||
16769 | ~st_data() | |
16770 | { | |
16771 | for (std::size_t i = 0; i < free_function_list_.size(); ++i) | |
16772 | { | |
16773 | delete free_function_list_[i]; | |
16774 | } | |
16775 | } | |
16776 | ||
16777 | inline bool is_reserved_symbol(const std::string& symbol) const | |
16778 | { | |
16779 | return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol)); | |
16780 | } | |
16781 | ||
16782 | static inline st_data* create() | |
16783 | { | |
16784 | return (new st_data); | |
16785 | } | |
16786 | ||
16787 | static inline void destroy(st_data*& sd) | |
16788 | { | |
16789 | delete sd; | |
16790 | sd = reinterpret_cast<st_data*>(0); | |
16791 | } | |
16792 | ||
16793 | std::list<T> local_symbol_list_; | |
16794 | std::list<std::string> local_stringvar_list_; | |
16795 | std::set<std::string> reserved_symbol_table_; | |
16796 | std::vector<ifunction<T>*> free_function_list_; | |
16797 | }; | |
16798 | ||
16799 | control_block() | |
16800 | : ref_count(1), | |
16801 | data_(st_data::create()) | |
16802 | {} | |
16803 | ||
16804 | explicit control_block(st_data* data) | |
16805 | : ref_count(1), | |
16806 | data_(data) | |
16807 | {} | |
16808 | ||
16809 | ~control_block() | |
16810 | { | |
16811 | if (data_ && (0 == ref_count)) | |
16812 | { | |
16813 | st_data::destroy(data_); | |
16814 | } | |
16815 | } | |
16816 | ||
16817 | static inline control_block* create() | |
16818 | { | |
16819 | return (new control_block); | |
16820 | } | |
16821 | ||
16822 | template <typename SymTab> | |
16823 | static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab) | |
16824 | { | |
16825 | if (cntrl_blck) | |
16826 | { | |
16827 | if ( | |
16828 | (0 != cntrl_blck->ref_count) && | |
16829 | (0 == --cntrl_blck->ref_count) | |
16830 | ) | |
16831 | { | |
16832 | if (sym_tab) | |
16833 | sym_tab->clear(); | |
16834 | ||
16835 | delete cntrl_blck; | |
16836 | } | |
16837 | ||
16838 | cntrl_blck = 0; | |
16839 | } | |
16840 | } | |
16841 | ||
16842 | std::size_t ref_count; | |
16843 | st_data* data_; | |
16844 | }; | |
16845 | ||
16846 | public: | |
16847 | ||
16848 | symbol_table() | |
16849 | : control_block_(control_block::create()) | |
16850 | { | |
16851 | clear(); | |
16852 | } | |
16853 | ||
16854 | ~symbol_table() | |
16855 | { | |
16856 | control_block::destroy(control_block_,this); | |
16857 | } | |
16858 | ||
16859 | symbol_table(const symbol_table<T>& st) | |
16860 | { | |
16861 | control_block_ = st.control_block_; | |
16862 | control_block_->ref_count++; | |
16863 | } | |
16864 | ||
16865 | inline symbol_table<T>& operator=(const symbol_table<T>& st) | |
16866 | { | |
16867 | if (this != &st) | |
16868 | { | |
16869 | control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0)); | |
16870 | ||
16871 | control_block_ = st.control_block_; | |
16872 | control_block_->ref_count++; | |
16873 | } | |
16874 | ||
16875 | return (*this); | |
16876 | } | |
16877 | ||
16878 | inline bool operator==(const symbol_table<T>& st) const | |
16879 | { | |
16880 | return (this == &st) || (control_block_ == st.control_block_); | |
16881 | } | |
16882 | ||
16883 | inline void clear_variables(const bool delete_node = true) | |
16884 | { | |
16885 | local_data().variable_store.clear(delete_node); | |
16886 | } | |
16887 | ||
16888 | inline void clear_functions() | |
16889 | { | |
16890 | local_data().function_store.clear(); | |
16891 | } | |
16892 | ||
16893 | inline void clear_strings() | |
16894 | { | |
16895 | #ifndef exprtk_disable_string_capabilities | |
16896 | local_data().stringvar_store.clear(); | |
16897 | #endif | |
16898 | } | |
16899 | ||
16900 | inline void clear_vectors() | |
16901 | { | |
16902 | local_data().vector_store.clear(); | |
16903 | } | |
16904 | ||
16905 | inline void clear_local_constants() | |
16906 | { | |
16907 | local_data().local_symbol_list_.clear(); | |
16908 | } | |
16909 | ||
16910 | inline void clear() | |
16911 | { | |
16912 | if (!valid()) return; | |
16913 | clear_variables (); | |
16914 | clear_functions (); | |
16915 | clear_strings (); | |
16916 | clear_vectors (); | |
16917 | clear_local_constants(); | |
16918 | } | |
16919 | ||
16920 | inline std::size_t variable_count() const | |
16921 | { | |
16922 | if (valid()) | |
16923 | return local_data().variable_store.size; | |
16924 | else | |
16925 | return 0; | |
16926 | } | |
16927 | ||
16928 | #ifndef exprtk_disable_string_capabilities | |
16929 | inline std::size_t stringvar_count() const | |
16930 | { | |
16931 | if (valid()) | |
16932 | return local_data().stringvar_store.size; | |
16933 | else | |
16934 | return 0; | |
16935 | } | |
16936 | #endif | |
16937 | ||
16938 | inline std::size_t function_count() const | |
16939 | { | |
16940 | if (valid()) | |
16941 | return local_data().function_store.size; | |
16942 | else | |
16943 | return 0; | |
16944 | } | |
16945 | ||
16946 | inline std::size_t vector_count() const | |
16947 | { | |
16948 | if (valid()) | |
16949 | return local_data().vector_store.size; | |
16950 | else | |
16951 | return 0; | |
16952 | } | |
16953 | ||
16954 | inline variable_ptr get_variable(const std::string& variable_name) const | |
16955 | { | |
16956 | if (!valid()) | |
16957 | return reinterpret_cast<variable_ptr>(0); | |
16958 | else if (!valid_symbol(variable_name)) | |
16959 | return reinterpret_cast<variable_ptr>(0); | |
16960 | else | |
16961 | return local_data().variable_store.get(variable_name); | |
16962 | } | |
16963 | ||
16964 | inline variable_ptr get_variable(const T& var_ref) const | |
16965 | { | |
16966 | if (!valid()) | |
16967 | return reinterpret_cast<variable_ptr>(0); | |
16968 | else | |
16969 | return local_data().variable_store.get_from_varptr( | |
16970 | reinterpret_cast<const void*>(&var_ref)); | |
16971 | } | |
16972 | ||
16973 | #ifndef exprtk_disable_string_capabilities | |
16974 | inline stringvar_ptr get_stringvar(const std::string& string_name) const | |
16975 | { | |
16976 | if (!valid()) | |
16977 | return reinterpret_cast<stringvar_ptr>(0); | |
16978 | else if (!valid_symbol(string_name)) | |
16979 | return reinterpret_cast<stringvar_ptr>(0); | |
16980 | else | |
16981 | return local_data().stringvar_store.get(string_name); | |
16982 | } | |
16983 | #endif | |
16984 | ||
16985 | inline function_ptr get_function(const std::string& function_name) const | |
16986 | { | |
16987 | if (!valid()) | |
16988 | return reinterpret_cast<function_ptr>(0); | |
16989 | else if (!valid_symbol(function_name)) | |
16990 | return reinterpret_cast<function_ptr>(0); | |
16991 | else | |
16992 | return local_data().function_store.get(function_name); | |
16993 | } | |
16994 | ||
16995 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const | |
16996 | { | |
16997 | if (!valid()) | |
16998 | return reinterpret_cast<vararg_function_ptr>(0); | |
16999 | else if (!valid_symbol(vararg_function_name)) | |
17000 | return reinterpret_cast<vararg_function_ptr>(0); | |
17001 | else | |
17002 | return local_data().vararg_function_store.get(vararg_function_name); | |
17003 | } | |
17004 | ||
17005 | inline generic_function_ptr get_generic_function(const std::string& function_name) const | |
17006 | { | |
17007 | if (!valid()) | |
17008 | return reinterpret_cast<generic_function_ptr>(0); | |
17009 | else if (!valid_symbol(function_name)) | |
17010 | return reinterpret_cast<generic_function_ptr>(0); | |
17011 | else | |
17012 | return local_data().generic_function_store.get(function_name); | |
17013 | } | |
17014 | ||
17015 | inline generic_function_ptr get_string_function(const std::string& function_name) const | |
17016 | { | |
17017 | if (!valid()) | |
17018 | return reinterpret_cast<generic_function_ptr>(0); | |
17019 | else if (!valid_symbol(function_name)) | |
17020 | return reinterpret_cast<generic_function_ptr>(0); | |
17021 | else | |
17022 | return local_data().string_function_store.get(function_name); | |
17023 | } | |
17024 | ||
17025 | inline generic_function_ptr get_overload_function(const std::string& function_name) const | |
17026 | { | |
17027 | if (!valid()) | |
17028 | return reinterpret_cast<generic_function_ptr>(0); | |
17029 | else if (!valid_symbol(function_name)) | |
17030 | return reinterpret_cast<generic_function_ptr>(0); | |
17031 | else | |
17032 | return local_data().overload_function_store.get(function_name); | |
17033 | } | |
17034 | ||
17035 | typedef vector_holder_t* vector_holder_ptr; | |
17036 | ||
17037 | inline vector_holder_ptr get_vector(const std::string& vector_name) const | |
17038 | { | |
17039 | if (!valid()) | |
17040 | return reinterpret_cast<vector_holder_ptr>(0); | |
17041 | else if (!valid_symbol(vector_name)) | |
17042 | return reinterpret_cast<vector_holder_ptr>(0); | |
17043 | else | |
17044 | return local_data().vector_store.get(vector_name); | |
17045 | } | |
17046 | ||
17047 | inline T& variable_ref(const std::string& symbol_name) | |
17048 | { | |
17049 | static T null_var = T(0); | |
17050 | if (!valid()) | |
17051 | return null_var; | |
17052 | else if (!valid_symbol(symbol_name)) | |
17053 | return null_var; | |
17054 | else | |
17055 | return local_data().variable_store.type_ref(symbol_name); | |
17056 | } | |
17057 | ||
17058 | #ifndef exprtk_disable_string_capabilities | |
17059 | inline std::string& stringvar_ref(const std::string& symbol_name) | |
17060 | { | |
17061 | static std::string null_stringvar; | |
17062 | if (!valid()) | |
17063 | return null_stringvar; | |
17064 | else if (!valid_symbol(symbol_name)) | |
17065 | return null_stringvar; | |
17066 | else | |
17067 | return local_data().stringvar_store.type_ref(symbol_name); | |
17068 | } | |
17069 | #endif | |
17070 | ||
17071 | inline bool is_constant_node(const std::string& symbol_name) const | |
17072 | { | |
17073 | if (!valid()) | |
17074 | return false; | |
17075 | else if (!valid_symbol(symbol_name)) | |
17076 | return false; | |
17077 | else | |
17078 | return local_data().variable_store.is_constant(symbol_name); | |
17079 | } | |
17080 | ||
17081 | #ifndef exprtk_disable_string_capabilities | |
17082 | inline bool is_constant_string(const std::string& symbol_name) const | |
17083 | { | |
17084 | if (!valid()) | |
17085 | return false; | |
17086 | else if (!valid_symbol(symbol_name)) | |
17087 | return false; | |
17088 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) | |
17089 | return false; | |
17090 | else | |
17091 | return local_data().stringvar_store.is_constant(symbol_name); | |
17092 | } | |
17093 | #endif | |
17094 | ||
17095 | inline bool create_variable(const std::string& variable_name, const T& value = T(0)) | |
17096 | { | |
17097 | if (!valid()) | |
17098 | return false; | |
17099 | else if (!valid_symbol(variable_name)) | |
17100 | return false; | |
17101 | else if (symbol_exists(variable_name)) | |
17102 | return false; | |
17103 | ||
17104 | local_data().local_symbol_list_.push_back(value); | |
17105 | T& t = local_data().local_symbol_list_.back(); | |
17106 | ||
17107 | return add_variable(variable_name,t); | |
17108 | } | |
17109 | ||
17110 | #ifndef exprtk_disable_string_capabilities | |
17111 | inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string("")) | |
17112 | { | |
17113 | if (!valid()) | |
17114 | return false; | |
17115 | else if (!valid_symbol(stringvar_name)) | |
17116 | return false; | |
17117 | else if (symbol_exists(stringvar_name)) | |
17118 | return false; | |
17119 | ||
17120 | local_data().local_stringvar_list_.push_back(value); | |
17121 | std::string& s = local_data().local_stringvar_list_.back(); | |
17122 | ||
17123 | return add_stringvar(stringvar_name,s); | |
17124 | } | |
17125 | #endif | |
17126 | ||
17127 | inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false) | |
17128 | { | |
17129 | if (!valid()) | |
17130 | return false; | |
17131 | else if (!valid_symbol(variable_name)) | |
17132 | return false; | |
17133 | else if (symbol_exists(variable_name)) | |
17134 | return false; | |
17135 | else | |
17136 | return local_data().variable_store.add(variable_name, t, is_constant); | |
17137 | } | |
17138 | ||
17139 | inline bool add_constant(const std::string& constant_name, const T& value) | |
17140 | { | |
17141 | if (!valid()) | |
17142 | return false; | |
17143 | else if (!valid_symbol(constant_name)) | |
17144 | return false; | |
17145 | else if (symbol_exists(constant_name)) | |
17146 | return false; | |
17147 | ||
17148 | local_data().local_symbol_list_.push_back(value); | |
17149 | T& t = local_data().local_symbol_list_.back(); | |
17150 | ||
17151 | return add_variable(constant_name, t, true); | |
17152 | } | |
17153 | ||
17154 | #ifndef exprtk_disable_string_capabilities | |
17155 | inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false) | |
17156 | { | |
17157 | if (!valid()) | |
17158 | return false; | |
17159 | else if (!valid_symbol(stringvar_name)) | |
17160 | return false; | |
17161 | else if (symbol_exists(stringvar_name)) | |
17162 | return false; | |
17163 | else | |
17164 | return local_data().stringvar_store.add(stringvar_name, s, is_constant); | |
17165 | } | |
17166 | #endif | |
17167 | ||
17168 | inline bool add_function(const std::string& function_name, function_t& function) | |
17169 | { | |
17170 | if (!valid()) | |
17171 | return false; | |
17172 | else if (!valid_symbol(function_name)) | |
17173 | return false; | |
17174 | else if (symbol_exists(function_name)) | |
17175 | return false; | |
17176 | else | |
17177 | return local_data().function_store.add(function_name,function); | |
17178 | } | |
17179 | ||
17180 | inline bool add_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) | |
17181 | { | |
17182 | if (!valid()) | |
17183 | return false; | |
17184 | else if (!valid_symbol(vararg_function_name)) | |
17185 | return false; | |
17186 | else if (symbol_exists(vararg_function_name)) | |
17187 | return false; | |
17188 | else | |
17189 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); | |
17190 | } | |
17191 | ||
17192 | inline bool add_function(const std::string& function_name, generic_function_t& function) | |
17193 | { | |
17194 | if (!valid()) | |
17195 | return false; | |
17196 | else if (!valid_symbol(function_name)) | |
17197 | return false; | |
17198 | else if (symbol_exists(function_name)) | |
17199 | return false; | |
17200 | else if ( | |
17201 | ( | |
17202 | (generic_function_t::e_rtrn_scalar == function.rtrn_type) || | |
17203 | (generic_function_t::e_rtrn_string == function.rtrn_type) | |
17204 | ) && | |
17205 | std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|") | |
17206 | ) | |
17207 | return false; | |
17208 | else if ( | |
17209 | (generic_function_t::e_rtrn_overload == function.rtrn_type) && | |
17210 | std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:") | |
17211 | ) | |
17212 | return false; | |
17213 | ||
17214 | switch (function.rtrn_type) | |
17215 | { | |
17216 | case generic_function_t::e_rtrn_scalar : | |
17217 | return local_data().generic_function_store.add(function_name,function); | |
17218 | ||
17219 | case generic_function_t::e_rtrn_string : | |
17220 | return local_data().string_function_store.add(function_name,function); | |
17221 | ||
17222 | case generic_function_t::e_rtrn_overload : | |
17223 | return local_data().overload_function_store.add(function_name,function); | |
17224 | } | |
17225 | ||
17226 | return false; | |
17227 | } | |
17228 | ||
17229 | #define exprtk_define_freefunction(NN) \ | |
17230 | inline bool add_function(const std::string& function_name, ff##NN##_functor function) \ | |
17231 | { \ | |
17232 | if (!valid()) \ | |
17233 | { return false; } \ | |
17234 | if (!valid_symbol(function_name)) \ | |
17235 | { return false; } \ | |
17236 | if (symbol_exists(function_name)) \ | |
17237 | { return false; } \ | |
17238 | \ | |
17239 | exprtk::ifunction<T>* ifunc = new freefunc##NN(function); \ | |
17240 | \ | |
17241 | local_data().free_function_list_.push_back(ifunc); \ | |
17242 | \ | |
17243 | return add_function(function_name,(*local_data().free_function_list_.back())); \ | |
17244 | } \ | |
17245 | ||
17246 | exprtk_define_freefunction(00) exprtk_define_freefunction(01) | |
17247 | exprtk_define_freefunction(02) exprtk_define_freefunction(03) | |
17248 | exprtk_define_freefunction(04) exprtk_define_freefunction(05) | |
17249 | exprtk_define_freefunction(06) exprtk_define_freefunction(07) | |
17250 | exprtk_define_freefunction(08) exprtk_define_freefunction(09) | |
17251 | exprtk_define_freefunction(10) exprtk_define_freefunction(11) | |
17252 | exprtk_define_freefunction(12) exprtk_define_freefunction(13) | |
17253 | exprtk_define_freefunction(14) exprtk_define_freefunction(15) | |
17254 | ||
17255 | #undef exprtk_define_freefunction | |
17256 | ||
17257 | inline bool add_reserved_function(const std::string& function_name, function_t& function) | |
17258 | { | |
17259 | if (!valid()) | |
17260 | return false; | |
17261 | else if (!valid_symbol(function_name,false)) | |
17262 | return false; | |
17263 | else if (symbol_exists(function_name,false)) | |
17264 | return false; | |
17265 | else | |
17266 | return local_data().function_store.add(function_name,function); | |
17267 | } | |
17268 | ||
17269 | inline bool add_reserved_function(const std::string& vararg_function_name, vararg_function_t& vararg_function) | |
17270 | { | |
17271 | if (!valid()) | |
17272 | return false; | |
17273 | else if (!valid_symbol(vararg_function_name,false)) | |
17274 | return false; | |
17275 | else if (symbol_exists(vararg_function_name,false)) | |
17276 | return false; | |
17277 | else | |
17278 | return local_data().vararg_function_store.add(vararg_function_name,vararg_function); | |
17279 | } | |
17280 | ||
17281 | inline bool add_reserved_function(const std::string& function_name, generic_function_t& function) | |
17282 | { | |
17283 | if (!valid()) | |
17284 | return false; | |
17285 | else if (!valid_symbol(function_name,false)) | |
17286 | return false; | |
17287 | else if (symbol_exists(function_name,false)) | |
17288 | return false; | |
17289 | else if ( | |
17290 | ( | |
17291 | (generic_function_t::e_rtrn_scalar == function.rtrn_type) || | |
17292 | (generic_function_t::e_rtrn_string == function.rtrn_type) | |
17293 | ) && | |
17294 | std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|") | |
17295 | ) | |
17296 | return false; | |
17297 | else if ( | |
17298 | generic_function_t::e_rtrn_overload && | |
17299 | std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:") | |
17300 | ) | |
17301 | return false; | |
17302 | ||
17303 | switch (function.rtrn_type) | |
17304 | { | |
17305 | case generic_function_t::e_rtrn_scalar : | |
17306 | return local_data().generic_function_store.add(function_name,function); | |
17307 | ||
17308 | case generic_function_t::e_rtrn_string : | |
17309 | return local_data().string_function_store.add(function_name,function); | |
17310 | ||
17311 | case generic_function_t::e_rtrn_overload : | |
17312 | return local_data().overload_function_store.add(function_name,function); | |
17313 | } | |
17314 | ||
17315 | return false; | |
17316 | } | |
17317 | ||
17318 | template <std::size_t N> | |
17319 | inline bool add_vector(const std::string& vector_name, T (&v)[N]) | |
17320 | { | |
17321 | if (!valid()) | |
17322 | return false; | |
17323 | else if (!valid_symbol(vector_name)) | |
17324 | return false; | |
17325 | else if (symbol_exists(vector_name)) | |
17326 | return false; | |
17327 | else | |
17328 | return local_data().vector_store.add(vector_name,v); | |
17329 | } | |
17330 | ||
17331 | inline bool add_vector(const std::string& vector_name, T* v, const std::size_t& v_size) | |
17332 | { | |
17333 | if (!valid()) | |
17334 | return false; | |
17335 | else if (!valid_symbol(vector_name)) | |
17336 | return false; | |
17337 | else if (symbol_exists(vector_name)) | |
17338 | return false; | |
17339 | else if (0 == v_size) | |
17340 | return false; | |
17341 | else | |
17342 | return local_data().vector_store.add(vector_name, v, v_size); | |
17343 | } | |
17344 | ||
17345 | template <typename Allocator> | |
17346 | inline bool add_vector(const std::string& vector_name, std::vector<T,Allocator>& v) | |
17347 | { | |
17348 | if (!valid()) | |
17349 | return false; | |
17350 | else if (!valid_symbol(vector_name)) | |
17351 | return false; | |
17352 | else if (symbol_exists(vector_name)) | |
17353 | return false; | |
17354 | else if (0 == v.size()) | |
17355 | return false; | |
17356 | else | |
17357 | return local_data().vector_store.add(vector_name,v); | |
17358 | } | |
17359 | ||
17360 | inline bool add_vector(const std::string& vector_name, exprtk::vector_view<T>& v) | |
17361 | { | |
17362 | if (!valid()) | |
17363 | return false; | |
17364 | else if (!valid_symbol(vector_name)) | |
17365 | return false; | |
17366 | else if (symbol_exists(vector_name)) | |
17367 | return false; | |
17368 | else if (0 == v.size()) | |
17369 | return false; | |
17370 | else | |
17371 | return local_data().vector_store.add(vector_name,v); | |
17372 | } | |
17373 | ||
17374 | inline bool remove_variable(const std::string& variable_name, const bool delete_node = true) | |
17375 | { | |
17376 | if (!valid()) | |
17377 | return false; | |
17378 | else | |
17379 | return local_data().variable_store.remove(variable_name, delete_node); | |
17380 | } | |
17381 | ||
17382 | #ifndef exprtk_disable_string_capabilities | |
17383 | inline bool remove_stringvar(const std::string& string_name) | |
17384 | { | |
17385 | if (!valid()) | |
17386 | return false; | |
17387 | else | |
17388 | return local_data().stringvar_store.remove(string_name); | |
17389 | } | |
17390 | #endif | |
17391 | ||
17392 | inline bool remove_function(const std::string& function_name) | |
17393 | { | |
17394 | if (!valid()) | |
17395 | return false; | |
17396 | else | |
17397 | return local_data().function_store.remove(function_name); | |
17398 | } | |
17399 | ||
17400 | inline bool remove_vararg_function(const std::string& vararg_function_name) | |
17401 | { | |
17402 | if (!valid()) | |
17403 | return false; | |
17404 | else | |
17405 | return local_data().vararg_function_store.remove(vararg_function_name); | |
17406 | } | |
17407 | ||
17408 | inline bool remove_vector(const std::string& vector_name) | |
17409 | { | |
17410 | if (!valid()) | |
17411 | return false; | |
17412 | else | |
17413 | return local_data().vector_store.remove(vector_name); | |
17414 | } | |
17415 | ||
17416 | inline bool add_constants() | |
17417 | { | |
17418 | return add_pi () && | |
17419 | add_epsilon () && | |
17420 | add_infinity() ; | |
17421 | } | |
17422 | ||
17423 | inline bool add_pi() | |
17424 | { | |
17425 | const typename details::numeric::details::number_type<T>::type num_type; | |
17426 | static const T local_pi = details::numeric::details::const_pi_impl<T>(num_type); | |
17427 | return add_constant("pi",local_pi); | |
17428 | } | |
17429 | ||
17430 | inline bool add_epsilon() | |
17431 | { | |
17432 | static const T local_epsilon = details::numeric::details::epsilon_type<T>::value(); | |
17433 | return add_constant("epsilon",local_epsilon); | |
17434 | } | |
17435 | ||
17436 | inline bool add_infinity() | |
17437 | { | |
17438 | static const T local_infinity = std::numeric_limits<T>::infinity(); | |
17439 | return add_constant("inf",local_infinity); | |
17440 | } | |
17441 | ||
17442 | template <typename Package> | |
17443 | inline bool add_package(Package& package) | |
17444 | { | |
17445 | return package.register_package(*this); | |
17446 | } | |
17447 | ||
17448 | template <typename Allocator, | |
17449 | template <typename, typename> class Sequence> | |
17450 | inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const | |
17451 | { | |
17452 | if (!valid()) | |
17453 | return 0; | |
17454 | else | |
17455 | return local_data().variable_store.get_list(vlist); | |
17456 | } | |
17457 | ||
17458 | template <typename Allocator, | |
17459 | template <typename, typename> class Sequence> | |
17460 | inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const | |
17461 | { | |
17462 | if (!valid()) | |
17463 | return 0; | |
17464 | else | |
17465 | return local_data().variable_store.get_list(vlist); | |
17466 | } | |
17467 | ||
17468 | #ifndef exprtk_disable_string_capabilities | |
17469 | template <typename Allocator, | |
17470 | template <typename, typename> class Sequence> | |
17471 | inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const | |
17472 | { | |
17473 | if (!valid()) | |
17474 | return 0; | |
17475 | else | |
17476 | return local_data().stringvar_store.get_list(svlist); | |
17477 | } | |
17478 | ||
17479 | template <typename Allocator, | |
17480 | template <typename, typename> class Sequence> | |
17481 | inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const | |
17482 | { | |
17483 | if (!valid()) | |
17484 | return 0; | |
17485 | else | |
17486 | return local_data().stringvar_store.get_list(svlist); | |
17487 | } | |
17488 | #endif | |
17489 | ||
17490 | template <typename Allocator, | |
17491 | template <typename, typename> class Sequence> | |
17492 | inline std::size_t get_vector_list(Sequence<std::string,Allocator>& vlist) const | |
17493 | { | |
17494 | if (!valid()) | |
17495 | return 0; | |
17496 | else | |
17497 | return local_data().vector_store.get_list(vlist); | |
17498 | } | |
17499 | ||
17500 | inline bool symbol_exists(const std::string& symbol_name, const bool check_reserved_symb = true) const | |
17501 | { | |
17502 | /* | |
17503 | Function will return true if symbol_name exists as either a | |
17504 | reserved symbol, variable, stringvar, vector or function name | |
17505 | in any of the type stores. | |
17506 | */ | |
17507 | if (!valid()) | |
17508 | return false; | |
17509 | else if (local_data().variable_store.symbol_exists(symbol_name)) | |
17510 | return true; | |
17511 | #ifndef exprtk_disable_string_capabilities | |
17512 | else if (local_data().stringvar_store.symbol_exists(symbol_name)) | |
17513 | return true; | |
17514 | #endif | |
17515 | else if (local_data().vector_store.symbol_exists(symbol_name)) | |
17516 | return true; | |
17517 | else if (local_data().function_store.symbol_exists(symbol_name)) | |
17518 | return true; | |
17519 | else if (check_reserved_symb && local_data().is_reserved_symbol(symbol_name)) | |
17520 | return true; | |
17521 | else | |
17522 | return false; | |
17523 | } | |
17524 | ||
17525 | inline bool is_variable(const std::string& variable_name) const | |
17526 | { | |
17527 | if (!valid()) | |
17528 | return false; | |
17529 | else | |
17530 | return local_data().variable_store.symbol_exists(variable_name); | |
17531 | } | |
17532 | ||
17533 | #ifndef exprtk_disable_string_capabilities | |
17534 | inline bool is_stringvar(const std::string& stringvar_name) const | |
17535 | { | |
17536 | if (!valid()) | |
17537 | return false; | |
17538 | else | |
17539 | return local_data().stringvar_store.symbol_exists(stringvar_name); | |
17540 | } | |
17541 | ||
17542 | inline bool is_conststr_stringvar(const std::string& symbol_name) const | |
17543 | { | |
17544 | if (!valid()) | |
17545 | return false; | |
17546 | else if (!valid_symbol(symbol_name)) | |
17547 | return false; | |
17548 | else if (!local_data().stringvar_store.symbol_exists(symbol_name)) | |
17549 | return false; | |
17550 | ||
17551 | return ( | |
17552 | local_data().stringvar_store.symbol_exists(symbol_name) || | |
17553 | local_data().stringvar_store.is_constant (symbol_name) | |
17554 | ); | |
17555 | } | |
17556 | #endif | |
17557 | ||
17558 | inline bool is_function(const std::string& function_name) const | |
17559 | { | |
17560 | if (!valid()) | |
17561 | return false; | |
17562 | else | |
17563 | return local_data().function_store.symbol_exists(function_name); | |
17564 | } | |
17565 | ||
17566 | inline bool is_vararg_function(const std::string& vararg_function_name) const | |
17567 | { | |
17568 | if (!valid()) | |
17569 | return false; | |
17570 | else | |
17571 | return local_data().vararg_function_store.symbol_exists(vararg_function_name); | |
17572 | } | |
17573 | ||
17574 | inline bool is_vector(const std::string& vector_name) const | |
17575 | { | |
17576 | if (!valid()) | |
17577 | return false; | |
17578 | else | |
17579 | return local_data().vector_store.symbol_exists(vector_name); | |
17580 | } | |
17581 | ||
17582 | inline std::string get_variable_name(const expression_ptr& ptr) const | |
17583 | { | |
17584 | return local_data().variable_store.entity_name(ptr); | |
17585 | } | |
17586 | ||
17587 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const | |
17588 | { | |
17589 | return local_data().vector_store.entity_name(ptr); | |
17590 | } | |
17591 | ||
17592 | #ifndef exprtk_disable_string_capabilities | |
17593 | inline std::string get_stringvar_name(const expression_ptr& ptr) const | |
17594 | { | |
17595 | return local_data().stringvar_store.entity_name(ptr); | |
17596 | } | |
17597 | ||
17598 | inline std::string get_conststr_stringvar_name(const expression_ptr& ptr) const | |
17599 | { | |
17600 | return local_data().stringvar_store.entity_name(ptr); | |
17601 | } | |
17602 | #endif | |
17603 | ||
17604 | inline bool valid() const | |
17605 | { | |
17606 | // Symbol table sanity check. | |
17607 | return control_block_ && control_block_->data_; | |
17608 | } | |
17609 | ||
17610 | inline void load_from(const symbol_table<T>& st) | |
17611 | { | |
17612 | { | |
17613 | std::vector<std::string> name_list; | |
17614 | ||
17615 | st.local_data().function_store.get_list(name_list); | |
17616 | ||
17617 | if (!name_list.empty()) | |
17618 | { | |
17619 | for (std::size_t i = 0; i < name_list.size(); ++i) | |
17620 | { | |
17621 | exprtk::ifunction<T>& ifunc = *st.get_function(name_list[i]); | |
17622 | add_function(name_list[i],ifunc); | |
17623 | } | |
17624 | } | |
17625 | } | |
17626 | ||
17627 | { | |
17628 | std::vector<std::string> name_list; | |
17629 | ||
17630 | st.local_data().vararg_function_store.get_list(name_list); | |
17631 | ||
17632 | if (!name_list.empty()) | |
17633 | { | |
17634 | for (std::size_t i = 0; i < name_list.size(); ++i) | |
17635 | { | |
17636 | exprtk::ivararg_function<T>& ivafunc = *st.get_vararg_function(name_list[i]); | |
17637 | add_function(name_list[i],ivafunc); | |
17638 | } | |
17639 | } | |
17640 | } | |
17641 | ||
17642 | { | |
17643 | std::vector<std::string> name_list; | |
17644 | ||
17645 | st.local_data().generic_function_store.get_list(name_list); | |
17646 | ||
17647 | if (!name_list.empty()) | |
17648 | { | |
17649 | for (std::size_t i = 0; i < name_list.size(); ++i) | |
17650 | { | |
17651 | exprtk::igeneric_function<T>& ifunc = *st.get_generic_function(name_list[i]); | |
17652 | add_function(name_list[i],ifunc); | |
17653 | } | |
17654 | } | |
17655 | } | |
17656 | ||
17657 | { | |
17658 | std::vector<std::string> name_list; | |
17659 | ||
17660 | st.local_data().string_function_store.get_list(name_list); | |
17661 | ||
17662 | if (!name_list.empty()) | |
17663 | { | |
17664 | for (std::size_t i = 0; i < name_list.size(); ++i) | |
17665 | { | |
17666 | exprtk::igeneric_function<T>& ifunc = *st.get_string_function(name_list[i]); | |
17667 | add_function(name_list[i],ifunc); | |
17668 | } | |
17669 | } | |
17670 | } | |
17671 | ||
17672 | { | |
17673 | std::vector<std::string> name_list; | |
17674 | ||
17675 | st.local_data().overload_function_store.get_list(name_list); | |
17676 | ||
17677 | if (!name_list.empty()) | |
17678 | { | |
17679 | for (std::size_t i = 0; i < name_list.size(); ++i) | |
17680 | { | |
17681 | exprtk::igeneric_function<T>& ifunc = *st.get_overload_function(name_list[i]); | |
17682 | add_function(name_list[i],ifunc); | |
17683 | } | |
17684 | } | |
17685 | } | |
17686 | } | |
17687 | ||
17688 | private: | |
17689 | ||
17690 | inline bool valid_symbol(const std::string& symbol, const bool check_reserved_symb = true) const | |
17691 | { | |
17692 | if (symbol.empty()) | |
17693 | return false; | |
17694 | else if (!details::is_letter(symbol[0])) | |
17695 | return false; | |
17696 | else if (symbol.size() > 1) | |
17697 | { | |
17698 | for (std::size_t i = 1; i < symbol.size(); ++i) | |
17699 | { | |
17700 | if ( | |
17701 | !details::is_letter_or_digit(symbol[i]) && | |
17702 | ('_' != symbol[i]) | |
17703 | ) | |
17704 | { | |
17705 | if (('.' == symbol[i]) && (i < (symbol.size() - 1))) | |
17706 | continue; | |
17707 | else | |
17708 | return false; | |
17709 | } | |
17710 | } | |
17711 | } | |
17712 | ||
17713 | return (check_reserved_symb) ? (!local_data().is_reserved_symbol(symbol)) : true; | |
17714 | } | |
17715 | ||
17716 | inline bool valid_function(const std::string& symbol) const | |
17717 | { | |
17718 | if (symbol.empty()) | |
17719 | return false; | |
17720 | else if (!details::is_letter(symbol[0])) | |
17721 | return false; | |
17722 | else if (symbol.size() > 1) | |
17723 | { | |
17724 | for (std::size_t i = 1; i < symbol.size(); ++i) | |
17725 | { | |
17726 | if ( | |
17727 | !details::is_letter_or_digit(symbol[i]) && | |
17728 | ('_' != symbol[i]) | |
17729 | ) | |
17730 | { | |
17731 | if (('.' == symbol[i]) && (i < (symbol.size() - 1))) | |
17732 | continue; | |
17733 | else | |
17734 | return false; | |
17735 | } | |
17736 | } | |
17737 | } | |
17738 | ||
17739 | return true; | |
17740 | } | |
17741 | ||
17742 | typedef typename control_block::st_data local_data_t; | |
17743 | ||
17744 | inline local_data_t& local_data() | |
17745 | { | |
17746 | return *(control_block_->data_); | |
17747 | } | |
17748 | ||
17749 | inline const local_data_t& local_data() const | |
17750 | { | |
17751 | return *(control_block_->data_); | |
17752 | } | |
17753 | ||
17754 | control_block* control_block_; | |
17755 | ||
17756 | friend class parser<T>; | |
17757 | }; | |
17758 | ||
17759 | template <typename T> | |
17760 | class function_compositor; | |
17761 | ||
17762 | template <typename T> | |
17763 | class expression | |
17764 | { | |
17765 | private: | |
17766 | ||
17767 | typedef details::expression_node<T>* expression_ptr; | |
17768 | typedef details::vector_holder<T>* vector_holder_ptr; | |
17769 | typedef std::vector<symbol_table<T> > symtab_list_t; | |
17770 | ||
17771 | struct control_block | |
17772 | { | |
17773 | enum data_type | |
17774 | { | |
17775 | e_unknown , | |
17776 | e_expr , | |
17777 | e_vecholder, | |
17778 | e_data , | |
17779 | e_vecdata , | |
17780 | e_string | |
17781 | }; | |
17782 | ||
17783 | struct data_pack | |
17784 | { | |
17785 | data_pack() | |
17786 | : pointer(0), | |
17787 | type(e_unknown), | |
17788 | size(0) | |
17789 | {} | |
17790 | ||
17791 | data_pack(void* ptr, const data_type dt, const std::size_t sz = 0) | |
17792 | : pointer(ptr), | |
17793 | type(dt), | |
17794 | size(sz) | |
17795 | {} | |
17796 | ||
17797 | void* pointer; | |
17798 | data_type type; | |
17799 | std::size_t size; | |
17800 | }; | |
17801 | ||
17802 | typedef std::vector<data_pack> local_data_list_t; | |
17803 | typedef results_context<T> results_context_t; | |
17804 | ||
17805 | control_block() | |
17806 | : ref_count(0), | |
17807 | expr (0), | |
17808 | results (0), | |
17809 | retinv_null(false), | |
17810 | return_invoked(&retinv_null) | |
17811 | {} | |
17812 | ||
17813 | explicit control_block(expression_ptr e) | |
17814 | : ref_count(1), | |
17815 | expr (e), | |
17816 | results (0), | |
17817 | retinv_null(false), | |
17818 | return_invoked(&retinv_null) | |
17819 | {} | |
17820 | ||
17821 | ~control_block() | |
17822 | { | |
17823 | if (expr && details::branch_deletable(expr)) | |
17824 | { | |
17825 | destroy_node(expr); | |
17826 | } | |
17827 | ||
17828 | if (!local_data_list.empty()) | |
17829 | { | |
17830 | for (std::size_t i = 0; i < local_data_list.size(); ++i) | |
17831 | { | |
17832 | switch (local_data_list[i].type) | |
17833 | { | |
17834 | case e_expr : delete reinterpret_cast<expression_ptr>(local_data_list[i].pointer); | |
17835 | break; | |
17836 | ||
17837 | case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); | |
17838 | break; | |
17839 | ||
17840 | case e_data : delete (T*)(local_data_list[i].pointer); | |
17841 | break; | |
17842 | ||
17843 | case e_vecdata : delete [] (T*)(local_data_list[i].pointer); | |
17844 | break; | |
17845 | ||
17846 | case e_string : delete (std::string*)(local_data_list[i].pointer); | |
17847 | break; | |
17848 | ||
17849 | default : break; | |
17850 | } | |
17851 | } | |
17852 | } | |
17853 | ||
17854 | if (results) | |
17855 | { | |
17856 | delete results; | |
17857 | } | |
17858 | } | |
17859 | ||
17860 | static inline control_block* create(expression_ptr e) | |
17861 | { | |
17862 | return new control_block(e); | |
17863 | } | |
17864 | ||
17865 | static inline void destroy(control_block*& cntrl_blck) | |
17866 | { | |
17867 | if (cntrl_blck) | |
17868 | { | |
17869 | if ( | |
17870 | (0 != cntrl_blck->ref_count) && | |
17871 | (0 == --cntrl_blck->ref_count) | |
17872 | ) | |
17873 | { | |
17874 | delete cntrl_blck; | |
17875 | } | |
17876 | ||
17877 | cntrl_blck = 0; | |
17878 | } | |
17879 | } | |
17880 | ||
17881 | std::size_t ref_count; | |
17882 | expression_ptr expr; | |
17883 | local_data_list_t local_data_list; | |
17884 | results_context_t* results; | |
17885 | bool retinv_null; | |
17886 | bool* return_invoked; | |
17887 | ||
17888 | friend class function_compositor<T>; | |
17889 | }; | |
17890 | ||
17891 | public: | |
17892 | ||
17893 | expression() | |
17894 | : control_block_(0) | |
17895 | { | |
17896 | set_expression(new details::null_node<T>()); | |
17897 | } | |
17898 | ||
17899 | expression(const expression<T>& e) | |
17900 | : control_block_ (e.control_block_ ), | |
17901 | symbol_table_list_(e.symbol_table_list_) | |
17902 | { | |
17903 | control_block_->ref_count++; | |
17904 | } | |
17905 | ||
17906 | explicit expression(const symbol_table<T>& symbol_table) | |
17907 | : control_block_(0) | |
17908 | { | |
17909 | set_expression(new details::null_node<T>()); | |
17910 | symbol_table_list_.push_back(symbol_table); | |
17911 | } | |
17912 | ||
17913 | inline expression<T>& operator=(const expression<T>& e) | |
17914 | { | |
17915 | if (this != &e) | |
17916 | { | |
17917 | if (control_block_) | |
17918 | { | |
17919 | if ( | |
17920 | (0 != control_block_->ref_count) && | |
17921 | (0 == --control_block_->ref_count) | |
17922 | ) | |
17923 | { | |
17924 | delete control_block_; | |
17925 | } | |
17926 | ||
17927 | control_block_ = 0; | |
17928 | } | |
17929 | ||
17930 | control_block_ = e.control_block_; | |
17931 | control_block_->ref_count++; | |
17932 | symbol_table_list_ = e.symbol_table_list_; | |
17933 | } | |
17934 | ||
17935 | return *this; | |
17936 | } | |
17937 | ||
17938 | inline bool operator==(const expression<T>& e) const | |
17939 | { | |
17940 | return (this == &e); | |
17941 | } | |
17942 | ||
17943 | inline bool operator!() const | |
17944 | { | |
17945 | return ( | |
17946 | (0 == control_block_ ) || | |
17947 | (0 == control_block_->expr) | |
17948 | ); | |
17949 | } | |
17950 | ||
17951 | inline expression<T>& release() | |
17952 | { | |
17953 | control_block::destroy(control_block_); | |
17954 | ||
17955 | return (*this); | |
17956 | } | |
17957 | ||
17958 | ~expression() | |
17959 | { | |
17960 | control_block::destroy(control_block_); | |
17961 | } | |
17962 | ||
17963 | inline T value() const | |
17964 | { | |
17965 | return control_block_->expr->value(); | |
17966 | } | |
17967 | ||
17968 | inline T operator() () const | |
17969 | { | |
17970 | return value(); | |
17971 | } | |
17972 | ||
17973 | inline operator T() const | |
17974 | { | |
17975 | return value(); | |
17976 | } | |
17977 | ||
17978 | inline operator bool() const | |
17979 | { | |
17980 | return details::is_true(value()); | |
17981 | } | |
17982 | ||
17983 | inline void register_symbol_table(symbol_table<T>& st) | |
17984 | { | |
17985 | symbol_table_list_.push_back(st); | |
17986 | } | |
17987 | ||
17988 | inline const symbol_table<T>& get_symbol_table(const std::size_t& index = 0) const | |
17989 | { | |
17990 | return symbol_table_list_[index]; | |
17991 | } | |
17992 | ||
17993 | inline symbol_table<T>& get_symbol_table(const std::size_t& index = 0) | |
17994 | { | |
17995 | return symbol_table_list_[index]; | |
17996 | } | |
17997 | ||
17998 | typedef results_context<T> results_context_t; | |
17999 | ||
18000 | inline const results_context_t& results() const | |
18001 | { | |
18002 | if (control_block_->results) | |
18003 | return (*control_block_->results); | |
18004 | else | |
18005 | { | |
18006 | static const results_context_t null_results; | |
18007 | return null_results; | |
18008 | } | |
18009 | } | |
18010 | ||
18011 | inline bool return_invoked() const | |
18012 | { | |
18013 | return (*control_block_->return_invoked); | |
18014 | } | |
18015 | ||
18016 | private: | |
18017 | ||
18018 | inline symtab_list_t get_symbol_table_list() const | |
18019 | { | |
18020 | return symbol_table_list_; | |
18021 | } | |
18022 | ||
18023 | inline void set_expression(const expression_ptr expr) | |
18024 | { | |
18025 | if (expr) | |
18026 | { | |
18027 | if (control_block_) | |
18028 | { | |
18029 | if (0 == --control_block_->ref_count) | |
18030 | { | |
18031 | delete control_block_; | |
18032 | } | |
18033 | } | |
18034 | ||
18035 | control_block_ = control_block::create(expr); | |
18036 | } | |
18037 | } | |
18038 | ||
18039 | inline void register_local_var(expression_ptr expr) | |
18040 | { | |
18041 | if (expr) | |
18042 | { | |
18043 | if (control_block_) | |
18044 | { | |
18045 | control_block_-> | |
18046 | local_data_list.push_back( | |
18047 | typename expression<T>::control_block:: | |
18048 | data_pack(reinterpret_cast<void*>(expr), | |
18049 | control_block::e_expr)); | |
18050 | } | |
18051 | } | |
18052 | } | |
18053 | ||
18054 | inline void register_local_var(vector_holder_ptr vec_holder) | |
18055 | { | |
18056 | if (vec_holder) | |
18057 | { | |
18058 | if (control_block_) | |
18059 | { | |
18060 | control_block_-> | |
18061 | local_data_list.push_back( | |
18062 | typename expression<T>::control_block:: | |
18063 | data_pack(reinterpret_cast<void*>(vec_holder), | |
18064 | control_block::e_vecholder)); | |
18065 | } | |
18066 | } | |
18067 | } | |
18068 | ||
18069 | inline void register_local_data(void* data, const std::size_t& size = 0, const std::size_t data_mode = 0) | |
18070 | { | |
18071 | if (data) | |
18072 | { | |
18073 | if (control_block_) | |
18074 | { | |
18075 | typename control_block::data_type dt = control_block::e_data; | |
18076 | ||
18077 | switch (data_mode) | |
18078 | { | |
18079 | case 0 : dt = control_block::e_data; break; | |
18080 | case 1 : dt = control_block::e_vecdata; break; | |
18081 | case 2 : dt = control_block::e_string; break; | |
18082 | } | |
18083 | ||
18084 | control_block_-> | |
18085 | local_data_list.push_back( | |
18086 | typename expression<T>::control_block:: | |
18087 | data_pack(reinterpret_cast<void*>(data), dt, size)); | |
18088 | } | |
18089 | } | |
18090 | } | |
18091 | ||
18092 | inline const typename control_block::local_data_list_t& local_data_list() | |
18093 | { | |
18094 | if (control_block_) | |
18095 | { | |
18096 | return control_block_->local_data_list; | |
18097 | } | |
18098 | else | |
18099 | { | |
18100 | static typename control_block::local_data_list_t null_local_data_list; | |
18101 | return null_local_data_list; | |
18102 | } | |
18103 | } | |
18104 | ||
18105 | inline void register_return_results(results_context_t* rc) | |
18106 | { | |
18107 | if (control_block_ && rc) | |
18108 | { | |
18109 | control_block_->results = rc; | |
18110 | } | |
18111 | } | |
18112 | ||
18113 | inline void set_retinvk(bool* retinvk_ptr) | |
18114 | { | |
18115 | if (control_block_) | |
18116 | { | |
18117 | control_block_->return_invoked = retinvk_ptr; | |
18118 | } | |
18119 | } | |
18120 | ||
18121 | control_block* control_block_; | |
18122 | symtab_list_t symbol_table_list_; | |
18123 | ||
18124 | friend class parser<T>; | |
18125 | friend class expression_helper<T>; | |
18126 | friend class function_compositor<T>; | |
18127 | }; | |
18128 | ||
18129 | template <typename T> | |
18130 | class expression_helper | |
18131 | { | |
18132 | public: | |
18133 | ||
18134 | static inline bool is_constant(const expression<T>& expr) | |
18135 | { | |
18136 | return details::is_constant_node(expr.control_block_->expr); | |
18137 | } | |
18138 | ||
18139 | static inline bool is_variable(const expression<T>& expr) | |
18140 | { | |
18141 | return details::is_variable_node(expr.control_block_->expr); | |
18142 | } | |
18143 | ||
18144 | static inline bool is_unary(const expression<T>& expr) | |
18145 | { | |
18146 | return details::is_unary_node(expr.control_block_->expr); | |
18147 | } | |
18148 | ||
18149 | static inline bool is_binary(const expression<T>& expr) | |
18150 | { | |
18151 | return details::is_binary_node(expr.control_block_->expr); | |
18152 | } | |
18153 | ||
18154 | static inline bool is_function(const expression<T>& expr) | |
18155 | { | |
18156 | return details::is_function(expr.control_block_->expr); | |
18157 | } | |
18158 | ||
18159 | static inline bool is_null(const expression<T>& expr) | |
18160 | { | |
18161 | return details::is_null_node(expr.control_block_->expr); | |
18162 | } | |
18163 | }; | |
18164 | ||
18165 | template <typename T> | |
18166 | inline bool is_valid(const expression<T>& expr) | |
18167 | { | |
18168 | return !expression_helper<T>::is_null(expr); | |
18169 | } | |
18170 | ||
18171 | namespace parser_error | |
18172 | { | |
18173 | enum error_mode | |
18174 | { | |
18175 | e_unknown = 0, | |
18176 | e_syntax = 1, | |
18177 | e_token = 2, | |
18178 | e_numeric = 4, | |
18179 | e_symtab = 5, | |
18180 | e_lexer = 6, | |
18181 | e_helper = 7 | |
18182 | }; | |
18183 | ||
18184 | struct type | |
18185 | { | |
18186 | type() | |
18187 | : mode(parser_error::e_unknown), | |
18188 | line_no (0), | |
18189 | column_no(0) | |
18190 | {} | |
18191 | ||
18192 | lexer::token token; | |
18193 | error_mode mode; | |
18194 | std::string diagnostic; | |
18195 | std::string src_location; | |
18196 | std::string error_line; | |
18197 | std::size_t line_no; | |
18198 | std::size_t column_no; | |
18199 | }; | |
18200 | ||
18201 | inline type make_error(const error_mode mode, | |
18202 | const std::string& diagnostic = "", | |
18203 | const std::string& src_location = "") | |
18204 | { | |
18205 | type t; | |
18206 | t.mode = mode; | |
18207 | t.token.type = lexer::token::e_error; | |
18208 | t.diagnostic = diagnostic; | |
18209 | t.src_location = src_location; | |
18210 | exprtk_debug(("%s\n",diagnostic .c_str())); | |
18211 | return t; | |
18212 | } | |
18213 | ||
18214 | inline type make_error(const error_mode mode, | |
18215 | const lexer::token& tk, | |
18216 | const std::string& diagnostic = "", | |
18217 | const std::string& src_location = "") | |
18218 | { | |
18219 | type t; | |
18220 | t.mode = mode; | |
18221 | t.token = tk; | |
18222 | t.diagnostic = diagnostic; | |
18223 | t.src_location = src_location; | |
18224 | exprtk_debug(("%s\n",diagnostic .c_str())); | |
18225 | return t; | |
18226 | } | |
18227 | ||
18228 | inline std::string to_str(error_mode mode) | |
18229 | { | |
18230 | switch (mode) | |
18231 | { | |
18232 | case e_unknown : return std::string("Unknown Error"); | |
18233 | case e_syntax : return std::string("Syntax Error" ); | |
18234 | case e_token : return std::string("Token Error" ); | |
18235 | case e_numeric : return std::string("Numeric Error"); | |
18236 | case e_symtab : return std::string("Symbol Error" ); | |
18237 | case e_lexer : return std::string("Lexer Error" ); | |
18238 | case e_helper : return std::string("Helper Error" ); | |
18239 | default : return std::string("Unknown Error"); | |
18240 | } | |
18241 | } | |
18242 | ||
18243 | inline bool update_error(type& error, const std::string& expression) | |
18244 | { | |
18245 | if ( | |
18246 | expression.empty() || | |
18247 | (error.token.position > expression.size()) || | |
18248 | (std::numeric_limits<std::size_t>::max() == error.token.position) | |
18249 | ) | |
18250 | { | |
18251 | return false; | |
18252 | } | |
18253 | ||
18254 | std::size_t error_line_start = 0; | |
18255 | ||
18256 | for (std::size_t i = error.token.position; i > 0; --i) | |
18257 | { | |
18258 | const details::char_t c = expression[i]; | |
18259 | ||
18260 | if (('\n' == c) || ('\r' == c)) | |
18261 | { | |
18262 | error_line_start = i + 1; | |
18263 | break; | |
18264 | } | |
18265 | } | |
18266 | ||
18267 | std::size_t next_nl_position = std::min(expression.size(), | |
18268 | expression.find_first_of('\n',error.token.position + 1)); | |
18269 | ||
18270 | error.column_no = error.token.position - error_line_start; | |
18271 | error.error_line = expression.substr(error_line_start, | |
18272 | next_nl_position - error_line_start); | |
18273 | ||
18274 | error.line_no = 0; | |
18275 | ||
18276 | for (std::size_t i = 0; i < next_nl_position; ++i) | |
18277 | { | |
18278 | if ('\n' == expression[i]) | |
18279 | ++error.line_no; | |
18280 | } | |
18281 | ||
18282 | return true; | |
18283 | } | |
18284 | ||
18285 | inline void dump_error(const type& error) | |
18286 | { | |
18287 | printf("Position: %02d Type: [%s] Msg: %s\n", | |
18288 | static_cast<int>(error.token.position), | |
18289 | exprtk::parser_error::to_str(error.mode).c_str(), | |
18290 | error.diagnostic.c_str()); | |
18291 | } | |
18292 | } | |
18293 | ||
18294 | namespace details | |
18295 | { | |
18296 | template <typename Parser> | |
18297 | inline void disable_type_checking(Parser& p) | |
18298 | { | |
18299 | p.state_.type_check_enabled = false; | |
18300 | } | |
18301 | } | |
18302 | ||
18303 | template <typename T> | |
18304 | class parser : public lexer::parser_helper | |
18305 | { | |
18306 | private: | |
18307 | ||
18308 | enum precedence_level | |
18309 | { | |
18310 | e_level00, | |
18311 | e_level01, | |
18312 | e_level02, | |
18313 | e_level03, | |
18314 | e_level04, | |
18315 | e_level05, | |
18316 | e_level06, | |
18317 | e_level07, | |
18318 | e_level08, | |
18319 | e_level09, | |
18320 | e_level10, | |
18321 | e_level11, | |
18322 | e_level12, | |
18323 | e_level13, | |
18324 | e_level14 | |
18325 | }; | |
18326 | ||
18327 | typedef const T& cref_t; | |
18328 | typedef const T const_t; | |
18329 | typedef ifunction <T> F; | |
18330 | typedef ivararg_function <T> VAF; | |
18331 | typedef igeneric_function <T> GF; | |
18332 | typedef ifunction <T> ifunction_t; | |
18333 | typedef ivararg_function <T> ivararg_function_t; | |
18334 | typedef igeneric_function <T> igeneric_function_t; | |
18335 | typedef details::expression_node <T> expression_node_t; | |
18336 | typedef details::literal_node <T> literal_node_t; | |
18337 | typedef details::unary_node <T> unary_node_t; | |
18338 | typedef details::binary_node <T> binary_node_t; | |
18339 | typedef details::trinary_node <T> trinary_node_t; | |
18340 | typedef details::quaternary_node <T> quaternary_node_t; | |
18341 | typedef details::conditional_node<T> conditional_node_t; | |
18342 | typedef details::cons_conditional_node<T> cons_conditional_node_t; | |
18343 | typedef details::while_loop_node <T> while_loop_node_t; | |
18344 | typedef details::repeat_until_loop_node<T> repeat_until_loop_node_t; | |
18345 | typedef details::for_loop_node <T> for_loop_node_t; | |
18346 | #ifndef exprtk_disable_break_continue | |
18347 | typedef details::while_loop_bc_node <T> while_loop_bc_node_t; | |
18348 | typedef details::repeat_until_loop_bc_node<T> repeat_until_loop_bc_node_t; | |
18349 | typedef details::for_loop_bc_node<T> for_loop_bc_node_t; | |
18350 | #endif | |
18351 | typedef details::switch_node <T> switch_node_t; | |
18352 | typedef details::variable_node <T> variable_node_t; | |
18353 | typedef details::vector_elem_node<T> vector_elem_node_t; | |
18354 | typedef details::rebasevector_elem_node<T> rebasevector_elem_node_t; | |
18355 | typedef details::rebasevector_celem_node<T> rebasevector_celem_node_t; | |
18356 | typedef details::vector_node <T> vector_node_t; | |
18357 | typedef details::range_pack <T> range_t; | |
18358 | #ifndef exprtk_disable_string_capabilities | |
18359 | typedef details::stringvar_node <T> stringvar_node_t; | |
18360 | typedef details::string_literal_node<T> string_literal_node_t; | |
18361 | typedef details::string_range_node <T> string_range_node_t; | |
18362 | typedef details::const_string_range_node<T> const_string_range_node_t; | |
18363 | typedef details::generic_string_range_node<T> generic_string_range_node_t; | |
18364 | typedef details::string_concat_node <T> string_concat_node_t; | |
18365 | typedef details::assignment_string_node<T> assignment_string_node_t; | |
18366 | typedef details::assignment_string_range_node<T> assignment_string_range_node_t; | |
18367 | typedef details::conditional_string_node<T> conditional_string_node_t; | |
18368 | typedef details::cons_conditional_str_node<T> cons_conditional_str_node_t; | |
18369 | #endif | |
18370 | typedef details::assignment_node<T> assignment_node_t; | |
18371 | typedef details::assignment_vec_elem_node <T> assignment_vec_elem_node_t; | |
18372 | typedef details::assignment_rebasevec_elem_node <T> assignment_rebasevec_elem_node_t; | |
18373 | typedef details::assignment_rebasevec_celem_node<T> assignment_rebasevec_celem_node_t; | |
18374 | typedef details::assignment_vec_node <T> assignment_vec_node_t; | |
18375 | typedef details::assignment_vecvec_node <T> assignment_vecvec_node_t; | |
18376 | typedef details::scand_node<T> scand_node_t; | |
18377 | typedef details::scor_node<T> scor_node_t; | |
18378 | typedef lexer::token token_t; | |
18379 | typedef expression_node_t* expression_node_ptr; | |
18380 | typedef expression<T> expression_t; | |
18381 | typedef symbol_table<T> symbol_table_t; | |
18382 | typedef typename expression<T>::symtab_list_t symbol_table_list_t; | |
18383 | typedef details::vector_holder<T>* vector_holder_ptr; | |
18384 | ||
18385 | typedef typename details::functor_t<T> functor_t; | |
18386 | typedef typename functor_t::qfunc_t quaternary_functor_t; | |
18387 | typedef typename functor_t::tfunc_t trinary_functor_t; | |
18388 | typedef typename functor_t::bfunc_t binary_functor_t; | |
18389 | typedef typename functor_t::ufunc_t unary_functor_t; | |
18390 | ||
18391 | typedef details::operator_type operator_t; | |
18392 | ||
18393 | typedef std::map<operator_t, unary_functor_t> unary_op_map_t; | |
18394 | typedef std::map<operator_t, binary_functor_t> binary_op_map_t; | |
18395 | typedef std::map<operator_t,trinary_functor_t> trinary_op_map_t; | |
18396 | ||
18397 | typedef std::map<std::string,std::pair<trinary_functor_t ,operator_t> > sf3_map_t; | |
18398 | typedef std::map<std::string,std::pair<quaternary_functor_t,operator_t> > sf4_map_t; | |
18399 | ||
18400 | typedef std::map<binary_functor_t,operator_t> inv_binary_op_map_t; | |
18401 | typedef std::multimap<std::string,details::base_operation_t,details::ilesscompare> base_ops_map_t; | |
18402 | typedef std::set<std::string,details::ilesscompare> disabled_func_set_t; | |
18403 | ||
18404 | typedef details::T0oT1_define<T, cref_t, cref_t> vov_t; | |
18405 | typedef details::T0oT1_define<T, const_t, cref_t> cov_t; | |
18406 | typedef details::T0oT1_define<T, cref_t, const_t> voc_t; | |
18407 | ||
18408 | typedef details::T0oT1oT2_define<T, cref_t, cref_t, cref_t> vovov_t; | |
18409 | typedef details::T0oT1oT2_define<T, cref_t, cref_t, const_t> vovoc_t; | |
18410 | typedef details::T0oT1oT2_define<T, cref_t, const_t, cref_t> vocov_t; | |
18411 | typedef details::T0oT1oT2_define<T, const_t, cref_t, cref_t> covov_t; | |
18412 | typedef details::T0oT1oT2_define<T, const_t, cref_t, const_t> covoc_t; | |
18413 | typedef details::T0oT1oT2_define<T, const_t, const_t, cref_t> cocov_t; | |
18414 | typedef details::T0oT1oT2_define<T, cref_t, const_t, const_t> vococ_t; | |
18415 | ||
18416 | typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, cref_t> vovovov_t; | |
18417 | typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, cref_t, const_t> vovovoc_t; | |
18418 | typedef details::T0oT1oT2oT3_define<T, cref_t, cref_t, const_t, cref_t> vovocov_t; | |
18419 | typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, cref_t> vocovov_t; | |
18420 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, cref_t> covovov_t; | |
18421 | ||
18422 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, const_t, cref_t> covocov_t; | |
18423 | typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, cref_t, const_t> vocovoc_t; | |
18424 | typedef details::T0oT1oT2oT3_define<T, const_t, cref_t, cref_t, const_t> covovoc_t; | |
18425 | typedef details::T0oT1oT2oT3_define<T, cref_t, const_t, const_t, cref_t> vococov_t; | |
18426 | ||
18427 | typedef results_context<T> results_context_t; | |
18428 | ||
18429 | typedef parser_helper prsrhlpr_t; | |
18430 | ||
18431 | struct scope_element | |
18432 | { | |
18433 | enum element_type | |
18434 | { | |
18435 | e_none , | |
18436 | e_variable, | |
18437 | e_vector , | |
18438 | e_vecelem , | |
18439 | e_string | |
18440 | }; | |
18441 | ||
18442 | typedef details::vector_holder<T> vector_holder_t; | |
18443 | typedef variable_node_t* variable_node_ptr; | |
18444 | typedef vector_holder_t* vector_holder_ptr; | |
18445 | typedef expression_node_t* expression_node_ptr; | |
18446 | #ifndef exprtk_disable_string_capabilities | |
18447 | typedef stringvar_node_t* stringvar_node_ptr; | |
18448 | #endif | |
18449 | ||
18450 | scope_element() | |
18451 | : name("???"), | |
18452 | size (std::numeric_limits<std::size_t>::max()), | |
18453 | index(std::numeric_limits<std::size_t>::max()), | |
18454 | depth(std::numeric_limits<std::size_t>::max()), | |
18455 | ref_count(0), | |
18456 | ip_index (0), | |
18457 | type (e_none), | |
18458 | active(false), | |
18459 | data (0), | |
18460 | var_node(0), | |
18461 | vec_node(0) | |
18462 | #ifndef exprtk_disable_string_capabilities | |
18463 | ,str_node(0) | |
18464 | #endif | |
18465 | {} | |
18466 | ||
18467 | bool operator < (const scope_element& se) const | |
18468 | { | |
18469 | if (ip_index < se.ip_index) | |
18470 | return true; | |
18471 | else if (ip_index > se.ip_index) | |
18472 | return false; | |
18473 | else if (depth < se.depth) | |
18474 | return true; | |
18475 | else if (depth > se.depth) | |
18476 | return false; | |
18477 | else if (index < se.index) | |
18478 | return true; | |
18479 | else if (index > se.index) | |
18480 | return false; | |
18481 | else | |
18482 | return (name < se.name); | |
18483 | } | |
18484 | ||
18485 | void clear() | |
18486 | { | |
18487 | name = "???"; | |
18488 | size = std::numeric_limits<std::size_t>::max(); | |
18489 | index = std::numeric_limits<std::size_t>::max(); | |
18490 | depth = std::numeric_limits<std::size_t>::max(); | |
18491 | type = e_none; | |
18492 | active = false; | |
18493 | ref_count = 0; | |
18494 | ip_index = 0; | |
18495 | data = 0; | |
18496 | var_node = 0; | |
18497 | vec_node = 0; | |
18498 | #ifndef exprtk_disable_string_capabilities | |
18499 | str_node = 0; | |
18500 | #endif | |
18501 | } | |
18502 | ||
18503 | std::string name; | |
18504 | std::size_t size; | |
18505 | std::size_t index; | |
18506 | std::size_t depth; | |
18507 | std::size_t ref_count; | |
18508 | std::size_t ip_index; | |
18509 | element_type type; | |
18510 | bool active; | |
18511 | void* data; | |
18512 | expression_node_ptr var_node; | |
18513 | vector_holder_ptr vec_node; | |
18514 | #ifndef exprtk_disable_string_capabilities | |
18515 | stringvar_node_ptr str_node; | |
18516 | #endif | |
18517 | }; | |
18518 | ||
18519 | class scope_element_manager | |
18520 | { | |
18521 | public: | |
18522 | ||
18523 | typedef expression_node_t* expression_node_ptr; | |
18524 | typedef variable_node_t* variable_node_ptr; | |
18525 | typedef parser<T> parser_t; | |
18526 | ||
18527 | explicit scope_element_manager(parser<T>& p) | |
18528 | : parser_(p), | |
18529 | input_param_cnt_(0) | |
18530 | {} | |
18531 | ||
18532 | inline std::size_t size() const | |
18533 | { | |
18534 | return element_.size(); | |
18535 | } | |
18536 | ||
18537 | inline bool empty() const | |
18538 | { | |
18539 | return element_.empty(); | |
18540 | } | |
18541 | ||
18542 | inline scope_element& get_element(const std::size_t& index) | |
18543 | { | |
18544 | if (index < element_.size()) | |
18545 | return element_[index]; | |
18546 | else | |
18547 | return null_element_; | |
18548 | } | |
18549 | ||
18550 | inline scope_element& get_element(const std::string& var_name, | |
18551 | const std::size_t index = std::numeric_limits<std::size_t>::max()) | |
18552 | { | |
18553 | const std::size_t current_depth = parser_.state_.scope_depth; | |
18554 | ||
18555 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18556 | { | |
18557 | scope_element& se = element_[i]; | |
18558 | ||
18559 | if (se.depth > current_depth) | |
18560 | continue; | |
18561 | else if ( | |
18562 | details::imatch(se.name, var_name) && | |
18563 | (se.index == index) | |
18564 | ) | |
18565 | return se; | |
18566 | } | |
18567 | ||
18568 | return null_element_; | |
18569 | } | |
18570 | ||
18571 | inline scope_element& get_active_element(const std::string& var_name, | |
18572 | const std::size_t index = std::numeric_limits<std::size_t>::max()) | |
18573 | { | |
18574 | const std::size_t current_depth = parser_.state_.scope_depth; | |
18575 | ||
18576 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18577 | { | |
18578 | scope_element& se = element_[i]; | |
18579 | ||
18580 | if (se.depth > current_depth) | |
18581 | continue; | |
18582 | else if ( | |
18583 | details::imatch(se.name, var_name) && | |
18584 | (se.index == index) && | |
18585 | (se.active) | |
18586 | ) | |
18587 | return se; | |
18588 | } | |
18589 | ||
18590 | return null_element_; | |
18591 | } | |
18592 | ||
18593 | inline bool add_element(const scope_element& se) | |
18594 | { | |
18595 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18596 | { | |
18597 | scope_element& cse = element_[i]; | |
18598 | ||
18599 | if ( | |
18600 | details::imatch(cse.name, se.name) && | |
18601 | (cse.depth <= se.depth) && | |
18602 | (cse.index == se.index) && | |
18603 | (cse.size == se.size ) && | |
18604 | (cse.type == se.type ) && | |
18605 | (cse.active) | |
18606 | ) | |
18607 | return false; | |
18608 | } | |
18609 | ||
18610 | element_.push_back(se); | |
18611 | std::sort(element_.begin(),element_.end()); | |
18612 | ||
18613 | return true; | |
18614 | } | |
18615 | ||
18616 | inline void deactivate(const std::size_t& scope_depth) | |
18617 | { | |
18618 | exprtk_debug(("deactivate() - Scope depth: %d\n", | |
18619 | static_cast<int>(parser_.state_.scope_depth))); | |
18620 | ||
18621 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18622 | { | |
18623 | scope_element& se = element_[i]; | |
18624 | ||
18625 | if (se.active && (se.depth >= scope_depth)) | |
18626 | { | |
18627 | exprtk_debug(("deactivate() - element[%02d] '%s'\n", | |
18628 | static_cast<int>(i), | |
18629 | se.name.c_str())); | |
18630 | ||
18631 | se.active = false; | |
18632 | } | |
18633 | } | |
18634 | } | |
18635 | ||
18636 | inline void free_element(scope_element& se) | |
18637 | { | |
18638 | #ifdef exprtk_enable_debugging | |
18639 | exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); | |
18640 | #endif | |
18641 | ||
18642 | switch (se.type) | |
18643 | { | |
18644 | case scope_element::e_variable : if (se.data ) delete (T*) se.data; | |
18645 | if (se.var_node) delete se.var_node; | |
18646 | break; | |
18647 | ||
18648 | case scope_element::e_vector : if (se.data ) delete[] (T*) se.data; | |
18649 | if (se.vec_node) delete se.vec_node; | |
18650 | break; | |
18651 | ||
18652 | case scope_element::e_vecelem : if (se.var_node) delete se.var_node; | |
18653 | break; | |
18654 | ||
18655 | #ifndef exprtk_disable_string_capabilities | |
18656 | case scope_element::e_string : if (se.data ) delete (std::string*) se.data; | |
18657 | if (se.str_node) delete se.str_node; | |
18658 | break; | |
18659 | #endif | |
18660 | ||
18661 | default : return; | |
18662 | } | |
18663 | ||
18664 | se.clear(); | |
18665 | } | |
18666 | ||
18667 | inline void cleanup() | |
18668 | { | |
18669 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18670 | { | |
18671 | free_element(element_[i]); | |
18672 | } | |
18673 | ||
18674 | element_.clear(); | |
18675 | ||
18676 | input_param_cnt_ = 0; | |
18677 | } | |
18678 | ||
18679 | inline std::size_t next_ip_index() | |
18680 | { | |
18681 | return ++input_param_cnt_; | |
18682 | } | |
18683 | ||
18684 | inline expression_node_ptr get_variable(const T& v) | |
18685 | { | |
18686 | for (std::size_t i = 0; i < element_.size(); ++i) | |
18687 | { | |
18688 | scope_element& se = element_[i]; | |
18689 | ||
18690 | if ( | |
18691 | se.active && | |
18692 | se.var_node && | |
18693 | details::is_variable_node(se.var_node) | |
18694 | ) | |
18695 | { | |
18696 | variable_node_ptr vn = reinterpret_cast<variable_node_ptr>(se.var_node); | |
18697 | ||
18698 | if (&(vn->ref()) == (&v)) | |
18699 | { | |
18700 | return se.var_node; | |
18701 | } | |
18702 | } | |
18703 | } | |
18704 | ||
18705 | return expression_node_ptr(0); | |
18706 | } | |
18707 | ||
18708 | private: | |
18709 | ||
18710 | scope_element_manager& operator=(const scope_element_manager&); | |
18711 | ||
18712 | parser_t& parser_; | |
18713 | std::vector<scope_element> element_; | |
18714 | scope_element null_element_; | |
18715 | std::size_t input_param_cnt_; | |
18716 | }; | |
18717 | ||
18718 | class scope_handler | |
18719 | { | |
18720 | public: | |
18721 | ||
18722 | typedef parser<T> parser_t; | |
18723 | ||
18724 | explicit scope_handler(parser<T>& p) | |
18725 | : parser_(p) | |
18726 | { | |
18727 | parser_.state_.scope_depth++; | |
18728 | #ifdef exprtk_enable_debugging | |
18729 | const std::string depth(2 * parser_.state_.scope_depth,'-'); | |
18730 | exprtk_debug(("%s> Scope Depth: %02d\n", | |
18731 | depth.c_str(), | |
18732 | static_cast<int>(parser_.state_.scope_depth))); | |
18733 | #endif | |
18734 | } | |
18735 | ||
18736 | ~scope_handler() | |
18737 | { | |
18738 | parser_.sem_.deactivate(parser_.state_.scope_depth); | |
18739 | parser_.state_.scope_depth--; | |
18740 | #ifdef exprtk_enable_debugging | |
18741 | const std::string depth(2 * parser_.state_.scope_depth,'-'); | |
18742 | exprtk_debug(("<%s Scope Depth: %02d\n", | |
18743 | depth.c_str(), | |
18744 | static_cast<int>(parser_.state_.scope_depth))); | |
18745 | #endif | |
18746 | } | |
18747 | ||
18748 | private: | |
18749 | ||
18750 | scope_handler& operator=(const scope_handler&); | |
18751 | ||
18752 | parser_t& parser_; | |
18753 | }; | |
18754 | ||
18755 | struct symtab_store | |
18756 | { | |
18757 | symbol_table_list_t symtab_list_; | |
18758 | ||
18759 | typedef typename symbol_table_t::local_data_t local_data_t; | |
18760 | typedef typename symbol_table_t::variable_ptr variable_ptr; | |
18761 | typedef typename symbol_table_t::function_ptr function_ptr; | |
18762 | #ifndef exprtk_disable_string_capabilities | |
18763 | typedef typename symbol_table_t::stringvar_ptr stringvar_ptr; | |
18764 | #endif | |
18765 | typedef typename symbol_table_t::vector_holder_ptr vector_holder_ptr; | |
18766 | typedef typename symbol_table_t::vararg_function_ptr vararg_function_ptr; | |
18767 | typedef typename symbol_table_t::generic_function_ptr generic_function_ptr; | |
18768 | ||
18769 | inline bool empty() const | |
18770 | { | |
18771 | return symtab_list_.empty(); | |
18772 | } | |
18773 | ||
18774 | inline void clear() | |
18775 | { | |
18776 | symtab_list_.clear(); | |
18777 | } | |
18778 | ||
18779 | inline bool valid() const | |
18780 | { | |
18781 | if (!empty()) | |
18782 | { | |
18783 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18784 | { | |
18785 | if (symtab_list_[i].valid()) | |
18786 | return true; | |
18787 | } | |
18788 | } | |
18789 | ||
18790 | return false; | |
18791 | } | |
18792 | ||
18793 | inline bool valid_symbol(const std::string& symbol) const | |
18794 | { | |
18795 | if (!symtab_list_.empty()) | |
18796 | return symtab_list_[0].valid_symbol(symbol); | |
18797 | else | |
18798 | return false; | |
18799 | } | |
18800 | ||
18801 | inline bool valid_function_name(const std::string& symbol) const | |
18802 | { | |
18803 | if (!symtab_list_.empty()) | |
18804 | return symtab_list_[0].valid_function(symbol); | |
18805 | else | |
18806 | return false; | |
18807 | } | |
18808 | ||
18809 | inline variable_ptr get_variable(const std::string& variable_name) const | |
18810 | { | |
18811 | if (!valid_symbol(variable_name)) | |
18812 | return reinterpret_cast<variable_ptr>(0); | |
18813 | ||
18814 | variable_ptr result = reinterpret_cast<variable_ptr>(0); | |
18815 | ||
18816 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18817 | { | |
18818 | if (!symtab_list_[i].valid()) | |
18819 | continue; | |
18820 | else | |
18821 | result = local_data(i) | |
18822 | .variable_store.get(variable_name); | |
18823 | ||
18824 | if (result) break; | |
18825 | } | |
18826 | ||
18827 | return result; | |
18828 | } | |
18829 | ||
18830 | inline variable_ptr get_variable(const T& var_ref) const | |
18831 | { | |
18832 | variable_ptr result = reinterpret_cast<variable_ptr>(0); | |
18833 | ||
18834 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18835 | { | |
18836 | if (!symtab_list_[i].valid()) | |
18837 | continue; | |
18838 | else | |
18839 | result = local_data(i).variable_store | |
18840 | .get_from_varptr(reinterpret_cast<const void*>(&var_ref)); | |
18841 | ||
18842 | if (result) break; | |
18843 | } | |
18844 | ||
18845 | return result; | |
18846 | } | |
18847 | ||
18848 | #ifndef exprtk_disable_string_capabilities | |
18849 | inline stringvar_ptr get_stringvar(const std::string& string_name) const | |
18850 | { | |
18851 | if (!valid_symbol(string_name)) | |
18852 | return reinterpret_cast<stringvar_ptr>(0); | |
18853 | ||
18854 | stringvar_ptr result = reinterpret_cast<stringvar_ptr>(0); | |
18855 | ||
18856 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18857 | { | |
18858 | if (!symtab_list_[i].valid()) | |
18859 | continue; | |
18860 | else | |
18861 | result = local_data(i) | |
18862 | .stringvar_store.get(string_name); | |
18863 | ||
18864 | if (result) break; | |
18865 | } | |
18866 | ||
18867 | return result; | |
18868 | } | |
18869 | #endif | |
18870 | ||
18871 | inline function_ptr get_function(const std::string& function_name) const | |
18872 | { | |
18873 | if (!valid_function_name(function_name)) | |
18874 | return reinterpret_cast<function_ptr>(0); | |
18875 | ||
18876 | function_ptr result = reinterpret_cast<function_ptr>(0); | |
18877 | ||
18878 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18879 | { | |
18880 | if (!symtab_list_[i].valid()) | |
18881 | continue; | |
18882 | else | |
18883 | result = local_data(i) | |
18884 | .function_store.get(function_name); | |
18885 | ||
18886 | if (result) break; | |
18887 | } | |
18888 | ||
18889 | return result; | |
18890 | } | |
18891 | ||
18892 | inline vararg_function_ptr get_vararg_function(const std::string& vararg_function_name) const | |
18893 | { | |
18894 | if (!valid_function_name(vararg_function_name)) | |
18895 | return reinterpret_cast<vararg_function_ptr>(0); | |
18896 | ||
18897 | vararg_function_ptr result = reinterpret_cast<vararg_function_ptr>(0); | |
18898 | ||
18899 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18900 | { | |
18901 | if (!symtab_list_[i].valid()) | |
18902 | continue; | |
18903 | else | |
18904 | result = local_data(i) | |
18905 | .vararg_function_store.get(vararg_function_name); | |
18906 | ||
18907 | if (result) break; | |
18908 | } | |
18909 | ||
18910 | return result; | |
18911 | } | |
18912 | ||
18913 | inline generic_function_ptr get_generic_function(const std::string& function_name) const | |
18914 | { | |
18915 | if (!valid_function_name(function_name)) | |
18916 | return reinterpret_cast<generic_function_ptr>(0); | |
18917 | ||
18918 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); | |
18919 | ||
18920 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18921 | { | |
18922 | if (!symtab_list_[i].valid()) | |
18923 | continue; | |
18924 | else | |
18925 | result = local_data(i) | |
18926 | .generic_function_store.get(function_name); | |
18927 | ||
18928 | if (result) break; | |
18929 | } | |
18930 | ||
18931 | return result; | |
18932 | } | |
18933 | ||
18934 | inline generic_function_ptr get_string_function(const std::string& function_name) const | |
18935 | { | |
18936 | if (!valid_function_name(function_name)) | |
18937 | return reinterpret_cast<generic_function_ptr>(0); | |
18938 | ||
18939 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); | |
18940 | ||
18941 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18942 | { | |
18943 | if (!symtab_list_[i].valid()) | |
18944 | continue; | |
18945 | else | |
18946 | result = | |
18947 | local_data(i).string_function_store.get(function_name); | |
18948 | ||
18949 | if (result) break; | |
18950 | } | |
18951 | ||
18952 | return result; | |
18953 | } | |
18954 | ||
18955 | inline generic_function_ptr get_overload_function(const std::string& function_name) const | |
18956 | { | |
18957 | if (!valid_function_name(function_name)) | |
18958 | return reinterpret_cast<generic_function_ptr>(0); | |
18959 | ||
18960 | generic_function_ptr result = reinterpret_cast<generic_function_ptr>(0); | |
18961 | ||
18962 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18963 | { | |
18964 | if (!symtab_list_[i].valid()) | |
18965 | continue; | |
18966 | else | |
18967 | result = | |
18968 | local_data(i).overload_function_store.get(function_name); | |
18969 | ||
18970 | if (result) break; | |
18971 | } | |
18972 | ||
18973 | return result; | |
18974 | } | |
18975 | ||
18976 | inline vector_holder_ptr get_vector(const std::string& vector_name) const | |
18977 | { | |
18978 | if (!valid_symbol(vector_name)) | |
18979 | return reinterpret_cast<vector_holder_ptr>(0); | |
18980 | ||
18981 | vector_holder_ptr result = reinterpret_cast<vector_holder_ptr>(0); | |
18982 | ||
18983 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
18984 | { | |
18985 | if (!symtab_list_[i].valid()) | |
18986 | continue; | |
18987 | else | |
18988 | result = | |
18989 | local_data(i).vector_store.get(vector_name); | |
18990 | ||
18991 | if (result) break; | |
18992 | } | |
18993 | ||
18994 | return result; | |
18995 | } | |
18996 | ||
18997 | inline bool is_constant_node(const std::string& symbol_name) const | |
18998 | { | |
18999 | if (!valid_symbol(symbol_name)) | |
19000 | return false; | |
19001 | ||
19002 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19003 | { | |
19004 | if (!symtab_list_[i].valid()) | |
19005 | continue; | |
19006 | else if (local_data(i).variable_store.is_constant(symbol_name)) | |
19007 | return true; | |
19008 | } | |
19009 | ||
19010 | return false; | |
19011 | } | |
19012 | ||
19013 | #ifndef exprtk_disable_string_capabilities | |
19014 | inline bool is_constant_string(const std::string& symbol_name) const | |
19015 | { | |
19016 | if (!valid_symbol(symbol_name)) | |
19017 | return false; | |
19018 | ||
19019 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19020 | { | |
19021 | if (!symtab_list_[i].valid()) | |
19022 | continue; | |
19023 | else if (!local_data(i).stringvar_store.symbol_exists(symbol_name)) | |
19024 | continue; | |
19025 | else if ( local_data(i).stringvar_store.is_constant(symbol_name)) | |
19026 | return true; | |
19027 | } | |
19028 | ||
19029 | return false; | |
19030 | } | |
19031 | #endif | |
19032 | ||
19033 | inline bool symbol_exists(const std::string& symbol) const | |
19034 | { | |
19035 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19036 | { | |
19037 | if (!symtab_list_[i].valid()) | |
19038 | continue; | |
19039 | else if (symtab_list_[i].symbol_exists(symbol)) | |
19040 | return true; | |
19041 | } | |
19042 | ||
19043 | return false; | |
19044 | } | |
19045 | ||
19046 | inline bool is_variable(const std::string& variable_name) const | |
19047 | { | |
19048 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19049 | { | |
19050 | if (!symtab_list_[i].valid()) | |
19051 | continue; | |
19052 | else if ( | |
19053 | symtab_list_[i].local_data().variable_store | |
19054 | .symbol_exists(variable_name) | |
19055 | ) | |
19056 | return true; | |
19057 | } | |
19058 | ||
19059 | return false; | |
19060 | } | |
19061 | ||
19062 | #ifndef exprtk_disable_string_capabilities | |
19063 | inline bool is_stringvar(const std::string& stringvar_name) const | |
19064 | { | |
19065 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19066 | { | |
19067 | if (!symtab_list_[i].valid()) | |
19068 | continue; | |
19069 | else if ( | |
19070 | symtab_list_[i].local_data().stringvar_store | |
19071 | .symbol_exists(stringvar_name) | |
19072 | ) | |
19073 | return true; | |
19074 | } | |
19075 | ||
19076 | return false; | |
19077 | } | |
19078 | ||
19079 | inline bool is_conststr_stringvar(const std::string& symbol_name) const | |
19080 | { | |
19081 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19082 | { | |
19083 | if (!symtab_list_[i].valid()) | |
19084 | continue; | |
19085 | else if ( | |
19086 | symtab_list_[i].local_data().stringvar_store | |
19087 | .symbol_exists(symbol_name) | |
19088 | ) | |
19089 | { | |
19090 | return ( | |
19091 | local_data(i).stringvar_store.symbol_exists(symbol_name) || | |
19092 | local_data(i).stringvar_store.is_constant (symbol_name) | |
19093 | ); | |
19094 | ||
19095 | } | |
19096 | } | |
19097 | ||
19098 | return false; | |
19099 | } | |
19100 | #endif | |
19101 | ||
19102 | inline bool is_function(const std::string& function_name) const | |
19103 | { | |
19104 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19105 | { | |
19106 | if (!symtab_list_[i].valid()) | |
19107 | continue; | |
19108 | else if ( | |
19109 | local_data(i).vararg_function_store | |
19110 | .symbol_exists(function_name) | |
19111 | ) | |
19112 | return true; | |
19113 | } | |
19114 | ||
19115 | return false; | |
19116 | } | |
19117 | ||
19118 | inline bool is_vararg_function(const std::string& vararg_function_name) const | |
19119 | { | |
19120 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19121 | { | |
19122 | if (!symtab_list_[i].valid()) | |
19123 | continue; | |
19124 | else if ( | |
19125 | local_data(i).vararg_function_store | |
19126 | .symbol_exists(vararg_function_name) | |
19127 | ) | |
19128 | return true; | |
19129 | } | |
19130 | ||
19131 | return false; | |
19132 | } | |
19133 | ||
19134 | inline bool is_vector(const std::string& vector_name) const | |
19135 | { | |
19136 | for (std::size_t i = 0; i < symtab_list_.size(); ++i) | |
19137 | { | |
19138 | if (!symtab_list_[i].valid()) | |
19139 | continue; | |
19140 | else if ( | |
19141 | local_data(i).vector_store | |
19142 | .symbol_exists(vector_name) | |
19143 | ) | |
19144 | return true; | |
19145 | } | |
19146 | ||
19147 | return false; | |
19148 | } | |
19149 | ||
19150 | inline std::string get_variable_name(const expression_node_ptr& ptr) const | |
19151 | { | |
19152 | return local_data().variable_store.entity_name(ptr); | |
19153 | } | |
19154 | ||
19155 | inline std::string get_vector_name(const vector_holder_ptr& ptr) const | |
19156 | { | |
19157 | return local_data().vector_store.entity_name(ptr); | |
19158 | } | |
19159 | ||
19160 | #ifndef exprtk_disable_string_capabilities | |
19161 | inline std::string get_stringvar_name(const expression_node_ptr& ptr) const | |
19162 | { | |
19163 | return local_data().stringvar_store.entity_name(ptr); | |
19164 | } | |
19165 | ||
19166 | inline std::string get_conststr_stringvar_name(const expression_node_ptr& ptr) const | |
19167 | { | |
19168 | return local_data().stringvar_store.entity_name(ptr); | |
19169 | } | |
19170 | #endif | |
19171 | ||
19172 | inline local_data_t& local_data(const std::size_t& index = 0) | |
19173 | { | |
19174 | return symtab_list_[index].local_data(); | |
19175 | } | |
19176 | ||
19177 | inline const local_data_t& local_data(const std::size_t& index = 0) const | |
19178 | { | |
19179 | return symtab_list_[index].local_data(); | |
19180 | } | |
19181 | ||
19182 | inline symbol_table_t& get_symbol_table(const std::size_t& index = 0) | |
19183 | { | |
19184 | return symtab_list_[index]; | |
19185 | } | |
19186 | }; | |
19187 | ||
19188 | struct parser_state | |
19189 | { | |
19190 | parser_state() | |
19191 | : type_check_enabled(true) | |
19192 | { | |
19193 | reset(); | |
19194 | } | |
19195 | ||
19196 | void reset() | |
19197 | { | |
19198 | parsing_return_stmt = false; | |
19199 | parsing_break_stmt = false; | |
19200 | return_stmt_present = false; | |
19201 | side_effect_present = false; | |
19202 | scope_depth = 0; | |
19203 | } | |
19204 | ||
19205 | #ifndef exprtk_enable_debugging | |
19206 | void activate_side_effect(const std::string&) | |
19207 | #else | |
19208 | void activate_side_effect(const std::string& source) | |
19209 | #endif | |
19210 | { | |
19211 | if (!side_effect_present) | |
19212 | { | |
19213 | side_effect_present = true; | |
19214 | ||
19215 | exprtk_debug(("activate_side_effect() - caller: %s\n",source.c_str())); | |
19216 | } | |
19217 | } | |
19218 | ||
19219 | bool parsing_return_stmt; | |
19220 | bool parsing_break_stmt; | |
19221 | bool return_stmt_present; | |
19222 | bool side_effect_present; | |
19223 | bool type_check_enabled; | |
19224 | std::size_t scope_depth; | |
19225 | }; | |
19226 | ||
19227 | public: | |
19228 | ||
19229 | struct unknown_symbol_resolver | |
19230 | { | |
19231 | ||
19232 | enum usr_symbol_type | |
19233 | { | |
19234 | e_usr_unknown_type = 0, | |
19235 | e_usr_variable_type = 1, | |
19236 | e_usr_constant_type = 2 | |
19237 | }; | |
19238 | ||
19239 | enum usr_mode | |
19240 | { | |
19241 | e_usrmode_default = 0, | |
19242 | e_usrmode_extended = 1 | |
19243 | }; | |
19244 | ||
19245 | usr_mode mode; | |
19246 | ||
19247 | unknown_symbol_resolver(const usr_mode m = e_usrmode_default) | |
19248 | : mode(m) | |
19249 | {} | |
19250 | ||
19251 | virtual ~unknown_symbol_resolver() | |
19252 | {} | |
19253 | ||
19254 | virtual bool process(const std::string& /*unknown_symbol*/, | |
19255 | usr_symbol_type& st, | |
19256 | T& default_value, | |
19257 | std::string& error_message) | |
19258 | { | |
19259 | if (e_usrmode_default != mode) | |
19260 | return false; | |
19261 | ||
19262 | st = e_usr_variable_type; | |
19263 | default_value = T(0); | |
19264 | error_message.clear(); | |
19265 | ||
19266 | return true; | |
19267 | } | |
19268 | ||
19269 | virtual bool process(const std::string& /* unknown_symbol */, | |
19270 | symbol_table_t& /* symbol_table */, | |
19271 | std::string& /* error_message */) | |
19272 | { | |
19273 | return false; | |
19274 | } | |
19275 | }; | |
19276 | ||
19277 | enum collect_type | |
19278 | { | |
19279 | e_ct_none = 0, | |
19280 | e_ct_variables = 1, | |
19281 | e_ct_functions = 2, | |
19282 | e_ct_assignments = 4 | |
19283 | }; | |
19284 | ||
19285 | enum symbol_type | |
19286 | { | |
19287 | e_st_unknown = 0, | |
19288 | e_st_variable = 1, | |
19289 | e_st_vector = 2, | |
19290 | e_st_vecelem = 3, | |
19291 | e_st_string = 4, | |
19292 | e_st_function = 5, | |
19293 | e_st_local_variable = 6, | |
19294 | e_st_local_vector = 7, | |
19295 | e_st_local_string = 8 | |
19296 | }; | |
19297 | ||
19298 | class dependent_entity_collector | |
19299 | { | |
19300 | public: | |
19301 | ||
19302 | typedef std::pair<std::string,symbol_type> symbol_t; | |
19303 | typedef std::vector<symbol_t> symbol_list_t; | |
19304 | ||
19305 | dependent_entity_collector(const std::size_t options = e_ct_none) | |
19306 | : options_(options), | |
19307 | collect_variables_ ((options_ & e_ct_variables ) == e_ct_variables ), | |
19308 | collect_functions_ ((options_ & e_ct_functions ) == e_ct_functions ), | |
19309 | collect_assignments_((options_ & e_ct_assignments) == e_ct_assignments), | |
19310 | return_present_ (false), | |
19311 | final_stmt_return_(false) | |
19312 | {} | |
19313 | ||
19314 | template <typename Allocator, | |
19315 | template <typename, typename> class Sequence> | |
19316 | inline std::size_t symbols(Sequence<symbol_t,Allocator>& symbols_list) | |
19317 | { | |
19318 | if (!collect_variables_ && !collect_functions_) | |
19319 | return 0; | |
19320 | else if (symbol_name_list_.empty()) | |
19321 | return 0; | |
19322 | ||
19323 | for (std::size_t i = 0; i < symbol_name_list_.size(); ++i) | |
19324 | { | |
19325 | details::case_normalise(symbol_name_list_[i].first); | |
19326 | } | |
19327 | ||
19328 | std::sort(symbol_name_list_.begin(),symbol_name_list_.end()); | |
19329 | ||
19330 | std::unique_copy(symbol_name_list_.begin(), | |
19331 | symbol_name_list_.end (), | |
19332 | std::back_inserter(symbols_list)); | |
19333 | ||
19334 | return symbols_list.size(); | |
19335 | } | |
19336 | ||
19337 | template <typename Allocator, | |
19338 | template <typename, typename> class Sequence> | |
19339 | inline std::size_t assignment_symbols(Sequence<symbol_t,Allocator>& assignment_list) | |
19340 | { | |
19341 | if (!collect_assignments_) | |
19342 | return 0; | |
19343 | else if (assignment_name_list_.empty()) | |
19344 | return 0; | |
19345 | ||
19346 | for (std::size_t i = 0; i < assignment_name_list_.size(); ++i) | |
19347 | { | |
19348 | details::case_normalise(assignment_name_list_[i].first); | |
19349 | } | |
19350 | ||
19351 | std::sort(assignment_name_list_.begin(),assignment_name_list_.end()); | |
19352 | ||
19353 | std::unique_copy(assignment_name_list_.begin(), | |
19354 | assignment_name_list_.end (), | |
19355 | std::back_inserter(assignment_list)); | |
19356 | ||
19357 | return assignment_list.size(); | |
19358 | } | |
19359 | ||
19360 | void clear() | |
19361 | { | |
19362 | symbol_name_list_ .clear(); | |
19363 | assignment_name_list_.clear(); | |
19364 | retparam_list_ .clear(); | |
19365 | return_present_ = false; | |
19366 | final_stmt_return_ = false; | |
19367 | } | |
19368 | ||
19369 | bool& collect_variables() | |
19370 | { | |
19371 | return collect_variables_; | |
19372 | } | |
19373 | ||
19374 | bool& collect_functions() | |
19375 | { | |
19376 | return collect_functions_; | |
19377 | } | |
19378 | ||
19379 | bool& collect_assignments() | |
19380 | { | |
19381 | return collect_assignments_; | |
19382 | } | |
19383 | ||
19384 | bool return_present() const | |
19385 | { | |
19386 | return return_present_; | |
19387 | } | |
19388 | ||
19389 | bool final_stmt_return() const | |
19390 | { | |
19391 | return final_stmt_return_; | |
19392 | } | |
19393 | ||
19394 | typedef std::vector<std::string> retparam_list_t; | |
19395 | ||
19396 | retparam_list_t return_param_type_list() const | |
19397 | { | |
19398 | return retparam_list_; | |
19399 | } | |
19400 | ||
19401 | private: | |
19402 | ||
19403 | inline void add_symbol(const std::string& symbol, const symbol_type st) | |
19404 | { | |
19405 | switch (st) | |
19406 | { | |
19407 | case e_st_variable : | |
19408 | case e_st_vector : | |
19409 | case e_st_string : | |
19410 | case e_st_local_variable : | |
19411 | case e_st_local_vector : | |
19412 | case e_st_local_string : if (collect_variables_) | |
19413 | symbol_name_list_ | |
19414 | .push_back(std::make_pair(symbol, st)); | |
19415 | break; | |
19416 | ||
19417 | case e_st_function : if (collect_functions_) | |
19418 | symbol_name_list_ | |
19419 | .push_back(std::make_pair(symbol, st)); | |
19420 | break; | |
19421 | ||
19422 | default : return; | |
19423 | } | |
19424 | } | |
19425 | ||
19426 | inline void add_assignment(const std::string& symbol, const symbol_type st) | |
19427 | { | |
19428 | switch (st) | |
19429 | { | |
19430 | case e_st_variable : | |
19431 | case e_st_vector : | |
19432 | case e_st_string : if (collect_assignments_) | |
19433 | assignment_name_list_ | |
19434 | .push_back(std::make_pair(symbol, st)); | |
19435 | break; | |
19436 | ||
19437 | default : return; | |
19438 | } | |
19439 | } | |
19440 | ||
19441 | std::size_t options_; | |
19442 | bool collect_variables_; | |
19443 | bool collect_functions_; | |
19444 | bool collect_assignments_; | |
19445 | bool return_present_; | |
19446 | bool final_stmt_return_; | |
19447 | symbol_list_t symbol_name_list_; | |
19448 | symbol_list_t assignment_name_list_; | |
19449 | retparam_list_t retparam_list_; | |
19450 | ||
19451 | friend class parser<T>; | |
19452 | }; | |
19453 | ||
19454 | class settings_store | |
19455 | { | |
19456 | private: | |
19457 | ||
19458 | typedef std::set<std::string,details::ilesscompare> disabled_entity_set_t; | |
19459 | typedef disabled_entity_set_t::iterator des_itr_t; | |
19460 | ||
19461 | public: | |
19462 | ||
19463 | enum settings_compilation_options | |
19464 | { | |
19465 | e_unknown = 0, | |
19466 | e_replacer = 1, | |
19467 | e_joiner = 2, | |
19468 | e_numeric_check = 4, | |
19469 | e_bracket_check = 8, | |
19470 | e_sequence_check = 16, | |
19471 | e_commutative_check = 32, | |
19472 | e_strength_reduction = 64, | |
19473 | e_disable_vardef = 128, | |
19474 | e_collect_vars = 256, | |
19475 | e_collect_funcs = 512, | |
19476 | e_collect_assings = 1024, | |
19477 | e_disable_usr_on_rsrvd = 2048, | |
19478 | e_disable_zero_return = 4096 | |
19479 | }; | |
19480 | ||
19481 | enum settings_base_funcs | |
19482 | { | |
19483 | e_bf_unknown = 0, | |
19484 | e_bf_abs , e_bf_acos , e_bf_acosh , e_bf_asin , | |
19485 | e_bf_asinh , e_bf_atan , e_bf_atan2 , e_bf_atanh , | |
19486 | e_bf_avg , e_bf_ceil , e_bf_clamp , e_bf_cos , | |
19487 | e_bf_cosh , e_bf_cot , e_bf_csc , e_bf_equal , | |
19488 | e_bf_erf , e_bf_erfc , e_bf_exp , e_bf_expm1 , | |
19489 | e_bf_floor , e_bf_frac , e_bf_hypot , e_bf_iclamp , | |
19490 | e_bf_like , e_bf_log , e_bf_log10 , e_bf_log1p , | |
19491 | e_bf_log2 , e_bf_logn , e_bf_mand , e_bf_max , | |
19492 | e_bf_min , e_bf_mod , e_bf_mor , e_bf_mul , | |
19493 | e_bf_ncdf , e_bf_pow , e_bf_root , e_bf_round , | |
19494 | e_bf_roundn , e_bf_sec , e_bf_sgn , e_bf_sin , | |
19495 | e_bf_sinc , e_bf_sinh , e_bf_sqrt , e_bf_sum , | |
19496 | e_bf_swap , e_bf_tan , e_bf_tanh , e_bf_trunc , | |
19497 | e_bf_not_equal , e_bf_inrange , e_bf_deg2grad , e_bf_deg2rad, | |
19498 | e_bf_rad2deg , e_bf_grad2deg | |
19499 | }; | |
19500 | ||
19501 | enum settings_control_structs | |
19502 | { | |
19503 | e_ctrl_unknown = 0, | |
19504 | e_ctrl_ifelse, | |
19505 | e_ctrl_switch, | |
19506 | e_ctrl_for_loop, | |
19507 | e_ctrl_while_loop, | |
19508 | e_ctrl_repeat_loop, | |
19509 | e_ctrl_return | |
19510 | }; | |
19511 | ||
19512 | enum settings_logic_opr | |
19513 | { | |
19514 | e_logic_unknown = 0, | |
19515 | e_logic_and, e_logic_nand, e_logic_nor, | |
19516 | e_logic_not, e_logic_or, e_logic_xnor, | |
19517 | e_logic_xor, e_logic_scand, e_logic_scor | |
19518 | }; | |
19519 | ||
19520 | enum settings_arithmetic_opr | |
19521 | { | |
19522 | e_arith_unknown = 0, | |
19523 | e_arith_add, e_arith_sub, e_arith_mul, | |
19524 | e_arith_div, e_arith_mod, e_arith_pow | |
19525 | }; | |
19526 | ||
19527 | enum settings_assignment_opr | |
19528 | { | |
19529 | e_assign_unknown = 0, | |
19530 | e_assign_assign, e_assign_addass, e_assign_subass, | |
19531 | e_assign_mulass, e_assign_divass, e_assign_modass | |
19532 | }; | |
19533 | ||
19534 | enum settings_inequality_opr | |
19535 | { | |
19536 | e_ineq_unknown = 0, | |
19537 | e_ineq_lt, e_ineq_lte, e_ineq_eq, | |
19538 | e_ineq_equal, e_ineq_ne, e_ineq_nequal, | |
19539 | e_ineq_gte, e_ineq_gt | |
19540 | }; | |
19541 | ||
19542 | static const std::size_t compile_all_opts = e_replacer + | |
19543 | e_joiner + | |
19544 | e_numeric_check + | |
19545 | e_bracket_check + | |
19546 | e_sequence_check + | |
19547 | e_commutative_check + | |
19548 | e_strength_reduction; | |
19549 | ||
19550 | settings_store(const std::size_t compile_options = compile_all_opts) | |
19551 | { | |
19552 | load_compile_options(compile_options); | |
19553 | } | |
19554 | ||
19555 | settings_store& enable_all_base_functions() | |
19556 | { | |
19557 | disabled_func_set_.clear(); | |
19558 | return (*this); | |
19559 | } | |
19560 | ||
19561 | settings_store& enable_all_control_structures() | |
19562 | { | |
19563 | disabled_ctrl_set_.clear(); | |
19564 | return (*this); | |
19565 | } | |
19566 | ||
19567 | settings_store& enable_all_logic_ops() | |
19568 | { | |
19569 | disabled_logic_set_.clear(); | |
19570 | return (*this); | |
19571 | } | |
19572 | ||
19573 | settings_store& enable_all_arithmetic_ops() | |
19574 | { | |
19575 | disabled_arithmetic_set_.clear(); | |
19576 | return (*this); | |
19577 | } | |
19578 | ||
19579 | settings_store& enable_all_assignment_ops() | |
19580 | { | |
19581 | disabled_assignment_set_.clear(); | |
19582 | return (*this); | |
19583 | } | |
19584 | ||
19585 | settings_store& enable_all_inequality_ops() | |
19586 | { | |
19587 | disabled_inequality_set_.clear(); | |
19588 | return (*this); | |
19589 | } | |
19590 | ||
19591 | settings_store& enable_local_vardef() | |
19592 | { | |
19593 | disable_vardef_ = false; | |
19594 | return (*this); | |
19595 | } | |
19596 | ||
19597 | settings_store& disable_all_base_functions() | |
19598 | { | |
19599 | std::copy(details::base_function_list, | |
19600 | details::base_function_list + details::base_function_list_size, | |
19601 | std::insert_iterator<disabled_entity_set_t> | |
19602 | (disabled_func_set_, disabled_func_set_.begin())); | |
19603 | return (*this); | |
19604 | } | |
19605 | ||
19606 | settings_store& disable_all_control_structures() | |
19607 | { | |
19608 | std::copy(details::cntrl_struct_list, | |
19609 | details::cntrl_struct_list + details::cntrl_struct_list_size, | |
19610 | std::insert_iterator<disabled_entity_set_t> | |
19611 | (disabled_ctrl_set_, disabled_ctrl_set_.begin())); | |
19612 | return (*this); | |
19613 | } | |
19614 | ||
19615 | settings_store& disable_all_logic_ops() | |
19616 | { | |
19617 | std::copy(details::logic_ops_list, | |
19618 | details::logic_ops_list + details::logic_ops_list_size, | |
19619 | std::insert_iterator<disabled_entity_set_t> | |
19620 | (disabled_logic_set_, disabled_logic_set_.begin())); | |
19621 | return (*this); | |
19622 | } | |
19623 | ||
19624 | settings_store& disable_all_arithmetic_ops() | |
19625 | { | |
19626 | std::copy(details::arithmetic_ops_list, | |
19627 | details::arithmetic_ops_list + details::arithmetic_ops_list_size, | |
19628 | std::insert_iterator<disabled_entity_set_t> | |
19629 | (disabled_arithmetic_set_, disabled_arithmetic_set_.begin())); | |
19630 | return (*this); | |
19631 | } | |
19632 | ||
19633 | settings_store& disable_all_assignment_ops() | |
19634 | { | |
19635 | std::copy(details::assignment_ops_list, | |
19636 | details::assignment_ops_list + details::assignment_ops_list_size, | |
19637 | std::insert_iterator<disabled_entity_set_t> | |
19638 | (disabled_assignment_set_, disabled_assignment_set_.begin())); | |
19639 | return (*this); | |
19640 | } | |
19641 | ||
19642 | settings_store& disable_all_inequality_ops() | |
19643 | { | |
19644 | std::copy(details::inequality_ops_list, | |
19645 | details::inequality_ops_list + details::inequality_ops_list_size, | |
19646 | std::insert_iterator<disabled_entity_set_t> | |
19647 | (disabled_inequality_set_, disabled_inequality_set_.begin())); | |
19648 | return (*this); | |
19649 | } | |
19650 | ||
19651 | settings_store& disable_local_vardef() | |
19652 | { | |
19653 | disable_vardef_ = true; | |
19654 | return (*this); | |
19655 | } | |
19656 | ||
19657 | bool replacer_enabled () const { return enable_replacer_; } | |
19658 | bool commutative_check_enabled () const { return enable_commutative_check_; } | |
19659 | bool joiner_enabled () const { return enable_joiner_; } | |
19660 | bool numeric_check_enabled () const { return enable_numeric_check_; } | |
19661 | bool bracket_check_enabled () const { return enable_bracket_check_; } | |
19662 | bool sequence_check_enabled () const { return enable_sequence_check_; } | |
19663 | bool strength_reduction_enabled () const { return enable_strength_reduction_; } | |
19664 | bool collect_variables_enabled () const { return enable_collect_vars_; } | |
19665 | bool collect_functions_enabled () const { return enable_collect_funcs_; } | |
19666 | bool collect_assignments_enabled() const { return enable_collect_assings_; } | |
19667 | bool vardef_disabled () const { return disable_vardef_; } | |
19668 | bool rsrvd_sym_usr_disabled () const { return disable_rsrvd_sym_usr_; } | |
19669 | bool zero_return_disabled () const { return disable_zero_return_; } | |
19670 | ||
19671 | bool function_enabled(const std::string& function_name) const | |
19672 | { | |
19673 | if (disabled_func_set_.empty()) | |
19674 | return true; | |
19675 | else | |
19676 | return (disabled_func_set_.end() == disabled_func_set_.find(function_name)); | |
19677 | } | |
19678 | ||
19679 | bool control_struct_enabled(const std::string& control_struct) const | |
19680 | { | |
19681 | if (disabled_ctrl_set_.empty()) | |
19682 | return true; | |
19683 | else | |
19684 | return (disabled_ctrl_set_.end() == disabled_ctrl_set_.find(control_struct)); | |
19685 | } | |
19686 | ||
19687 | bool logic_enabled(const std::string& logic_operation) const | |
19688 | { | |
19689 | if (disabled_logic_set_.empty()) | |
19690 | return true; | |
19691 | else | |
19692 | return (disabled_logic_set_.end() == disabled_logic_set_.find(logic_operation)); | |
19693 | } | |
19694 | ||
19695 | bool arithmetic_enabled(const details::operator_type& arithmetic_operation) const | |
19696 | { | |
19697 | if (disabled_logic_set_.empty()) | |
19698 | return true; | |
19699 | else | |
19700 | return disabled_arithmetic_set_.end() == disabled_arithmetic_set_ | |
19701 | .find(arith_opr_to_string(arithmetic_operation)); | |
19702 | } | |
19703 | ||
19704 | bool assignment_enabled(const details::operator_type& assignment) const | |
19705 | { | |
19706 | if (disabled_assignment_set_.empty()) | |
19707 | return true; | |
19708 | else | |
19709 | return disabled_assignment_set_.end() == disabled_assignment_set_ | |
19710 | .find(assign_opr_to_string(assignment)); | |
19711 | } | |
19712 | ||
19713 | bool inequality_enabled(const details::operator_type& inequality) const | |
19714 | { | |
19715 | if (disabled_inequality_set_.empty()) | |
19716 | return true; | |
19717 | else | |
19718 | return disabled_inequality_set_.end() == disabled_inequality_set_ | |
19719 | .find(inequality_opr_to_string(inequality)); | |
19720 | } | |
19721 | ||
19722 | bool function_disabled(const std::string& function_name) const | |
19723 | { | |
19724 | if (disabled_func_set_.empty()) | |
19725 | return false; | |
19726 | else | |
19727 | return (disabled_func_set_.end() != disabled_func_set_.find(function_name)); | |
19728 | } | |
19729 | ||
19730 | bool control_struct_disabled(const std::string& control_struct) const | |
19731 | { | |
19732 | if (disabled_ctrl_set_.empty()) | |
19733 | return false; | |
19734 | else | |
19735 | return (disabled_ctrl_set_.end() != disabled_ctrl_set_.find(control_struct)); | |
19736 | } | |
19737 | ||
19738 | bool logic_disabled(const std::string& logic_operation) const | |
19739 | { | |
19740 | if (disabled_logic_set_.empty()) | |
19741 | return false; | |
19742 | else | |
19743 | return (disabled_logic_set_.end() != disabled_logic_set_.find(logic_operation)); | |
19744 | } | |
19745 | ||
19746 | bool assignment_disabled(const details::operator_type assignment_operation) const | |
19747 | { | |
19748 | if (disabled_assignment_set_.empty()) | |
19749 | return false; | |
19750 | else | |
19751 | return disabled_assignment_set_.end() != disabled_assignment_set_ | |
19752 | .find(assign_opr_to_string(assignment_operation)); | |
19753 | } | |
19754 | ||
19755 | bool logic_disabled(const details::operator_type logic_operation) const | |
19756 | { | |
19757 | if (disabled_logic_set_.empty()) | |
19758 | return false; | |
19759 | else | |
19760 | return disabled_logic_set_.end() != disabled_logic_set_ | |
19761 | .find(logic_opr_to_string(logic_operation)); | |
19762 | } | |
19763 | ||
19764 | bool arithmetic_disabled(const details::operator_type arithmetic_operation) const | |
19765 | { | |
19766 | if (disabled_arithmetic_set_.empty()) | |
19767 | return false; | |
19768 | else | |
19769 | return disabled_arithmetic_set_.end() != disabled_arithmetic_set_ | |
19770 | .find(arith_opr_to_string(arithmetic_operation)); | |
19771 | } | |
19772 | ||
19773 | bool inequality_disabled(const details::operator_type& inequality) const | |
19774 | { | |
19775 | if (disabled_inequality_set_.empty()) | |
19776 | return false; | |
19777 | else | |
19778 | return disabled_inequality_set_.end() != disabled_inequality_set_ | |
19779 | .find(inequality_opr_to_string(inequality)); | |
19780 | } | |
19781 | ||
19782 | settings_store& disable_base_function(settings_base_funcs bf) | |
19783 | { | |
19784 | if ( | |
19785 | (e_bf_unknown != bf) && | |
19786 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) | |
19787 | ) | |
19788 | { | |
19789 | disabled_func_set_.insert(details::base_function_list[bf - 1]); | |
19790 | } | |
19791 | ||
19792 | return (*this); | |
19793 | } | |
19794 | ||
19795 | settings_store& disable_control_structure(settings_control_structs ctrl_struct) | |
19796 | { | |
19797 | if ( | |
19798 | (e_ctrl_unknown != ctrl_struct) && | |
19799 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) | |
19800 | ) | |
19801 | { | |
19802 | disabled_ctrl_set_.insert(details::cntrl_struct_list[ctrl_struct - 1]); | |
19803 | } | |
19804 | ||
19805 | return (*this); | |
19806 | } | |
19807 | ||
19808 | settings_store& disable_logic_operation(settings_logic_opr logic) | |
19809 | { | |
19810 | if ( | |
19811 | (e_logic_unknown != logic) && | |
19812 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) | |
19813 | ) | |
19814 | { | |
19815 | disabled_logic_set_.insert(details::logic_ops_list[logic - 1]); | |
19816 | } | |
19817 | ||
19818 | return (*this); | |
19819 | } | |
19820 | ||
19821 | settings_store& disable_arithmetic_operation(settings_arithmetic_opr arithmetic) | |
19822 | { | |
19823 | if ( | |
19824 | (e_arith_unknown != arithmetic) && | |
19825 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) | |
19826 | ) | |
19827 | { | |
19828 | disabled_arithmetic_set_.insert(details::arithmetic_ops_list[arithmetic - 1]); | |
19829 | } | |
19830 | ||
19831 | return (*this); | |
19832 | } | |
19833 | ||
19834 | settings_store& disable_assignment_operation(settings_assignment_opr assignment) | |
19835 | { | |
19836 | if ( | |
19837 | (e_assign_unknown != assignment) && | |
19838 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) | |
19839 | ) | |
19840 | { | |
19841 | disabled_assignment_set_.insert(details::assignment_ops_list[assignment - 1]); | |
19842 | } | |
19843 | ||
19844 | return (*this); | |
19845 | } | |
19846 | ||
19847 | settings_store& disable_inequality_operation(settings_inequality_opr inequality) | |
19848 | { | |
19849 | if ( | |
19850 | (e_ineq_unknown != inequality) && | |
19851 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) | |
19852 | ) | |
19853 | { | |
19854 | disabled_inequality_set_.insert(details::inequality_ops_list[inequality - 1]); | |
19855 | } | |
19856 | ||
19857 | return (*this); | |
19858 | } | |
19859 | ||
19860 | settings_store& enable_base_function(settings_base_funcs bf) | |
19861 | { | |
19862 | if ( | |
19863 | (e_bf_unknown != bf) && | |
19864 | (static_cast<std::size_t>(bf) < (details::base_function_list_size + 1)) | |
19865 | ) | |
19866 | { | |
19867 | const des_itr_t itr = disabled_func_set_.find(details::base_function_list[bf - 1]); | |
19868 | ||
19869 | if (disabled_func_set_.end() != itr) | |
19870 | { | |
19871 | disabled_func_set_.erase(itr); | |
19872 | } | |
19873 | } | |
19874 | ||
19875 | return (*this); | |
19876 | } | |
19877 | ||
19878 | settings_store& enable_control_structure(settings_control_structs ctrl_struct) | |
19879 | { | |
19880 | if ( | |
19881 | (e_ctrl_unknown != ctrl_struct) && | |
19882 | (static_cast<std::size_t>(ctrl_struct) < (details::cntrl_struct_list_size + 1)) | |
19883 | ) | |
19884 | { | |
19885 | const des_itr_t itr = disabled_ctrl_set_.find(details::cntrl_struct_list[ctrl_struct - 1]); | |
19886 | ||
19887 | if (disabled_ctrl_set_.end() != itr) | |
19888 | { | |
19889 | disabled_ctrl_set_.erase(itr); | |
19890 | } | |
19891 | } | |
19892 | ||
19893 | return (*this); | |
19894 | } | |
19895 | ||
19896 | settings_store& enable_logic_operation(settings_logic_opr logic) | |
19897 | { | |
19898 | if ( | |
19899 | (e_logic_unknown != logic) && | |
19900 | (static_cast<std::size_t>(logic) < (details::logic_ops_list_size + 1)) | |
19901 | ) | |
19902 | { | |
19903 | const des_itr_t itr = disabled_logic_set_.find(details::logic_ops_list[logic - 1]); | |
19904 | ||
19905 | if (disabled_logic_set_.end() != itr) | |
19906 | { | |
19907 | disabled_logic_set_.erase(itr); | |
19908 | } | |
19909 | } | |
19910 | ||
19911 | return (*this); | |
19912 | } | |
19913 | ||
19914 | settings_store& enable_arithmetic_operation(settings_arithmetic_opr arithmetic) | |
19915 | { | |
19916 | if ( | |
19917 | (e_arith_unknown != arithmetic) && | |
19918 | (static_cast<std::size_t>(arithmetic) < (details::arithmetic_ops_list_size + 1)) | |
19919 | ) | |
19920 | { | |
19921 | const des_itr_t itr = disabled_arithmetic_set_.find(details::arithmetic_ops_list[arithmetic - 1]); | |
19922 | ||
19923 | if (disabled_arithmetic_set_.end() != itr) | |
19924 | { | |
19925 | disabled_arithmetic_set_.erase(itr); | |
19926 | } | |
19927 | } | |
19928 | ||
19929 | return (*this); | |
19930 | } | |
19931 | ||
19932 | settings_store& enable_assignment_operation(settings_assignment_opr assignment) | |
19933 | { | |
19934 | if ( | |
19935 | (e_assign_unknown != assignment) && | |
19936 | (static_cast<std::size_t>(assignment) < (details::assignment_ops_list_size + 1)) | |
19937 | ) | |
19938 | { | |
19939 | const des_itr_t itr = disabled_assignment_set_.find(details::assignment_ops_list[assignment - 1]); | |
19940 | ||
19941 | if (disabled_assignment_set_.end() != itr) | |
19942 | { | |
19943 | disabled_assignment_set_.erase(itr); | |
19944 | } | |
19945 | } | |
19946 | ||
19947 | return (*this); | |
19948 | } | |
19949 | ||
19950 | settings_store& enable_inequality_operation(settings_inequality_opr inequality) | |
19951 | { | |
19952 | if ( | |
19953 | (e_ineq_unknown != inequality) && | |
19954 | (static_cast<std::size_t>(inequality) < (details::inequality_ops_list_size + 1)) | |
19955 | ) | |
19956 | { | |
19957 | const des_itr_t itr = disabled_inequality_set_.find(details::inequality_ops_list[inequality - 1]); | |
19958 | ||
19959 | if (disabled_inequality_set_.end() != itr) | |
19960 | { | |
19961 | disabled_inequality_set_.erase(itr); | |
19962 | } | |
19963 | } | |
19964 | ||
19965 | return (*this); | |
19966 | } | |
19967 | ||
19968 | private: | |
19969 | ||
19970 | void load_compile_options(const std::size_t compile_options) | |
19971 | { | |
19972 | enable_replacer_ = (compile_options & e_replacer ) == e_replacer; | |
19973 | enable_joiner_ = (compile_options & e_joiner ) == e_joiner; | |
19974 | enable_numeric_check_ = (compile_options & e_numeric_check ) == e_numeric_check; | |
19975 | enable_bracket_check_ = (compile_options & e_bracket_check ) == e_bracket_check; | |
19976 | enable_sequence_check_ = (compile_options & e_sequence_check ) == e_sequence_check; | |
19977 | enable_commutative_check_ = (compile_options & e_commutative_check ) == e_commutative_check; | |
19978 | enable_strength_reduction_ = (compile_options & e_strength_reduction ) == e_strength_reduction; | |
19979 | enable_collect_vars_ = (compile_options & e_collect_vars ) == e_collect_vars; | |
19980 | enable_collect_funcs_ = (compile_options & e_collect_funcs ) == e_collect_funcs; | |
19981 | enable_collect_assings_ = (compile_options & e_collect_assings ) == e_collect_assings; | |
19982 | disable_vardef_ = (compile_options & e_disable_vardef ) == e_disable_vardef; | |
19983 | disable_rsrvd_sym_usr_ = (compile_options & e_disable_usr_on_rsrvd) == e_disable_usr_on_rsrvd; | |
19984 | disable_zero_return_ = (compile_options & e_disable_zero_return ) == e_disable_zero_return; | |
19985 | } | |
19986 | ||
19987 | std::string assign_opr_to_string(details::operator_type opr) const | |
19988 | { | |
19989 | switch (opr) | |
19990 | { | |
19991 | case details::e_assign : return ":="; | |
19992 | case details::e_addass : return "+="; | |
19993 | case details::e_subass : return "-="; | |
19994 | case details::e_mulass : return "*="; | |
19995 | case details::e_divass : return "/="; | |
19996 | case details::e_modass : return "%="; | |
19997 | default : return ""; | |
19998 | } | |
19999 | } | |
20000 | ||
20001 | std::string arith_opr_to_string(details::operator_type opr) const | |
20002 | { | |
20003 | switch (opr) | |
20004 | { | |
20005 | case details::e_add : return "+"; | |
20006 | case details::e_sub : return "-"; | |
20007 | case details::e_mul : return "*"; | |
20008 | case details::e_div : return "/"; | |
20009 | case details::e_mod : return "%"; | |
20010 | default : return ""; | |
20011 | } | |
20012 | } | |
20013 | ||
20014 | std::string inequality_opr_to_string(details::operator_type opr) const | |
20015 | { | |
20016 | switch (opr) | |
20017 | { | |
20018 | case details::e_lt : return "<"; | |
20019 | case details::e_lte : return "<="; | |
20020 | case details::e_eq : return "=="; | |
20021 | case details::e_equal : return "="; | |
20022 | case details::e_ne : return "!="; | |
20023 | case details::e_nequal: return "<>"; | |
20024 | case details::e_gte : return ">="; | |
20025 | case details::e_gt : return ">"; | |
20026 | default : return ""; | |
20027 | } | |
20028 | } | |
20029 | ||
20030 | std::string logic_opr_to_string(details::operator_type opr) const | |
20031 | { | |
20032 | switch (opr) | |
20033 | { | |
20034 | case details::e_and : return "and" ; | |
20035 | case details::e_or : return "or" ; | |
20036 | case details::e_xor : return "xor" ; | |
20037 | case details::e_nand : return "nand"; | |
20038 | case details::e_nor : return "nor" ; | |
20039 | case details::e_xnor : return "xnor"; | |
20040 | case details::e_notl : return "not" ; | |
20041 | default : return "" ; | |
20042 | } | |
20043 | } | |
20044 | ||
20045 | bool enable_replacer_; | |
20046 | bool enable_joiner_; | |
20047 | bool enable_numeric_check_; | |
20048 | bool enable_bracket_check_; | |
20049 | bool enable_sequence_check_; | |
20050 | bool enable_commutative_check_; | |
20051 | bool enable_strength_reduction_; | |
20052 | bool enable_collect_vars_; | |
20053 | bool enable_collect_funcs_; | |
20054 | bool enable_collect_assings_; | |
20055 | bool disable_vardef_; | |
20056 | bool disable_rsrvd_sym_usr_; | |
20057 | bool disable_zero_return_; | |
20058 | ||
20059 | disabled_entity_set_t disabled_func_set_ ; | |
20060 | disabled_entity_set_t disabled_ctrl_set_ ; | |
20061 | disabled_entity_set_t disabled_logic_set_; | |
20062 | disabled_entity_set_t disabled_arithmetic_set_; | |
20063 | disabled_entity_set_t disabled_assignment_set_; | |
20064 | disabled_entity_set_t disabled_inequality_set_; | |
20065 | ||
20066 | friend class parser<T>; | |
20067 | }; | |
20068 | ||
20069 | typedef settings_store settings_t; | |
20070 | ||
20071 | parser(const settings_t& settings = settings_t()) | |
20072 | : settings_(settings), | |
20073 | resolve_unknown_symbol_(false), | |
20074 | results_context_(0), | |
20075 | unknown_symbol_resolver_(reinterpret_cast<unknown_symbol_resolver*>(0)), | |
20076 | #ifdef _MSC_VER | |
20077 | #pragma warning(push) | |
20078 | #pragma warning (disable:4355) | |
20079 | #endif | |
20080 | sem_(*this), | |
20081 | #ifdef _MSC_VER | |
20082 | #pragma warning(pop) | |
20083 | #endif | |
20084 | operator_joiner_2_(2), | |
20085 | operator_joiner_3_(3) | |
20086 | { | |
20087 | init_precompilation(); | |
20088 | ||
20089 | load_operations_map (base_ops_map_ ); | |
20090 | load_unary_operations_map (unary_op_map_ ); | |
20091 | load_binary_operations_map (binary_op_map_ ); | |
20092 | load_inv_binary_operations_map(inv_binary_op_map_); | |
20093 | load_sf3_map (sf3_map_ ); | |
20094 | load_sf4_map (sf4_map_ ); | |
20095 | ||
20096 | expression_generator_.init_synthesize_map(); | |
20097 | expression_generator_.set_parser(*this); | |
20098 | expression_generator_.set_uom(unary_op_map_); | |
20099 | expression_generator_.set_bom(binary_op_map_); | |
20100 | expression_generator_.set_ibom(inv_binary_op_map_); | |
20101 | expression_generator_.set_sf3m(sf3_map_); | |
20102 | expression_generator_.set_sf4m(sf4_map_); | |
20103 | expression_generator_.set_strength_reduction_state(settings_.strength_reduction_enabled()); | |
20104 | } | |
20105 | ||
20106 | ~parser() | |
20107 | {} | |
20108 | ||
20109 | inline void init_precompilation() | |
20110 | { | |
20111 | if (settings_.collect_variables_enabled()) | |
20112 | dec_.collect_variables() = true; | |
20113 | ||
20114 | if (settings_.collect_functions_enabled()) | |
20115 | dec_.collect_functions() = true; | |
20116 | ||
20117 | if (settings_.collect_assignments_enabled()) | |
20118 | dec_.collect_assignments() = true; | |
20119 | ||
20120 | if (settings_.replacer_enabled()) | |
20121 | { | |
20122 | symbol_replacer_.clear(); | |
20123 | symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); | |
20124 | symbol_replacer_.add_replace("false", "0", lexer::token::e_number); | |
20125 | helper_assembly_.token_modifier_list.clear(); | |
20126 | helper_assembly_.register_modifier(&symbol_replacer_); | |
20127 | } | |
20128 | ||
20129 | if (settings_.commutative_check_enabled()) | |
20130 | { | |
20131 | for (std::size_t i = 0; i < details::reserved_words_size; ++i) | |
20132 | { | |
20133 | commutative_inserter_.ignore_symbol(details::reserved_words[i]); | |
20134 | } | |
20135 | ||
20136 | helper_assembly_.token_inserter_list.clear(); | |
20137 | helper_assembly_.register_inserter(&commutative_inserter_); | |
20138 | } | |
20139 | ||
20140 | if (settings_.joiner_enabled()) | |
20141 | { | |
20142 | helper_assembly_.token_joiner_list.clear(); | |
20143 | helper_assembly_.register_joiner(&operator_joiner_2_); | |
20144 | helper_assembly_.register_joiner(&operator_joiner_3_); | |
20145 | } | |
20146 | ||
20147 | if ( | |
20148 | settings_.numeric_check_enabled () || | |
20149 | settings_.bracket_check_enabled () || | |
20150 | settings_.sequence_check_enabled() | |
20151 | ) | |
20152 | { | |
20153 | helper_assembly_.token_scanner_list.clear(); | |
20154 | ||
20155 | if (settings_.numeric_check_enabled()) | |
20156 | { | |
20157 | helper_assembly_.register_scanner(&numeric_checker_); | |
20158 | } | |
20159 | ||
20160 | if (settings_.bracket_check_enabled()) | |
20161 | { | |
20162 | helper_assembly_.register_scanner(&bracket_checker_); | |
20163 | } | |
20164 | ||
20165 | if (settings_.sequence_check_enabled()) | |
20166 | { | |
20167 | helper_assembly_.register_scanner(&sequence_validator_ ); | |
20168 | helper_assembly_.register_scanner(&sequence_validator_3tkns_); | |
20169 | } | |
20170 | } | |
20171 | } | |
20172 | ||
20173 | inline bool compile(const std::string& expression_string, expression<T>& expr) | |
20174 | { | |
20175 | state_ .reset(); | |
20176 | error_list_ .clear(); | |
20177 | brkcnt_list_ .clear(); | |
20178 | synthesis_error_.clear(); | |
20179 | sem_ .cleanup(); | |
20180 | ||
20181 | return_cleanup(); | |
20182 | ||
20183 | expression_generator_.set_allocator(node_allocator_); | |
20184 | ||
20185 | if (expression_string.empty()) | |
20186 | { | |
20187 | set_error( | |
20188 | make_error(parser_error::e_syntax, | |
20189 | "ERR000 - Empty expression!", | |
20190 | exprtk_error_location)); | |
20191 | ||
20192 | return false; | |
20193 | } | |
20194 | ||
20195 | if (!init(expression_string)) | |
20196 | { | |
20197 | process_lexer_errors(); | |
20198 | return false; | |
20199 | } | |
20200 | ||
20201 | if (lexer().empty()) | |
20202 | { | |
20203 | set_error( | |
20204 | make_error(parser_error::e_syntax, | |
20205 | "ERR001 - Empty expression!", | |
20206 | exprtk_error_location)); | |
20207 | ||
20208 | return false; | |
20209 | } | |
20210 | ||
20211 | if (!run_assemblies()) | |
20212 | { | |
20213 | return false; | |
20214 | } | |
20215 | ||
20216 | symtab_store_.symtab_list_ = expr.get_symbol_table_list(); | |
20217 | dec_.clear(); | |
20218 | ||
20219 | lexer().begin(); | |
20220 | ||
20221 | next_token(); | |
20222 | ||
20223 | expression_node_ptr e = parse_corpus(); | |
20224 | ||
20225 | if ((0 != e) && (token_t::e_eof == current_token().type)) | |
20226 | { | |
20227 | bool* retinvk_ptr = 0; | |
20228 | ||
20229 | if (state_.return_stmt_present) | |
20230 | { | |
20231 | dec_.return_present_ = true; | |
20232 | ||
20233 | e = expression_generator_ | |
20234 | .return_envelope(e, results_context_, retinvk_ptr); | |
20235 | } | |
20236 | ||
20237 | expr.set_expression(e); | |
20238 | expr.set_retinvk(retinvk_ptr); | |
20239 | ||
20240 | register_local_vars(expr); | |
20241 | register_return_results(expr); | |
20242 | ||
20243 | return !(!expr); | |
20244 | } | |
20245 | else | |
20246 | { | |
20247 | if (error_list_.empty()) | |
20248 | { | |
20249 | set_error( | |
20250 | make_error(parser_error::e_syntax, | |
20251 | current_token(), | |
20252 | "ERR002 - Invalid expression encountered", | |
20253 | exprtk_error_location)); | |
20254 | } | |
20255 | ||
20256 | if ((0 != e) && branch_deletable(e)) | |
20257 | { | |
20258 | destroy_node(e); | |
20259 | } | |
20260 | ||
20261 | dec_.clear (); | |
20262 | sem_.cleanup (); | |
20263 | return_cleanup(); | |
20264 | ||
20265 | return false; | |
20266 | } | |
20267 | } | |
20268 | ||
20269 | inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) | |
20270 | { | |
20271 | expression_t expr; | |
20272 | ||
20273 | expr.register_symbol_table(symtab); | |
20274 | ||
20275 | compile(expression_string,expr); | |
20276 | ||
20277 | return expr; | |
20278 | } | |
20279 | ||
20280 | void process_lexer_errors() | |
20281 | { | |
20282 | for (std::size_t i = 0; i < lexer().size(); ++i) | |
20283 | { | |
20284 | if (lexer()[i].is_error()) | |
20285 | { | |
20286 | std::string diagnostic = "ERR003 - "; | |
20287 | ||
20288 | switch (lexer()[i].type) | |
20289 | { | |
20290 | case lexer::token::e_error : diagnostic += "General token error"; | |
20291 | break; | |
20292 | ||
20293 | case lexer::token::e_err_symbol : diagnostic += "Symbol error"; | |
20294 | break; | |
20295 | ||
20296 | case lexer::token::e_err_number : diagnostic += "Invalid numeric token"; | |
20297 | break; | |
20298 | ||
20299 | case lexer::token::e_err_string : diagnostic += "Invalid string token"; | |
20300 | break; | |
20301 | ||
20302 | case lexer::token::e_err_sfunc : diagnostic += "Invalid special function token"; | |
20303 | break; | |
20304 | ||
20305 | default : diagnostic += "Unknown compiler error"; | |
20306 | } | |
20307 | ||
20308 | set_error( | |
20309 | make_error(parser_error::e_lexer, | |
20310 | lexer()[i], | |
20311 | diagnostic + ": " + lexer()[i].value, | |
20312 | exprtk_error_location)); | |
20313 | } | |
20314 | } | |
20315 | } | |
20316 | ||
20317 | inline bool run_assemblies() | |
20318 | { | |
20319 | if (settings_.commutative_check_enabled()) | |
20320 | { | |
20321 | helper_assembly_.run_inserters(lexer()); | |
20322 | } | |
20323 | ||
20324 | if (settings_.joiner_enabled()) | |
20325 | { | |
20326 | helper_assembly_.run_joiners(lexer()); | |
20327 | } | |
20328 | ||
20329 | if (settings_.replacer_enabled()) | |
20330 | { | |
20331 | helper_assembly_.run_modifiers(lexer()); | |
20332 | } | |
20333 | ||
20334 | if ( | |
20335 | settings_.numeric_check_enabled () || | |
20336 | settings_.bracket_check_enabled () || | |
20337 | settings_.sequence_check_enabled() | |
20338 | ) | |
20339 | { | |
20340 | if (!helper_assembly_.run_scanners(lexer())) | |
20341 | { | |
20342 | if (helper_assembly_.error_token_scanner) | |
20343 | { | |
20344 | lexer::helper::bracket_checker* bracket_checker_ptr = 0; | |
20345 | lexer::helper::numeric_checker* numeric_checker_ptr = 0; | |
20346 | lexer::helper::sequence_validator* sequence_validator_ptr = 0; | |
20347 | lexer::helper::sequence_validator_3tokens* sequence_validator3_ptr = 0; | |
20348 | ||
20349 | if (0 != (bracket_checker_ptr = dynamic_cast<lexer::helper::bracket_checker*>(helper_assembly_.error_token_scanner))) | |
20350 | { | |
20351 | set_error( | |
20352 | make_error(parser_error::e_token, | |
20353 | bracket_checker_ptr->error_token(), | |
20354 | "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", | |
20355 | exprtk_error_location)); | |
20356 | } | |
20357 | else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner))) | |
20358 | { | |
20359 | for (std::size_t i = 0; i < numeric_checker_ptr->error_count(); ++i) | |
20360 | { | |
20361 | lexer::token error_token = lexer()[numeric_checker_ptr->error_index(i)]; | |
20362 | ||
20363 | set_error( | |
20364 | make_error(parser_error::e_token, | |
20365 | error_token, | |
20366 | "ERR005 - Invalid numeric token: '" + error_token.value + "'", | |
20367 | exprtk_error_location)); | |
20368 | } | |
20369 | ||
20370 | if (numeric_checker_ptr->error_count()) | |
20371 | { | |
20372 | numeric_checker_ptr->clear_errors(); | |
20373 | } | |
20374 | } | |
20375 | else if (0 != (sequence_validator_ptr = dynamic_cast<lexer::helper::sequence_validator*>(helper_assembly_.error_token_scanner))) | |
20376 | { | |
20377 | for (std::size_t i = 0; i < sequence_validator_ptr->error_count(); ++i) | |
20378 | { | |
20379 | std::pair<lexer::token,lexer::token> error_token = sequence_validator_ptr->error(i); | |
20380 | ||
20381 | set_error( | |
20382 | make_error(parser_error::e_token, | |
20383 | error_token.first, | |
20384 | "ERR006 - Invalid token sequence: '" + | |
20385 | error_token.first.value + "' and '" + | |
20386 | error_token.second.value + "'", | |
20387 | exprtk_error_location)); | |
20388 | } | |
20389 | ||
20390 | if (sequence_validator_ptr->error_count()) | |
20391 | { | |
20392 | sequence_validator_ptr->clear_errors(); | |
20393 | } | |
20394 | } | |
20395 | else if (0 != (sequence_validator3_ptr = dynamic_cast<lexer::helper::sequence_validator_3tokens*>(helper_assembly_.error_token_scanner))) | |
20396 | { | |
20397 | for (std::size_t i = 0; i < sequence_validator3_ptr->error_count(); ++i) | |
20398 | { | |
20399 | std::pair<lexer::token,lexer::token> error_token = sequence_validator3_ptr->error(i); | |
20400 | ||
20401 | set_error( | |
20402 | make_error(parser_error::e_token, | |
20403 | error_token.first, | |
20404 | "ERR007 - Invalid token sequence: '" + | |
20405 | error_token.first.value + "' and '" + | |
20406 | error_token.second.value + "'", | |
20407 | exprtk_error_location)); | |
20408 | } | |
20409 | ||
20410 | if (sequence_validator3_ptr->error_count()) | |
20411 | { | |
20412 | sequence_validator3_ptr->clear_errors(); | |
20413 | } | |
20414 | } | |
20415 | } | |
20416 | ||
20417 | return false; | |
20418 | } | |
20419 | } | |
20420 | ||
20421 | return true; | |
20422 | } | |
20423 | ||
20424 | inline settings_store& settings() | |
20425 | { | |
20426 | return settings_; | |
20427 | } | |
20428 | ||
20429 | inline parser_error::type get_error(const std::size_t& index) const | |
20430 | { | |
20431 | if (index < error_list_.size()) | |
20432 | return error_list_[index]; | |
20433 | else | |
20434 | throw std::invalid_argument("parser::get_error() - Invalid error index specificed"); | |
20435 | } | |
20436 | ||
20437 | inline std::string error() const | |
20438 | { | |
20439 | if (!error_list_.empty()) | |
20440 | { | |
20441 | return error_list_[0].diagnostic; | |
20442 | } | |
20443 | else | |
20444 | return std::string("No Error"); | |
20445 | } | |
20446 | ||
20447 | inline std::size_t error_count() const | |
20448 | { | |
20449 | return error_list_.size(); | |
20450 | } | |
20451 | ||
20452 | inline dependent_entity_collector& dec() | |
20453 | { | |
20454 | return dec_; | |
20455 | } | |
20456 | ||
20457 | inline bool replace_symbol(const std::string& old_symbol, const std::string& new_symbol) | |
20458 | { | |
20459 | if (!settings_.replacer_enabled()) | |
20460 | return false; | |
20461 | else if (details::is_reserved_word(old_symbol)) | |
20462 | return false; | |
20463 | else | |
20464 | return symbol_replacer_.add_replace(old_symbol,new_symbol,lexer::token::e_symbol); | |
20465 | } | |
20466 | ||
20467 | inline bool remove_replace_symbol(const std::string& symbol) | |
20468 | { | |
20469 | if (!settings_.replacer_enabled()) | |
20470 | return false; | |
20471 | else if (details::is_reserved_word(symbol)) | |
20472 | return false; | |
20473 | else | |
20474 | return symbol_replacer_.remove(symbol); | |
20475 | } | |
20476 | ||
20477 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver* usr = reinterpret_cast<unknown_symbol_resolver*>(0)) | |
20478 | { | |
20479 | resolve_unknown_symbol_ = true; | |
20480 | ||
20481 | if (usr) | |
20482 | unknown_symbol_resolver_ = usr; | |
20483 | else | |
20484 | unknown_symbol_resolver_ = &default_usr_; | |
20485 | } | |
20486 | ||
20487 | inline void enable_unknown_symbol_resolver(unknown_symbol_resolver& usr) | |
20488 | { | |
20489 | enable_unknown_symbol_resolver(&usr); | |
20490 | } | |
20491 | ||
20492 | inline void disable_unknown_symbol_resolver() | |
20493 | { | |
20494 | resolve_unknown_symbol_ = false; | |
20495 | unknown_symbol_resolver_ = &default_usr_; | |
20496 | } | |
20497 | ||
20498 | private: | |
20499 | ||
20500 | inline bool valid_base_operation(const std::string& symbol) const | |
20501 | { | |
20502 | const std::size_t length = symbol.size(); | |
20503 | ||
20504 | if ( | |
20505 | (length < 3) || // Shortest base op symbol length | |
20506 | (length > 9) // Longest base op symbol length | |
20507 | ) | |
20508 | return false; | |
20509 | else | |
20510 | return settings_.function_enabled(symbol) && | |
20511 | (base_ops_map_.end() != base_ops_map_.find(symbol)); | |
20512 | } | |
20513 | ||
20514 | inline bool valid_vararg_operation(const std::string& symbol) const | |
20515 | { | |
20516 | static const std::string s_sum = "sum" ; | |
20517 | static const std::string s_mul = "mul" ; | |
20518 | static const std::string s_avg = "avg" ; | |
20519 | static const std::string s_min = "min" ; | |
20520 | static const std::string s_max = "max" ; | |
20521 | static const std::string s_mand = "mand"; | |
20522 | static const std::string s_mor = "mor" ; | |
20523 | static const std::string s_multi = "~" ; | |
20524 | static const std::string s_mswitch = "[*]" ; | |
20525 | ||
20526 | return | |
20527 | ( | |
20528 | details::imatch(symbol,s_sum ) || | |
20529 | details::imatch(symbol,s_mul ) || | |
20530 | details::imatch(symbol,s_avg ) || | |
20531 | details::imatch(symbol,s_min ) || | |
20532 | details::imatch(symbol,s_max ) || | |
20533 | details::imatch(symbol,s_mand ) || | |
20534 | details::imatch(symbol,s_mor ) || | |
20535 | details::imatch(symbol,s_multi ) || | |
20536 | details::imatch(symbol,s_mswitch) | |
20537 | ) && | |
20538 | settings_.function_enabled(symbol); | |
20539 | } | |
20540 | ||
20541 | bool is_invalid_logic_operation(const details::operator_type operation) const | |
20542 | { | |
20543 | return settings_.logic_disabled(operation); | |
20544 | } | |
20545 | ||
20546 | bool is_invalid_arithmetic_operation(const details::operator_type operation) const | |
20547 | { | |
20548 | return settings_.arithmetic_disabled(operation); | |
20549 | } | |
20550 | ||
20551 | bool is_invalid_assignment_operation(const details::operator_type operation) const | |
20552 | { | |
20553 | return settings_.assignment_disabled(operation); | |
20554 | } | |
20555 | ||
20556 | bool is_invalid_inequality_operation(const details::operator_type operation) const | |
20557 | { | |
20558 | return settings_.inequality_disabled(operation); | |
20559 | } | |
20560 | ||
20561 | #ifdef exprtk_enable_debugging | |
20562 | inline void next_token() | |
20563 | { | |
20564 | const std::string ct_str = current_token().value; | |
20565 | parser_helper::next_token(); | |
20566 | const std::string depth(2 * state_.scope_depth,' '); | |
20567 | exprtk_debug(("%s" | |
20568 | "prev[%s] --> curr[%s]\n", | |
20569 | depth.c_str(), | |
20570 | ct_str.c_str(), | |
20571 | current_token().value.c_str())); | |
20572 | } | |
20573 | #endif | |
20574 | ||
20575 | inline expression_node_ptr parse_corpus() | |
20576 | { | |
20577 | std::vector<expression_node_ptr> arg_list; | |
20578 | std::vector<bool> side_effect_list; | |
20579 | ||
20580 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
20581 | ||
20582 | lexer::token begin_token; | |
20583 | lexer::token end_token; | |
20584 | ||
20585 | for ( ; ; ) | |
20586 | { | |
20587 | state_.side_effect_present = false; | |
20588 | ||
20589 | begin_token = current_token(); | |
20590 | ||
20591 | expression_node_ptr arg = parse_expression(); | |
20592 | ||
20593 | if (0 == arg) | |
20594 | { | |
20595 | if (error_list_.empty()) | |
20596 | { | |
20597 | set_error( | |
20598 | make_error(parser_error::e_syntax, | |
20599 | current_token(), | |
20600 | "ERR008 - Invalid expression encountered", | |
20601 | exprtk_error_location)); | |
20602 | } | |
20603 | ||
20604 | return error_node(); | |
20605 | } | |
20606 | else | |
20607 | { | |
20608 | arg_list.push_back(arg); | |
20609 | ||
20610 | side_effect_list.push_back(state_.side_effect_present); | |
20611 | ||
20612 | end_token = current_token(); | |
20613 | ||
20614 | const std::string sub_expr = construct_subexpr(begin_token, end_token); | |
20615 | ||
20616 | exprtk_debug(("parse_corpus(%02d) Subexpr: %s\n", | |
20617 | static_cast<int>(arg_list.size() - 1), | |
20618 | sub_expr.c_str())); | |
20619 | ||
20620 | exprtk_debug(("parse_corpus(%02d) - Side effect present: %s\n", | |
20621 | static_cast<int>(arg_list.size() - 1), | |
20622 | state_.side_effect_present ? "true" : "false")); | |
20623 | ||
20624 | exprtk_debug(("-------------------------------------------------\n")); | |
20625 | } | |
20626 | ||
20627 | if (lexer().finished()) | |
20628 | break; | |
20629 | else if (token_is(token_t::e_eof,prsrhlpr_t::e_hold)) | |
20630 | { | |
20631 | if (lexer().finished()) | |
20632 | break; | |
20633 | else | |
20634 | next_token(); | |
20635 | } | |
20636 | } | |
20637 | ||
20638 | if ( | |
20639 | !arg_list.empty() && | |
20640 | is_return_node(arg_list.back()) | |
20641 | ) | |
20642 | { | |
20643 | dec_.final_stmt_return_ = true; | |
20644 | } | |
20645 | ||
20646 | const expression_node_ptr result = simplify(arg_list,side_effect_list); | |
20647 | ||
20648 | sdd.delete_ptr = (0 == result); | |
20649 | ||
20650 | return result; | |
20651 | } | |
20652 | ||
20653 | std::string construct_subexpr(lexer::token& begin_token, lexer::token& end_token) | |
20654 | { | |
20655 | std::string result = lexer().substr(begin_token.position,end_token.position); | |
20656 | ||
20657 | for (std::size_t i = 0; i < result.size(); ++i) | |
20658 | { | |
20659 | if (details::is_whitespace(result[i])) result[i] = ' '; | |
20660 | } | |
20661 | ||
20662 | return result; | |
20663 | } | |
20664 | ||
20665 | static const precedence_level default_precedence = e_level00; | |
20666 | ||
20667 | struct state_t | |
20668 | { | |
20669 | inline void set(const precedence_level& l, | |
20670 | const precedence_level& r, | |
20671 | const details::operator_type& o) | |
20672 | { | |
20673 | left = l; | |
20674 | right = r; | |
20675 | operation = o; | |
20676 | } | |
20677 | ||
20678 | inline void reset() | |
20679 | { | |
20680 | left = e_level00; | |
20681 | right = e_level00; | |
20682 | operation = details::e_default; | |
20683 | } | |
20684 | ||
20685 | precedence_level left; | |
20686 | precedence_level right; | |
20687 | details::operator_type operation; | |
20688 | }; | |
20689 | ||
20690 | inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) | |
20691 | { | |
20692 | expression_node_ptr expression = parse_branch(precedence); | |
20693 | ||
20694 | if (0 == expression) | |
20695 | { | |
20696 | return error_node(); | |
20697 | } | |
20698 | ||
20699 | bool break_loop = false; | |
20700 | ||
20701 | state_t current_state; | |
20702 | ||
20703 | for ( ; ; ) | |
20704 | { | |
20705 | current_state.reset(); | |
20706 | ||
20707 | switch (current_token().type) | |
20708 | { | |
20709 | case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break; | |
20710 | case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break; | |
20711 | case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break; | |
20712 | case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break; | |
20713 | case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break; | |
20714 | case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break; | |
20715 | case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break; | |
20716 | case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break; | |
20717 | case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break; | |
20718 | case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break; | |
20719 | case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break; | |
20720 | case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break; | |
20721 | case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break; | |
20722 | case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break; | |
20723 | case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break; | |
20724 | case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break; | |
20725 | case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break; | |
20726 | case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break; | |
20727 | case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break; | |
20728 | default : if (token_t::e_symbol == current_token().type) | |
20729 | { | |
20730 | static const std::string s_and = "and"; | |
20731 | static const std::string s_nand = "nand"; | |
20732 | static const std::string s_or = "or"; | |
20733 | static const std::string s_nor = "nor"; | |
20734 | static const std::string s_xor = "xor"; | |
20735 | static const std::string s_xnor = "xnor"; | |
20736 | static const std::string s_in = "in"; | |
20737 | static const std::string s_like = "like"; | |
20738 | static const std::string s_ilike = "ilike"; | |
20739 | static const std::string s_and1 = "&"; | |
20740 | static const std::string s_or1 = "|"; | |
20741 | static const std::string s_not = "not"; | |
20742 | ||
20743 | if (details::imatch(current_token().value,s_and)) | |
20744 | { | |
20745 | current_state.set(e_level03, e_level04, details::e_and); | |
20746 | break; | |
20747 | } | |
20748 | else if (details::imatch(current_token().value,s_and1)) | |
20749 | { | |
20750 | #ifndef exprtk_disable_sc_andor | |
20751 | current_state.set(e_level03, e_level04, details::e_scand); | |
20752 | #else | |
20753 | current_state.set(e_level03, e_level04, details::e_and); | |
20754 | #endif | |
20755 | break; | |
20756 | } | |
20757 | else if (details::imatch(current_token().value,s_nand)) | |
20758 | { | |
20759 | current_state.set(e_level03, e_level04, details::e_nand); | |
20760 | break; | |
20761 | } | |
20762 | else if (details::imatch(current_token().value,s_or)) | |
20763 | { | |
20764 | current_state.set(e_level01, e_level02, details::e_or); | |
20765 | break; | |
20766 | } | |
20767 | else if (details::imatch(current_token().value,s_or1)) | |
20768 | { | |
20769 | #ifndef exprtk_disable_sc_andor | |
20770 | current_state.set(e_level01, e_level02, details::e_scor); | |
20771 | #else | |
20772 | current_state.set(e_level01, e_level02, details::e_or); | |
20773 | #endif | |
20774 | break; | |
20775 | } | |
20776 | else if (details::imatch(current_token().value,s_nor)) | |
20777 | { | |
20778 | current_state.set(e_level01, e_level02, details::e_nor); | |
20779 | break; | |
20780 | } | |
20781 | else if (details::imatch(current_token().value,s_xor)) | |
20782 | { | |
20783 | current_state.set(e_level01, e_level02, details::e_xor); | |
20784 | break; | |
20785 | } | |
20786 | else if (details::imatch(current_token().value,s_xnor)) | |
20787 | { | |
20788 | current_state.set(e_level01, e_level02, details::e_xnor); | |
20789 | break; | |
20790 | } | |
20791 | else if (details::imatch(current_token().value,s_in)) | |
20792 | { | |
20793 | current_state.set(e_level04, e_level04, details::e_in); | |
20794 | break; | |
20795 | } | |
20796 | else if (details::imatch(current_token().value,s_like)) | |
20797 | { | |
20798 | current_state.set(e_level04, e_level04, details::e_like); | |
20799 | break; | |
20800 | } | |
20801 | else if (details::imatch(current_token().value,s_ilike)) | |
20802 | { | |
20803 | current_state.set(e_level04, e_level04, details::e_ilike); | |
20804 | break; | |
20805 | } | |
20806 | else if (details::imatch(current_token().value,s_not)) | |
20807 | { | |
20808 | break; | |
20809 | } | |
20810 | } | |
20811 | ||
20812 | break_loop = true; | |
20813 | } | |
20814 | ||
20815 | if (break_loop) | |
20816 | { | |
20817 | parse_pending_string_rangesize(expression); | |
20818 | break; | |
20819 | } | |
20820 | else if (current_state.left < precedence) | |
20821 | break; | |
20822 | ||
20823 | const lexer::token prev_token = current_token(); | |
20824 | ||
20825 | next_token(); | |
20826 | ||
20827 | expression_node_ptr right_branch = error_node(); | |
20828 | expression_node_ptr new_expression = error_node(); | |
20829 | ||
20830 | if (is_invalid_logic_operation(current_state.operation)) | |
20831 | { | |
20832 | free_node(node_allocator_,expression); | |
20833 | ||
20834 | set_error( | |
20835 | make_error(parser_error::e_syntax, | |
20836 | prev_token, | |
20837 | "ERR009 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", | |
20838 | exprtk_error_location)); | |
20839 | ||
20840 | return error_node(); | |
20841 | } | |
20842 | else if (is_invalid_arithmetic_operation(current_state.operation)) | |
20843 | { | |
20844 | free_node(node_allocator_,expression); | |
20845 | ||
20846 | set_error( | |
20847 | make_error(parser_error::e_syntax, | |
20848 | prev_token, | |
20849 | "ERR010 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", | |
20850 | exprtk_error_location)); | |
20851 | ||
20852 | return error_node(); | |
20853 | } | |
20854 | else if (is_invalid_inequality_operation(current_state.operation)) | |
20855 | { | |
20856 | free_node(node_allocator_,expression); | |
20857 | ||
20858 | set_error( | |
20859 | make_error(parser_error::e_syntax, | |
20860 | prev_token, | |
20861 | "ERR011 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", | |
20862 | exprtk_error_location)); | |
20863 | ||
20864 | return error_node(); | |
20865 | } | |
20866 | else if (is_invalid_assignment_operation(current_state.operation)) | |
20867 | { | |
20868 | free_node(node_allocator_,expression); | |
20869 | ||
20870 | set_error( | |
20871 | make_error(parser_error::e_syntax, | |
20872 | prev_token, | |
20873 | "ERR012 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", | |
20874 | exprtk_error_location)); | |
20875 | ||
20876 | return error_node(); | |
20877 | } | |
20878 | ||
20879 | if (0 != (right_branch = parse_expression(current_state.right))) | |
20880 | { | |
20881 | if ( | |
20882 | details::is_return_node( expression) || | |
20883 | details::is_return_node(right_branch) | |
20884 | ) | |
20885 | { | |
20886 | free_node(node_allocator_, expression); | |
20887 | free_node(node_allocator_, right_branch); | |
20888 | ||
20889 | set_error( | |
20890 | make_error(parser_error::e_syntax, | |
20891 | prev_token, | |
20892 | "ERR013 - Return statements cannot be part of sub-expressions", | |
20893 | exprtk_error_location)); | |
20894 | ||
20895 | return error_node(); | |
20896 | } | |
20897 | ||
20898 | new_expression = expression_generator_ | |
20899 | ( | |
20900 | current_state.operation, | |
20901 | expression, | |
20902 | right_branch | |
20903 | ); | |
20904 | } | |
20905 | ||
20906 | if (0 == new_expression) | |
20907 | { | |
20908 | if (error_list_.empty()) | |
20909 | { | |
20910 | set_error( | |
20911 | make_error(parser_error::e_syntax, | |
20912 | prev_token, | |
20913 | !synthesis_error_.empty() ? | |
20914 | synthesis_error_ : | |
20915 | "ERR014 - General parsing error at token: '" + prev_token.value + "'", | |
20916 | exprtk_error_location)); | |
20917 | } | |
20918 | ||
20919 | free_node(node_allocator_, expression); | |
20920 | free_node(node_allocator_, right_branch); | |
20921 | ||
20922 | return error_node(); | |
20923 | } | |
20924 | else | |
20925 | { | |
20926 | if ( | |
20927 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) && | |
20928 | (precedence == e_level00) | |
20929 | ) | |
20930 | { | |
20931 | expression = parse_ternary_conditional_statement(new_expression); | |
20932 | } | |
20933 | else | |
20934 | expression = new_expression; | |
20935 | ||
20936 | parse_pending_string_rangesize(expression); | |
20937 | } | |
20938 | } | |
20939 | ||
20940 | return expression; | |
20941 | } | |
20942 | ||
20943 | bool simplify_unary_negation_branch(expression_node_ptr& node) | |
20944 | { | |
20945 | { | |
20946 | typedef details::unary_branch_node<T,details::neg_op<T> > ubn_t; | |
20947 | ubn_t* n = dynamic_cast<ubn_t*>(node); | |
20948 | ||
20949 | if (n) | |
20950 | { | |
20951 | expression_node_ptr un_r = n->branch(0); | |
20952 | n->release(); | |
20953 | free_node(node_allocator_,node); | |
20954 | node = un_r; | |
20955 | ||
20956 | return true; | |
20957 | } | |
20958 | } | |
20959 | ||
20960 | { | |
20961 | typedef details::unary_variable_node<T,details::neg_op<T> > uvn_t; | |
20962 | ||
20963 | uvn_t* n = dynamic_cast<uvn_t*>(node); | |
20964 | ||
20965 | if (n) | |
20966 | { | |
20967 | const T& v = n->v(); | |
20968 | expression_node_ptr return_node = error_node(); | |
20969 | ||
20970 | if ( | |
20971 | (0 != (return_node = symtab_store_.get_variable(v))) || | |
20972 | (0 != (return_node = sem_ .get_variable(v))) | |
20973 | ) | |
20974 | { | |
20975 | free_node(node_allocator_,node); | |
20976 | node = return_node; | |
20977 | ||
20978 | return true; | |
20979 | } | |
20980 | else | |
20981 | { | |
20982 | set_error( | |
20983 | make_error(parser_error::e_syntax, | |
20984 | current_token(), | |
20985 | "ERR015 - Failed to find variable node in symbol table", | |
20986 | exprtk_error_location)); | |
20987 | ||
20988 | free_node(node_allocator_,node); | |
20989 | ||
20990 | return false; | |
20991 | } | |
20992 | } | |
20993 | } | |
20994 | ||
20995 | return false; | |
20996 | } | |
20997 | ||
20998 | static inline expression_node_ptr error_node() | |
20999 | { | |
21000 | return reinterpret_cast<expression_node_ptr>(0); | |
21001 | } | |
21002 | ||
21003 | template <typename Type, std::size_t N> | |
21004 | struct scoped_delete | |
21005 | { | |
21006 | typedef Type* ptr_t; | |
21007 | ||
21008 | scoped_delete(parser<T>& pr, ptr_t& p) | |
21009 | : delete_ptr(true), | |
21010 | parser_(pr), | |
21011 | p_(&p) | |
21012 | {} | |
21013 | ||
21014 | scoped_delete(parser<T>& pr, ptr_t (&p)[N]) | |
21015 | : delete_ptr(true), | |
21016 | parser_(pr), | |
21017 | p_(&p[0]) | |
21018 | {} | |
21019 | ||
21020 | ~scoped_delete() | |
21021 | { | |
21022 | if (delete_ptr) | |
21023 | { | |
21024 | for (std::size_t i = 0; i < N; ++i) | |
21025 | { | |
21026 | free_node(parser_.node_allocator_,p_[i]); | |
21027 | } | |
21028 | } | |
21029 | } | |
21030 | ||
21031 | bool delete_ptr; | |
21032 | parser<T>& parser_; | |
21033 | ptr_t* p_; | |
21034 | ||
21035 | private: | |
21036 | ||
21037 | scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&); | |
21038 | }; | |
21039 | ||
21040 | template <typename Type> | |
21041 | struct scoped_deq_delete | |
21042 | { | |
21043 | typedef Type* ptr_t; | |
21044 | ||
21045 | scoped_deq_delete(parser<T>& pr, std::deque<ptr_t>& deq) | |
21046 | : delete_ptr(true), | |
21047 | parser_(pr), | |
21048 | deq_(deq) | |
21049 | {} | |
21050 | ||
21051 | ~scoped_deq_delete() | |
21052 | { | |
21053 | if (delete_ptr && !deq_.empty()) | |
21054 | { | |
21055 | for (std::size_t i = 0; i < deq_.size(); ++i) | |
21056 | { | |
21057 | free_node(parser_.node_allocator_,deq_[i]); | |
21058 | } | |
21059 | ||
21060 | deq_.clear(); | |
21061 | } | |
21062 | } | |
21063 | ||
21064 | bool delete_ptr; | |
21065 | parser<T>& parser_; | |
21066 | std::deque<ptr_t>& deq_; | |
21067 | ||
21068 | private: | |
21069 | ||
21070 | scoped_deq_delete<Type>& operator=(const scoped_deq_delete<Type>&); | |
21071 | }; | |
21072 | ||
21073 | template <typename Type> | |
21074 | struct scoped_vec_delete | |
21075 | { | |
21076 | typedef Type* ptr_t; | |
21077 | ||
21078 | scoped_vec_delete(parser<T>& pr, std::vector<ptr_t>& vec) | |
21079 | : delete_ptr(true), | |
21080 | parser_(pr), | |
21081 | vec_(vec) | |
21082 | {} | |
21083 | ||
21084 | ~scoped_vec_delete() | |
21085 | { | |
21086 | if (delete_ptr && !vec_.empty()) | |
21087 | { | |
21088 | for (std::size_t i = 0; i < vec_.size(); ++i) | |
21089 | { | |
21090 | free_node(parser_.node_allocator_,vec_[i]); | |
21091 | } | |
21092 | ||
21093 | vec_.clear(); | |
21094 | } | |
21095 | } | |
21096 | ||
21097 | bool delete_ptr; | |
21098 | parser<T>& parser_; | |
21099 | std::vector<ptr_t>& vec_; | |
21100 | ||
21101 | private: | |
21102 | ||
21103 | scoped_vec_delete<Type>& operator=(const scoped_vec_delete<Type>&); | |
21104 | }; | |
21105 | ||
21106 | struct scoped_bool_negator | |
21107 | { | |
21108 | explicit scoped_bool_negator(bool& bb) | |
21109 | : b(bb) | |
21110 | { b = !b; } | |
21111 | ||
21112 | ~scoped_bool_negator() | |
21113 | { b = !b; } | |
21114 | ||
21115 | bool& b; | |
21116 | }; | |
21117 | ||
21118 | struct scoped_bool_or_restorer | |
21119 | { | |
21120 | explicit scoped_bool_or_restorer(bool& bb) | |
21121 | : b(bb), | |
21122 | original_value_(bb) | |
21123 | {} | |
21124 | ||
21125 | ~scoped_bool_or_restorer() | |
21126 | { | |
21127 | b = b || original_value_; | |
21128 | } | |
21129 | ||
21130 | bool& b; | |
21131 | bool original_value_; | |
21132 | }; | |
21133 | ||
21134 | inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) | |
21135 | { | |
21136 | expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); | |
21137 | ||
21138 | switch (function->param_count) | |
21139 | { | |
21140 | case 0 : func_node = parse_function_call_0 (function,function_name); break; | |
21141 | case 1 : func_node = parse_function_call< 1>(function,function_name); break; | |
21142 | case 2 : func_node = parse_function_call< 2>(function,function_name); break; | |
21143 | case 3 : func_node = parse_function_call< 3>(function,function_name); break; | |
21144 | case 4 : func_node = parse_function_call< 4>(function,function_name); break; | |
21145 | case 5 : func_node = parse_function_call< 5>(function,function_name); break; | |
21146 | case 6 : func_node = parse_function_call< 6>(function,function_name); break; | |
21147 | case 7 : func_node = parse_function_call< 7>(function,function_name); break; | |
21148 | case 8 : func_node = parse_function_call< 8>(function,function_name); break; | |
21149 | case 9 : func_node = parse_function_call< 9>(function,function_name); break; | |
21150 | case 10 : func_node = parse_function_call<10>(function,function_name); break; | |
21151 | case 11 : func_node = parse_function_call<11>(function,function_name); break; | |
21152 | case 12 : func_node = parse_function_call<12>(function,function_name); break; | |
21153 | case 13 : func_node = parse_function_call<13>(function,function_name); break; | |
21154 | case 14 : func_node = parse_function_call<14>(function,function_name); break; | |
21155 | case 15 : func_node = parse_function_call<15>(function,function_name); break; | |
21156 | case 16 : func_node = parse_function_call<16>(function,function_name); break; | |
21157 | case 17 : func_node = parse_function_call<17>(function,function_name); break; | |
21158 | case 18 : func_node = parse_function_call<18>(function,function_name); break; | |
21159 | case 19 : func_node = parse_function_call<19>(function,function_name); break; | |
21160 | case 20 : func_node = parse_function_call<20>(function,function_name); break; | |
21161 | default : { | |
21162 | set_error( | |
21163 | make_error(parser_error::e_syntax, | |
21164 | current_token(), | |
21165 | "ERR016 - Invalid number of parameters for function: '" + function_name + "'", | |
21166 | exprtk_error_location)); | |
21167 | ||
21168 | return error_node(); | |
21169 | } | |
21170 | } | |
21171 | ||
21172 | if (func_node) | |
21173 | return func_node; | |
21174 | else | |
21175 | { | |
21176 | set_error( | |
21177 | make_error(parser_error::e_syntax, | |
21178 | current_token(), | |
21179 | "ERR017 - Failed to generate call to function: '" + function_name + "'", | |
21180 | exprtk_error_location)); | |
21181 | ||
21182 | return error_node(); | |
21183 | } | |
21184 | } | |
21185 | ||
21186 | template <std::size_t NumberofParameters> | |
21187 | inline expression_node_ptr parse_function_call(ifunction<T>* function, const std::string& function_name) | |
21188 | { | |
21189 | #ifdef _MSC_VER | |
21190 | #pragma warning(push) | |
21191 | #pragma warning(disable: 4127) | |
21192 | #endif | |
21193 | if (0 == NumberofParameters) | |
21194 | { | |
21195 | set_error( | |
21196 | make_error(parser_error::e_syntax, | |
21197 | current_token(), | |
21198 | "ERR018 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", | |
21199 | exprtk_error_location)); | |
21200 | ||
21201 | return error_node(); | |
21202 | } | |
21203 | #ifdef _MSC_VER | |
21204 | #pragma warning(pop) | |
21205 | #endif | |
21206 | ||
21207 | expression_node_ptr branch[NumberofParameters]; | |
21208 | expression_node_ptr result = error_node(); | |
21209 | ||
21210 | std::fill_n(branch, NumberofParameters, reinterpret_cast<expression_node_ptr>(0)); | |
21211 | ||
21212 | scoped_delete<expression_node_t,NumberofParameters> sd((*this),branch); | |
21213 | ||
21214 | next_token(); | |
21215 | ||
21216 | if (!token_is(token_t::e_lbracket)) | |
21217 | { | |
21218 | set_error( | |
21219 | make_error(parser_error::e_syntax, | |
21220 | current_token(), | |
21221 | "ERR019 - Expecting argument list for function: '" + function_name + "'", | |
21222 | exprtk_error_location)); | |
21223 | ||
21224 | return error_node(); | |
21225 | } | |
21226 | ||
21227 | for (int i = 0; i < static_cast<int>(NumberofParameters); ++i) | |
21228 | { | |
21229 | branch[i] = parse_expression(); | |
21230 | ||
21231 | if (0 == branch[i]) | |
21232 | { | |
21233 | set_error( | |
21234 | make_error(parser_error::e_syntax, | |
21235 | current_token(), | |
21236 | "ERR020 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", | |
21237 | exprtk_error_location)); | |
21238 | ||
21239 | return error_node(); | |
21240 | } | |
21241 | else if (i < static_cast<int>(NumberofParameters - 1)) | |
21242 | { | |
21243 | if (!token_is(token_t::e_comma)) | |
21244 | { | |
21245 | set_error( | |
21246 | make_error(parser_error::e_syntax, | |
21247 | current_token(), | |
21248 | "ERR021 - Invalid number of arguments for function: '" + function_name + "'", | |
21249 | exprtk_error_location)); | |
21250 | ||
21251 | return error_node(); | |
21252 | } | |
21253 | } | |
21254 | } | |
21255 | ||
21256 | if (!token_is(token_t::e_rbracket)) | |
21257 | { | |
21258 | set_error( | |
21259 | make_error(parser_error::e_syntax, | |
21260 | current_token(), | |
21261 | "ERR022 - Invalid number of arguments for function: '" + function_name + "'", | |
21262 | exprtk_error_location)); | |
21263 | ||
21264 | return error_node(); | |
21265 | } | |
21266 | else | |
21267 | result = expression_generator_.function(function,branch); | |
21268 | ||
21269 | sd.delete_ptr = false; | |
21270 | ||
21271 | return result; | |
21272 | } | |
21273 | ||
21274 | inline expression_node_ptr parse_function_call_0(ifunction<T>* function, const std::string& function_name) | |
21275 | { | |
21276 | expression_node_ptr result = expression_generator_.function(function); | |
21277 | ||
21278 | state_.side_effect_present = function->has_side_effects(); | |
21279 | ||
21280 | next_token(); | |
21281 | ||
21282 | if ( | |
21283 | token_is(token_t::e_lbracket) && | |
21284 | !token_is(token_t::e_rbracket) | |
21285 | ) | |
21286 | { | |
21287 | set_error( | |
21288 | make_error(parser_error::e_syntax, | |
21289 | current_token(), | |
21290 | "ERR023 - Expecting '()' to proceed call to function: '" + function_name + "'", | |
21291 | exprtk_error_location)); | |
21292 | ||
21293 | free_node(node_allocator_,result); | |
21294 | ||
21295 | return error_node(); | |
21296 | } | |
21297 | else | |
21298 | return result; | |
21299 | } | |
21300 | ||
21301 | template <std::size_t MaxNumberofParameters> | |
21302 | inline std::size_t parse_base_function_call(expression_node_ptr (¶m_list)[MaxNumberofParameters], const std::string& function_name = "") | |
21303 | { | |
21304 | std::fill_n(param_list, MaxNumberofParameters, reinterpret_cast<expression_node_ptr>(0)); | |
21305 | ||
21306 | scoped_delete<expression_node_t,MaxNumberofParameters> sd((*this),param_list); | |
21307 | ||
21308 | next_token(); | |
21309 | ||
21310 | if (!token_is(token_t::e_lbracket)) | |
21311 | { | |
21312 | set_error( | |
21313 | make_error(parser_error::e_syntax, | |
21314 | current_token(), | |
21315 | "ERR024 - Expected a '(' at start of function call to '" + function_name + | |
21316 | "', instead got: '" + current_token().value + "'", | |
21317 | exprtk_error_location)); | |
21318 | ||
21319 | return 0; | |
21320 | } | |
21321 | ||
21322 | if (token_is(token_t::e_rbracket, e_hold)) | |
21323 | { | |
21324 | set_error( | |
21325 | make_error(parser_error::e_syntax, | |
21326 | current_token(), | |
21327 | "ERR025 - Expected at least one input parameter for function call '" + function_name + "'", | |
21328 | exprtk_error_location)); | |
21329 | ||
21330 | return 0; | |
21331 | } | |
21332 | ||
21333 | std::size_t param_index = 0; | |
21334 | ||
21335 | for (; param_index < MaxNumberofParameters; ++param_index) | |
21336 | { | |
21337 | param_list[param_index] = parse_expression(); | |
21338 | ||
21339 | if (0 == param_list[param_index]) | |
21340 | return 0; | |
21341 | else if (token_is(token_t::e_rbracket)) | |
21342 | { | |
21343 | sd.delete_ptr = false; | |
21344 | break; | |
21345 | } | |
21346 | else if (token_is(token_t::e_comma)) | |
21347 | continue; | |
21348 | else | |
21349 | { | |
21350 | set_error( | |
21351 | make_error(parser_error::e_syntax, | |
21352 | current_token(), | |
21353 | "ERR026 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", | |
21354 | exprtk_error_location)); | |
21355 | ||
21356 | return 0; | |
21357 | } | |
21358 | } | |
21359 | ||
21360 | if (sd.delete_ptr) | |
21361 | { | |
21362 | set_error( | |
21363 | make_error(parser_error::e_syntax, | |
21364 | current_token(), | |
21365 | "ERR027 - Invalid number of input parameters passed to function '" + function_name + "'", | |
21366 | exprtk_error_location)); | |
21367 | ||
21368 | return 0; | |
21369 | } | |
21370 | ||
21371 | return (param_index + 1); | |
21372 | } | |
21373 | ||
21374 | inline expression_node_ptr parse_base_operation() | |
21375 | { | |
21376 | typedef std::pair<base_ops_map_t::iterator,base_ops_map_t::iterator> map_range_t; | |
21377 | ||
21378 | const std::string operation_name = current_token().value; | |
21379 | const token_t diagnostic_token = current_token(); | |
21380 | ||
21381 | map_range_t itr_range = base_ops_map_.equal_range(operation_name); | |
21382 | ||
21383 | if (0 == std::distance(itr_range.first,itr_range.second)) | |
21384 | { | |
21385 | set_error( | |
21386 | make_error(parser_error::e_syntax, | |
21387 | diagnostic_token, | |
21388 | "ERR028 - No entry found for base operation: " + operation_name, | |
21389 | exprtk_error_location)); | |
21390 | ||
21391 | return error_node(); | |
21392 | } | |
21393 | ||
21394 | static const std::size_t MaxNumberofParameters = 4; | |
21395 | expression_node_ptr param_list[MaxNumberofParameters] = {0}; | |
21396 | ||
21397 | const std::size_t parameter_count = parse_base_function_call(param_list, operation_name); | |
21398 | ||
21399 | if ((parameter_count > 0) && (parameter_count <= MaxNumberofParameters)) | |
21400 | { | |
21401 | for (base_ops_map_t::iterator itr = itr_range.first; itr != itr_range.second; ++itr) | |
21402 | { | |
21403 | const details::base_operation_t& operation = itr->second; | |
21404 | ||
21405 | if (operation.num_params == parameter_count) | |
21406 | { | |
21407 | switch (parameter_count) | |
21408 | { | |
21409 | #define base_opr_case(N) \ | |
21410 | case N : { \ | |
21411 | expression_node_ptr pl##N[N] = {0}; \ | |
21412 | std::copy(param_list, param_list + N, pl##N); \ | |
21413 | lodge_symbol(operation_name, e_st_function); \ | |
21414 | return expression_generator_(operation.type, pl##N); \ | |
21415 | } \ | |
21416 | ||
21417 | base_opr_case(1) | |
21418 | base_opr_case(2) | |
21419 | base_opr_case(3) | |
21420 | base_opr_case(4) | |
21421 | #undef base_opr_case | |
21422 | } | |
21423 | } | |
21424 | } | |
21425 | } | |
21426 | ||
21427 | for (std::size_t i = 0; i < MaxNumberofParameters; ++i) | |
21428 | { | |
21429 | free_node(node_allocator_, param_list[i]); | |
21430 | } | |
21431 | ||
21432 | set_error( | |
21433 | make_error(parser_error::e_syntax, | |
21434 | diagnostic_token, | |
21435 | "ERR029 - Invalid number of input parameters for call to function: '" + operation_name + "'", | |
21436 | exprtk_error_location)); | |
21437 | ||
21438 | return error_node(); | |
21439 | } | |
21440 | ||
21441 | inline expression_node_ptr parse_conditional_statement_01(expression_node_ptr condition) | |
21442 | { | |
21443 | // Parse: [if][(][condition][,][consequent][,][alternative][)] | |
21444 | ||
21445 | expression_node_ptr consequent = error_node(); | |
21446 | expression_node_ptr alternative = error_node(); | |
21447 | ||
21448 | bool result = true; | |
21449 | ||
21450 | if (!token_is(token_t::e_comma)) | |
21451 | { | |
21452 | set_error( | |
21453 | make_error(parser_error::e_syntax, | |
21454 | current_token(), | |
21455 | "ERR030 - Expected ',' between if-statement condition and consequent", | |
21456 | exprtk_error_location)); | |
21457 | result = false; | |
21458 | } | |
21459 | else if (0 == (consequent = parse_expression())) | |
21460 | { | |
21461 | set_error( | |
21462 | make_error(parser_error::e_syntax, | |
21463 | current_token(), | |
21464 | "ERR031 - Failed to parse consequent for if-statement", | |
21465 | exprtk_error_location)); | |
21466 | result = false; | |
21467 | } | |
21468 | else if (!token_is(token_t::e_comma)) | |
21469 | { | |
21470 | set_error( | |
21471 | make_error(parser_error::e_syntax, | |
21472 | current_token(), | |
21473 | "ERR032 - Expected ',' between if-statement consequent and alternative", | |
21474 | exprtk_error_location)); | |
21475 | result = false; | |
21476 | } | |
21477 | else if (0 == (alternative = parse_expression())) | |
21478 | { | |
21479 | set_error( | |
21480 | make_error(parser_error::e_syntax, | |
21481 | current_token(), | |
21482 | "ERR033 - Failed to parse alternative for if-statement", | |
21483 | exprtk_error_location)); | |
21484 | result = false; | |
21485 | } | |
21486 | else if (!token_is(token_t::e_rbracket)) | |
21487 | { | |
21488 | set_error( | |
21489 | make_error(parser_error::e_syntax, | |
21490 | current_token(), | |
21491 | "ERR034 - Expected ')' at the end of if-statement", | |
21492 | exprtk_error_location)); | |
21493 | result = false; | |
21494 | } | |
21495 | ||
21496 | #ifndef exprtk_disable_string_capabilities | |
21497 | if (result) | |
21498 | { | |
21499 | const bool consq_is_str = is_generally_string_node( consequent); | |
21500 | const bool alter_is_str = is_generally_string_node(alternative); | |
21501 | ||
21502 | if (consq_is_str || alter_is_str) | |
21503 | { | |
21504 | if (consq_is_str && alter_is_str) | |
21505 | { | |
21506 | return expression_generator_ | |
21507 | .conditional_string(condition, consequent, alternative); | |
21508 | } | |
21509 | ||
21510 | set_error( | |
21511 | make_error(parser_error::e_syntax, | |
21512 | current_token(), | |
21513 | "ERR035 - Return types of ternary if-statement differ", | |
21514 | exprtk_error_location)); | |
21515 | ||
21516 | result = false; | |
21517 | } | |
21518 | } | |
21519 | #endif | |
21520 | ||
21521 | if (!result) | |
21522 | { | |
21523 | free_node(node_allocator_, condition); | |
21524 | free_node(node_allocator_, consequent); | |
21525 | free_node(node_allocator_,alternative); | |
21526 | ||
21527 | return error_node(); | |
21528 | } | |
21529 | else | |
21530 | return expression_generator_ | |
21531 | .conditional(condition, consequent, alternative); | |
21532 | } | |
21533 | ||
21534 | inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) | |
21535 | { | |
21536 | expression_node_ptr consequent = error_node(); | |
21537 | expression_node_ptr alternative = error_node(); | |
21538 | ||
21539 | bool result = true; | |
21540 | ||
21541 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) | |
21542 | { | |
21543 | if (0 == (consequent = parse_multi_sequence("if-statement-01"))) | |
21544 | { | |
21545 | set_error( | |
21546 | make_error(parser_error::e_syntax, | |
21547 | current_token(), | |
21548 | "ERR036 - Failed to parse body of consequent for if-statement", | |
21549 | exprtk_error_location)); | |
21550 | ||
21551 | result = false; | |
21552 | } | |
21553 | } | |
21554 | else | |
21555 | { | |
21556 | if ( | |
21557 | settings_.commutative_check_enabled() && | |
21558 | token_is(token_t::e_mul,prsrhlpr_t::e_hold) | |
21559 | ) | |
21560 | { | |
21561 | next_token(); | |
21562 | } | |
21563 | ||
21564 | if (0 != (consequent = parse_expression())) | |
21565 | { | |
21566 | if (!token_is(token_t::e_eof)) | |
21567 | { | |
21568 | set_error( | |
21569 | make_error(parser_error::e_syntax, | |
21570 | current_token(), | |
21571 | "ERR037 - Expected ';' at the end of the consequent for if-statement", | |
21572 | exprtk_error_location)); | |
21573 | ||
21574 | result = false; | |
21575 | } | |
21576 | } | |
21577 | else | |
21578 | { | |
21579 | set_error( | |
21580 | make_error(parser_error::e_syntax, | |
21581 | current_token(), | |
21582 | "ERR038 - Failed to parse body of consequent for if-statement", | |
21583 | exprtk_error_location)); | |
21584 | ||
21585 | result = false; | |
21586 | } | |
21587 | } | |
21588 | ||
21589 | if (result) | |
21590 | { | |
21591 | if (details::imatch(current_token().value,"else")) | |
21592 | { | |
21593 | next_token(); | |
21594 | ||
21595 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) | |
21596 | { | |
21597 | if (0 == (alternative = parse_multi_sequence("else-statement-01"))) | |
21598 | { | |
21599 | set_error( | |
21600 | make_error(parser_error::e_syntax, | |
21601 | current_token(), | |
21602 | "ERR039 - Failed to parse body of the 'else' for if-statement", | |
21603 | exprtk_error_location)); | |
21604 | ||
21605 | result = false; | |
21606 | } | |
21607 | } | |
21608 | else if (details::imatch(current_token().value,"if")) | |
21609 | { | |
21610 | if (0 == (alternative = parse_conditional_statement())) | |
21611 | { | |
21612 | set_error( | |
21613 | make_error(parser_error::e_syntax, | |
21614 | current_token(), | |
21615 | "ERR040 - Failed to parse body of if-else statement", | |
21616 | exprtk_error_location)); | |
21617 | ||
21618 | result = false; | |
21619 | } | |
21620 | } | |
21621 | else if (0 != (alternative = parse_expression())) | |
21622 | { | |
21623 | if (!token_is(token_t::e_eof)) | |
21624 | { | |
21625 | set_error( | |
21626 | make_error(parser_error::e_syntax, | |
21627 | current_token(), | |
21628 | "ERR041 - Expected ';' at the end of the 'else-if' for the if-statement", | |
21629 | exprtk_error_location)); | |
21630 | ||
21631 | result = false; | |
21632 | } | |
21633 | } | |
21634 | else | |
21635 | { | |
21636 | set_error( | |
21637 | make_error(parser_error::e_syntax, | |
21638 | current_token(), | |
21639 | "ERR042 - Failed to parse body of the 'else' for if-statement", | |
21640 | exprtk_error_location)); | |
21641 | ||
21642 | result = false; | |
21643 | } | |
21644 | } | |
21645 | } | |
21646 | ||
21647 | #ifndef exprtk_disable_string_capabilities | |
21648 | if (result) | |
21649 | { | |
21650 | const bool consq_is_str = is_generally_string_node( consequent); | |
21651 | const bool alter_is_str = is_generally_string_node(alternative); | |
21652 | ||
21653 | if (consq_is_str || alter_is_str) | |
21654 | { | |
21655 | if (consq_is_str && alter_is_str) | |
21656 | { | |
21657 | return expression_generator_ | |
21658 | .conditional_string(condition, consequent, alternative); | |
21659 | } | |
21660 | ||
21661 | set_error( | |
21662 | make_error(parser_error::e_syntax, | |
21663 | current_token(), | |
21664 | "ERR043 - Return types of ternary if-statement differ", | |
21665 | exprtk_error_location)); | |
21666 | ||
21667 | result = false; | |
21668 | } | |
21669 | } | |
21670 | #endif | |
21671 | ||
21672 | if (!result) | |
21673 | { | |
21674 | free_node(node_allocator_, condition); | |
21675 | free_node(node_allocator_, consequent); | |
21676 | free_node(node_allocator_, alternative); | |
21677 | ||
21678 | return error_node(); | |
21679 | } | |
21680 | else | |
21681 | return expression_generator_ | |
21682 | .conditional(condition, consequent, alternative); | |
21683 | } | |
21684 | ||
21685 | inline expression_node_ptr parse_conditional_statement() | |
21686 | { | |
21687 | expression_node_ptr condition = error_node(); | |
21688 | ||
21689 | next_token(); | |
21690 | ||
21691 | if (!token_is(token_t::e_lbracket)) | |
21692 | { | |
21693 | set_error( | |
21694 | make_error(parser_error::e_syntax, | |
21695 | current_token(), | |
21696 | "ERR044 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", | |
21697 | exprtk_error_location)); | |
21698 | ||
21699 | return error_node(); | |
21700 | } | |
21701 | else if (0 == (condition = parse_expression())) | |
21702 | { | |
21703 | set_error( | |
21704 | make_error(parser_error::e_syntax, | |
21705 | current_token(), | |
21706 | "ERR045 - Failed to parse condition for if-statement", | |
21707 | exprtk_error_location)); | |
21708 | ||
21709 | return error_node(); | |
21710 | } | |
21711 | else if (token_is(token_t::e_comma,prsrhlpr_t::e_hold)) | |
21712 | { | |
21713 | // if (x,y,z) | |
21714 | return parse_conditional_statement_01(condition); | |
21715 | } | |
21716 | else if (token_is(token_t::e_rbracket)) | |
21717 | { | |
21718 | // 00. if (x) y; | |
21719 | // 01. if (x) y; else z; | |
21720 | // 02. if (x) y; else {z0; ... zn;} | |
21721 | // 03. if (x) y; else if (z) w; | |
21722 | // 04. if (x) y; else if (z) w; else u; | |
21723 | // 05. if (x) y; else if (z) w; else {u0; ... un;} | |
21724 | // 06. if (x) y; else if (z) {w0; ... wn;} | |
21725 | // 07. if (x) {y0; ... yn;} | |
21726 | // 08. if (x) {y0; ... yn;} else z; | |
21727 | // 09. if (x) {y0; ... yn;} else {z0; ... zn;}; | |
21728 | // 10. if (x) {y0; ... yn;} else if (z) w; | |
21729 | // 11. if (x) {y0; ... yn;} else if (z) w; else u; | |
21730 | // 12. if (x) {y0; ... nex;} else if (z) w; else {u0 ... un;} | |
21731 | // 13. if (x) {y0; ... yn;} else if (z) {w0; ... wn;} | |
21732 | return parse_conditional_statement_02(condition); | |
21733 | } | |
21734 | ||
21735 | set_error( | |
21736 | make_error(parser_error::e_syntax, | |
21737 | current_token(), | |
21738 | "ERR046 - Invalid if-statement", | |
21739 | exprtk_error_location)); | |
21740 | ||
21741 | free_node(node_allocator_,condition); | |
21742 | ||
21743 | return error_node(); | |
21744 | } | |
21745 | ||
21746 | inline expression_node_ptr parse_ternary_conditional_statement(expression_node_ptr condition) | |
21747 | { | |
21748 | // Parse: [condition][?][consequent][:][alternative] | |
21749 | expression_node_ptr consequent = error_node(); | |
21750 | expression_node_ptr alternative = error_node(); | |
21751 | ||
21752 | bool result = true; | |
21753 | ||
21754 | if (0 == condition) | |
21755 | { | |
21756 | set_error( | |
21757 | make_error(parser_error::e_syntax, | |
21758 | current_token(), | |
21759 | "ERR047 - Encountered invalid condition branch for ternary if-statement", | |
21760 | exprtk_error_location)); | |
21761 | ||
21762 | return error_node(); | |
21763 | } | |
21764 | else if (!token_is(token_t::e_ternary)) | |
21765 | { | |
21766 | set_error( | |
21767 | make_error(parser_error::e_syntax, | |
21768 | current_token(), | |
21769 | "ERR048 - Expected '?' after condition of ternary if-statement", | |
21770 | exprtk_error_location)); | |
21771 | ||
21772 | result = false; | |
21773 | } | |
21774 | else if (0 == (consequent = parse_expression())) | |
21775 | { | |
21776 | set_error( | |
21777 | make_error(parser_error::e_syntax, | |
21778 | current_token(), | |
21779 | "ERR049 - Failed to parse consequent for ternary if-statement", | |
21780 | exprtk_error_location)); | |
21781 | ||
21782 | result = false; | |
21783 | } | |
21784 | else if (!token_is(token_t::e_colon)) | |
21785 | { | |
21786 | set_error( | |
21787 | make_error(parser_error::e_syntax, | |
21788 | current_token(), | |
21789 | "ERR050 - Expected ':' between ternary if-statement consequent and alternative", | |
21790 | exprtk_error_location)); | |
21791 | ||
21792 | result = false; | |
21793 | } | |
21794 | else if (0 == (alternative = parse_expression())) | |
21795 | { | |
21796 | set_error( | |
21797 | make_error(parser_error::e_syntax, | |
21798 | current_token(), | |
21799 | "ERR051 - Failed to parse alternative for ternary if-statement", | |
21800 | exprtk_error_location)); | |
21801 | ||
21802 | result = false; | |
21803 | } | |
21804 | ||
21805 | #ifndef exprtk_disable_string_capabilities | |
21806 | if (result) | |
21807 | { | |
21808 | const bool consq_is_str = is_generally_string_node( consequent); | |
21809 | const bool alter_is_str = is_generally_string_node(alternative); | |
21810 | ||
21811 | if (consq_is_str || alter_is_str) | |
21812 | { | |
21813 | if (consq_is_str && alter_is_str) | |
21814 | { | |
21815 | return expression_generator_ | |
21816 | .conditional_string(condition, consequent, alternative); | |
21817 | } | |
21818 | ||
21819 | set_error( | |
21820 | make_error(parser_error::e_syntax, | |
21821 | current_token(), | |
21822 | "ERR052 - Return types of ternary if-statement differ", | |
21823 | exprtk_error_location)); | |
21824 | ||
21825 | result = false; | |
21826 | } | |
21827 | } | |
21828 | #endif | |
21829 | ||
21830 | if (!result) | |
21831 | { | |
21832 | free_node(node_allocator_, condition); | |
21833 | free_node(node_allocator_, consequent); | |
21834 | free_node(node_allocator_, alternative); | |
21835 | ||
21836 | return error_node(); | |
21837 | } | |
21838 | else | |
21839 | return expression_generator_ | |
21840 | .conditional(condition, consequent, alternative); | |
21841 | } | |
21842 | ||
21843 | inline expression_node_ptr parse_not_statement() | |
21844 | { | |
21845 | if (settings_.logic_disabled("not")) | |
21846 | { | |
21847 | set_error( | |
21848 | make_error(parser_error::e_syntax, | |
21849 | current_token(), | |
21850 | "ERR053 - Invalid or disabled logic operation 'not'", | |
21851 | exprtk_error_location)); | |
21852 | ||
21853 | return error_node(); | |
21854 | } | |
21855 | ||
21856 | return parse_base_operation(); | |
21857 | } | |
21858 | ||
21859 | inline expression_node_ptr parse_while_loop() | |
21860 | { | |
21861 | // Parse: [while][(][test expr][)][{][expression][}] | |
21862 | expression_node_ptr condition = error_node(); | |
21863 | expression_node_ptr branch = error_node(); | |
21864 | expression_node_ptr result_node = error_node(); | |
21865 | ||
21866 | bool result = true; | |
21867 | ||
21868 | next_token(); | |
21869 | ||
21870 | if (!token_is(token_t::e_lbracket)) | |
21871 | { | |
21872 | set_error( | |
21873 | make_error(parser_error::e_syntax, | |
21874 | current_token(), | |
21875 | "ERR054 - Expected '(' at start of while-loop condition statement", | |
21876 | exprtk_error_location)); | |
21877 | ||
21878 | return error_node(); | |
21879 | } | |
21880 | else if (0 == (condition = parse_expression())) | |
21881 | { | |
21882 | set_error( | |
21883 | make_error(parser_error::e_syntax, | |
21884 | current_token(), | |
21885 | "ERR055 - Failed to parse condition for while-loop", | |
21886 | exprtk_error_location)); | |
21887 | ||
21888 | return error_node(); | |
21889 | } | |
21890 | else if (!token_is(token_t::e_rbracket)) | |
21891 | { | |
21892 | set_error( | |
21893 | make_error(parser_error::e_syntax, | |
21894 | current_token(), | |
21895 | "ERR056 - Expected ')' at end of while-loop condition statement", | |
21896 | exprtk_error_location)); | |
21897 | ||
21898 | result = false; | |
21899 | } | |
21900 | ||
21901 | brkcnt_list_.push_front(false); | |
21902 | ||
21903 | if (result) | |
21904 | { | |
21905 | if (0 == (branch = parse_multi_sequence("while-loop"))) | |
21906 | { | |
21907 | set_error( | |
21908 | make_error(parser_error::e_syntax, | |
21909 | current_token(), | |
21910 | "ERR057 - Failed to parse body of while-loop")); | |
21911 | result = false; | |
21912 | } | |
21913 | else if (0 == (result_node = expression_generator_.while_loop(condition, | |
21914 | branch, | |
21915 | brkcnt_list_.front()))) | |
21916 | { | |
21917 | set_error( | |
21918 | make_error(parser_error::e_syntax, | |
21919 | current_token(), | |
21920 | "ERR058 - Failed to synthesize while-loop", | |
21921 | exprtk_error_location)); | |
21922 | ||
21923 | result = false; | |
21924 | } | |
21925 | } | |
21926 | ||
21927 | if (!result) | |
21928 | { | |
21929 | free_node(node_allocator_, branch); | |
21930 | free_node(node_allocator_, condition); | |
21931 | free_node(node_allocator_, result_node); | |
21932 | ||
21933 | brkcnt_list_.pop_front(); | |
21934 | ||
21935 | return error_node(); | |
21936 | } | |
21937 | else | |
21938 | return result_node; | |
21939 | } | |
21940 | ||
21941 | inline expression_node_ptr parse_repeat_until_loop() | |
21942 | { | |
21943 | // Parse: [repeat][{][expression][}][until][(][test expr][)] | |
21944 | expression_node_ptr condition = error_node(); | |
21945 | expression_node_ptr branch = error_node(); | |
21946 | next_token(); | |
21947 | ||
21948 | std::vector<expression_node_ptr> arg_list; | |
21949 | std::vector<bool> side_effect_list; | |
21950 | ||
21951 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
21952 | ||
21953 | brkcnt_list_.push_front(false); | |
21954 | ||
21955 | if (details::imatch(current_token().value,"until")) | |
21956 | { | |
21957 | next_token(); | |
21958 | branch = node_allocator_.allocate<details::null_node<T> >(); | |
21959 | } | |
21960 | else | |
21961 | { | |
21962 | const token_t::token_type seperator = token_t::e_eof; | |
21963 | ||
21964 | scope_handler sh(*this); | |
21965 | ||
21966 | scoped_bool_or_restorer sbr(state_.side_effect_present); | |
21967 | ||
21968 | for ( ; ; ) | |
21969 | { | |
21970 | state_.side_effect_present = false; | |
21971 | ||
21972 | expression_node_ptr arg = parse_expression(); | |
21973 | ||
21974 | if (0 == arg) | |
21975 | return error_node(); | |
21976 | else | |
21977 | { | |
21978 | arg_list.push_back(arg); | |
21979 | side_effect_list.push_back(state_.side_effect_present); | |
21980 | } | |
21981 | ||
21982 | if (details::imatch(current_token().value,"until")) | |
21983 | { | |
21984 | next_token(); | |
21985 | break; | |
21986 | } | |
21987 | ||
21988 | const bool is_next_until = peek_token_is(token_t::e_symbol) && | |
21989 | peek_token_is("until"); | |
21990 | ||
21991 | if (!token_is(seperator) && is_next_until) | |
21992 | { | |
21993 | set_error( | |
21994 | make_error(parser_error::e_syntax, | |
21995 | current_token(), | |
21996 | "ERR059 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", | |
21997 | exprtk_error_location)); | |
21998 | ||
21999 | return error_node(); | |
22000 | } | |
22001 | ||
22002 | if (details::imatch(current_token().value,"until")) | |
22003 | { | |
22004 | next_token(); | |
22005 | break; | |
22006 | } | |
22007 | } | |
22008 | ||
22009 | branch = simplify(arg_list,side_effect_list); | |
22010 | ||
22011 | sdd.delete_ptr = (0 == branch); | |
22012 | ||
22013 | if (sdd.delete_ptr) | |
22014 | { | |
22015 | brkcnt_list_.pop_front(); | |
22016 | ||
22017 | set_error( | |
22018 | make_error(parser_error::e_syntax, | |
22019 | current_token(), | |
22020 | "ERR060 - Failed to parse body of repeat until loop", | |
22021 | exprtk_error_location)); | |
22022 | ||
22023 | return error_node(); | |
22024 | } | |
22025 | } | |
22026 | ||
22027 | if (!token_is(token_t::e_lbracket)) | |
22028 | { | |
22029 | brkcnt_list_.pop_front(); | |
22030 | ||
22031 | set_error( | |
22032 | make_error(parser_error::e_syntax, | |
22033 | current_token(), | |
22034 | "ERR061 - Expected '(' before condition statement of repeat until loop", | |
22035 | exprtk_error_location)); | |
22036 | ||
22037 | free_node(node_allocator_,branch); | |
22038 | ||
22039 | return error_node(); | |
22040 | } | |
22041 | else if (0 == (condition = parse_expression())) | |
22042 | { | |
22043 | brkcnt_list_.pop_front(); | |
22044 | ||
22045 | set_error( | |
22046 | make_error(parser_error::e_syntax, | |
22047 | current_token(), | |
22048 | "ERR062 - Failed to parse condition for repeat until loop", | |
22049 | exprtk_error_location)); | |
22050 | ||
22051 | free_node(node_allocator_,branch); | |
22052 | ||
22053 | return error_node(); | |
22054 | } | |
22055 | else if (!token_is(token_t::e_rbracket)) | |
22056 | { | |
22057 | set_error( | |
22058 | make_error(parser_error::e_syntax, | |
22059 | current_token(), | |
22060 | "ERR063 - Expected ')' after condition of repeat until loop", | |
22061 | exprtk_error_location)); | |
22062 | ||
22063 | free_node(node_allocator_, branch); | |
22064 | free_node(node_allocator_, condition); | |
22065 | ||
22066 | brkcnt_list_.pop_front(); | |
22067 | ||
22068 | return error_node(); | |
22069 | } | |
22070 | ||
22071 | expression_node_ptr result; | |
22072 | ||
22073 | result = expression_generator_ | |
22074 | .repeat_until_loop(condition, branch, brkcnt_list_.front()); | |
22075 | ||
22076 | if (0 == result) | |
22077 | { | |
22078 | set_error( | |
22079 | make_error(parser_error::e_syntax, | |
22080 | current_token(), | |
22081 | "ERR064 - Failed to synthesize repeat until loop", | |
22082 | exprtk_error_location)); | |
22083 | ||
22084 | free_node(node_allocator_,condition); | |
22085 | ||
22086 | brkcnt_list_.pop_front(); | |
22087 | ||
22088 | return error_node(); | |
22089 | } | |
22090 | else | |
22091 | { | |
22092 | brkcnt_list_.pop_front(); | |
22093 | return result; | |
22094 | } | |
22095 | } | |
22096 | ||
22097 | inline expression_node_ptr parse_for_loop() | |
22098 | { | |
22099 | expression_node_ptr initialiser = error_node(); | |
22100 | expression_node_ptr condition = error_node(); | |
22101 | expression_node_ptr incrementor = error_node(); | |
22102 | expression_node_ptr loop_body = error_node(); | |
22103 | ||
22104 | scope_element* se = 0; | |
22105 | bool result = true; | |
22106 | ||
22107 | next_token(); | |
22108 | ||
22109 | scope_handler sh(*this); | |
22110 | ||
22111 | if (!token_is(token_t::e_lbracket)) | |
22112 | { | |
22113 | set_error( | |
22114 | make_error(parser_error::e_syntax, | |
22115 | current_token(), | |
22116 | "ERR065 - Expected '(' at start of for-loop", | |
22117 | exprtk_error_location)); | |
22118 | ||
22119 | return error_node(); | |
22120 | } | |
22121 | ||
22122 | if (!token_is(token_t::e_eof)) | |
22123 | { | |
22124 | if ( | |
22125 | !token_is(token_t::e_symbol,prsrhlpr_t::e_hold) && | |
22126 | details::imatch(current_token().value,"var") | |
22127 | ) | |
22128 | { | |
22129 | next_token(); | |
22130 | ||
22131 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) | |
22132 | { | |
22133 | set_error( | |
22134 | make_error(parser_error::e_syntax, | |
22135 | current_token(), | |
22136 | "ERR066 - Expected a variable at the start of initialiser section of for-loop", | |
22137 | exprtk_error_location)); | |
22138 | ||
22139 | return error_node(); | |
22140 | } | |
22141 | else if (!peek_token_is(token_t::e_assign)) | |
22142 | { | |
22143 | set_error( | |
22144 | make_error(parser_error::e_syntax, | |
22145 | current_token(), | |
22146 | "ERR067 - Expected variable assignment of initialiser section of for-loop", | |
22147 | exprtk_error_location)); | |
22148 | ||
22149 | return error_node(); | |
22150 | } | |
22151 | ||
22152 | const std::string loop_counter_symbol = current_token().value; | |
22153 | ||
22154 | se = &sem_.get_element(loop_counter_symbol); | |
22155 | ||
22156 | if ((se->name == loop_counter_symbol) && se->active) | |
22157 | { | |
22158 | set_error( | |
22159 | make_error(parser_error::e_syntax, | |
22160 | current_token(), | |
22161 | "ERR068 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", | |
22162 | exprtk_error_location)); | |
22163 | ||
22164 | return error_node(); | |
22165 | } | |
22166 | else if (!symtab_store_.is_variable(loop_counter_symbol)) | |
22167 | { | |
22168 | if ( | |
22169 | !se->active && | |
22170 | (se->name == loop_counter_symbol) && | |
22171 | (se->type == scope_element::e_variable) | |
22172 | ) | |
22173 | { | |
22174 | se->active = true; | |
22175 | se->ref_count++; | |
22176 | } | |
22177 | else | |
22178 | { | |
22179 | scope_element nse; | |
22180 | nse.name = loop_counter_symbol; | |
22181 | nse.active = true; | |
22182 | nse.ref_count = 1; | |
22183 | nse.type = scope_element::e_variable; | |
22184 | nse.depth = state_.scope_depth; | |
22185 | nse.data = new T(T(0)); | |
22186 | nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); | |
22187 | ||
22188 | if (!sem_.add_element(nse)) | |
22189 | { | |
22190 | set_error( | |
22191 | make_error(parser_error::e_syntax, | |
22192 | current_token(), | |
22193 | "ERR069 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", | |
22194 | exprtk_error_location)); | |
22195 | ||
22196 | sem_.free_element(nse); | |
22197 | ||
22198 | result = false; | |
22199 | } | |
22200 | else | |
22201 | { | |
22202 | exprtk_debug(("parse_for_loop() - INFO - Added new local variable: %s\n",nse.name.c_str())); | |
22203 | ||
22204 | state_.activate_side_effect("parse_for_loop()"); | |
22205 | } | |
22206 | } | |
22207 | } | |
22208 | } | |
22209 | ||
22210 | if (0 == (initialiser = parse_expression())) | |
22211 | { | |
22212 | set_error( | |
22213 | make_error(parser_error::e_syntax, | |
22214 | current_token(), | |
22215 | "ERR070 - Failed to parse initialiser of for-loop", | |
22216 | exprtk_error_location)); | |
22217 | ||
22218 | result = false; | |
22219 | } | |
22220 | else if (!token_is(token_t::e_eof)) | |
22221 | { | |
22222 | set_error( | |
22223 | make_error(parser_error::e_syntax, | |
22224 | current_token(), | |
22225 | "ERR071 - Expected ';' after initialiser of for-loop", | |
22226 | exprtk_error_location)); | |
22227 | ||
22228 | result = false; | |
22229 | } | |
22230 | } | |
22231 | ||
22232 | if (!token_is(token_t::e_eof)) | |
22233 | { | |
22234 | if (0 == (condition = parse_expression())) | |
22235 | { | |
22236 | set_error( | |
22237 | make_error(parser_error::e_syntax, | |
22238 | current_token(), | |
22239 | "ERR072 - Failed to parse condition of for-loop", | |
22240 | exprtk_error_location)); | |
22241 | ||
22242 | result = false; | |
22243 | } | |
22244 | else if (!token_is(token_t::e_eof)) | |
22245 | { | |
22246 | set_error( | |
22247 | make_error(parser_error::e_syntax, | |
22248 | current_token(), | |
22249 | "ERR073 - Expected ';' after condition section of for-loop", | |
22250 | exprtk_error_location)); | |
22251 | ||
22252 | result = false; | |
22253 | } | |
22254 | } | |
22255 | ||
22256 | if (!token_is(token_t::e_rbracket)) | |
22257 | { | |
22258 | if (0 == (incrementor = parse_expression())) | |
22259 | { | |
22260 | set_error( | |
22261 | make_error(parser_error::e_syntax, | |
22262 | current_token(), | |
22263 | "ERR074 - Failed to parse incrementor of for-loop", | |
22264 | exprtk_error_location)); | |
22265 | ||
22266 | result = false; | |
22267 | } | |
22268 | else if (!token_is(token_t::e_rbracket)) | |
22269 | { | |
22270 | set_error( | |
22271 | make_error(parser_error::e_syntax, | |
22272 | current_token(), | |
22273 | "ERR075 - Expected ')' after incrementor section of for-loop", | |
22274 | exprtk_error_location)); | |
22275 | ||
22276 | result = false; | |
22277 | } | |
22278 | } | |
22279 | ||
22280 | if (result) | |
22281 | { | |
22282 | brkcnt_list_.push_front(false); | |
22283 | ||
22284 | if (0 == (loop_body = parse_multi_sequence("for-loop"))) | |
22285 | { | |
22286 | set_error( | |
22287 | make_error(parser_error::e_syntax, | |
22288 | current_token(), | |
22289 | "ERR076 - Failed to parse body of for-loop", | |
22290 | exprtk_error_location)); | |
22291 | ||
22292 | result = false; | |
22293 | } | |
22294 | } | |
22295 | ||
22296 | if (!result) | |
22297 | { | |
22298 | if (se) | |
22299 | { | |
22300 | se->ref_count--; | |
22301 | } | |
22302 | ||
22303 | free_node(node_allocator_, initialiser); | |
22304 | free_node(node_allocator_, condition); | |
22305 | free_node(node_allocator_, incrementor); | |
22306 | free_node(node_allocator_, loop_body); | |
22307 | ||
22308 | if (!brkcnt_list_.empty()) | |
22309 | { | |
22310 | brkcnt_list_.pop_front(); | |
22311 | } | |
22312 | ||
22313 | return error_node(); | |
22314 | } | |
22315 | else | |
22316 | { | |
22317 | expression_node_ptr result_node = | |
22318 | expression_generator_.for_loop(initialiser, | |
22319 | condition, | |
22320 | incrementor, | |
22321 | loop_body, | |
22322 | brkcnt_list_.front()); | |
22323 | brkcnt_list_.pop_front(); | |
22324 | ||
22325 | return result_node; | |
22326 | } | |
22327 | } | |
22328 | ||
22329 | inline expression_node_ptr parse_switch_statement() | |
22330 | { | |
22331 | std::vector<expression_node_ptr> arg_list; | |
22332 | expression_node_ptr result = error_node(); | |
22333 | ||
22334 | if (!details::imatch(current_token().value,"switch")) | |
22335 | { | |
22336 | set_error( | |
22337 | make_error(parser_error::e_syntax, | |
22338 | current_token(), | |
22339 | "ERR077 - Expected keyword 'switch'", | |
22340 | exprtk_error_location)); | |
22341 | ||
22342 | return error_node(); | |
22343 | } | |
22344 | ||
22345 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); | |
22346 | ||
22347 | next_token(); | |
22348 | ||
22349 | if (!token_is(token_t::e_lcrlbracket)) | |
22350 | { | |
22351 | set_error( | |
22352 | make_error(parser_error::e_syntax, | |
22353 | current_token(), | |
22354 | "ERR078 - Expected '{' for call to switch statement", | |
22355 | exprtk_error_location)); | |
22356 | ||
22357 | return error_node(); | |
22358 | } | |
22359 | ||
22360 | for ( ; ; ) | |
22361 | { | |
22362 | if (!details::imatch("case",current_token().value)) | |
22363 | { | |
22364 | set_error( | |
22365 | make_error(parser_error::e_syntax, | |
22366 | current_token(), | |
22367 | "ERR079 - Expected either a 'case' or 'default' statement", | |
22368 | exprtk_error_location)); | |
22369 | ||
22370 | return error_node(); | |
22371 | } | |
22372 | ||
22373 | next_token(); | |
22374 | ||
22375 | expression_node_ptr condition = parse_expression(); | |
22376 | ||
22377 | if (0 == condition) | |
22378 | return error_node(); | |
22379 | else if (!token_is(token_t::e_colon)) | |
22380 | { | |
22381 | set_error( | |
22382 | make_error(parser_error::e_syntax, | |
22383 | current_token(), | |
22384 | "ERR080 - Expected ':' for case of switch statement", | |
22385 | exprtk_error_location)); | |
22386 | ||
22387 | return error_node(); | |
22388 | } | |
22389 | ||
22390 | expression_node_ptr consequent = parse_expression(); | |
22391 | ||
22392 | if (0 == consequent) | |
22393 | return error_node(); | |
22394 | else if (!token_is(token_t::e_eof)) | |
22395 | { | |
22396 | set_error( | |
22397 | make_error(parser_error::e_syntax, | |
22398 | current_token(), | |
22399 | "ERR081 - Expected ';' at end of case for switch statement", | |
22400 | exprtk_error_location)); | |
22401 | ||
22402 | return error_node(); | |
22403 | } | |
22404 | ||
22405 | // Can we optimise away the case statement? | |
22406 | if (is_constant_node(condition) && is_false(condition)) | |
22407 | { | |
22408 | free_node(node_allocator_, condition); | |
22409 | free_node(node_allocator_, consequent); | |
22410 | } | |
22411 | else | |
22412 | { | |
22413 | arg_list.push_back( condition); | |
22414 | arg_list.push_back(consequent); | |
22415 | } | |
22416 | ||
22417 | if (details::imatch("default",current_token().value)) | |
22418 | { | |
22419 | next_token(); | |
22420 | if (!token_is(token_t::e_colon)) | |
22421 | { | |
22422 | set_error( | |
22423 | make_error(parser_error::e_syntax, | |
22424 | current_token(), | |
22425 | "ERR082 - Expected ':' for default of switch statement", | |
22426 | exprtk_error_location)); | |
22427 | ||
22428 | return error_node(); | |
22429 | } | |
22430 | ||
22431 | expression_node_ptr default_statement = error_node(); | |
22432 | ||
22433 | if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) | |
22434 | default_statement = parse_multi_sequence("switch-default"); | |
22435 | else | |
22436 | default_statement = parse_expression(); | |
22437 | ||
22438 | if (0 == default_statement) | |
22439 | return error_node(); | |
22440 | else if (!token_is(token_t::e_eof)) | |
22441 | { | |
22442 | free_node(node_allocator_,default_statement); | |
22443 | ||
22444 | set_error( | |
22445 | make_error(parser_error::e_syntax, | |
22446 | current_token(), | |
22447 | "ERR083 - Expected ';' at end of default for switch statement", | |
22448 | exprtk_error_location)); | |
22449 | ||
22450 | return error_node(); | |
22451 | } | |
22452 | ||
22453 | arg_list.push_back(default_statement); | |
22454 | break; | |
22455 | } | |
22456 | } | |
22457 | ||
22458 | if (!token_is(token_t::e_rcrlbracket)) | |
22459 | { | |
22460 | set_error( | |
22461 | make_error(parser_error::e_syntax, | |
22462 | current_token(), | |
22463 | "ERR084 - Expected '}' at end of switch statement", | |
22464 | exprtk_error_location)); | |
22465 | ||
22466 | return error_node(); | |
22467 | } | |
22468 | ||
22469 | result = expression_generator_.switch_statement(arg_list); | |
22470 | ||
22471 | svd.delete_ptr = (0 == result); | |
22472 | ||
22473 | return result; | |
22474 | } | |
22475 | ||
22476 | inline expression_node_ptr parse_multi_switch_statement() | |
22477 | { | |
22478 | std::vector<expression_node_ptr> arg_list; | |
22479 | ||
22480 | if (!details::imatch(current_token().value,"[*]")) | |
22481 | { | |
22482 | set_error( | |
22483 | make_error(parser_error::e_syntax, | |
22484 | current_token(), | |
22485 | "ERR085 - Expected token '[*]'", | |
22486 | exprtk_error_location)); | |
22487 | ||
22488 | return error_node(); | |
22489 | } | |
22490 | ||
22491 | scoped_vec_delete<expression_node_t> svd((*this),arg_list); | |
22492 | ||
22493 | next_token(); | |
22494 | ||
22495 | if (!token_is(token_t::e_lcrlbracket)) | |
22496 | { | |
22497 | set_error( | |
22498 | make_error(parser_error::e_syntax, | |
22499 | current_token(), | |
22500 | "ERR086 - Expected '{' for call to [*] statement", | |
22501 | exprtk_error_location)); | |
22502 | ||
22503 | return error_node(); | |
22504 | } | |
22505 | ||
22506 | for ( ; ; ) | |
22507 | { | |
22508 | if (!details::imatch("case",current_token().value)) | |
22509 | { | |
22510 | set_error( | |
22511 | make_error(parser_error::e_syntax, | |
22512 | current_token(), | |
22513 | "ERR087 - Expected a 'case' statement for multi-switch", | |
22514 | exprtk_error_location)); | |
22515 | ||
22516 | return error_node(); | |
22517 | } | |
22518 | ||
22519 | next_token(); | |
22520 | ||
22521 | expression_node_ptr condition = parse_expression(); | |
22522 | ||
22523 | if (0 == condition) | |
22524 | return error_node(); | |
22525 | ||
22526 | if (!token_is(token_t::e_colon)) | |
22527 | { | |
22528 | set_error( | |
22529 | make_error(parser_error::e_syntax, | |
22530 | current_token(), | |
22531 | "ERR088 - Expected ':' for case of [*] statement", | |
22532 | exprtk_error_location)); | |
22533 | ||
22534 | return error_node(); | |
22535 | } | |
22536 | ||
22537 | expression_node_ptr consequent = parse_expression(); | |
22538 | ||
22539 | if (0 == consequent) | |
22540 | return error_node(); | |
22541 | ||
22542 | if (!token_is(token_t::e_eof)) | |
22543 | { | |
22544 | set_error( | |
22545 | make_error(parser_error::e_syntax, | |
22546 | current_token(), | |
22547 | "ERR089 - Expected ';' at end of case for [*] statement", | |
22548 | exprtk_error_location)); | |
22549 | ||
22550 | return error_node(); | |
22551 | } | |
22552 | ||
22553 | // Can we optimise away the case statement? | |
22554 | if (is_constant_node(condition) && is_false(condition)) | |
22555 | { | |
22556 | free_node(node_allocator_, condition); | |
22557 | free_node(node_allocator_, consequent); | |
22558 | } | |
22559 | else | |
22560 | { | |
22561 | arg_list.push_back( condition); | |
22562 | arg_list.push_back(consequent); | |
22563 | } | |
22564 | ||
22565 | if (token_is(token_t::e_rcrlbracket,prsrhlpr_t::e_hold)) | |
22566 | { | |
22567 | break; | |
22568 | } | |
22569 | } | |
22570 | ||
22571 | if (!token_is(token_t::e_rcrlbracket)) | |
22572 | { | |
22573 | set_error( | |
22574 | make_error(parser_error::e_syntax, | |
22575 | current_token(), | |
22576 | "ERR090 - Expected '}' at end of [*] statement", | |
22577 | exprtk_error_location)); | |
22578 | ||
22579 | return error_node(); | |
22580 | } | |
22581 | ||
22582 | const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); | |
22583 | ||
22584 | svd.delete_ptr = (0 == result); | |
22585 | ||
22586 | return result; | |
22587 | } | |
22588 | ||
22589 | inline expression_node_ptr parse_vararg_function() | |
22590 | { | |
22591 | std::vector<expression_node_ptr> arg_list; | |
22592 | ||
22593 | details::operator_type opt_type = details::e_default; | |
22594 | const std::string symbol = current_token().value; | |
22595 | ||
22596 | if (details::imatch(symbol,"~")) | |
22597 | { | |
22598 | next_token(); | |
22599 | return parse_multi_sequence(); | |
22600 | } | |
22601 | else if (details::imatch(symbol,"[*]")) | |
22602 | { | |
22603 | return parse_multi_switch_statement(); | |
22604 | } | |
22605 | else if (details::imatch(symbol, "avg" )) opt_type = details::e_avg ; | |
22606 | else if (details::imatch(symbol, "mand")) opt_type = details::e_mand; | |
22607 | else if (details::imatch(symbol, "max" )) opt_type = details::e_max ; | |
22608 | else if (details::imatch(symbol, "min" )) opt_type = details::e_min ; | |
22609 | else if (details::imatch(symbol, "mor" )) opt_type = details::e_mor ; | |
22610 | else if (details::imatch(symbol, "mul" )) opt_type = details::e_prod; | |
22611 | else if (details::imatch(symbol, "sum" )) opt_type = details::e_sum ; | |
22612 | else | |
22613 | { | |
22614 | set_error( | |
22615 | make_error(parser_error::e_syntax, | |
22616 | current_token(), | |
22617 | "ERR091 - Unsupported vararg function: " + symbol, | |
22618 | exprtk_error_location)); | |
22619 | ||
22620 | return error_node(); | |
22621 | } | |
22622 | ||
22623 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
22624 | ||
22625 | lodge_symbol(symbol, e_st_function); | |
22626 | ||
22627 | next_token(); | |
22628 | ||
22629 | if (!token_is(token_t::e_lbracket)) | |
22630 | { | |
22631 | set_error( | |
22632 | make_error(parser_error::e_syntax, | |
22633 | current_token(), | |
22634 | "ERR092 - Expected '(' for call to vararg function: " + symbol, | |
22635 | exprtk_error_location)); | |
22636 | ||
22637 | return error_node(); | |
22638 | } | |
22639 | ||
22640 | for ( ; ; ) | |
22641 | { | |
22642 | expression_node_ptr arg = parse_expression(); | |
22643 | ||
22644 | if (0 == arg) | |
22645 | return error_node(); | |
22646 | else | |
22647 | arg_list.push_back(arg); | |
22648 | ||
22649 | if (token_is(token_t::e_rbracket)) | |
22650 | break; | |
22651 | else if (!token_is(token_t::e_comma)) | |
22652 | { | |
22653 | set_error( | |
22654 | make_error(parser_error::e_syntax, | |
22655 | current_token(), | |
22656 | "ERR093 - Expected ',' for call to vararg function: " + symbol, | |
22657 | exprtk_error_location)); | |
22658 | ||
22659 | return error_node(); | |
22660 | } | |
22661 | } | |
22662 | ||
22663 | const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); | |
22664 | ||
22665 | sdd.delete_ptr = (0 == result); | |
22666 | return result; | |
22667 | } | |
22668 | ||
22669 | #ifndef exprtk_disable_string_capabilities | |
22670 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr& expression) | |
22671 | { | |
22672 | if (!token_is(token_t::e_lsqrbracket)) | |
22673 | { | |
22674 | set_error( | |
22675 | make_error(parser_error::e_syntax, | |
22676 | current_token(), | |
22677 | "ERR094 - Expected '[' as start of string range definition", | |
22678 | exprtk_error_location)); | |
22679 | ||
22680 | free_node(node_allocator_,expression); | |
22681 | ||
22682 | return error_node(); | |
22683 | } | |
22684 | else if (token_is(token_t::e_rsqrbracket)) | |
22685 | { | |
22686 | return node_allocator_.allocate<details::string_size_node<T> >(expression); | |
22687 | } | |
22688 | ||
22689 | range_t rp; | |
22690 | ||
22691 | if (!parse_range(rp,true)) | |
22692 | { | |
22693 | free_node(node_allocator_,expression); | |
22694 | ||
22695 | return error_node(); | |
22696 | } | |
22697 | ||
22698 | expression_node_ptr result = expression_generator_(expression,rp); | |
22699 | ||
22700 | if (0 == result) | |
22701 | { | |
22702 | set_error( | |
22703 | make_error(parser_error::e_syntax, | |
22704 | current_token(), | |
22705 | "ERR095 - Failed to generate string range node", | |
22706 | exprtk_error_location)); | |
22707 | ||
22708 | free_node(node_allocator_,expression); | |
22709 | } | |
22710 | ||
22711 | rp.clear(); | |
22712 | ||
22713 | return result; | |
22714 | } | |
22715 | #else | |
22716 | inline expression_node_ptr parse_string_range_statement(expression_node_ptr&) | |
22717 | { | |
22718 | return error_node(); | |
22719 | } | |
22720 | #endif | |
22721 | ||
22722 | inline void parse_pending_string_rangesize(expression_node_ptr& expression) | |
22723 | { | |
22724 | // Allow no more than 100 range calls, eg: s[][][]...[][] | |
22725 | const std::size_t max_rangesize_parses = 100; | |
22726 | ||
22727 | std::size_t i = 0; | |
22728 | ||
22729 | while | |
22730 | ( | |
22731 | (0 != expression) && | |
22732 | (i++ < max_rangesize_parses) && | |
22733 | error_list_.empty() && | |
22734 | is_generally_string_node(expression) && | |
22735 | token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold) | |
22736 | ) | |
22737 | { | |
22738 | expression = parse_string_range_statement(expression); | |
22739 | } | |
22740 | } | |
22741 | ||
22742 | template <typename Allocator1, | |
22743 | typename Allocator2, | |
22744 | template <typename, typename> class Sequence> | |
22745 | inline expression_node_ptr simplify(Sequence<expression_node_ptr,Allocator1>& expression_list, | |
22746 | Sequence<bool,Allocator2>& side_effect_list, | |
22747 | const bool specialise_on_final_type = false) | |
22748 | { | |
22749 | if (expression_list.empty()) | |
22750 | return error_node(); | |
22751 | else if (1 == expression_list.size()) | |
22752 | return expression_list[0]; | |
22753 | ||
22754 | Sequence<expression_node_ptr,Allocator1> tmp_expression_list; | |
22755 | ||
22756 | bool return_node_present = false; | |
22757 | ||
22758 | for (std::size_t i = 0; i < (expression_list.size() - 1); ++i) | |
22759 | { | |
22760 | if (is_variable_node(expression_list[i])) | |
22761 | continue; | |
22762 | else if ( | |
22763 | is_return_node (expression_list[i]) || | |
22764 | is_break_node (expression_list[i]) || | |
22765 | is_continue_node(expression_list[i]) | |
22766 | ) | |
22767 | { | |
22768 | tmp_expression_list.push_back(expression_list[i]); | |
22769 | ||
22770 | // Remove all subexpressions after first short-circuit | |
22771 | // node has been encountered. | |
22772 | ||
22773 | for (std::size_t j = i + 1; j < expression_list.size(); ++j) | |
22774 | { | |
22775 | free_node(node_allocator_,expression_list[j]); | |
22776 | } | |
22777 | ||
22778 | return_node_present = true; | |
22779 | ||
22780 | break; | |
22781 | } | |
22782 | else if ( | |
22783 | is_constant_node(expression_list[i]) || | |
22784 | is_null_node (expression_list[i]) || | |
22785 | !side_effect_list[i] | |
22786 | ) | |
22787 | { | |
22788 | free_node(node_allocator_,expression_list[i]); | |
22789 | continue; | |
22790 | } | |
22791 | else | |
22792 | tmp_expression_list.push_back(expression_list[i]); | |
22793 | } | |
22794 | ||
22795 | if (!return_node_present) | |
22796 | { | |
22797 | tmp_expression_list.push_back(expression_list.back()); | |
22798 | } | |
22799 | ||
22800 | expression_list.swap(tmp_expression_list); | |
22801 | ||
22802 | if (tmp_expression_list.size() > expression_list.size()) | |
22803 | { | |
22804 | exprtk_debug(("simplify() - Reduced subexpressions from %d to %d\n", | |
22805 | static_cast<int>(tmp_expression_list.size()), | |
22806 | static_cast<int>(expression_list .size()))); | |
22807 | } | |
22808 | ||
22809 | if ( | |
22810 | return_node_present || | |
22811 | side_effect_list.back() || | |
22812 | (expression_list.size() > 1) | |
22813 | ) | |
22814 | state_.activate_side_effect("simplify()"); | |
22815 | ||
22816 | if (1 == expression_list.size()) | |
22817 | return expression_list[0]; | |
22818 | else if (specialise_on_final_type && is_generally_string_node(expression_list.back())) | |
22819 | return expression_generator_.vararg_function(details::e_smulti,expression_list); | |
22820 | else | |
22821 | return expression_generator_.vararg_function(details::e_multi,expression_list); | |
22822 | } | |
22823 | ||
22824 | inline expression_node_ptr parse_multi_sequence(const std::string& source = "") | |
22825 | { | |
22826 | token_t::token_type close_bracket = token_t::e_rcrlbracket; | |
22827 | token_t::token_type seperator = token_t::e_eof; | |
22828 | ||
22829 | if (!token_is(token_t::e_lcrlbracket)) | |
22830 | { | |
22831 | if (token_is(token_t::e_lbracket)) | |
22832 | { | |
22833 | close_bracket = token_t::e_rbracket; | |
22834 | seperator = token_t::e_comma; | |
22835 | } | |
22836 | else | |
22837 | { | |
22838 | set_error( | |
22839 | make_error(parser_error::e_syntax, | |
22840 | current_token(), | |
22841 | "ERR096 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + | |
22842 | ((!source.empty()) ? std::string(" section of " + source): ""), | |
22843 | exprtk_error_location)); | |
22844 | ||
22845 | return error_node(); | |
22846 | } | |
22847 | } | |
22848 | else if (token_is(token_t::e_rcrlbracket)) | |
22849 | { | |
22850 | return node_allocator_.allocate<details::null_node<T> >(); | |
22851 | } | |
22852 | ||
22853 | std::vector<expression_node_ptr> arg_list; | |
22854 | std::vector<bool> side_effect_list; | |
22855 | ||
22856 | expression_node_ptr result = error_node(); | |
22857 | ||
22858 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
22859 | ||
22860 | scope_handler sh(*this); | |
22861 | ||
22862 | scoped_bool_or_restorer sbr(state_.side_effect_present); | |
22863 | ||
22864 | for ( ; ; ) | |
22865 | { | |
22866 | state_.side_effect_present = false; | |
22867 | ||
22868 | expression_node_ptr arg = parse_expression(); | |
22869 | ||
22870 | if (0 == arg) | |
22871 | return error_node(); | |
22872 | else | |
22873 | { | |
22874 | arg_list.push_back(arg); | |
22875 | side_effect_list.push_back(state_.side_effect_present); | |
22876 | } | |
22877 | ||
22878 | if (token_is(close_bracket)) | |
22879 | break; | |
22880 | ||
22881 | const bool is_next_close = peek_token_is(close_bracket); | |
22882 | ||
22883 | if (!token_is(seperator) && is_next_close) | |
22884 | { | |
22885 | set_error( | |
22886 | make_error(parser_error::e_syntax, | |
22887 | current_token(), | |
22888 | "ERR097 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, | |
22889 | exprtk_error_location)); | |
22890 | ||
22891 | return error_node(); | |
22892 | } | |
22893 | ||
22894 | if (token_is(close_bracket)) | |
22895 | break; | |
22896 | } | |
22897 | ||
22898 | result = simplify(arg_list,side_effect_list,source.empty()); | |
22899 | ||
22900 | sdd.delete_ptr = (0 == result); | |
22901 | return result; | |
22902 | } | |
22903 | ||
22904 | inline bool parse_range(range_t& rp, const bool skip_lsqr = false) | |
22905 | { | |
22906 | // Examples of valid ranges: | |
22907 | // 1. [1:5] -> 1..5 | |
22908 | // 2. [ :5] -> 0..5 | |
22909 | // 3. [1: ] -> 1..end | |
22910 | // 4. [x:y] -> x..y where x <= y | |
22911 | // 5. [x+1:y/2] -> x+1..y/2 where x+1 <= y/2 | |
22912 | // 6. [ :y] -> 0..y where 0 <= y | |
22913 | // 7. [x: ] -> x..end where x <= end | |
22914 | ||
22915 | rp.clear(); | |
22916 | ||
22917 | if (!skip_lsqr && !token_is(token_t::e_lsqrbracket)) | |
22918 | { | |
22919 | set_error( | |
22920 | make_error(parser_error::e_syntax, | |
22921 | current_token(), | |
22922 | "ERR098 - Expected '[' for start of range", | |
22923 | exprtk_error_location)); | |
22924 | ||
22925 | return false; | |
22926 | } | |
22927 | ||
22928 | if (token_is(token_t::e_colon)) | |
22929 | { | |
22930 | rp.n0_c.first = true; | |
22931 | rp.n0_c.second = 0; | |
22932 | rp.cache.first = 0; | |
22933 | } | |
22934 | else | |
22935 | { | |
22936 | expression_node_ptr r0 = parse_expression(); | |
22937 | ||
22938 | if (0 == r0) | |
22939 | { | |
22940 | set_error( | |
22941 | make_error(parser_error::e_syntax, | |
22942 | current_token(), | |
22943 | "ERR099 - Failed parse begin section of range", | |
22944 | exprtk_error_location)); | |
22945 | ||
22946 | return false; | |
22947 | } | |
22948 | else if (is_constant_node(r0)) | |
22949 | { | |
22950 | const T r0_value = r0->value(); | |
22951 | ||
22952 | if (r0_value >= T(0)) | |
22953 | { | |
22954 | rp.n0_c.first = true; | |
22955 | rp.n0_c.second = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); | |
22956 | rp.cache.first = rp.n0_c.second; | |
22957 | } | |
22958 | ||
22959 | free_node(node_allocator_,r0); | |
22960 | ||
22961 | if (r0_value < T(0)) | |
22962 | { | |
22963 | set_error( | |
22964 | make_error(parser_error::e_syntax, | |
22965 | current_token(), | |
22966 | "ERR100 - Range lower bound less than zero! Constraint: r0 >= 0", | |
22967 | exprtk_error_location)); | |
22968 | ||
22969 | return false; | |
22970 | } | |
22971 | } | |
22972 | else | |
22973 | { | |
22974 | rp.n0_e.first = true; | |
22975 | rp.n0_e.second = r0; | |
22976 | } | |
22977 | ||
22978 | if (!token_is(token_t::e_colon)) | |
22979 | { | |
22980 | set_error( | |
22981 | make_error(parser_error::e_syntax, | |
22982 | current_token(), | |
22983 | "ERR101 - Expected ':' for break in range", | |
22984 | exprtk_error_location)); | |
22985 | ||
22986 | rp.free(); | |
22987 | ||
22988 | return false; | |
22989 | } | |
22990 | } | |
22991 | ||
22992 | if (token_is(token_t::e_rsqrbracket)) | |
22993 | { | |
22994 | rp.n1_c.first = true; | |
22995 | rp.n1_c.second = std::numeric_limits<std::size_t>::max(); | |
22996 | } | |
22997 | else | |
22998 | { | |
22999 | expression_node_ptr r1 = parse_expression(); | |
23000 | ||
23001 | if (0 == r1) | |
23002 | { | |
23003 | set_error( | |
23004 | make_error(parser_error::e_syntax, | |
23005 | current_token(), | |
23006 | "ERR102 - Failed parse end section of range", | |
23007 | exprtk_error_location)); | |
23008 | ||
23009 | rp.free(); | |
23010 | ||
23011 | return false; | |
23012 | } | |
23013 | else if (is_constant_node(r1)) | |
23014 | { | |
23015 | const T r1_value = r1->value(); | |
23016 | ||
23017 | if (r1_value >= T(0)) | |
23018 | { | |
23019 | rp.n1_c.first = true; | |
23020 | rp.n1_c.second = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); | |
23021 | rp.cache.second = rp.n1_c.second; | |
23022 | } | |
23023 | ||
23024 | free_node(node_allocator_,r1); | |
23025 | ||
23026 | if (r1_value < T(0)) | |
23027 | { | |
23028 | set_error( | |
23029 | make_error(parser_error::e_syntax, | |
23030 | current_token(), | |
23031 | "ERR103 - Range upper bound less than zero! Constraint: r1 >= 0", | |
23032 | exprtk_error_location)); | |
23033 | ||
23034 | return false; | |
23035 | } | |
23036 | } | |
23037 | else | |
23038 | { | |
23039 | rp.n1_e.first = true; | |
23040 | rp.n1_e.second = r1; | |
23041 | } | |
23042 | ||
23043 | if (!token_is(token_t::e_rsqrbracket)) | |
23044 | { | |
23045 | set_error( | |
23046 | make_error(parser_error::e_syntax, | |
23047 | current_token(), | |
23048 | "ERR104 - Expected ']' for start of range", | |
23049 | exprtk_error_location)); | |
23050 | ||
23051 | rp.free(); | |
23052 | ||
23053 | return false; | |
23054 | } | |
23055 | } | |
23056 | ||
23057 | if (rp.const_range()) | |
23058 | { | |
23059 | std::size_t r0 = 0; | |
23060 | std::size_t r1 = 0; | |
23061 | ||
23062 | const bool rp_result = rp(r0,r1); | |
23063 | ||
23064 | if (!rp_result || (r0 > r1)) | |
23065 | { | |
23066 | set_error( | |
23067 | make_error(parser_error::e_syntax, | |
23068 | current_token(), | |
23069 | "ERR105 - Invalid range, Constraint: r0 <= r1", | |
23070 | exprtk_error_location)); | |
23071 | ||
23072 | return false; | |
23073 | } | |
23074 | } | |
23075 | ||
23076 | return true; | |
23077 | } | |
23078 | ||
23079 | inline void lodge_symbol(const std::string& symbol, | |
23080 | const symbol_type st) | |
23081 | { | |
23082 | dec_.add_symbol(symbol,st); | |
23083 | } | |
23084 | ||
23085 | #ifndef exprtk_disable_string_capabilities | |
23086 | inline expression_node_ptr parse_string() | |
23087 | { | |
23088 | const std::string symbol = current_token().value; | |
23089 | ||
23090 | typedef details::stringvar_node<T>* strvar_node_t; | |
23091 | ||
23092 | expression_node_ptr result = error_node(); | |
23093 | strvar_node_t const_str_node = static_cast<strvar_node_t>(0); | |
23094 | ||
23095 | scope_element& se = sem_.get_active_element(symbol); | |
23096 | ||
23097 | if (scope_element::e_string == se.type) | |
23098 | { | |
23099 | se.active = true; | |
23100 | result = se.str_node; | |
23101 | lodge_symbol(symbol, e_st_local_string); | |
23102 | } | |
23103 | else | |
23104 | { | |
23105 | if (!symtab_store_.is_conststr_stringvar(symbol)) | |
23106 | { | |
23107 | set_error( | |
23108 | make_error(parser_error::e_syntax, | |
23109 | current_token(), | |
23110 | "ERR106 - Unknown string symbol", | |
23111 | exprtk_error_location)); | |
23112 | ||
23113 | return error_node(); | |
23114 | } | |
23115 | ||
23116 | result = symtab_store_.get_stringvar(symbol); | |
23117 | ||
23118 | if (symtab_store_.is_constant_string(symbol)) | |
23119 | { | |
23120 | const_str_node = static_cast<strvar_node_t>(result); | |
23121 | result = expression_generator_(const_str_node->str()); | |
23122 | } | |
23123 | ||
23124 | lodge_symbol(symbol, e_st_string); | |
23125 | } | |
23126 | ||
23127 | if (peek_token_is(token_t::e_lsqrbracket)) | |
23128 | { | |
23129 | next_token(); | |
23130 | ||
23131 | if (peek_token_is(token_t::e_rsqrbracket)) | |
23132 | { | |
23133 | next_token(); | |
23134 | next_token(); | |
23135 | ||
23136 | if (const_str_node) | |
23137 | { | |
23138 | free_node(node_allocator_,result); | |
23139 | ||
23140 | return expression_generator_(T(const_str_node->size())); | |
23141 | } | |
23142 | else | |
23143 | return node_allocator_.allocate<details::stringvar_size_node<T> > | |
23144 | (static_cast<details::stringvar_node<T>*>(result)->ref()); | |
23145 | } | |
23146 | ||
23147 | range_t rp; | |
23148 | ||
23149 | if (!parse_range(rp)) | |
23150 | { | |
23151 | free_node(node_allocator_,result); | |
23152 | ||
23153 | return error_node(); | |
23154 | } | |
23155 | else if (const_str_node) | |
23156 | { | |
23157 | free_node(node_allocator_,result); | |
23158 | result = expression_generator_(const_str_node->ref(),rp); | |
23159 | } | |
23160 | else | |
23161 | result = expression_generator_(static_cast<details::stringvar_node<T>*> | |
23162 | (result)->ref(), rp); | |
23163 | ||
23164 | if (result) | |
23165 | rp.clear(); | |
23166 | } | |
23167 | else | |
23168 | next_token(); | |
23169 | ||
23170 | return result; | |
23171 | } | |
23172 | #else | |
23173 | inline expression_node_ptr parse_string() | |
23174 | { | |
23175 | return error_node(); | |
23176 | } | |
23177 | #endif | |
23178 | ||
23179 | #ifndef exprtk_disable_string_capabilities | |
23180 | inline expression_node_ptr parse_const_string() | |
23181 | { | |
23182 | const std::string const_str = current_token().value; | |
23183 | expression_node_ptr result = expression_generator_(const_str); | |
23184 | ||
23185 | if (peek_token_is(token_t::e_lsqrbracket)) | |
23186 | { | |
23187 | next_token(); | |
23188 | ||
23189 | if (peek_token_is(token_t::e_rsqrbracket)) | |
23190 | { | |
23191 | next_token(); | |
23192 | next_token(); | |
23193 | ||
23194 | free_node(node_allocator_,result); | |
23195 | ||
23196 | return expression_generator_(T(const_str.size())); | |
23197 | } | |
23198 | ||
23199 | range_t rp; | |
23200 | ||
23201 | if (!parse_range(rp)) | |
23202 | { | |
23203 | free_node(node_allocator_,result); | |
23204 | ||
23205 | return error_node(); | |
23206 | } | |
23207 | ||
23208 | free_node(node_allocator_,result); | |
23209 | ||
23210 | if (rp.n1_c.first && (rp.n1_c.second == std::numeric_limits<std::size_t>::max())) | |
23211 | { | |
23212 | rp.n1_c.second = const_str.size() - 1; | |
23213 | rp.cache.second = rp.n1_c.second; | |
23214 | } | |
23215 | ||
23216 | if ( | |
23217 | (rp.n0_c.first && (rp.n0_c.second >= const_str.size())) || | |
23218 | (rp.n1_c.first && (rp.n1_c.second >= const_str.size())) | |
23219 | ) | |
23220 | { | |
23221 | set_error( | |
23222 | make_error(parser_error::e_syntax, | |
23223 | current_token(), | |
23224 | "ERR107 - Overflow in range for string: '" + const_str + "'[" + | |
23225 | (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + | |
23226 | (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", | |
23227 | exprtk_error_location)); | |
23228 | ||
23229 | return error_node(); | |
23230 | } | |
23231 | ||
23232 | result = expression_generator_(const_str,rp); | |
23233 | ||
23234 | if (result) | |
23235 | rp.clear(); | |
23236 | } | |
23237 | else | |
23238 | next_token(); | |
23239 | ||
23240 | return result; | |
23241 | } | |
23242 | #else | |
23243 | inline expression_node_ptr parse_const_string() | |
23244 | { | |
23245 | return error_node(); | |
23246 | } | |
23247 | #endif | |
23248 | ||
23249 | inline expression_node_ptr parse_vector() | |
23250 | { | |
23251 | const std::string symbol = current_token().value; | |
23252 | ||
23253 | vector_holder_ptr vec = vector_holder_ptr(0); | |
23254 | ||
23255 | const scope_element& se = sem_.get_active_element(symbol); | |
23256 | ||
23257 | if ( | |
23258 | !details::imatch(se.name, symbol) || | |
23259 | (se.depth > state_.scope_depth) || | |
23260 | (scope_element::e_vector != se.type) | |
23261 | ) | |
23262 | { | |
23263 | if (0 == (vec = symtab_store_.get_vector(symbol))) | |
23264 | { | |
23265 | set_error( | |
23266 | make_error(parser_error::e_syntax, | |
23267 | current_token(), | |
23268 | "ERR108 - Symbol '" + symbol+ " not a vector", | |
23269 | exprtk_error_location)); | |
23270 | ||
23271 | return error_node(); | |
23272 | } | |
23273 | } | |
23274 | else | |
23275 | vec = se.vec_node; | |
23276 | ||
23277 | expression_node_ptr index_expr = error_node(); | |
23278 | ||
23279 | next_token(); | |
23280 | ||
23281 | if (!token_is(token_t::e_lsqrbracket)) | |
23282 | { | |
23283 | return node_allocator_.allocate<vector_node_t>(vec); | |
23284 | } | |
23285 | else if (token_is(token_t::e_rsqrbracket)) | |
23286 | { | |
23287 | return expression_generator_(T(vec->size())); | |
23288 | } | |
23289 | else if (0 == (index_expr = parse_expression())) | |
23290 | { | |
23291 | set_error( | |
23292 | make_error(parser_error::e_syntax, | |
23293 | current_token(), | |
23294 | "ERR109 - Failed to parse index for vector: '" + symbol + "'", | |
23295 | exprtk_error_location)); | |
23296 | ||
23297 | return error_node(); | |
23298 | } | |
23299 | else if (!token_is(token_t::e_rsqrbracket)) | |
23300 | { | |
23301 | set_error( | |
23302 | make_error(parser_error::e_syntax, | |
23303 | current_token(), | |
23304 | "ERR110 - Expected ']' for index of vector: '" + symbol + "'", | |
23305 | exprtk_error_location)); | |
23306 | ||
23307 | free_node(node_allocator_,index_expr); | |
23308 | ||
23309 | return error_node(); | |
23310 | } | |
23311 | ||
23312 | // Perform compile-time range check | |
23313 | if (details::is_constant_node(index_expr)) | |
23314 | { | |
23315 | const std::size_t index = static_cast<std::size_t>(details::numeric::to_int32(index_expr->value())); | |
23316 | const std::size_t vec_size = vec->size(); | |
23317 | ||
23318 | if (index >= vec_size) | |
23319 | { | |
23320 | set_error( | |
23321 | make_error(parser_error::e_syntax, | |
23322 | current_token(), | |
23323 | "ERR111 - Index of " + details::to_str(index) + " out of range for " | |
23324 | "vector '" + symbol + "' of size " + details::to_str(vec_size), | |
23325 | exprtk_error_location)); | |
23326 | ||
23327 | free_node(node_allocator_,index_expr); | |
23328 | ||
23329 | return error_node(); | |
23330 | } | |
23331 | } | |
23332 | ||
23333 | return expression_generator_.vector_element(symbol, vec, index_expr); | |
23334 | } | |
23335 | ||
23336 | inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) | |
23337 | { | |
23338 | std::vector<expression_node_ptr> arg_list; | |
23339 | ||
23340 | expression_node_ptr result = error_node(); | |
23341 | ||
23342 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
23343 | ||
23344 | next_token(); | |
23345 | ||
23346 | if (token_is(token_t::e_lbracket)) | |
23347 | { | |
23348 | if (token_is(token_t::e_rbracket)) | |
23349 | { | |
23350 | if (!vararg_function->allow_zero_parameters()) | |
23351 | { | |
23352 | set_error( | |
23353 | make_error(parser_error::e_syntax, | |
23354 | current_token(), | |
23355 | "ERR112 - Zero parameter call to vararg function: " | |
23356 | + vararg_function_name + " not allowed", | |
23357 | exprtk_error_location)); | |
23358 | ||
23359 | return error_node(); | |
23360 | } | |
23361 | } | |
23362 | else | |
23363 | { | |
23364 | for ( ; ; ) | |
23365 | { | |
23366 | expression_node_ptr arg = parse_expression(); | |
23367 | ||
23368 | if (0 == arg) | |
23369 | return error_node(); | |
23370 | else | |
23371 | arg_list.push_back(arg); | |
23372 | ||
23373 | if (token_is(token_t::e_rbracket)) | |
23374 | break; | |
23375 | else if (!token_is(token_t::e_comma)) | |
23376 | { | |
23377 | set_error( | |
23378 | make_error(parser_error::e_syntax, | |
23379 | current_token(), | |
23380 | "ERR113 - Expected ',' for call to vararg function: " | |
23381 | + vararg_function_name, | |
23382 | exprtk_error_location)); | |
23383 | ||
23384 | return error_node(); | |
23385 | } | |
23386 | } | |
23387 | } | |
23388 | } | |
23389 | else if (!vararg_function->allow_zero_parameters()) | |
23390 | { | |
23391 | set_error( | |
23392 | make_error(parser_error::e_syntax, | |
23393 | current_token(), | |
23394 | "ERR114 - Zero parameter call to vararg function: " | |
23395 | + vararg_function_name + " not allowed", | |
23396 | exprtk_error_location)); | |
23397 | ||
23398 | return error_node(); | |
23399 | } | |
23400 | ||
23401 | if (arg_list.size() < vararg_function->min_num_args()) | |
23402 | { | |
23403 | set_error( | |
23404 | make_error(parser_error::e_syntax, | |
23405 | current_token(), | |
23406 | "ERR115 - Invalid number of parameters to call to vararg function: " | |
23407 | + vararg_function_name + ", require at least " | |
23408 | + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", | |
23409 | exprtk_error_location)); | |
23410 | ||
23411 | return error_node(); | |
23412 | } | |
23413 | else if (arg_list.size() > vararg_function->max_num_args()) | |
23414 | { | |
23415 | set_error( | |
23416 | make_error(parser_error::e_syntax, | |
23417 | current_token(), | |
23418 | "ERR116 - Invalid number of parameters to call to vararg function: " | |
23419 | + vararg_function_name + ", require no more than " | |
23420 | + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", | |
23421 | exprtk_error_location)); | |
23422 | ||
23423 | return error_node(); | |
23424 | } | |
23425 | ||
23426 | result = expression_generator_.vararg_function_call(vararg_function,arg_list); | |
23427 | ||
23428 | sdd.delete_ptr = (0 == result); | |
23429 | ||
23430 | return result; | |
23431 | } | |
23432 | ||
23433 | class type_checker | |
23434 | { | |
23435 | public: | |
23436 | ||
23437 | enum return_type_t | |
23438 | { | |
23439 | e_overload = ' ', | |
23440 | e_numeric = 'T', | |
23441 | e_string = 'S' | |
23442 | }; | |
23443 | ||
23444 | struct function_prototype_t | |
23445 | { | |
23446 | return_type_t return_type; | |
23447 | std::string param_seq; | |
23448 | }; | |
23449 | ||
23450 | typedef parser<T> parser_t; | |
23451 | typedef std::vector<function_prototype_t> function_definition_list_t; | |
23452 | ||
23453 | type_checker(parser_t& p, | |
23454 | const std::string& func_name, | |
23455 | const std::string& func_prototypes, | |
23456 | const return_type_t default_return_type) | |
23457 | : invalid_state_(true), | |
23458 | parser_(p), | |
23459 | function_name_(func_name), | |
23460 | default_return_type_(default_return_type) | |
23461 | { | |
23462 | parse_function_prototypes(func_prototypes); | |
23463 | } | |
23464 | ||
23465 | void set_default_return_type(const std::string& return_type) | |
23466 | { | |
23467 | default_return_type_ = return_type; | |
23468 | } | |
23469 | ||
23470 | bool verify(const std::string& param_seq, std::size_t& pseq_index) | |
23471 | { | |
23472 | if (function_definition_list_.empty()) | |
23473 | return true; | |
23474 | ||
23475 | std::vector<std::pair<std::size_t,char> > error_list; | |
23476 | ||
23477 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) | |
23478 | { | |
23479 | details::char_t diff_value = 0; | |
23480 | std::size_t diff_index = 0; | |
23481 | ||
23482 | const bool result = details::sequence_match(function_definition_list_[i].param_seq, | |
23483 | param_seq, | |
23484 | diff_index, diff_value); | |
23485 | ||
23486 | if (result) | |
23487 | { | |
23488 | pseq_index = i; | |
23489 | return true; | |
23490 | } | |
23491 | else | |
23492 | error_list.push_back(std::make_pair(diff_index, diff_value)); | |
23493 | } | |
23494 | ||
23495 | if (1 == error_list.size()) | |
23496 | { | |
23497 | parser_. | |
23498 | set_error( | |
23499 | make_error(parser_error::e_syntax, | |
23500 | parser_.current_token(), | |
23501 | "ERR117 - Failed parameter type check for function '" + function_name_ + "', " | |
23502 | "Expected '" + function_definition_list_[0].param_seq + | |
23503 | "' call set: '" + param_seq + "'", | |
23504 | exprtk_error_location)); | |
23505 | } | |
23506 | else | |
23507 | { | |
23508 | // find first with largest diff_index; | |
23509 | std::size_t max_diff_index = 0; | |
23510 | ||
23511 | for (std::size_t i = 1; i < error_list.size(); ++i) | |
23512 | { | |
23513 | if (error_list[i].first > error_list[max_diff_index].first) | |
23514 | { | |
23515 | max_diff_index = i; | |
23516 | } | |
23517 | } | |
23518 | ||
23519 | parser_. | |
23520 | set_error( | |
23521 | make_error(parser_error::e_syntax, | |
23522 | parser_.current_token(), | |
23523 | "ERR118 - Failed parameter type check for function '" + function_name_ + "', " | |
23524 | "Best match: '" + function_definition_list_[max_diff_index].param_seq + | |
23525 | "' call set: '" + param_seq + "'", | |
23526 | exprtk_error_location)); | |
23527 | } | |
23528 | ||
23529 | return false; | |
23530 | } | |
23531 | ||
23532 | std::size_t paramseq_count() const | |
23533 | { | |
23534 | return function_definition_list_.size(); | |
23535 | } | |
23536 | ||
23537 | std::string paramseq(const std::size_t& index) const | |
23538 | { | |
23539 | return function_definition_list_[index].param_seq; | |
23540 | } | |
23541 | ||
23542 | return_type_t return_type(const std::size_t& index) const | |
23543 | { | |
23544 | return function_definition_list_[index].return_type; | |
23545 | } | |
23546 | ||
23547 | bool invalid() const | |
23548 | { | |
23549 | return !invalid_state_; | |
23550 | } | |
23551 | ||
23552 | bool allow_zero_parameters() const | |
23553 | { | |
23554 | ||
23555 | for (std::size_t i = 0; i < function_definition_list_.size(); ++i) | |
23556 | { | |
23557 | if (std::string::npos != function_definition_list_[i].param_seq.find("Z")) | |
23558 | { | |
23559 | return true; | |
23560 | } | |
23561 | } | |
23562 | ||
23563 | return false; | |
23564 | } | |
23565 | ||
23566 | private: | |
23567 | ||
23568 | std::vector<std::string> split_param_seq(const std::string& param_seq, const details::char_t delimiter = '|') const | |
23569 | { | |
23570 | std::string::const_iterator current_begin = param_seq.begin(); | |
23571 | std::string::const_iterator iter = param_seq.begin(); | |
23572 | ||
23573 | std::vector<std::string> result; | |
23574 | ||
23575 | while (iter != param_seq.end()) | |
23576 | { | |
23577 | if (*iter == delimiter) | |
23578 | { | |
23579 | result.push_back(std::string(current_begin, iter)); | |
23580 | current_begin = ++iter; | |
23581 | } | |
23582 | else | |
23583 | ++iter; | |
23584 | } | |
23585 | ||
23586 | if (current_begin != iter) | |
23587 | { | |
23588 | result.push_back(std::string(current_begin, iter)); | |
23589 | } | |
23590 | ||
23591 | return result; | |
23592 | } | |
23593 | ||
23594 | inline bool is_valid_token(std::string param_seq, | |
23595 | function_prototype_t& funcproto) const | |
23596 | { | |
23597 | // Determine return type | |
23598 | funcproto.return_type = default_return_type_; | |
23599 | ||
23600 | if (param_seq.size() > 2) | |
23601 | { | |
23602 | if (':' == param_seq[1]) | |
23603 | { | |
23604 | // Note: Only overloaded igeneric functions can have return | |
23605 | // type definitions. | |
23606 | if (type_checker::e_overload != default_return_type_) | |
23607 | return false; | |
23608 | ||
23609 | switch (param_seq[0]) | |
23610 | { | |
23611 | case 'T' : funcproto.return_type = type_checker::e_numeric; | |
23612 | break; | |
23613 | ||
23614 | case 'S' : funcproto.return_type = type_checker::e_string; | |
23615 | break; | |
23616 | ||
23617 | default : return false; | |
23618 | } | |
23619 | ||
23620 | param_seq.erase(0,2); | |
23621 | } | |
23622 | } | |
23623 | ||
23624 | if ( | |
23625 | (std::string::npos != param_seq.find("?*")) || | |
23626 | (std::string::npos != param_seq.find("**")) | |
23627 | ) | |
23628 | { | |
23629 | return false; | |
23630 | } | |
23631 | else if ( | |
23632 | (std::string::npos == param_seq.find_first_not_of("STV*?|")) || | |
23633 | ("Z" == param_seq) | |
23634 | ) | |
23635 | { | |
23636 | funcproto.param_seq = param_seq; | |
23637 | return true; | |
23638 | } | |
23639 | ||
23640 | return false; | |
23641 | } | |
23642 | ||
23643 | void parse_function_prototypes(const std::string& func_prototypes) | |
23644 | { | |
23645 | if (func_prototypes.empty()) | |
23646 | return; | |
23647 | ||
23648 | std::vector<std::string> param_seq_list = split_param_seq(func_prototypes); | |
23649 | ||
23650 | typedef std::map<std::string,std::size_t> param_seq_map_t; | |
23651 | param_seq_map_t param_seq_map; | |
23652 | ||
23653 | for (std::size_t i = 0; i < param_seq_list.size(); ++i) | |
23654 | { | |
23655 | function_prototype_t func_proto; | |
23656 | ||
23657 | if (!is_valid_token(param_seq_list[i], func_proto)) | |
23658 | { | |
23659 | invalid_state_ = false; | |
23660 | ||
23661 | parser_. | |
23662 | set_error( | |
23663 | make_error(parser_error::e_syntax, | |
23664 | parser_.current_token(), | |
23665 | "ERR119 - Invalid parameter sequence of '" + param_seq_list[i] + | |
23666 | "' for function: " + function_name_, | |
23667 | exprtk_error_location)); | |
23668 | return; | |
23669 | } | |
23670 | ||
23671 | param_seq_map_t::const_iterator seq_itr = param_seq_map.find(param_seq_list[i]); | |
23672 | ||
23673 | if (param_seq_map.end() != seq_itr) | |
23674 | { | |
23675 | invalid_state_ = false; | |
23676 | ||
23677 | parser_. | |
23678 | set_error( | |
23679 | make_error(parser_error::e_syntax, | |
23680 | parser_.current_token(), | |
23681 | "ERR120 - Function '" + function_name_ + "' has a parameter sequence conflict between " + | |
23682 | "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + | |
23683 | "pseq_idx[" + details::to_str(i) + "] " + | |
23684 | "param seq: " + param_seq_list[i], | |
23685 | exprtk_error_location)); | |
23686 | return; | |
23687 | } | |
23688 | ||
23689 | function_definition_list_.push_back(func_proto); | |
23690 | } | |
23691 | } | |
23692 | ||
23693 | type_checker(const type_checker&); | |
23694 | type_checker& operator=(const type_checker&); | |
23695 | ||
23696 | bool invalid_state_; | |
23697 | parser_t& parser_; | |
23698 | std::string function_name_; | |
23699 | const return_type_t default_return_type_; | |
23700 | function_definition_list_t function_definition_list_; | |
23701 | }; | |
23702 | ||
23703 | inline expression_node_ptr parse_generic_function_call(igeneric_function<T>* function, const std::string& function_name) | |
23704 | { | |
23705 | std::vector<expression_node_ptr> arg_list; | |
23706 | ||
23707 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
23708 | ||
23709 | next_token(); | |
23710 | ||
23711 | std::string param_type_list; | |
23712 | ||
23713 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); | |
23714 | ||
23715 | if (tc.invalid()) | |
23716 | { | |
23717 | set_error( | |
23718 | make_error(parser_error::e_syntax, | |
23719 | current_token(), | |
23720 | "ERR121 - Type checker instantiation failure for generic function: " + function_name, | |
23721 | exprtk_error_location)); | |
23722 | ||
23723 | return error_node(); | |
23724 | } | |
23725 | ||
23726 | if (token_is(token_t::e_lbracket)) | |
23727 | { | |
23728 | if (token_is(token_t::e_rbracket)) | |
23729 | { | |
23730 | if ( | |
23731 | !function->allow_zero_parameters() && | |
23732 | !tc .allow_zero_parameters() | |
23733 | ) | |
23734 | { | |
23735 | set_error( | |
23736 | make_error(parser_error::e_syntax, | |
23737 | current_token(), | |
23738 | "ERR122 - Zero parameter call to generic function: " | |
23739 | + function_name + " not allowed", | |
23740 | exprtk_error_location)); | |
23741 | ||
23742 | return error_node(); | |
23743 | } | |
23744 | } | |
23745 | else | |
23746 | { | |
23747 | for ( ; ; ) | |
23748 | { | |
23749 | expression_node_ptr arg = parse_expression(); | |
23750 | ||
23751 | if (0 == arg) | |
23752 | return error_node(); | |
23753 | ||
23754 | if (is_ivector_node(arg)) | |
23755 | param_type_list += 'V'; | |
23756 | else if (is_generally_string_node(arg)) | |
23757 | param_type_list += 'S'; | |
23758 | else // Everything else is assumed to be a scalar returning expression | |
23759 | param_type_list += 'T'; | |
23760 | ||
23761 | arg_list.push_back(arg); | |
23762 | ||
23763 | if (token_is(token_t::e_rbracket)) | |
23764 | break; | |
23765 | else if (!token_is(token_t::e_comma)) | |
23766 | { | |
23767 | set_error( | |
23768 | make_error(parser_error::e_syntax, | |
23769 | current_token(), | |
23770 | "ERR123 - Expected ',' for call to generic function: " + function_name, | |
23771 | exprtk_error_location)); | |
23772 | ||
23773 | return error_node(); | |
23774 | } | |
23775 | } | |
23776 | } | |
23777 | } | |
23778 | else if ( | |
23779 | !function->parameter_sequence.empty() && | |
23780 | function->allow_zero_parameters () && | |
23781 | !tc .allow_zero_parameters () | |
23782 | ) | |
23783 | { | |
23784 | set_error( | |
23785 | make_error(parser_error::e_syntax, | |
23786 | current_token(), | |
23787 | "ERR124 - Zero parameter call to generic function: " | |
23788 | + function_name + " not allowed", | |
23789 | exprtk_error_location)); | |
23790 | ||
23791 | return error_node(); | |
23792 | } | |
23793 | ||
23794 | std::size_t param_seq_index = 0; | |
23795 | ||
23796 | if ( | |
23797 | state_.type_check_enabled && | |
23798 | !tc.verify(param_type_list, param_seq_index) | |
23799 | ) | |
23800 | { | |
23801 | set_error( | |
23802 | make_error(parser_error::e_syntax, | |
23803 | current_token(), | |
23804 | "ERR125 - Invalid input parameter sequence for call to generic function: " + function_name, | |
23805 | exprtk_error_location)); | |
23806 | ||
23807 | return error_node(); | |
23808 | } | |
23809 | ||
23810 | expression_node_ptr result = error_node(); | |
23811 | ||
23812 | if (tc.paramseq_count() <= 1) | |
23813 | result = expression_generator_ | |
23814 | .generic_function_call(function, arg_list); | |
23815 | else | |
23816 | result = expression_generator_ | |
23817 | .generic_function_call(function, arg_list, param_seq_index); | |
23818 | ||
23819 | sdd.delete_ptr = (0 == result); | |
23820 | ||
23821 | return result; | |
23822 | } | |
23823 | ||
23824 | inline bool parse_igeneric_function_params(std::string& param_type_list, | |
23825 | std::vector<expression_node_ptr>& arg_list, | |
23826 | const std::string& function_name, | |
23827 | igeneric_function<T>* function, | |
23828 | const type_checker& tc) | |
23829 | { | |
23830 | if (token_is(token_t::e_lbracket)) | |
23831 | { | |
23832 | if (token_is(token_t::e_rbracket)) | |
23833 | { | |
23834 | if ( | |
23835 | !function->allow_zero_parameters() && | |
23836 | !tc .allow_zero_parameters() | |
23837 | ) | |
23838 | { | |
23839 | set_error( | |
23840 | make_error(parser_error::e_syntax, | |
23841 | current_token(), | |
23842 | "ERR126 - Zero parameter call to generic function: " | |
23843 | + function_name + " not allowed", | |
23844 | exprtk_error_location)); | |
23845 | ||
23846 | return false; | |
23847 | } | |
23848 | } | |
23849 | else | |
23850 | { | |
23851 | for ( ; ; ) | |
23852 | { | |
23853 | expression_node_ptr arg = parse_expression(); | |
23854 | ||
23855 | if (0 == arg) | |
23856 | return false; | |
23857 | ||
23858 | if (is_ivector_node(arg)) | |
23859 | param_type_list += 'V'; | |
23860 | else if (is_generally_string_node(arg)) | |
23861 | param_type_list += 'S'; | |
23862 | else // Everything else is a scalar returning expression | |
23863 | param_type_list += 'T'; | |
23864 | ||
23865 | arg_list.push_back(arg); | |
23866 | ||
23867 | if (token_is(token_t::e_rbracket)) | |
23868 | break; | |
23869 | else if (!token_is(token_t::e_comma)) | |
23870 | { | |
23871 | set_error( | |
23872 | make_error(parser_error::e_syntax, | |
23873 | current_token(), | |
23874 | "ERR127 - Expected ',' for call to string function: " + function_name, | |
23875 | exprtk_error_location)); | |
23876 | ||
23877 | return false; | |
23878 | } | |
23879 | } | |
23880 | } | |
23881 | ||
23882 | return true; | |
23883 | } | |
23884 | else | |
23885 | return false; | |
23886 | } | |
23887 | ||
23888 | #ifndef exprtk_disable_string_capabilities | |
23889 | inline expression_node_ptr parse_string_function_call(igeneric_function<T>* function, const std::string& function_name) | |
23890 | { | |
23891 | // Move pass the function name | |
23892 | next_token(); | |
23893 | ||
23894 | std::string param_type_list; | |
23895 | ||
23896 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_string); | |
23897 | ||
23898 | if ( | |
23899 | (!function->parameter_sequence.empty()) && | |
23900 | (0 == tc.paramseq_count()) | |
23901 | ) | |
23902 | { | |
23903 | return error_node(); | |
23904 | } | |
23905 | ||
23906 | std::vector<expression_node_ptr> arg_list; | |
23907 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
23908 | ||
23909 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) | |
23910 | { | |
23911 | return error_node(); | |
23912 | } | |
23913 | ||
23914 | std::size_t param_seq_index = 0; | |
23915 | ||
23916 | if (!tc.verify(param_type_list, param_seq_index)) | |
23917 | { | |
23918 | set_error( | |
23919 | make_error(parser_error::e_syntax, | |
23920 | current_token(), | |
23921 | "ERR128 - Invalid input parameter sequence for call to string function: " + function_name, | |
23922 | exprtk_error_location)); | |
23923 | ||
23924 | return error_node(); | |
23925 | } | |
23926 | ||
23927 | expression_node_ptr result = error_node(); | |
23928 | ||
23929 | if (tc.paramseq_count() <= 1) | |
23930 | result = expression_generator_ | |
23931 | .string_function_call(function, arg_list); | |
23932 | else | |
23933 | result = expression_generator_ | |
23934 | .string_function_call(function, arg_list, param_seq_index); | |
23935 | ||
23936 | sdd.delete_ptr = (0 == result); | |
23937 | ||
23938 | return result; | |
23939 | } | |
23940 | ||
23941 | inline expression_node_ptr parse_overload_function_call(igeneric_function<T>* function, const std::string& function_name) | |
23942 | { | |
23943 | // Move pass the function name | |
23944 | next_token(); | |
23945 | ||
23946 | std::string param_type_list; | |
23947 | ||
23948 | type_checker tc((*this), function_name, function->parameter_sequence, type_checker::e_overload); | |
23949 | ||
23950 | if ( | |
23951 | (!function->parameter_sequence.empty()) && | |
23952 | (0 == tc.paramseq_count()) | |
23953 | ) | |
23954 | { | |
23955 | return error_node(); | |
23956 | } | |
23957 | ||
23958 | std::vector<expression_node_ptr> arg_list; | |
23959 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
23960 | ||
23961 | if (!parse_igeneric_function_params(param_type_list, arg_list, function_name, function, tc)) | |
23962 | { | |
23963 | return error_node(); | |
23964 | } | |
23965 | ||
23966 | std::size_t param_seq_index = 0; | |
23967 | ||
23968 | if (!tc.verify(param_type_list, param_seq_index)) | |
23969 | { | |
23970 | set_error( | |
23971 | make_error(parser_error::e_syntax, | |
23972 | current_token(), | |
23973 | "ERR129 - Invalid input parameter sequence for call to overloaded function: " + function_name, | |
23974 | exprtk_error_location)); | |
23975 | ||
23976 | return error_node(); | |
23977 | } | |
23978 | ||
23979 | expression_node_ptr result = error_node(); | |
23980 | ||
23981 | if (type_checker::e_numeric == tc.return_type(param_seq_index)) | |
23982 | { | |
23983 | if (tc.paramseq_count() <= 1) | |
23984 | result = expression_generator_ | |
23985 | .generic_function_call(function, arg_list); | |
23986 | else | |
23987 | result = expression_generator_ | |
23988 | .generic_function_call(function, arg_list, param_seq_index); | |
23989 | } | |
23990 | else if (type_checker::e_string == tc.return_type(param_seq_index)) | |
23991 | { | |
23992 | if (tc.paramseq_count() <= 1) | |
23993 | result = expression_generator_ | |
23994 | .string_function_call(function, arg_list); | |
23995 | else | |
23996 | result = expression_generator_ | |
23997 | .string_function_call(function, arg_list, param_seq_index); | |
23998 | } | |
23999 | else | |
24000 | { | |
24001 | set_error( | |
24002 | make_error(parser_error::e_syntax, | |
24003 | current_token(), | |
24004 | "ERR130 - Invalid return type for call to overloaded function: " + function_name, | |
24005 | exprtk_error_location)); | |
24006 | } | |
24007 | ||
24008 | sdd.delete_ptr = (0 == result); | |
24009 | return result; | |
24010 | } | |
24011 | #endif | |
24012 | ||
24013 | template <typename Type, std::size_t NumberOfParameters> | |
24014 | struct parse_special_function_impl | |
24015 | { | |
24016 | static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) | |
24017 | { | |
24018 | expression_node_ptr branch[NumberOfParameters]; | |
24019 | expression_node_ptr result = error_node(); | |
24020 | ||
24021 | std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0)); | |
24022 | ||
24023 | scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); | |
24024 | ||
24025 | p.next_token(); | |
24026 | ||
24027 | if (!p.token_is(token_t::e_lbracket)) | |
24028 | { | |
24029 | p.set_error( | |
24030 | make_error(parser_error::e_syntax, | |
24031 | p.current_token(), | |
24032 | "ERR131 - Expected '(' for special function '" + sf_name + "'", | |
24033 | exprtk_error_location)); | |
24034 | ||
24035 | return error_node(); | |
24036 | } | |
24037 | ||
24038 | for (std::size_t i = 0; i < NumberOfParameters; ++i) | |
24039 | { | |
24040 | branch[i] = p.parse_expression(); | |
24041 | ||
24042 | if (0 == branch[i]) | |
24043 | { | |
24044 | return p.error_node(); | |
24045 | } | |
24046 | else if (i < (NumberOfParameters - 1)) | |
24047 | { | |
24048 | if (!p.token_is(token_t::e_comma)) | |
24049 | { | |
24050 | p.set_error( | |
24051 | make_error(parser_error::e_syntax, | |
24052 | p.current_token(), | |
24053 | "ERR132 - Expected ',' before next parameter of special function '" + sf_name + "'", | |
24054 | exprtk_error_location)); | |
24055 | ||
24056 | return p.error_node(); | |
24057 | } | |
24058 | } | |
24059 | } | |
24060 | ||
24061 | if (!p.token_is(token_t::e_rbracket)) | |
24062 | { | |
24063 | p.set_error( | |
24064 | make_error(parser_error::e_syntax, | |
24065 | p.current_token(), | |
24066 | "ERR133 - Invalid number of parameters for special function '" + sf_name + "'", | |
24067 | exprtk_error_location)); | |
24068 | ||
24069 | return p.error_node(); | |
24070 | } | |
24071 | else | |
24072 | result = p.expression_generator_.special_function(opt_type,branch); | |
24073 | ||
24074 | sd.delete_ptr = (0 == result); | |
24075 | ||
24076 | return result; | |
24077 | } | |
24078 | }; | |
24079 | ||
24080 | inline expression_node_ptr parse_special_function() | |
24081 | { | |
24082 | const std::string sf_name = current_token().value; | |
24083 | ||
24084 | // Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3) | |
24085 | if ( | |
24086 | !details::is_digit(sf_name[2]) || | |
24087 | !details::is_digit(sf_name[3]) | |
24088 | ) | |
24089 | { | |
24090 | set_error( | |
24091 | make_error(parser_error::e_token, | |
24092 | current_token(), | |
24093 | "ERR134 - Invalid special function[1]: " + sf_name, | |
24094 | exprtk_error_location)); | |
24095 | ||
24096 | return error_node(); | |
24097 | } | |
24098 | ||
24099 | const int id = (sf_name[2] - '0') * 10 + | |
24100 | (sf_name[3] - '0'); | |
24101 | ||
24102 | if (id >= details::e_sffinal) | |
24103 | { | |
24104 | set_error( | |
24105 | make_error(parser_error::e_token, | |
24106 | current_token(), | |
24107 | "ERR135 - Invalid special function[2]: " + sf_name, | |
24108 | exprtk_error_location)); | |
24109 | ||
24110 | return error_node(); | |
24111 | } | |
24112 | ||
24113 | const int sf_3_to_4 = details::e_sf48; | |
24114 | const details::operator_type opt_type = details::operator_type(id + 1000); | |
24115 | const std::size_t NumberOfParameters = (id < (sf_3_to_4 - 1000)) ? 3U : 4U; | |
24116 | ||
24117 | switch (NumberOfParameters) | |
24118 | { | |
24119 | case 3 : return parse_special_function_impl<T,3>::process((*this), opt_type, sf_name); | |
24120 | case 4 : return parse_special_function_impl<T,4>::process((*this), opt_type, sf_name); | |
24121 | default : return error_node(); | |
24122 | } | |
24123 | } | |
24124 | ||
24125 | inline expression_node_ptr parse_null_statement() | |
24126 | { | |
24127 | next_token(); | |
24128 | return node_allocator_.allocate<details::null_node<T> >(); | |
24129 | } | |
24130 | ||
24131 | #ifndef exprtk_disable_break_continue | |
24132 | inline expression_node_ptr parse_break_statement() | |
24133 | { | |
24134 | if (state_.parsing_break_stmt) | |
24135 | { | |
24136 | set_error( | |
24137 | make_error(parser_error::e_syntax, | |
24138 | current_token(), | |
24139 | "ERR136 - Break call within a break call is not allowed", | |
24140 | exprtk_error_location)); | |
24141 | ||
24142 | return error_node(); | |
24143 | } | |
24144 | ||
24145 | scoped_bool_negator sbn(state_.parsing_break_stmt); | |
24146 | ||
24147 | if (!brkcnt_list_.empty()) | |
24148 | { | |
24149 | next_token(); | |
24150 | ||
24151 | brkcnt_list_.front() = true; | |
24152 | ||
24153 | expression_node_ptr return_expr = error_node(); | |
24154 | ||
24155 | if (token_is(token_t::e_lsqrbracket)) | |
24156 | { | |
24157 | if (0 == (return_expr = parse_expression())) | |
24158 | { | |
24159 | set_error( | |
24160 | make_error(parser_error::e_syntax, | |
24161 | current_token(), | |
24162 | "ERR137 - Failed to parse return expression for 'break' statement", | |
24163 | exprtk_error_location)); | |
24164 | ||
24165 | return error_node(); | |
24166 | } | |
24167 | else if (!token_is(token_t::e_rsqrbracket)) | |
24168 | { | |
24169 | set_error( | |
24170 | make_error(parser_error::e_syntax, | |
24171 | current_token(), | |
24172 | "ERR138 - Expected ']' at the completion of break's return expression", | |
24173 | exprtk_error_location)); | |
24174 | ||
24175 | free_node(node_allocator_,return_expr); | |
24176 | ||
24177 | return error_node(); | |
24178 | } | |
24179 | } | |
24180 | ||
24181 | state_.activate_side_effect("parse_break_statement()"); | |
24182 | ||
24183 | return node_allocator_.allocate<details::break_node<T> >(return_expr); | |
24184 | } | |
24185 | else | |
24186 | { | |
24187 | set_error( | |
24188 | make_error(parser_error::e_syntax, | |
24189 | current_token(), | |
24190 | "ERR139 - Invalid use of 'break', allowed only in the scope of a loop", | |
24191 | exprtk_error_location)); | |
24192 | } | |
24193 | ||
24194 | return error_node(); | |
24195 | } | |
24196 | ||
24197 | inline expression_node_ptr parse_continue_statement() | |
24198 | { | |
24199 | if (!brkcnt_list_.empty()) | |
24200 | { | |
24201 | next_token(); | |
24202 | ||
24203 | brkcnt_list_.front() = true; | |
24204 | state_.activate_side_effect("parse_continue_statement()"); | |
24205 | ||
24206 | return node_allocator_.allocate<details::continue_node<T> >(); | |
24207 | } | |
24208 | else | |
24209 | { | |
24210 | set_error( | |
24211 | make_error(parser_error::e_syntax, | |
24212 | current_token(), | |
24213 | "ERR140 - Invalid use of 'continue', allowed only in the scope of a loop", | |
24214 | exprtk_error_location)); | |
24215 | ||
24216 | return error_node(); | |
24217 | } | |
24218 | } | |
24219 | #endif | |
24220 | ||
24221 | inline expression_node_ptr parse_define_vector_statement(const std::string& vec_name) | |
24222 | { | |
24223 | expression_node_ptr size_expr = error_node(); | |
24224 | ||
24225 | if (!token_is(token_t::e_lsqrbracket)) | |
24226 | { | |
24227 | set_error( | |
24228 | make_error(parser_error::e_syntax, | |
24229 | current_token(), | |
24230 | "ERR141 - Expected '[' as part of vector size definition", | |
24231 | exprtk_error_location)); | |
24232 | ||
24233 | return error_node(); | |
24234 | } | |
24235 | else if (0 == (size_expr = parse_expression())) | |
24236 | { | |
24237 | set_error( | |
24238 | make_error(parser_error::e_syntax, | |
24239 | current_token(), | |
24240 | "ERR142 - Failed to determine size of vector '" + vec_name + "'", | |
24241 | exprtk_error_location)); | |
24242 | ||
24243 | return error_node(); | |
24244 | } | |
24245 | else if (!is_constant_node(size_expr)) | |
24246 | { | |
24247 | free_node(node_allocator_,size_expr); | |
24248 | ||
24249 | set_error( | |
24250 | make_error(parser_error::e_syntax, | |
24251 | current_token(), | |
24252 | "ERR143 - Expected a literal number as size of vector '" + vec_name + "'", | |
24253 | exprtk_error_location)); | |
24254 | ||
24255 | return error_node(); | |
24256 | } | |
24257 | ||
24258 | const T vector_size = size_expr->value(); | |
24259 | ||
24260 | free_node(node_allocator_,size_expr); | |
24261 | ||
24262 | const T max_vector_size = T(2000000000.0); | |
24263 | ||
24264 | if ( | |
24265 | (vector_size <= T(0)) || | |
24266 | std::not_equal_to<T>() | |
24267 | (T(0),vector_size - details::numeric::trunc(vector_size)) || | |
24268 | (vector_size > max_vector_size) | |
24269 | ) | |
24270 | { | |
24271 | set_error( | |
24272 | make_error(parser_error::e_syntax, | |
24273 | current_token(), | |
24274 | "ERR144 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + | |
24275 | details::to_str(details::numeric::to_int32(vector_size)), | |
24276 | exprtk_error_location)); | |
24277 | ||
24278 | return error_node(); | |
24279 | } | |
24280 | ||
24281 | std::vector<expression_node_ptr> vec_initilizer_list; | |
24282 | ||
24283 | scoped_vec_delete<expression_node_t> svd((*this),vec_initilizer_list); | |
24284 | ||
24285 | bool single_value_initialiser = false; | |
24286 | bool vec_to_vec_initialiser = false; | |
24287 | bool null_initialisation = false; | |
24288 | ||
24289 | if (!token_is(token_t::e_rsqrbracket)) | |
24290 | { | |
24291 | set_error( | |
24292 | make_error(parser_error::e_syntax, | |
24293 | current_token(), | |
24294 | "ERR145 - Expected ']' as part of vector size definition", | |
24295 | exprtk_error_location)); | |
24296 | ||
24297 | return error_node(); | |
24298 | } | |
24299 | else if (!token_is(token_t::e_eof)) | |
24300 | { | |
24301 | if (!token_is(token_t::e_assign)) | |
24302 | { | |
24303 | set_error( | |
24304 | make_error(parser_error::e_syntax, | |
24305 | current_token(), | |
24306 | "ERR146 - Expected ':=' as part of vector definition", | |
24307 | exprtk_error_location)); | |
24308 | ||
24309 | return error_node(); | |
24310 | } | |
24311 | else if (token_is(token_t::e_lsqrbracket)) | |
24312 | { | |
24313 | expression_node_ptr initialiser = parse_expression(); | |
24314 | ||
24315 | if (0 == initialiser) | |
24316 | { | |
24317 | set_error( | |
24318 | make_error(parser_error::e_syntax, | |
24319 | current_token(), | |
24320 | "ERR147 - Failed to parse single vector initialiser", | |
24321 | exprtk_error_location)); | |
24322 | ||
24323 | return error_node(); | |
24324 | } | |
24325 | ||
24326 | vec_initilizer_list.push_back(initialiser); | |
24327 | ||
24328 | if (!token_is(token_t::e_rsqrbracket)) | |
24329 | { | |
24330 | set_error( | |
24331 | make_error(parser_error::e_syntax, | |
24332 | current_token(), | |
24333 | "ERR148 - Expected ']' to close single value vector initialiser", | |
24334 | exprtk_error_location)); | |
24335 | ||
24336 | return error_node(); | |
24337 | } | |
24338 | ||
24339 | single_value_initialiser = true; | |
24340 | } | |
24341 | else if (!token_is(token_t::e_lcrlbracket)) | |
24342 | { | |
24343 | expression_node_ptr initialiser = error_node(); | |
24344 | ||
24345 | // Is this a vector to vector assignment and initialisation? | |
24346 | if (token_t::e_symbol == current_token().type) | |
24347 | { | |
24348 | // Is it a locally defined vector? | |
24349 | scope_element& se = sem_.get_active_element(current_token().value); | |
24350 | ||
24351 | if (scope_element::e_vector == se.type) | |
24352 | { | |
24353 | if (0 != (initialiser = parse_expression())) | |
24354 | vec_initilizer_list.push_back(initialiser); | |
24355 | else | |
24356 | return error_node(); | |
24357 | } | |
24358 | // Are we dealing with a user defined vector? | |
24359 | else if (symtab_store_.is_vector(current_token().value)) | |
24360 | { | |
24361 | lodge_symbol(current_token().value, e_st_vector); | |
24362 | ||
24363 | if (0 != (initialiser = parse_expression())) | |
24364 | vec_initilizer_list.push_back(initialiser); | |
24365 | else | |
24366 | return error_node(); | |
24367 | } | |
24368 | // Are we dealing with a null initialisation vector definition? | |
24369 | else if (token_is(token_t::e_symbol,"null")) | |
24370 | null_initialisation = true; | |
24371 | } | |
24372 | ||
24373 | if (!null_initialisation) | |
24374 | { | |
24375 | if (0 == initialiser) | |
24376 | { | |
24377 | set_error( | |
24378 | make_error(parser_error::e_syntax, | |
24379 | current_token(), | |
24380 | "ERR149 - Expected '{' as part of vector initialiser list", | |
24381 | exprtk_error_location)); | |
24382 | ||
24383 | return error_node(); | |
24384 | } | |
24385 | else | |
24386 | vec_to_vec_initialiser = true; | |
24387 | } | |
24388 | } | |
24389 | else if (!token_is(token_t::e_rcrlbracket)) | |
24390 | { | |
24391 | for ( ; ; ) | |
24392 | { | |
24393 | expression_node_ptr initialiser = parse_expression(); | |
24394 | ||
24395 | if (0 == initialiser) | |
24396 | { | |
24397 | set_error( | |
24398 | make_error(parser_error::e_syntax, | |
24399 | current_token(), | |
24400 | "ERR150 - Expected '{' as part of vector initialiser list", | |
24401 | exprtk_error_location)); | |
24402 | ||
24403 | return error_node(); | |
24404 | } | |
24405 | else | |
24406 | vec_initilizer_list.push_back(initialiser); | |
24407 | ||
24408 | if (token_is(token_t::e_rcrlbracket)) | |
24409 | break; | |
24410 | ||
24411 | const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); | |
24412 | ||
24413 | if (!token_is(token_t::e_comma) && is_next_close) | |
24414 | { | |
24415 | set_error( | |
24416 | make_error(parser_error::e_syntax, | |
24417 | current_token(), | |
24418 | "ERR151 - Expected ',' between vector initialisers", | |
24419 | exprtk_error_location)); | |
24420 | ||
24421 | return error_node(); | |
24422 | } | |
24423 | ||
24424 | if (token_is(token_t::e_rcrlbracket)) | |
24425 | break; | |
24426 | } | |
24427 | } | |
24428 | ||
24429 | if ( | |
24430 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && | |
24431 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && | |
24432 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) | |
24433 | ) | |
24434 | { | |
24435 | if (!token_is(token_t::e_eof)) | |
24436 | { | |
24437 | set_error( | |
24438 | make_error(parser_error::e_syntax, | |
24439 | current_token(), | |
24440 | "ERR152 - Expected ';' at end of vector definition", | |
24441 | exprtk_error_location)); | |
24442 | ||
24443 | return error_node(); | |
24444 | } | |
24445 | } | |
24446 | ||
24447 | if (vec_initilizer_list.size() > vector_size) | |
24448 | { | |
24449 | set_error( | |
24450 | make_error(parser_error::e_syntax, | |
24451 | current_token(), | |
24452 | "ERR153 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", | |
24453 | exprtk_error_location)); | |
24454 | ||
24455 | return error_node(); | |
24456 | } | |
24457 | } | |
24458 | ||
24459 | typename symbol_table_t::vector_holder_ptr vec_holder = typename symbol_table_t::vector_holder_ptr(0); | |
24460 | ||
24461 | const std::size_t vec_size = static_cast<std::size_t>(details::numeric::to_int32(vector_size)); | |
24462 | ||
24463 | scope_element& se = sem_.get_element(vec_name); | |
24464 | ||
24465 | if (se.name == vec_name) | |
24466 | { | |
24467 | if (se.active) | |
24468 | { | |
24469 | set_error( | |
24470 | make_error(parser_error::e_syntax, | |
24471 | current_token(), | |
24472 | "ERR154 - Illegal redefinition of local vector: '" + vec_name + "'", | |
24473 | exprtk_error_location)); | |
24474 | ||
24475 | return error_node(); | |
24476 | } | |
24477 | else if ( | |
24478 | (se.size == vec_size) && | |
24479 | (scope_element::e_vector == se.type) | |
24480 | ) | |
24481 | { | |
24482 | vec_holder = se.vec_node; | |
24483 | se.active = true; | |
24484 | se.depth = state_.scope_depth; | |
24485 | se.ref_count++; | |
24486 | } | |
24487 | } | |
24488 | ||
24489 | if (0 == vec_holder) | |
24490 | { | |
24491 | scope_element nse; | |
24492 | nse.name = vec_name; | |
24493 | nse.active = true; | |
24494 | nse.ref_count = 1; | |
24495 | nse.type = scope_element::e_vector; | |
24496 | nse.depth = state_.scope_depth; | |
24497 | nse.size = vec_size; | |
24498 | nse.data = new T[vec_size]; | |
24499 | nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size); | |
24500 | ||
24501 | if (!sem_.add_element(nse)) | |
24502 | { | |
24503 | set_error( | |
24504 | make_error(parser_error::e_syntax, | |
24505 | current_token(), | |
24506 | "ERR155 - Failed to add new local vector '" + vec_name + "' to SEM", | |
24507 | exprtk_error_location)); | |
24508 | ||
24509 | sem_.free_element(nse); | |
24510 | ||
24511 | return error_node(); | |
24512 | } | |
24513 | ||
24514 | vec_holder = nse.vec_node; | |
24515 | ||
24516 | exprtk_debug(("parse_define_vector_statement() - INFO - Added new local vector: %s[%d]\n", | |
24517 | nse.name.c_str(), | |
24518 | static_cast<int>(nse.size))); | |
24519 | } | |
24520 | ||
24521 | state_.activate_side_effect("parse_define_vector_statement()"); | |
24522 | ||
24523 | lodge_symbol(vec_name, e_st_local_vector); | |
24524 | ||
24525 | expression_node_ptr result = error_node(); | |
24526 | ||
24527 | if (null_initialisation) | |
24528 | result = expression_generator_(T(0.0)); | |
24529 | else if (vec_to_vec_initialiser) | |
24530 | { | |
24531 | expression_node_ptr vec_node = node_allocator_.allocate<vector_node_t>(vec_holder); | |
24532 | ||
24533 | result = expression_generator_( | |
24534 | details::e_assign, | |
24535 | vec_node, | |
24536 | vec_initilizer_list[0]); | |
24537 | } | |
24538 | else | |
24539 | result = node_allocator_ | |
24540 | .allocate<details::vector_assignment_node<T> >( | |
24541 | (*vec_holder)[0], | |
24542 | vec_size, | |
24543 | vec_initilizer_list, | |
24544 | single_value_initialiser); | |
24545 | ||
24546 | svd.delete_ptr = (0 == result); | |
24547 | ||
24548 | return result; | |
24549 | } | |
24550 | ||
24551 | #ifndef exprtk_disable_string_capabilities | |
24552 | inline expression_node_ptr parse_define_string_statement(const std::string& str_name, expression_node_ptr initialisation_expression) | |
24553 | { | |
24554 | stringvar_node_t* str_node = reinterpret_cast<stringvar_node_t*>(0); | |
24555 | ||
24556 | scope_element& se = sem_.get_element(str_name); | |
24557 | ||
24558 | if (se.name == str_name) | |
24559 | { | |
24560 | if (se.active) | |
24561 | { | |
24562 | set_error( | |
24563 | make_error(parser_error::e_syntax, | |
24564 | current_token(), | |
24565 | "ERR156 - Illegal redefinition of local variable: '" + str_name + "'", | |
24566 | exprtk_error_location)); | |
24567 | ||
24568 | free_node(node_allocator_,initialisation_expression); | |
24569 | ||
24570 | return error_node(); | |
24571 | } | |
24572 | else if (scope_element::e_string == se.type) | |
24573 | { | |
24574 | str_node = se.str_node; | |
24575 | se.active = true; | |
24576 | se.depth = state_.scope_depth; | |
24577 | se.ref_count++; | |
24578 | } | |
24579 | } | |
24580 | ||
24581 | if (0 == str_node) | |
24582 | { | |
24583 | scope_element nse; | |
24584 | nse.name = str_name; | |
24585 | nse.active = true; | |
24586 | nse.ref_count = 1; | |
24587 | nse.type = scope_element::e_string; | |
24588 | nse.depth = state_.scope_depth; | |
24589 | nse.data = new std::string; | |
24590 | nse.str_node = new stringvar_node_t(*(std::string*)(nse.data)); | |
24591 | ||
24592 | if (!sem_.add_element(nse)) | |
24593 | { | |
24594 | set_error( | |
24595 | make_error(parser_error::e_syntax, | |
24596 | current_token(), | |
24597 | "ERR157 - Failed to add new local string variable '" + str_name + "' to SEM", | |
24598 | exprtk_error_location)); | |
24599 | ||
24600 | free_node(node_allocator_,initialisation_expression); | |
24601 | ||
24602 | sem_.free_element(nse); | |
24603 | ||
24604 | return error_node(); | |
24605 | } | |
24606 | ||
24607 | str_node = nse.str_node; | |
24608 | ||
24609 | exprtk_debug(("parse_define_string_statement() - INFO - Added new local string variable: %s\n",nse.name.c_str())); | |
24610 | } | |
24611 | ||
24612 | lodge_symbol(str_name, e_st_local_string); | |
24613 | ||
24614 | state_.activate_side_effect("parse_define_string_statement()"); | |
24615 | ||
24616 | expression_node_ptr branch[2] = {0}; | |
24617 | ||
24618 | branch[0] = str_node; | |
24619 | branch[1] = initialisation_expression; | |
24620 | ||
24621 | return expression_generator_(details::e_assign,branch); | |
24622 | } | |
24623 | #else | |
24624 | inline expression_node_ptr parse_define_string_statement(const std::string&, expression_node_ptr) | |
24625 | { | |
24626 | return error_node(); | |
24627 | } | |
24628 | #endif | |
24629 | ||
24630 | inline bool local_variable_is_shadowed(const std::string& symbol) | |
24631 | { | |
24632 | const scope_element& se = sem_.get_element(symbol); | |
24633 | return (se.name == symbol) && se.active; | |
24634 | } | |
24635 | ||
24636 | inline expression_node_ptr parse_define_var_statement() | |
24637 | { | |
24638 | if (settings_.vardef_disabled()) | |
24639 | { | |
24640 | set_error( | |
24641 | make_error(parser_error::e_syntax, | |
24642 | current_token(), | |
24643 | "ERR158 - Illegal variable definition", | |
24644 | exprtk_error_location)); | |
24645 | ||
24646 | return error_node(); | |
24647 | } | |
24648 | else if (!details::imatch(current_token().value,"var")) | |
24649 | { | |
24650 | return error_node(); | |
24651 | } | |
24652 | else | |
24653 | next_token(); | |
24654 | ||
24655 | const std::string var_name = current_token().value; | |
24656 | ||
24657 | expression_node_ptr initialisation_expression = error_node(); | |
24658 | ||
24659 | if (!token_is(token_t::e_symbol)) | |
24660 | { | |
24661 | set_error( | |
24662 | make_error(parser_error::e_syntax, | |
24663 | current_token(), | |
24664 | "ERR159 - Expected a symbol for variable definition", | |
24665 | exprtk_error_location)); | |
24666 | ||
24667 | return error_node(); | |
24668 | } | |
24669 | else if (details::is_reserved_symbol(var_name)) | |
24670 | { | |
24671 | set_error( | |
24672 | make_error(parser_error::e_syntax, | |
24673 | current_token(), | |
24674 | "ERR160 - Illegal redefinition of reserved keyword: '" + var_name + "'", | |
24675 | exprtk_error_location)); | |
24676 | ||
24677 | return error_node(); | |
24678 | } | |
24679 | else if (symtab_store_.symbol_exists(var_name)) | |
24680 | { | |
24681 | set_error( | |
24682 | make_error(parser_error::e_syntax, | |
24683 | current_token(), | |
24684 | "ERR161 - Illegal redefinition of variable '" + var_name + "'", | |
24685 | exprtk_error_location)); | |
24686 | ||
24687 | return error_node(); | |
24688 | } | |
24689 | else if (local_variable_is_shadowed(var_name)) | |
24690 | { | |
24691 | set_error( | |
24692 | make_error(parser_error::e_syntax, | |
24693 | current_token(), | |
24694 | "ERR162 - Illegal redefinition of local variable: '" + var_name + "'", | |
24695 | exprtk_error_location)); | |
24696 | ||
24697 | return error_node(); | |
24698 | } | |
24699 | else if (token_is(token_t::e_lsqrbracket,prsrhlpr_t::e_hold)) | |
24700 | { | |
24701 | return parse_define_vector_statement(var_name); | |
24702 | } | |
24703 | else if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) | |
24704 | { | |
24705 | return parse_uninitialised_var_statement(var_name); | |
24706 | } | |
24707 | else if (token_is(token_t::e_assign)) | |
24708 | { | |
24709 | if (0 == (initialisation_expression = parse_expression())) | |
24710 | { | |
24711 | set_error( | |
24712 | make_error(parser_error::e_syntax, | |
24713 | current_token(), | |
24714 | "ERR163 - Failed to parse initialisation expression", | |
24715 | exprtk_error_location)); | |
24716 | ||
24717 | return error_node(); | |
24718 | } | |
24719 | } | |
24720 | ||
24721 | if ( | |
24722 | !token_is(token_t::e_rbracket , prsrhlpr_t::e_hold) && | |
24723 | !token_is(token_t::e_rcrlbracket, prsrhlpr_t::e_hold) && | |
24724 | !token_is(token_t::e_rsqrbracket, prsrhlpr_t::e_hold) | |
24725 | ) | |
24726 | { | |
24727 | if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) | |
24728 | { | |
24729 | set_error( | |
24730 | make_error(parser_error::e_syntax, | |
24731 | current_token(), | |
24732 | "ERR164 - Expected ';' after variable definition", | |
24733 | exprtk_error_location)); | |
24734 | ||
24735 | free_node(node_allocator_,initialisation_expression); | |
24736 | ||
24737 | return error_node(); | |
24738 | } | |
24739 | } | |
24740 | ||
24741 | if ( | |
24742 | (0 != initialisation_expression) && | |
24743 | details::is_generally_string_node(initialisation_expression) | |
24744 | ) | |
24745 | { | |
24746 | return parse_define_string_statement(var_name,initialisation_expression); | |
24747 | } | |
24748 | ||
24749 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); | |
24750 | ||
24751 | scope_element& se = sem_.get_element(var_name); | |
24752 | ||
24753 | if (se.name == var_name) | |
24754 | { | |
24755 | if (se.active) | |
24756 | { | |
24757 | set_error( | |
24758 | make_error(parser_error::e_syntax, | |
24759 | current_token(), | |
24760 | "ERR165 - Illegal redefinition of local variable: '" + var_name + "'", | |
24761 | exprtk_error_location)); | |
24762 | ||
24763 | free_node(node_allocator_, initialisation_expression); | |
24764 | ||
24765 | return error_node(); | |
24766 | } | |
24767 | else if (scope_element::e_variable == se.type) | |
24768 | { | |
24769 | var_node = se.var_node; | |
24770 | se.active = true; | |
24771 | se.depth = state_.scope_depth; | |
24772 | se.ref_count++; | |
24773 | } | |
24774 | } | |
24775 | ||
24776 | if (0 == var_node) | |
24777 | { | |
24778 | scope_element nse; | |
24779 | nse.name = var_name; | |
24780 | nse.active = true; | |
24781 | nse.ref_count = 1; | |
24782 | nse.type = scope_element::e_variable; | |
24783 | nse.depth = state_.scope_depth; | |
24784 | nse.data = new T(T(0)); | |
24785 | nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); | |
24786 | ||
24787 | if (!sem_.add_element(nse)) | |
24788 | { | |
24789 | set_error( | |
24790 | make_error(parser_error::e_syntax, | |
24791 | current_token(), | |
24792 | "ERR166 - Failed to add new local variable '" + var_name + "' to SEM", | |
24793 | exprtk_error_location)); | |
24794 | ||
24795 | free_node(node_allocator_, initialisation_expression); | |
24796 | ||
24797 | sem_.free_element(nse); | |
24798 | ||
24799 | return error_node(); | |
24800 | } | |
24801 | ||
24802 | var_node = nse.var_node; | |
24803 | ||
24804 | exprtk_debug(("parse_define_var_statement() - INFO - Added new local variable: %s\n",nse.name.c_str())); | |
24805 | } | |
24806 | ||
24807 | state_.activate_side_effect("parse_define_var_statement()"); | |
24808 | ||
24809 | lodge_symbol(var_name, e_st_local_variable); | |
24810 | ||
24811 | expression_node_ptr branch[2] = {0}; | |
24812 | ||
24813 | branch[0] = var_node; | |
24814 | branch[1] = initialisation_expression ? initialisation_expression : expression_generator_(T(0)); | |
24815 | ||
24816 | return expression_generator_(details::e_assign,branch); | |
24817 | } | |
24818 | ||
24819 | inline expression_node_ptr parse_uninitialised_var_statement(const std::string& var_name) | |
24820 | { | |
24821 | if ( | |
24822 | !token_is(token_t::e_lcrlbracket) || | |
24823 | !token_is(token_t::e_rcrlbracket) | |
24824 | ) | |
24825 | { | |
24826 | set_error( | |
24827 | make_error(parser_error::e_syntax, | |
24828 | current_token(), | |
24829 | "ERR167 - Expected a '{}' for uninitialised var definition", | |
24830 | exprtk_error_location)); | |
24831 | ||
24832 | return error_node(); | |
24833 | } | |
24834 | else if (!token_is(token_t::e_eof,prsrhlpr_t::e_hold)) | |
24835 | { | |
24836 | set_error( | |
24837 | make_error(parser_error::e_syntax, | |
24838 | current_token(), | |
24839 | "ERR168 - Expected ';' after uninitialised variable definition", | |
24840 | exprtk_error_location)); | |
24841 | ||
24842 | return error_node(); | |
24843 | } | |
24844 | ||
24845 | expression_node_ptr var_node = reinterpret_cast<expression_node_ptr>(0); | |
24846 | ||
24847 | scope_element& se = sem_.get_element(var_name); | |
24848 | ||
24849 | if (se.name == var_name) | |
24850 | { | |
24851 | if (se.active) | |
24852 | { | |
24853 | set_error( | |
24854 | make_error(parser_error::e_syntax, | |
24855 | current_token(), | |
24856 | "ERR169 - Illegal redefinition of local variable: '" + var_name + "'", | |
24857 | exprtk_error_location)); | |
24858 | ||
24859 | return error_node(); | |
24860 | } | |
24861 | else if (scope_element::e_variable == se.type) | |
24862 | { | |
24863 | var_node = se.var_node; | |
24864 | se.active = true; | |
24865 | se.ref_count++; | |
24866 | } | |
24867 | } | |
24868 | ||
24869 | if (0 == var_node) | |
24870 | { | |
24871 | scope_element nse; | |
24872 | nse.name = var_name; | |
24873 | nse.active = true; | |
24874 | nse.ref_count = 1; | |
24875 | nse.type = scope_element::e_variable; | |
24876 | nse.depth = state_.scope_depth; | |
24877 | nse.ip_index = sem_.next_ip_index(); | |
24878 | nse.data = new T(T(0)); | |
24879 | nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); | |
24880 | ||
24881 | if (!sem_.add_element(nse)) | |
24882 | { | |
24883 | set_error( | |
24884 | make_error(parser_error::e_syntax, | |
24885 | current_token(), | |
24886 | "ERR170 - Failed to add new local variable '" + var_name + "' to SEM", | |
24887 | exprtk_error_location)); | |
24888 | ||
24889 | sem_.free_element(nse); | |
24890 | ||
24891 | return error_node(); | |
24892 | } | |
24893 | ||
24894 | exprtk_debug(("parse_uninitialised_var_statement() - INFO - Added new local variable: %s\n", | |
24895 | nse.name.c_str())); | |
24896 | } | |
24897 | ||
24898 | lodge_symbol(var_name, e_st_local_variable); | |
24899 | ||
24900 | state_.activate_side_effect("parse_uninitialised_var_statement()"); | |
24901 | ||
24902 | return expression_generator_(T(0)); | |
24903 | } | |
24904 | ||
24905 | inline expression_node_ptr parse_swap_statement() | |
24906 | { | |
24907 | if (!details::imatch(current_token().value,"swap")) | |
24908 | { | |
24909 | return error_node(); | |
24910 | } | |
24911 | else | |
24912 | next_token(); | |
24913 | ||
24914 | if (!token_is(token_t::e_lbracket)) | |
24915 | { | |
24916 | set_error( | |
24917 | make_error(parser_error::e_syntax, | |
24918 | current_token(), | |
24919 | "ERR171 - Expected '(' at start of swap statement", | |
24920 | exprtk_error_location)); | |
24921 | ||
24922 | return error_node(); | |
24923 | } | |
24924 | ||
24925 | expression_node_ptr variable0 = error_node(); | |
24926 | expression_node_ptr variable1 = error_node(); | |
24927 | ||
24928 | bool variable0_generated = false; | |
24929 | bool variable1_generated = false; | |
24930 | ||
24931 | const std::string var0_name = current_token().value; | |
24932 | ||
24933 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) | |
24934 | { | |
24935 | set_error( | |
24936 | make_error(parser_error::e_syntax, | |
24937 | current_token(), | |
24938 | "ERR172 - Expected a symbol for variable or vector element definition", | |
24939 | exprtk_error_location)); | |
24940 | ||
24941 | return error_node(); | |
24942 | } | |
24943 | else if (peek_token_is(token_t::e_lsqrbracket)) | |
24944 | { | |
24945 | if (0 == (variable0 = parse_vector())) | |
24946 | { | |
24947 | set_error( | |
24948 | make_error(parser_error::e_syntax, | |
24949 | current_token(), | |
24950 | "ERR173 - First parameter to swap is an invalid vector element: '" + var0_name + "'", | |
24951 | exprtk_error_location)); | |
24952 | ||
24953 | return error_node(); | |
24954 | } | |
24955 | ||
24956 | variable0_generated = true; | |
24957 | } | |
24958 | else | |
24959 | { | |
24960 | if (symtab_store_.is_variable(var0_name)) | |
24961 | { | |
24962 | variable0 = symtab_store_.get_variable(var0_name); | |
24963 | } | |
24964 | ||
24965 | scope_element& se = sem_.get_element(var0_name); | |
24966 | ||
24967 | if ( | |
24968 | (se.active) && | |
24969 | (se.name == var0_name) && | |
24970 | (scope_element::e_variable == se.type) | |
24971 | ) | |
24972 | { | |
24973 | variable0 = se.var_node; | |
24974 | } | |
24975 | ||
24976 | lodge_symbol(var0_name, e_st_variable); | |
24977 | ||
24978 | if (0 == variable0) | |
24979 | { | |
24980 | set_error( | |
24981 | make_error(parser_error::e_syntax, | |
24982 | current_token(), | |
24983 | "ERR174 - First parameter to swap is an invalid variable: '" + var0_name + "'", | |
24984 | exprtk_error_location)); | |
24985 | ||
24986 | return error_node(); | |
24987 | } | |
24988 | else | |
24989 | next_token(); | |
24990 | } | |
24991 | ||
24992 | if (!token_is(token_t::e_comma)) | |
24993 | { | |
24994 | set_error( | |
24995 | make_error(parser_error::e_syntax, | |
24996 | current_token(), | |
24997 | "ERR175 - Expected ',' between parameters to swap", | |
24998 | exprtk_error_location)); | |
24999 | ||
25000 | if (variable0_generated) | |
25001 | { | |
25002 | free_node(node_allocator_,variable0); | |
25003 | } | |
25004 | ||
25005 | return error_node(); | |
25006 | } | |
25007 | ||
25008 | const std::string var1_name = current_token().value; | |
25009 | ||
25010 | if (!token_is(token_t::e_symbol,prsrhlpr_t::e_hold)) | |
25011 | { | |
25012 | set_error( | |
25013 | make_error(parser_error::e_syntax, | |
25014 | current_token(), | |
25015 | "ERR176 - Expected a symbol for variable or vector element definition", | |
25016 | exprtk_error_location)); | |
25017 | ||
25018 | if (variable0_generated) | |
25019 | { | |
25020 | free_node(node_allocator_,variable0); | |
25021 | } | |
25022 | ||
25023 | return error_node(); | |
25024 | } | |
25025 | else if (peek_token_is(token_t::e_lsqrbracket)) | |
25026 | { | |
25027 | if (0 == (variable1 = parse_vector())) | |
25028 | { | |
25029 | set_error( | |
25030 | make_error(parser_error::e_syntax, | |
25031 | current_token(), | |
25032 | "ERR177 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", | |
25033 | exprtk_error_location)); | |
25034 | ||
25035 | if (variable0_generated) | |
25036 | { | |
25037 | free_node(node_allocator_,variable0); | |
25038 | } | |
25039 | ||
25040 | return error_node(); | |
25041 | } | |
25042 | ||
25043 | variable1_generated = true; | |
25044 | } | |
25045 | else | |
25046 | { | |
25047 | if (symtab_store_.is_variable(var1_name)) | |
25048 | { | |
25049 | variable1 = symtab_store_.get_variable(var1_name); | |
25050 | } | |
25051 | ||
25052 | scope_element& se = sem_.get_element(var1_name); | |
25053 | ||
25054 | if ( | |
25055 | (se.active) && | |
25056 | (se.name == var1_name) && | |
25057 | (scope_element::e_variable == se.type) | |
25058 | ) | |
25059 | { | |
25060 | variable1 = se.var_node; | |
25061 | } | |
25062 | ||
25063 | lodge_symbol(var1_name, e_st_variable); | |
25064 | ||
25065 | if (0 == variable1) | |
25066 | { | |
25067 | set_error( | |
25068 | make_error(parser_error::e_syntax, | |
25069 | current_token(), | |
25070 | "ERR178 - Second parameter to swap is an invalid variable: '" + var1_name + "'", | |
25071 | exprtk_error_location)); | |
25072 | ||
25073 | if (variable0_generated) | |
25074 | { | |
25075 | free_node(node_allocator_,variable0); | |
25076 | } | |
25077 | ||
25078 | return error_node(); | |
25079 | } | |
25080 | else | |
25081 | next_token(); | |
25082 | } | |
25083 | ||
25084 | if (!token_is(token_t::e_rbracket)) | |
25085 | { | |
25086 | set_error( | |
25087 | make_error(parser_error::e_syntax, | |
25088 | current_token(), | |
25089 | "ERR179 - Expected ')' at end of swap statement", | |
25090 | exprtk_error_location)); | |
25091 | ||
25092 | if (variable0_generated) | |
25093 | { | |
25094 | free_node(node_allocator_,variable0); | |
25095 | } | |
25096 | ||
25097 | if (variable1_generated) | |
25098 | { | |
25099 | free_node(node_allocator_,variable1); | |
25100 | } | |
25101 | ||
25102 | return error_node(); | |
25103 | } | |
25104 | ||
25105 | typedef details::variable_node<T>* variable_node_ptr; | |
25106 | ||
25107 | variable_node_ptr v0 = variable_node_ptr(0); | |
25108 | variable_node_ptr v1 = variable_node_ptr(0); | |
25109 | ||
25110 | expression_node_ptr result = error_node(); | |
25111 | ||
25112 | if ( | |
25113 | (0 != (v0 = dynamic_cast<variable_node_ptr>(variable0))) && | |
25114 | (0 != (v1 = dynamic_cast<variable_node_ptr>(variable1))) | |
25115 | ) | |
25116 | { | |
25117 | result = node_allocator_.allocate<details::swap_node<T> >(v0, v1); | |
25118 | ||
25119 | if (variable0_generated) | |
25120 | { | |
25121 | free_node(node_allocator_,variable0); | |
25122 | } | |
25123 | ||
25124 | if (variable1_generated) | |
25125 | { | |
25126 | free_node(node_allocator_,variable1); | |
25127 | } | |
25128 | } | |
25129 | else | |
25130 | result = node_allocator_.allocate<details::swap_generic_node<T> > | |
25131 | (variable0, variable1); | |
25132 | ||
25133 | state_.activate_side_effect("parse_swap_statement()"); | |
25134 | ||
25135 | return result; | |
25136 | } | |
25137 | ||
25138 | #ifndef exprtk_disable_return_statement | |
25139 | inline expression_node_ptr parse_return_statement() | |
25140 | { | |
25141 | if (state_.parsing_return_stmt) | |
25142 | { | |
25143 | set_error( | |
25144 | make_error(parser_error::e_syntax, | |
25145 | current_token(), | |
25146 | "ERR180 - Return call within a return call is not allowed", | |
25147 | exprtk_error_location)); | |
25148 | ||
25149 | return error_node(); | |
25150 | } | |
25151 | ||
25152 | scoped_bool_negator sbn(state_.parsing_return_stmt); | |
25153 | ||
25154 | std::vector<expression_node_ptr> arg_list; | |
25155 | ||
25156 | scoped_vec_delete<expression_node_t> sdd((*this),arg_list); | |
25157 | ||
25158 | if (!details::imatch(current_token().value,"return")) | |
25159 | { | |
25160 | return error_node(); | |
25161 | } | |
25162 | else | |
25163 | next_token(); | |
25164 | ||
25165 | if (!token_is(token_t::e_lsqrbracket)) | |
25166 | { | |
25167 | set_error( | |
25168 | make_error(parser_error::e_syntax, | |
25169 | current_token(), | |
25170 | "ERR181 - Expected '[' at start of return statement", | |
25171 | exprtk_error_location)); | |
25172 | ||
25173 | return error_node(); | |
25174 | } | |
25175 | else if (!token_is(token_t::e_rsqrbracket)) | |
25176 | { | |
25177 | for ( ; ; ) | |
25178 | { | |
25179 | expression_node_ptr arg = parse_expression(); | |
25180 | ||
25181 | if (0 == arg) | |
25182 | return error_node(); | |
25183 | ||
25184 | arg_list.push_back(arg); | |
25185 | ||
25186 | if (token_is(token_t::e_rsqrbracket)) | |
25187 | break; | |
25188 | else if (!token_is(token_t::e_comma)) | |
25189 | { | |
25190 | set_error( | |
25191 | make_error(parser_error::e_syntax, | |
25192 | current_token(), | |
25193 | "ERR182 - Expected ',' between values during call to return", | |
25194 | exprtk_error_location)); | |
25195 | ||
25196 | return error_node(); | |
25197 | } | |
25198 | } | |
25199 | } | |
25200 | else if (settings_.zero_return_disabled()) | |
25201 | { | |
25202 | set_error( | |
25203 | make_error(parser_error::e_syntax, | |
25204 | current_token(), | |
25205 | "ERR183 - Zero parameter return statement not allowed", | |
25206 | exprtk_error_location)); | |
25207 | ||
25208 | return error_node(); | |
25209 | } | |
25210 | ||
25211 | const lexer::token prev_token = current_token(); | |
25212 | ||
25213 | if (token_is(token_t::e_rsqrbracket)) | |
25214 | { | |
25215 | if (!arg_list.empty()) | |
25216 | { | |
25217 | set_error( | |
25218 | make_error(parser_error::e_syntax, | |
25219 | prev_token, | |
25220 | "ERR184 - Invalid ']' found during return call", | |
25221 | exprtk_error_location)); | |
25222 | ||
25223 | return error_node(); | |
25224 | } | |
25225 | } | |
25226 | ||
25227 | std::string ret_param_type_list; | |
25228 | ||
25229 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
25230 | { | |
25231 | if (0 == arg_list[i]) | |
25232 | return error_node(); | |
25233 | else if (is_ivector_node(arg_list[i])) | |
25234 | ret_param_type_list += 'V'; | |
25235 | else if (is_generally_string_node(arg_list[i])) | |
25236 | ret_param_type_list += 'S'; | |
25237 | else | |
25238 | ret_param_type_list += 'T'; | |
25239 | } | |
25240 | ||
25241 | dec_.retparam_list_.push_back(ret_param_type_list); | |
25242 | ||
25243 | expression_node_ptr result = expression_generator_.return_call(arg_list); | |
25244 | ||
25245 | sdd.delete_ptr = (0 == result); | |
25246 | ||
25247 | state_.return_stmt_present = true; | |
25248 | ||
25249 | state_.activate_side_effect("parse_return_statement()"); | |
25250 | ||
25251 | return result; | |
25252 | } | |
25253 | #else | |
25254 | inline expression_node_ptr parse_return_statement() | |
25255 | { | |
25256 | return error_node(); | |
25257 | } | |
25258 | #endif | |
25259 | ||
25260 | inline bool post_variable_process(const std::string& symbol) | |
25261 | { | |
25262 | if ( | |
25263 | peek_token_is(token_t::e_lbracket ) || | |
25264 | peek_token_is(token_t::e_lcrlbracket) || | |
25265 | peek_token_is(token_t::e_lsqrbracket) | |
25266 | ) | |
25267 | { | |
25268 | if (!settings_.commutative_check_enabled()) | |
25269 | { | |
25270 | set_error( | |
25271 | make_error(parser_error::e_syntax, | |
25272 | current_token(), | |
25273 | "ERR185 - Invalid sequence of variable '"+ symbol + "' and bracket", | |
25274 | exprtk_error_location)); | |
25275 | ||
25276 | return false; | |
25277 | } | |
25278 | ||
25279 | lexer().insert_front(token_t::e_mul); | |
25280 | } | |
25281 | ||
25282 | return true; | |
25283 | } | |
25284 | ||
25285 | inline bool post_bracket_process(const typename token_t::token_type& token, expression_node_ptr& branch) | |
25286 | { | |
25287 | bool implied_mul = false; | |
25288 | ||
25289 | if (is_generally_string_node(branch)) | |
25290 | return true; | |
25291 | ||
25292 | const lexer::parser_helper::token_advance_mode hold = prsrhlpr_t::e_hold; | |
25293 | ||
25294 | switch (token) | |
25295 | { | |
25296 | case token_t::e_lcrlbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || | |
25297 | token_is(token_t::e_lcrlbracket,hold) || | |
25298 | token_is(token_t::e_lsqrbracket,hold) ; | |
25299 | break; | |
25300 | ||
25301 | case token_t::e_lbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || | |
25302 | token_is(token_t::e_lcrlbracket,hold) || | |
25303 | token_is(token_t::e_lsqrbracket,hold) ; | |
25304 | break; | |
25305 | ||
25306 | case token_t::e_lsqrbracket : implied_mul = token_is(token_t::e_lbracket ,hold) || | |
25307 | token_is(token_t::e_lcrlbracket,hold) || | |
25308 | token_is(token_t::e_lsqrbracket,hold) ; | |
25309 | break; | |
25310 | ||
25311 | default : return true; | |
25312 | } | |
25313 | ||
25314 | if (implied_mul) | |
25315 | { | |
25316 | if (!settings_.commutative_check_enabled()) | |
25317 | { | |
25318 | set_error( | |
25319 | make_error(parser_error::e_syntax, | |
25320 | current_token(), | |
25321 | "ERR186 - Invalid sequence of brackets", | |
25322 | exprtk_error_location)); | |
25323 | ||
25324 | return false; | |
25325 | } | |
25326 | else if (token_t::e_eof != current_token().type) | |
25327 | { | |
25328 | lexer().insert_front(current_token().type); | |
25329 | lexer().insert_front(token_t::e_mul); | |
25330 | next_token(); | |
25331 | } | |
25332 | } | |
25333 | ||
25334 | return true; | |
25335 | } | |
25336 | ||
25337 | inline expression_node_ptr parse_symtab_symbol() | |
25338 | { | |
25339 | const std::string symbol = current_token().value; | |
25340 | ||
25341 | // Are we dealing with a variable or a special constant? | |
25342 | expression_node_ptr variable = symtab_store_.get_variable(symbol); | |
25343 | ||
25344 | if (variable) | |
25345 | { | |
25346 | if (symtab_store_.is_constant_node(symbol)) | |
25347 | { | |
25348 | variable = expression_generator_(variable->value()); | |
25349 | } | |
25350 | ||
25351 | if (!post_variable_process(symbol)) | |
25352 | return error_node(); | |
25353 | ||
25354 | lodge_symbol(symbol, e_st_variable); | |
25355 | next_token(); | |
25356 | ||
25357 | return variable; | |
25358 | } | |
25359 | ||
25360 | // Are we dealing with a locally defined variable, vector or string? | |
25361 | if (!sem_.empty()) | |
25362 | { | |
25363 | scope_element& se = sem_.get_active_element(symbol); | |
25364 | ||
25365 | if (se.active && details::imatch(se.name, symbol)) | |
25366 | { | |
25367 | if (scope_element::e_variable == se.type) | |
25368 | { | |
25369 | se.active = true; | |
25370 | lodge_symbol(symbol, e_st_local_variable); | |
25371 | ||
25372 | if (!post_variable_process(symbol)) | |
25373 | return error_node(); | |
25374 | ||
25375 | next_token(); | |
25376 | ||
25377 | return se.var_node; | |
25378 | } | |
25379 | else if (scope_element::e_vector == se.type) | |
25380 | { | |
25381 | return parse_vector(); | |
25382 | } | |
25383 | #ifndef exprtk_disable_string_capabilities | |
25384 | else if (scope_element::e_string == se.type) | |
25385 | { | |
25386 | return parse_string(); | |
25387 | } | |
25388 | #endif | |
25389 | } | |
25390 | } | |
25391 | ||
25392 | #ifndef exprtk_disable_string_capabilities | |
25393 | // Are we dealing with a string variable? | |
25394 | if (symtab_store_.is_stringvar(symbol)) | |
25395 | { | |
25396 | return parse_string(); | |
25397 | } | |
25398 | #endif | |
25399 | ||
25400 | { | |
25401 | // Are we dealing with a function? | |
25402 | ifunction<T>* function = symtab_store_.get_function(symbol); | |
25403 | ||
25404 | if (function) | |
25405 | { | |
25406 | lodge_symbol(symbol, e_st_function); | |
25407 | ||
25408 | expression_node_ptr func_node = | |
25409 | parse_function_invocation(function,symbol); | |
25410 | ||
25411 | if (func_node) | |
25412 | return func_node; | |
25413 | else | |
25414 | { | |
25415 | set_error( | |
25416 | make_error(parser_error::e_syntax, | |
25417 | current_token(), | |
25418 | "ERR187 - Failed to generate node for function: '" + symbol + "'", | |
25419 | exprtk_error_location)); | |
25420 | ||
25421 | return error_node(); | |
25422 | } | |
25423 | } | |
25424 | } | |
25425 | ||
25426 | { | |
25427 | // Are we dealing with a vararg function? | |
25428 | ivararg_function<T>* vararg_function = symtab_store_.get_vararg_function(symbol); | |
25429 | ||
25430 | if (vararg_function) | |
25431 | { | |
25432 | lodge_symbol(symbol, e_st_function); | |
25433 | ||
25434 | expression_node_ptr vararg_func_node = | |
25435 | parse_vararg_function_call(vararg_function, symbol); | |
25436 | ||
25437 | if (vararg_func_node) | |
25438 | return vararg_func_node; | |
25439 | else | |
25440 | { | |
25441 | set_error( | |
25442 | make_error(parser_error::e_syntax, | |
25443 | current_token(), | |
25444 | "ERR188 - Failed to generate node for vararg function: '" + symbol + "'", | |
25445 | exprtk_error_location)); | |
25446 | ||
25447 | return error_node(); | |
25448 | } | |
25449 | } | |
25450 | } | |
25451 | ||
25452 | { | |
25453 | // Are we dealing with a vararg generic function? | |
25454 | igeneric_function<T>* generic_function = symtab_store_.get_generic_function(symbol); | |
25455 | ||
25456 | if (generic_function) | |
25457 | { | |
25458 | lodge_symbol(symbol, e_st_function); | |
25459 | ||
25460 | expression_node_ptr genericfunc_node = | |
25461 | parse_generic_function_call(generic_function, symbol); | |
25462 | ||
25463 | if (genericfunc_node) | |
25464 | return genericfunc_node; | |
25465 | else | |
25466 | { | |
25467 | set_error( | |
25468 | make_error(parser_error::e_syntax, | |
25469 | current_token(), | |
25470 | "ERR189 - Failed to generate node for generic function: '" + symbol + "'", | |
25471 | exprtk_error_location)); | |
25472 | ||
25473 | return error_node(); | |
25474 | } | |
25475 | } | |
25476 | } | |
25477 | ||
25478 | #ifndef exprtk_disable_string_capabilities | |
25479 | { | |
25480 | // Are we dealing with a vararg string returning function? | |
25481 | igeneric_function<T>* string_function = symtab_store_.get_string_function(symbol); | |
25482 | ||
25483 | if (string_function) | |
25484 | { | |
25485 | lodge_symbol(symbol, e_st_function); | |
25486 | ||
25487 | expression_node_ptr stringfunc_node = | |
25488 | parse_string_function_call(string_function, symbol); | |
25489 | ||
25490 | if (stringfunc_node) | |
25491 | return stringfunc_node; | |
25492 | else | |
25493 | { | |
25494 | set_error( | |
25495 | make_error(parser_error::e_syntax, | |
25496 | current_token(), | |
25497 | "ERR190 - Failed to generate node for string function: '" + symbol + "'", | |
25498 | exprtk_error_location)); | |
25499 | ||
25500 | return error_node(); | |
25501 | } | |
25502 | } | |
25503 | } | |
25504 | ||
25505 | { | |
25506 | // Are we dealing with a vararg overloaded scalar/string returning function? | |
25507 | igeneric_function<T>* overload_function = symtab_store_.get_overload_function(symbol); | |
25508 | ||
25509 | if (overload_function) | |
25510 | { | |
25511 | lodge_symbol(symbol, e_st_function); | |
25512 | ||
25513 | expression_node_ptr overloadfunc_node = | |
25514 | parse_overload_function_call(overload_function, symbol); | |
25515 | ||
25516 | if (overloadfunc_node) | |
25517 | return overloadfunc_node; | |
25518 | else | |
25519 | { | |
25520 | set_error( | |
25521 | make_error(parser_error::e_syntax, | |
25522 | current_token(), | |
25523 | "ERR191 - Failed to generate node for overload function: '" + symbol + "'", | |
25524 | exprtk_error_location)); | |
25525 | ||
25526 | return error_node(); | |
25527 | } | |
25528 | } | |
25529 | } | |
25530 | #endif | |
25531 | ||
25532 | // Are we dealing with a vector? | |
25533 | if (symtab_store_.is_vector(symbol)) | |
25534 | { | |
25535 | lodge_symbol(symbol, e_st_vector); | |
25536 | return parse_vector(); | |
25537 | } | |
25538 | ||
25539 | if (details::is_reserved_symbol(symbol)) | |
25540 | { | |
25541 | if ( | |
25542 | settings_.function_enabled(symbol) || | |
25543 | !details::is_base_function(symbol) | |
25544 | ) | |
25545 | { | |
25546 | set_error( | |
25547 | make_error(parser_error::e_syntax, | |
25548 | current_token(), | |
25549 | "ERR192 - Invalid use of reserved symbol '" + symbol + "'", | |
25550 | exprtk_error_location)); | |
25551 | ||
25552 | return error_node(); | |
25553 | } | |
25554 | } | |
25555 | ||
25556 | // Should we handle unknown symbols? | |
25557 | if (resolve_unknown_symbol_ && unknown_symbol_resolver_) | |
25558 | { | |
25559 | if (!(settings_.rsrvd_sym_usr_disabled() && details::is_reserved_symbol(symbol))) | |
25560 | { | |
25561 | symbol_table_t& symtab = symtab_store_.get_symbol_table(); | |
25562 | ||
25563 | std::string error_message; | |
25564 | ||
25565 | if (unknown_symbol_resolver::e_usrmode_default == unknown_symbol_resolver_->mode) | |
25566 | { | |
25567 | T default_value = T(0); | |
25568 | ||
25569 | typename unknown_symbol_resolver::usr_symbol_type usr_symbol_type = unknown_symbol_resolver::e_usr_unknown_type; | |
25570 | ||
25571 | if (unknown_symbol_resolver_->process(symbol, usr_symbol_type, default_value, error_message)) | |
25572 | { | |
25573 | bool create_result = false; | |
25574 | ||
25575 | switch (usr_symbol_type) | |
25576 | { | |
25577 | case unknown_symbol_resolver::e_usr_variable_type : create_result = symtab.create_variable(symbol, default_value); | |
25578 | break; | |
25579 | ||
25580 | case unknown_symbol_resolver::e_usr_constant_type : create_result = symtab.add_constant(symbol, default_value); | |
25581 | break; | |
25582 | ||
25583 | default : create_result = false; | |
25584 | } | |
25585 | ||
25586 | if (create_result) | |
25587 | { | |
25588 | expression_node_ptr var = symtab_store_.get_variable(symbol); | |
25589 | ||
25590 | if (var) | |
25591 | { | |
25592 | if (symtab_store_.is_constant_node(symbol)) | |
25593 | { | |
25594 | var = expression_generator_(var->value()); | |
25595 | } | |
25596 | ||
25597 | lodge_symbol(symbol, e_st_variable); | |
25598 | ||
25599 | if (!post_variable_process(symbol)) | |
25600 | return error_node(); | |
25601 | ||
25602 | next_token(); | |
25603 | ||
25604 | return var; | |
25605 | } | |
25606 | } | |
25607 | } | |
25608 | ||
25609 | set_error( | |
25610 | make_error(parser_error::e_symtab, | |
25611 | current_token(), | |
25612 | "ERR193 - Failed to create variable: '" + symbol + "'" + | |
25613 | (error_message.empty() ? "" : " - " + error_message), | |
25614 | exprtk_error_location)); | |
25615 | ||
25616 | } | |
25617 | else if (unknown_symbol_resolver::e_usrmode_extended == unknown_symbol_resolver_->mode) | |
25618 | { | |
25619 | if (unknown_symbol_resolver_->process(symbol, symtab, error_message)) | |
25620 | { | |
25621 | expression_node_ptr result = parse_symtab_symbol(); | |
25622 | ||
25623 | if (result) | |
25624 | { | |
25625 | return result; | |
25626 | } | |
25627 | } | |
25628 | ||
25629 | set_error( | |
25630 | make_error(parser_error::e_symtab, | |
25631 | current_token(), | |
25632 | "ERR194 - Failed to resolve symbol: '" + symbol + "'" + | |
25633 | (error_message.empty() ? "" : " - " + error_message), | |
25634 | exprtk_error_location)); | |
25635 | } | |
25636 | ||
25637 | return error_node(); | |
25638 | } | |
25639 | } | |
25640 | ||
25641 | set_error( | |
25642 | make_error(parser_error::e_syntax, | |
25643 | current_token(), | |
25644 | "ERR195 - Undefined symbol: '" + symbol + "'", | |
25645 | exprtk_error_location)); | |
25646 | ||
25647 | return error_node(); | |
25648 | } | |
25649 | ||
25650 | inline expression_node_ptr parse_symbol() | |
25651 | { | |
25652 | static const std::string symbol_if = "if" ; | |
25653 | static const std::string symbol_while = "while" ; | |
25654 | static const std::string symbol_repeat = "repeat" ; | |
25655 | static const std::string symbol_for = "for" ; | |
25656 | static const std::string symbol_switch = "switch" ; | |
25657 | static const std::string symbol_null = "null" ; | |
25658 | static const std::string symbol_break = "break" ; | |
25659 | static const std::string symbol_continue = "continue"; | |
25660 | static const std::string symbol_var = "var" ; | |
25661 | static const std::string symbol_swap = "swap" ; | |
25662 | static const std::string symbol_return = "return" ; | |
25663 | static const std::string symbol_not = "not" ; | |
25664 | ||
25665 | if (valid_vararg_operation(current_token().value)) | |
25666 | { | |
25667 | return parse_vararg_function(); | |
25668 | } | |
25669 | else if (details::imatch(current_token().value, symbol_not)) | |
25670 | { | |
25671 | return parse_not_statement(); | |
25672 | } | |
25673 | else if (valid_base_operation(current_token().value)) | |
25674 | { | |
25675 | return parse_base_operation(); | |
25676 | } | |
25677 | else if ( | |
25678 | details::imatch(current_token().value, symbol_if) && | |
25679 | settings_.control_struct_enabled(current_token().value) | |
25680 | ) | |
25681 | { | |
25682 | return parse_conditional_statement(); | |
25683 | } | |
25684 | else if ( | |
25685 | details::imatch(current_token().value, symbol_while) && | |
25686 | settings_.control_struct_enabled(current_token().value) | |
25687 | ) | |
25688 | { | |
25689 | return parse_while_loop(); | |
25690 | } | |
25691 | else if ( | |
25692 | details::imatch(current_token().value, symbol_repeat) && | |
25693 | settings_.control_struct_enabled(current_token().value) | |
25694 | ) | |
25695 | { | |
25696 | return parse_repeat_until_loop(); | |
25697 | } | |
25698 | else if ( | |
25699 | details::imatch(current_token().value, symbol_for) && | |
25700 | settings_.control_struct_enabled(current_token().value) | |
25701 | ) | |
25702 | { | |
25703 | return parse_for_loop(); | |
25704 | } | |
25705 | else if ( | |
25706 | details::imatch(current_token().value, symbol_switch) && | |
25707 | settings_.control_struct_enabled(current_token().value) | |
25708 | ) | |
25709 | { | |
25710 | return parse_switch_statement(); | |
25711 | } | |
25712 | else if (details::is_valid_sf_symbol(current_token().value)) | |
25713 | { | |
25714 | return parse_special_function(); | |
25715 | } | |
25716 | else if (details::imatch(current_token().value, symbol_null)) | |
25717 | { | |
25718 | return parse_null_statement(); | |
25719 | } | |
25720 | #ifndef exprtk_disable_break_continue | |
25721 | else if (details::imatch(current_token().value, symbol_break)) | |
25722 | { | |
25723 | return parse_break_statement(); | |
25724 | } | |
25725 | else if (details::imatch(current_token().value, symbol_continue)) | |
25726 | { | |
25727 | return parse_continue_statement(); | |
25728 | } | |
25729 | #endif | |
25730 | else if (details::imatch(current_token().value, symbol_var)) | |
25731 | { | |
25732 | return parse_define_var_statement(); | |
25733 | } | |
25734 | else if (details::imatch(current_token().value, symbol_swap)) | |
25735 | { | |
25736 | return parse_swap_statement(); | |
25737 | } | |
25738 | #ifndef exprtk_disable_return_statement | |
25739 | else if ( | |
25740 | details::imatch(current_token().value, symbol_return) && | |
25741 | settings_.control_struct_enabled(current_token().value) | |
25742 | ) | |
25743 | { | |
25744 | return parse_return_statement(); | |
25745 | } | |
25746 | #endif | |
25747 | else if (symtab_store_.valid() || !sem_.empty()) | |
25748 | { | |
25749 | return parse_symtab_symbol(); | |
25750 | } | |
25751 | else | |
25752 | { | |
25753 | set_error( | |
25754 | make_error(parser_error::e_symtab, | |
25755 | current_token(), | |
25756 | "ERR196 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, | |
25757 | exprtk_error_location)); | |
25758 | ||
25759 | return error_node(); | |
25760 | } | |
25761 | } | |
25762 | ||
25763 | inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) | |
25764 | { | |
25765 | expression_node_ptr branch = error_node(); | |
25766 | ||
25767 | if (token_t::e_number == current_token().type) | |
25768 | { | |
25769 | T numeric_value = T(0); | |
25770 | ||
25771 | if (details::string_to_real(current_token().value, numeric_value)) | |
25772 | { | |
25773 | expression_node_ptr literal_exp = expression_generator_(numeric_value); | |
25774 | ||
25775 | if (0 == literal_exp) | |
25776 | { | |
25777 | set_error( | |
25778 | make_error(parser_error::e_numeric, | |
25779 | current_token(), | |
25780 | "ERR197 - Failed generate node for scalar: '" + current_token().value + "'", | |
25781 | exprtk_error_location)); | |
25782 | ||
25783 | return error_node(); | |
25784 | } | |
25785 | ||
25786 | next_token(); | |
25787 | branch = literal_exp; | |
25788 | } | |
25789 | else | |
25790 | { | |
25791 | set_error( | |
25792 | make_error(parser_error::e_numeric, | |
25793 | current_token(), | |
25794 | "ERR198 - Failed to convert '" + current_token().value + "' to a number", | |
25795 | exprtk_error_location)); | |
25796 | ||
25797 | return error_node(); | |
25798 | } | |
25799 | } | |
25800 | else if (token_t::e_symbol == current_token().type) | |
25801 | { | |
25802 | branch = parse_symbol(); | |
25803 | } | |
25804 | #ifndef exprtk_disable_string_capabilities | |
25805 | else if (token_t::e_string == current_token().type) | |
25806 | { | |
25807 | branch = parse_const_string(); | |
25808 | } | |
25809 | #endif | |
25810 | else if (token_t::e_lbracket == current_token().type) | |
25811 | { | |
25812 | next_token(); | |
25813 | ||
25814 | if (0 == (branch = parse_expression())) | |
25815 | return error_node(); | |
25816 | else if (!token_is(token_t::e_rbracket)) | |
25817 | { | |
25818 | set_error( | |
25819 | make_error(parser_error::e_syntax, | |
25820 | current_token(), | |
25821 | "ERR199 - Expected ')' instead of: '" + current_token().value + "'", | |
25822 | exprtk_error_location)); | |
25823 | ||
25824 | free_node(node_allocator_,branch); | |
25825 | ||
25826 | return error_node(); | |
25827 | } | |
25828 | else if (!post_bracket_process(token_t::e_lbracket,branch)) | |
25829 | { | |
25830 | free_node(node_allocator_,branch); | |
25831 | ||
25832 | return error_node(); | |
25833 | } | |
25834 | } | |
25835 | else if (token_t::e_lsqrbracket == current_token().type) | |
25836 | { | |
25837 | next_token(); | |
25838 | ||
25839 | if (0 == (branch = parse_expression())) | |
25840 | return error_node(); | |
25841 | else if (!token_is(token_t::e_rsqrbracket)) | |
25842 | { | |
25843 | set_error( | |
25844 | make_error(parser_error::e_syntax, | |
25845 | current_token(), | |
25846 | "ERR200 - Expected ']' instead of: '" + current_token().value + "'", | |
25847 | exprtk_error_location)); | |
25848 | ||
25849 | free_node(node_allocator_,branch); | |
25850 | ||
25851 | return error_node(); | |
25852 | } | |
25853 | else if (!post_bracket_process(token_t::e_lsqrbracket,branch)) | |
25854 | { | |
25855 | free_node(node_allocator_,branch); | |
25856 | ||
25857 | return error_node(); | |
25858 | } | |
25859 | } | |
25860 | else if (token_t::e_lcrlbracket == current_token().type) | |
25861 | { | |
25862 | next_token(); | |
25863 | ||
25864 | if (0 == (branch = parse_expression())) | |
25865 | return error_node(); | |
25866 | else if (!token_is(token_t::e_rcrlbracket)) | |
25867 | { | |
25868 | set_error( | |
25869 | make_error(parser_error::e_syntax, | |
25870 | current_token(), | |
25871 | "ERR201 - Expected '}' instead of: '" + current_token().value + "'", | |
25872 | exprtk_error_location)); | |
25873 | ||
25874 | free_node(node_allocator_,branch); | |
25875 | ||
25876 | return error_node(); | |
25877 | } | |
25878 | else if (!post_bracket_process(token_t::e_lcrlbracket,branch)) | |
25879 | { | |
25880 | free_node(node_allocator_,branch); | |
25881 | ||
25882 | return error_node(); | |
25883 | } | |
25884 | } | |
25885 | else if (token_t::e_sub == current_token().type) | |
25886 | { | |
25887 | next_token(); | |
25888 | branch = parse_expression(e_level11); | |
25889 | ||
25890 | if ( | |
25891 | branch && | |
25892 | !( | |
25893 | details::is_neg_unary_node (branch) && | |
25894 | simplify_unary_negation_branch(branch) | |
25895 | ) | |
25896 | ) | |
25897 | { | |
25898 | branch = expression_generator_(details::e_neg,branch); | |
25899 | } | |
25900 | } | |
25901 | else if (token_t::e_add == current_token().type) | |
25902 | { | |
25903 | next_token(); | |
25904 | branch = parse_expression(e_level13); | |
25905 | } | |
25906 | else if (token_t::e_eof == current_token().type) | |
25907 | { | |
25908 | set_error( | |
25909 | make_error(parser_error::e_syntax, | |
25910 | current_token(), | |
25911 | "ERR202 - Premature end of expression[1]", | |
25912 | exprtk_error_location)); | |
25913 | ||
25914 | return error_node(); | |
25915 | } | |
25916 | else | |
25917 | { | |
25918 | set_error( | |
25919 | make_error(parser_error::e_syntax, | |
25920 | current_token(), | |
25921 | "ERR203 - Premature end of expression[2]", | |
25922 | exprtk_error_location)); | |
25923 | ||
25924 | return error_node(); | |
25925 | } | |
25926 | ||
25927 | if ( | |
25928 | branch && | |
25929 | (e_level00 == precedence) && | |
25930 | token_is(token_t::e_ternary,prsrhlpr_t::e_hold) | |
25931 | ) | |
25932 | { | |
25933 | branch = parse_ternary_conditional_statement(branch); | |
25934 | } | |
25935 | ||
25936 | parse_pending_string_rangesize(branch); | |
25937 | ||
25938 | return branch; | |
25939 | } | |
25940 | ||
25941 | template <typename Type> | |
25942 | class expression_generator | |
25943 | { | |
25944 | public: | |
25945 | ||
25946 | typedef details::expression_node<Type>* expression_node_ptr; | |
25947 | typedef expression_node_ptr (*synthesize_functor_t)(expression_generator<T>&, const details::operator_type& operation, expression_node_ptr (&branch)[2]); | |
25948 | typedef std::map<std::string,synthesize_functor_t> synthesize_map_t; | |
25949 | typedef typename exprtk::parser<Type> parser_t; | |
25950 | typedef const Type& vtype; | |
25951 | typedef const Type ctype; | |
25952 | ||
25953 | inline void init_synthesize_map() | |
25954 | { | |
25955 | #ifndef exprtk_disable_enhanced_features | |
25956 | synthesize_map_["(v)o(v)"] = synthesize_vov_expression::process; | |
25957 | synthesize_map_["(c)o(v)"] = synthesize_cov_expression::process; | |
25958 | synthesize_map_["(v)o(c)"] = synthesize_voc_expression::process; | |
25959 | ||
25960 | #define register_synthezier(S) \ | |
25961 | synthesize_map_[S ::node_type::id()] = S ::process; \ | |
25962 | ||
25963 | register_synthezier(synthesize_vovov_expression0) | |
25964 | register_synthezier(synthesize_vovov_expression1) | |
25965 | register_synthezier(synthesize_vovoc_expression0) | |
25966 | register_synthezier(synthesize_vovoc_expression1) | |
25967 | register_synthezier(synthesize_vocov_expression0) | |
25968 | register_synthezier(synthesize_vocov_expression1) | |
25969 | register_synthezier(synthesize_covov_expression0) | |
25970 | register_synthezier(synthesize_covov_expression1) | |
25971 | register_synthezier(synthesize_covoc_expression0) | |
25972 | register_synthezier(synthesize_covoc_expression1) | |
25973 | register_synthezier(synthesize_cocov_expression1) | |
25974 | register_synthezier(synthesize_vococ_expression0) | |
25975 | ||
25976 | register_synthezier(synthesize_vovovov_expression0) | |
25977 | register_synthezier(synthesize_vovovoc_expression0) | |
25978 | register_synthezier(synthesize_vovocov_expression0) | |
25979 | register_synthezier(synthesize_vocovov_expression0) | |
25980 | register_synthezier(synthesize_covovov_expression0) | |
25981 | register_synthezier(synthesize_covocov_expression0) | |
25982 | register_synthezier(synthesize_vocovoc_expression0) | |
25983 | register_synthezier(synthesize_covovoc_expression0) | |
25984 | register_synthezier(synthesize_vococov_expression0) | |
25985 | ||
25986 | register_synthezier(synthesize_vovovov_expression1) | |
25987 | register_synthezier(synthesize_vovovoc_expression1) | |
25988 | register_synthezier(synthesize_vovocov_expression1) | |
25989 | register_synthezier(synthesize_vocovov_expression1) | |
25990 | register_synthezier(synthesize_covovov_expression1) | |
25991 | register_synthezier(synthesize_covocov_expression1) | |
25992 | register_synthezier(synthesize_vocovoc_expression1) | |
25993 | register_synthezier(synthesize_covovoc_expression1) | |
25994 | register_synthezier(synthesize_vococov_expression1) | |
25995 | ||
25996 | register_synthezier(synthesize_vovovov_expression2) | |
25997 | register_synthezier(synthesize_vovovoc_expression2) | |
25998 | register_synthezier(synthesize_vovocov_expression2) | |
25999 | register_synthezier(synthesize_vocovov_expression2) | |
26000 | register_synthezier(synthesize_covovov_expression2) | |
26001 | register_synthezier(synthesize_covocov_expression2) | |
26002 | register_synthezier(synthesize_vocovoc_expression2) | |
26003 | register_synthezier(synthesize_covovoc_expression2) | |
26004 | ||
26005 | register_synthezier(synthesize_vovovov_expression3) | |
26006 | register_synthezier(synthesize_vovovoc_expression3) | |
26007 | register_synthezier(synthesize_vovocov_expression3) | |
26008 | register_synthezier(synthesize_vocovov_expression3) | |
26009 | register_synthezier(synthesize_covovov_expression3) | |
26010 | register_synthezier(synthesize_covocov_expression3) | |
26011 | register_synthezier(synthesize_vocovoc_expression3) | |
26012 | register_synthezier(synthesize_covovoc_expression3) | |
26013 | register_synthezier(synthesize_vococov_expression3) | |
26014 | ||
26015 | register_synthezier(synthesize_vovovov_expression4) | |
26016 | register_synthezier(synthesize_vovovoc_expression4) | |
26017 | register_synthezier(synthesize_vovocov_expression4) | |
26018 | register_synthezier(synthesize_vocovov_expression4) | |
26019 | register_synthezier(synthesize_covovov_expression4) | |
26020 | register_synthezier(synthesize_covocov_expression4) | |
26021 | register_synthezier(synthesize_vocovoc_expression4) | |
26022 | register_synthezier(synthesize_covovoc_expression4) | |
26023 | #endif | |
26024 | } | |
26025 | ||
26026 | inline void set_parser(parser_t& p) | |
26027 | { | |
26028 | parser_ = &p; | |
26029 | } | |
26030 | ||
26031 | inline void set_uom(unary_op_map_t& unary_op_map) | |
26032 | { | |
26033 | unary_op_map_ = &unary_op_map; | |
26034 | } | |
26035 | ||
26036 | inline void set_bom(binary_op_map_t& binary_op_map) | |
26037 | { | |
26038 | binary_op_map_ = &binary_op_map; | |
26039 | } | |
26040 | ||
26041 | inline void set_ibom(inv_binary_op_map_t& inv_binary_op_map) | |
26042 | { | |
26043 | inv_binary_op_map_ = &inv_binary_op_map; | |
26044 | } | |
26045 | ||
26046 | inline void set_sf3m(sf3_map_t& sf3_map) | |
26047 | { | |
26048 | sf3_map_ = &sf3_map; | |
26049 | } | |
26050 | ||
26051 | inline void set_sf4m(sf4_map_t& sf4_map) | |
26052 | { | |
26053 | sf4_map_ = &sf4_map; | |
26054 | } | |
26055 | ||
26056 | inline void set_allocator(details::node_allocator& na) | |
26057 | { | |
26058 | node_allocator_ = &na; | |
26059 | } | |
26060 | ||
26061 | inline void set_strength_reduction_state(const bool enabled) | |
26062 | { | |
26063 | strength_reduction_enabled_ = enabled; | |
26064 | } | |
26065 | ||
26066 | inline bool strength_reduction_enabled() const | |
26067 | { | |
26068 | return strength_reduction_enabled_; | |
26069 | } | |
26070 | ||
26071 | inline bool valid_operator(const details::operator_type& operation, binary_functor_t& bop) | |
26072 | { | |
26073 | typename binary_op_map_t::iterator bop_itr = binary_op_map_->find(operation); | |
26074 | ||
26075 | if ((*binary_op_map_).end() == bop_itr) | |
26076 | return false; | |
26077 | ||
26078 | bop = bop_itr->second; | |
26079 | ||
26080 | return true; | |
26081 | } | |
26082 | ||
26083 | inline bool valid_operator(const details::operator_type& operation, unary_functor_t& uop) | |
26084 | { | |
26085 | typename unary_op_map_t::iterator uop_itr = unary_op_map_->find(operation); | |
26086 | ||
26087 | if ((*unary_op_map_).end() == uop_itr) | |
26088 | return false; | |
26089 | ||
26090 | uop = uop_itr->second; | |
26091 | ||
26092 | return true; | |
26093 | } | |
26094 | ||
26095 | inline details::operator_type get_operator(const binary_functor_t& bop) const | |
26096 | { | |
26097 | return (*inv_binary_op_map_).find(bop)->second; | |
26098 | } | |
26099 | ||
26100 | inline expression_node_ptr operator() (const Type& v) const | |
26101 | { | |
26102 | return node_allocator_->allocate<literal_node_t>(v); | |
26103 | } | |
26104 | ||
26105 | #ifndef exprtk_disable_string_capabilities | |
26106 | inline expression_node_ptr operator() (const std::string& s) const | |
26107 | { | |
26108 | return node_allocator_->allocate<string_literal_node_t>(s); | |
26109 | } | |
26110 | ||
26111 | inline expression_node_ptr operator() (std::string& s, range_t& rp) const | |
26112 | { | |
26113 | return node_allocator_->allocate_rr<string_range_node_t>(s,rp); | |
26114 | } | |
26115 | ||
26116 | inline expression_node_ptr operator() (const std::string& s, range_t& rp) const | |
26117 | { | |
26118 | return node_allocator_->allocate_tt<const_string_range_node_t>(s,rp); | |
26119 | } | |
26120 | ||
26121 | inline expression_node_ptr operator() (expression_node_ptr branch, range_t& rp) const | |
26122 | { | |
26123 | if (is_generally_string_node(branch)) | |
26124 | return node_allocator_->allocate_tt<generic_string_range_node_t>(branch,rp); | |
26125 | else | |
26126 | return error_node(); | |
26127 | } | |
26128 | #endif | |
26129 | ||
26130 | inline bool unary_optimisable(const details::operator_type& operation) const | |
26131 | { | |
26132 | return (details::e_abs == operation) || (details::e_acos == operation) || | |
26133 | (details::e_acosh == operation) || (details::e_asin == operation) || | |
26134 | (details::e_asinh == operation) || (details::e_atan == operation) || | |
26135 | (details::e_atanh == operation) || (details::e_ceil == operation) || | |
26136 | (details::e_cos == operation) || (details::e_cosh == operation) || | |
26137 | (details::e_exp == operation) || (details::e_expm1 == operation) || | |
26138 | (details::e_floor == operation) || (details::e_log == operation) || | |
26139 | (details::e_log10 == operation) || (details::e_log2 == operation) || | |
26140 | (details::e_log1p == operation) || (details::e_neg == operation) || | |
26141 | (details::e_pos == operation) || (details::e_round == operation) || | |
26142 | (details::e_sin == operation) || (details::e_sinc == operation) || | |
26143 | (details::e_sinh == operation) || (details::e_sqrt == operation) || | |
26144 | (details::e_tan == operation) || (details::e_tanh == operation) || | |
26145 | (details::e_cot == operation) || (details::e_sec == operation) || | |
26146 | (details::e_csc == operation) || (details::e_r2d == operation) || | |
26147 | (details::e_d2r == operation) || (details::e_d2g == operation) || | |
26148 | (details::e_g2d == operation) || (details::e_notl == operation) || | |
26149 | (details::e_sgn == operation) || (details::e_erf == operation) || | |
26150 | (details::e_erfc == operation) || (details::e_ncdf == operation) || | |
26151 | (details::e_frac == operation) || (details::e_trunc == operation) ; | |
26152 | } | |
26153 | ||
26154 | inline bool sf3_optimisable(const std::string& sf3id, trinary_functor_t& tfunc) const | |
26155 | { | |
26156 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); | |
26157 | ||
26158 | if (sf3_map_->end() == itr) | |
26159 | return false; | |
26160 | else | |
26161 | tfunc = itr->second.first; | |
26162 | ||
26163 | return true; | |
26164 | } | |
26165 | ||
26166 | inline bool sf4_optimisable(const std::string& sf4id, quaternary_functor_t& qfunc) const | |
26167 | { | |
26168 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); | |
26169 | ||
26170 | if (sf4_map_->end() == itr) | |
26171 | return false; | |
26172 | else | |
26173 | qfunc = itr->second.first; | |
26174 | ||
26175 | return true; | |
26176 | } | |
26177 | ||
26178 | inline bool sf3_optimisable(const std::string& sf3id, details::operator_type& operation) const | |
26179 | { | |
26180 | typename sf3_map_t::const_iterator itr = sf3_map_->find(sf3id); | |
26181 | ||
26182 | if (sf3_map_->end() == itr) | |
26183 | return false; | |
26184 | else | |
26185 | operation = itr->second.second; | |
26186 | ||
26187 | return true; | |
26188 | } | |
26189 | ||
26190 | inline bool sf4_optimisable(const std::string& sf4id, details::operator_type& operation) const | |
26191 | { | |
26192 | typename sf4_map_t::const_iterator itr = sf4_map_->find(sf4id); | |
26193 | ||
26194 | if (sf4_map_->end() == itr) | |
26195 | return false; | |
26196 | else | |
26197 | operation = itr->second.second; | |
26198 | ||
26199 | return true; | |
26200 | } | |
26201 | ||
26202 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[1]) | |
26203 | { | |
26204 | if (0 == branch[0]) | |
26205 | { | |
26206 | return error_node(); | |
26207 | } | |
26208 | else if (details::is_null_node(branch[0])) | |
26209 | { | |
26210 | return branch[0]; | |
26211 | } | |
26212 | else if (details::is_break_node(branch[0])) | |
26213 | { | |
26214 | return error_node(); | |
26215 | } | |
26216 | else if (details::is_continue_node(branch[0])) | |
26217 | { | |
26218 | return error_node(); | |
26219 | } | |
26220 | else if (details::is_constant_node(branch[0])) | |
26221 | { | |
26222 | return synthesize_expression<unary_node_t,1>(operation,branch); | |
26223 | } | |
26224 | else if (unary_optimisable(operation) && details::is_variable_node(branch[0])) | |
26225 | { | |
26226 | return synthesize_uv_expression(operation,branch); | |
26227 | } | |
26228 | else if (unary_optimisable(operation) && details::is_ivector_node(branch[0])) | |
26229 | { | |
26230 | return synthesize_uvec_expression(operation,branch); | |
26231 | } | |
26232 | else | |
26233 | return synthesize_unary_expression(operation,branch); | |
26234 | } | |
26235 | ||
26236 | inline bool is_assignment_operation(const details::operator_type& operation) const | |
26237 | { | |
26238 | return ( | |
26239 | (details::e_addass == operation) || | |
26240 | (details::e_subass == operation) || | |
26241 | (details::e_mulass == operation) || | |
26242 | (details::e_divass == operation) || | |
26243 | (details::e_modass == operation) | |
26244 | ) && | |
26245 | parser_->settings_.assignment_enabled(operation); | |
26246 | } | |
26247 | ||
26248 | #ifndef exprtk_disable_string_capabilities | |
26249 | inline bool valid_string_operation(const details::operator_type& operation) const | |
26250 | { | |
26251 | return (details::e_add == operation) || | |
26252 | (details::e_lt == operation) || | |
26253 | (details::e_lte == operation) || | |
26254 | (details::e_gt == operation) || | |
26255 | (details::e_gte == operation) || | |
26256 | (details::e_eq == operation) || | |
26257 | (details::e_ne == operation) || | |
26258 | (details::e_in == operation) || | |
26259 | (details::e_like == operation) || | |
26260 | (details::e_ilike == operation) || | |
26261 | (details::e_assign == operation) || | |
26262 | (details::e_addass == operation) || | |
26263 | (details::e_swap == operation) ; | |
26264 | } | |
26265 | #else | |
26266 | inline bool valid_string_operation(const details::operator_type&) const | |
26267 | { | |
26268 | return false; | |
26269 | } | |
26270 | #endif | |
26271 | ||
26272 | inline std::string to_str(const details::operator_type& operation) const | |
26273 | { | |
26274 | switch (operation) | |
26275 | { | |
26276 | case details::e_add : return "+" ; | |
26277 | case details::e_sub : return "-" ; | |
26278 | case details::e_mul : return "*" ; | |
26279 | case details::e_div : return "/" ; | |
26280 | case details::e_mod : return "%" ; | |
26281 | case details::e_pow : return "^" ; | |
26282 | case details::e_lt : return "<" ; | |
26283 | case details::e_lte : return "<=" ; | |
26284 | case details::e_gt : return ">" ; | |
26285 | case details::e_gte : return ">=" ; | |
26286 | case details::e_eq : return "==" ; | |
26287 | case details::e_ne : return "!=" ; | |
26288 | case details::e_and : return "and" ; | |
26289 | case details::e_nand : return "nand" ; | |
26290 | case details::e_or : return "or" ; | |
26291 | case details::e_nor : return "nor" ; | |
26292 | case details::e_xor : return "xor" ; | |
26293 | case details::e_xnor : return "xnor" ; | |
26294 | default : return "UNKNOWN"; | |
26295 | } | |
26296 | } | |
26297 | ||
26298 | inline bool operation_optimisable(const details::operator_type& operation) const | |
26299 | { | |
26300 | return (details::e_add == operation) || | |
26301 | (details::e_sub == operation) || | |
26302 | (details::e_mul == operation) || | |
26303 | (details::e_div == operation) || | |
26304 | (details::e_mod == operation) || | |
26305 | (details::e_pow == operation) || | |
26306 | (details::e_lt == operation) || | |
26307 | (details::e_lte == operation) || | |
26308 | (details::e_gt == operation) || | |
26309 | (details::e_gte == operation) || | |
26310 | (details::e_eq == operation) || | |
26311 | (details::e_ne == operation) || | |
26312 | (details::e_and == operation) || | |
26313 | (details::e_nand == operation) || | |
26314 | (details::e_or == operation) || | |
26315 | (details::e_nor == operation) || | |
26316 | (details::e_xor == operation) || | |
26317 | (details::e_xnor == operation) ; | |
26318 | } | |
26319 | ||
26320 | inline std::string branch_to_id(expression_node_ptr branch) const | |
26321 | { | |
26322 | static const std::string null_str ("(null)" ); | |
26323 | static const std::string const_str ("(c)" ); | |
26324 | static const std::string var_str ("(v)" ); | |
26325 | static const std::string vov_str ("(vov)" ); | |
26326 | static const std::string cov_str ("(cov)" ); | |
26327 | static const std::string voc_str ("(voc)" ); | |
26328 | static const std::string str_str ("(s)" ); | |
26329 | static const std::string strrng_str ("(rngs)" ); | |
26330 | static const std::string cs_str ("(cs)" ); | |
26331 | static const std::string cstrrng_str("(crngs)"); | |
26332 | ||
26333 | if (details::is_null_node(branch)) | |
26334 | return null_str; | |
26335 | else if (details::is_constant_node(branch)) | |
26336 | return const_str; | |
26337 | else if (details::is_variable_node(branch)) | |
26338 | return var_str; | |
26339 | else if (details::is_vov_node(branch)) | |
26340 | return vov_str; | |
26341 | else if (details::is_cov_node(branch)) | |
26342 | return cov_str; | |
26343 | else if (details::is_voc_node(branch)) | |
26344 | return voc_str; | |
26345 | else if (details::is_string_node(branch)) | |
26346 | return str_str; | |
26347 | else if (details::is_const_string_node(branch)) | |
26348 | return cs_str; | |
26349 | else if (details::is_string_range_node(branch)) | |
26350 | return strrng_str; | |
26351 | else if (details::is_const_string_range_node(branch)) | |
26352 | return cstrrng_str; | |
26353 | else if (details::is_t0ot1ot2_node(branch)) | |
26354 | return "(" + dynamic_cast<details::T0oT1oT2_base_node<T>*>(branch)->type_id() + ")"; | |
26355 | else if (details::is_t0ot1ot2ot3_node(branch)) | |
26356 | return "(" + dynamic_cast<details::T0oT1oT2oT3_base_node<T>*>(branch)->type_id() + ")"; | |
26357 | else | |
26358 | return "ERROR"; | |
26359 | } | |
26360 | ||
26361 | inline std::string branch_to_id(expression_node_ptr (&branch)[2]) const | |
26362 | { | |
26363 | return branch_to_id(branch[0]) + std::string("o") + branch_to_id(branch[1]); | |
26364 | } | |
26365 | ||
26366 | inline bool cov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26367 | { | |
26368 | if (!operation_optimisable(operation)) | |
26369 | return false; | |
26370 | else | |
26371 | return details::is_constant_node(branch[0]) && | |
26372 | details::is_variable_node(branch[1]) ; | |
26373 | } | |
26374 | ||
26375 | inline bool voc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26376 | { | |
26377 | if (!operation_optimisable(operation)) | |
26378 | return false; | |
26379 | else | |
26380 | return details::is_variable_node(branch[0]) && | |
26381 | details::is_constant_node(branch[1]) ; | |
26382 | } | |
26383 | ||
26384 | inline bool vov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26385 | { | |
26386 | if (!operation_optimisable(operation)) | |
26387 | return false; | |
26388 | else | |
26389 | return details::is_variable_node(branch[0]) && | |
26390 | details::is_variable_node(branch[1]) ; | |
26391 | } | |
26392 | ||
26393 | inline bool cob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26394 | { | |
26395 | if (!operation_optimisable(operation)) | |
26396 | return false; | |
26397 | else | |
26398 | return details::is_constant_node(branch[0]) && | |
26399 | !details::is_constant_node(branch[1]) ; | |
26400 | } | |
26401 | ||
26402 | inline bool boc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26403 | { | |
26404 | if (!operation_optimisable(operation)) | |
26405 | return false; | |
26406 | else | |
26407 | return !details::is_constant_node(branch[0]) && | |
26408 | details::is_constant_node(branch[1]) ; | |
26409 | } | |
26410 | ||
26411 | inline bool cocob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26412 | { | |
26413 | if ( | |
26414 | (details::e_add == operation) || | |
26415 | (details::e_sub == operation) || | |
26416 | (details::e_mul == operation) || | |
26417 | (details::e_div == operation) | |
26418 | ) | |
26419 | { | |
26420 | return (details::is_constant_node(branch[0]) && details::is_cob_node(branch[1])) || | |
26421 | (details::is_constant_node(branch[1]) && details::is_cob_node(branch[0])) ; | |
26422 | } | |
26423 | else | |
26424 | return false; | |
26425 | } | |
26426 | ||
26427 | inline bool coboc_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26428 | { | |
26429 | if ( | |
26430 | (details::e_add == operation) || | |
26431 | (details::e_sub == operation) || | |
26432 | (details::e_mul == operation) || | |
26433 | (details::e_div == operation) | |
26434 | ) | |
26435 | { | |
26436 | return (details::is_constant_node(branch[0]) && details::is_boc_node(branch[1])) || | |
26437 | (details::is_constant_node(branch[1]) && details::is_boc_node(branch[0])) ; | |
26438 | } | |
26439 | else | |
26440 | return false; | |
26441 | } | |
26442 | ||
26443 | inline bool uvouv_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26444 | { | |
26445 | if (!operation_optimisable(operation)) | |
26446 | return false; | |
26447 | else | |
26448 | return details::is_uv_node(branch[0]) && | |
26449 | details::is_uv_node(branch[1]) ; | |
26450 | } | |
26451 | ||
26452 | inline bool vob_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26453 | { | |
26454 | if (!operation_optimisable(operation)) | |
26455 | return false; | |
26456 | else | |
26457 | return details::is_variable_node(branch[0]) && | |
26458 | !details::is_variable_node(branch[1]) ; | |
26459 | } | |
26460 | ||
26461 | inline bool bov_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26462 | { | |
26463 | if (!operation_optimisable(operation)) | |
26464 | return false; | |
26465 | else | |
26466 | return !details::is_variable_node(branch[0]) && | |
26467 | details::is_variable_node(branch[1]) ; | |
26468 | } | |
26469 | ||
26470 | inline bool binext_optimisable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26471 | { | |
26472 | if (!operation_optimisable(operation)) | |
26473 | return false; | |
26474 | else | |
26475 | return !details::is_constant_node(branch[0]) || | |
26476 | !details::is_constant_node(branch[1]) ; | |
26477 | } | |
26478 | ||
26479 | inline bool is_invalid_assignment_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26480 | { | |
26481 | if (is_assignment_operation(operation)) | |
26482 | { | |
26483 | const bool b1_is_genstring = details::is_generally_string_node(branch[1]); | |
26484 | ||
26485 | if (details::is_string_node(branch[0])) | |
26486 | return !b1_is_genstring; | |
26487 | else | |
26488 | return ( | |
26489 | !details::is_variable_node (branch[0]) && | |
26490 | !details::is_vector_elem_node (branch[0]) && | |
26491 | !details::is_rebasevector_elem_node (branch[0]) && | |
26492 | !details::is_rebasevector_celem_node(branch[0]) && | |
26493 | !details::is_vector_node (branch[0]) | |
26494 | ) | |
26495 | || b1_is_genstring; | |
26496 | } | |
26497 | else | |
26498 | return false; | |
26499 | } | |
26500 | ||
26501 | inline bool is_constpow_operation(const details::operator_type& operation, expression_node_ptr(&branch)[2]) const | |
26502 | { | |
26503 | if ( | |
26504 | !details::is_constant_node(branch[1]) || | |
26505 | details::is_constant_node(branch[0]) || | |
26506 | details::is_variable_node(branch[0]) || | |
26507 | details::is_vector_node (branch[0]) || | |
26508 | details::is_generally_string_node(branch[0]) | |
26509 | ) | |
26510 | return false; | |
26511 | ||
26512 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
26513 | ||
26514 | return cardinal_pow_optimisable(operation, c); | |
26515 | } | |
26516 | ||
26517 | inline bool is_invalid_break_continue_op(expression_node_ptr (&branch)[2]) const | |
26518 | { | |
26519 | return ( | |
26520 | details::is_break_node (branch[0]) || | |
26521 | details::is_break_node (branch[1]) || | |
26522 | details::is_continue_node(branch[0]) || | |
26523 | details::is_continue_node(branch[1]) | |
26524 | ); | |
26525 | } | |
26526 | ||
26527 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26528 | { | |
26529 | const bool b0_string = is_generally_string_node(branch[0]); | |
26530 | const bool b1_string = is_generally_string_node(branch[1]); | |
26531 | ||
26532 | bool result = false; | |
26533 | ||
26534 | if (b0_string != b1_string) | |
26535 | result = true; | |
26536 | else if (!valid_string_operation(operation) && b0_string && b1_string) | |
26537 | result = true; | |
26538 | ||
26539 | if (result) | |
26540 | { | |
26541 | parser_->set_synthesis_error("Invalid string operation"); | |
26542 | } | |
26543 | ||
26544 | return result; | |
26545 | } | |
26546 | ||
26547 | inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const | |
26548 | { | |
26549 | const bool b0_string = is_generally_string_node(branch[0]); | |
26550 | const bool b1_string = is_generally_string_node(branch[1]); | |
26551 | const bool b2_string = is_generally_string_node(branch[2]); | |
26552 | ||
26553 | bool result = false; | |
26554 | ||
26555 | if ((b0_string != b1_string) || (b1_string != b2_string)) | |
26556 | result = true; | |
26557 | else if ((details::e_inrange != operation) && b0_string && b1_string && b2_string) | |
26558 | result = true; | |
26559 | ||
26560 | if (result) | |
26561 | { | |
26562 | parser_->set_synthesis_error("Invalid string operation"); | |
26563 | } | |
26564 | ||
26565 | return result; | |
26566 | } | |
26567 | ||
26568 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26569 | { | |
26570 | const bool b0_string = is_generally_string_node(branch[0]); | |
26571 | const bool b1_string = is_generally_string_node(branch[1]); | |
26572 | ||
26573 | return (b0_string && b1_string && valid_string_operation(operation)); | |
26574 | } | |
26575 | ||
26576 | inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3]) const | |
26577 | { | |
26578 | const bool b0_string = is_generally_string_node(branch[0]); | |
26579 | const bool b1_string = is_generally_string_node(branch[1]); | |
26580 | const bool b2_string = is_generally_string_node(branch[2]); | |
26581 | ||
26582 | return (b0_string && b1_string && b2_string && (details::e_inrange == operation)); | |
26583 | } | |
26584 | ||
26585 | #ifndef exprtk_disable_sc_andor | |
26586 | inline bool is_shortcircuit_expression(const details::operator_type& operation) const | |
26587 | { | |
26588 | return ( | |
26589 | (details::e_scand == operation) || | |
26590 | (details::e_scor == operation) | |
26591 | ); | |
26592 | } | |
26593 | #else | |
26594 | inline bool is_shortcircuit_expression(const details::operator_type&) const | |
26595 | { | |
26596 | return false; | |
26597 | } | |
26598 | #endif | |
26599 | ||
26600 | inline bool is_null_present(expression_node_ptr (&branch)[2]) const | |
26601 | { | |
26602 | return ( | |
26603 | details::is_null_node(branch[0]) || | |
26604 | details::is_null_node(branch[1]) | |
26605 | ); | |
26606 | } | |
26607 | ||
26608 | inline bool is_vector_eqineq_logic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26609 | { | |
26610 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) | |
26611 | return false; | |
26612 | else | |
26613 | return ( | |
26614 | (details::e_lt == operation) || | |
26615 | (details::e_lte == operation) || | |
26616 | (details::e_gt == operation) || | |
26617 | (details::e_gte == operation) || | |
26618 | (details::e_eq == operation) || | |
26619 | (details::e_ne == operation) || | |
26620 | (details::e_equal == operation) || | |
26621 | (details::e_and == operation) || | |
26622 | (details::e_nand == operation) || | |
26623 | (details:: e_or == operation) || | |
26624 | (details:: e_nor == operation) || | |
26625 | (details:: e_xor == operation) || | |
26626 | (details::e_xnor == operation) | |
26627 | ); | |
26628 | } | |
26629 | ||
26630 | inline bool is_vector_arithmetic_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const | |
26631 | { | |
26632 | if (!is_ivector_node(branch[0]) && !is_ivector_node(branch[1])) | |
26633 | return false; | |
26634 | else | |
26635 | return ( | |
26636 | (details::e_add == operation) || | |
26637 | (details::e_sub == operation) || | |
26638 | (details::e_mul == operation) || | |
26639 | (details::e_div == operation) || | |
26640 | (details::e_pow == operation) | |
26641 | ); | |
26642 | } | |
26643 | ||
26644 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[2]) | |
26645 | { | |
26646 | if ((0 == branch[0]) || (0 == branch[1])) | |
26647 | { | |
26648 | return error_node(); | |
26649 | } | |
26650 | else if (is_invalid_string_op(operation,branch)) | |
26651 | { | |
26652 | return error_node(); | |
26653 | } | |
26654 | else if (is_invalid_assignment_op(operation,branch)) | |
26655 | { | |
26656 | return error_node(); | |
26657 | } | |
26658 | else if (is_invalid_break_continue_op(branch)) | |
26659 | { | |
26660 | return error_node(); | |
26661 | } | |
26662 | else if (details::e_assign == operation) | |
26663 | { | |
26664 | return synthesize_assignment_expression(operation, branch); | |
26665 | } | |
26666 | else if (details::e_swap == operation) | |
26667 | { | |
26668 | return synthesize_swap_expression(branch); | |
26669 | } | |
26670 | else if (is_assignment_operation(operation)) | |
26671 | { | |
26672 | return synthesize_assignment_operation_expression(operation, branch); | |
26673 | } | |
26674 | else if (is_vector_eqineq_logic_operation(operation, branch)) | |
26675 | { | |
26676 | return synthesize_veceqineqlogic_operation_expression(operation, branch); | |
26677 | } | |
26678 | else if (is_vector_arithmetic_operation(operation, branch)) | |
26679 | { | |
26680 | return synthesize_vecarithmetic_operation_expression(operation, branch); | |
26681 | } | |
26682 | else if (is_shortcircuit_expression(operation)) | |
26683 | { | |
26684 | return synthesize_shortcircuit_expression(operation, branch); | |
26685 | } | |
26686 | else if (is_string_operation(operation, branch)) | |
26687 | { | |
26688 | return synthesize_string_expression(operation, branch); | |
26689 | } | |
26690 | else if (is_null_present(branch)) | |
26691 | { | |
26692 | return synthesize_null_expression(operation, branch); | |
26693 | } | |
26694 | #ifndef exprtk_disable_cardinal_pow_optimisation | |
26695 | else if (is_constpow_operation(operation, branch)) | |
26696 | { | |
26697 | return cardinal_pow_optimisation(branch); | |
26698 | } | |
26699 | #endif | |
26700 | ||
26701 | expression_node_ptr result = error_node(); | |
26702 | ||
26703 | #ifndef exprtk_disable_enhanced_features | |
26704 | if (synthesize_expression(operation, branch, result)) | |
26705 | { | |
26706 | return result; | |
26707 | } | |
26708 | else | |
26709 | #endif | |
26710 | ||
26711 | { | |
26712 | /* | |
26713 | Possible reductions: | |
26714 | 1. c o cob -> cob | |
26715 | 2. cob o c -> cob | |
26716 | 3. c o boc -> boc | |
26717 | 4. boc o c -> boc | |
26718 | */ | |
26719 | result = error_node(); | |
26720 | ||
26721 | if (cocob_optimisable(operation, branch)) | |
26722 | { | |
26723 | result = synthesize_cocob_expression::process((*this), operation, branch); | |
26724 | } | |
26725 | else if (coboc_optimisable(operation, branch) && (0 == result)) | |
26726 | { | |
26727 | result = synthesize_coboc_expression::process((*this), operation, branch); | |
26728 | } | |
26729 | ||
26730 | if (result) | |
26731 | return result; | |
26732 | } | |
26733 | ||
26734 | if (uvouv_optimisable(operation, branch)) | |
26735 | { | |
26736 | return synthesize_uvouv_expression(operation, branch); | |
26737 | } | |
26738 | else if (vob_optimisable(operation, branch)) | |
26739 | { | |
26740 | return synthesize_vob_expression::process((*this), operation, branch); | |
26741 | } | |
26742 | else if (bov_optimisable(operation, branch)) | |
26743 | { | |
26744 | return synthesize_bov_expression::process((*this), operation, branch); | |
26745 | } | |
26746 | else if (cob_optimisable(operation, branch)) | |
26747 | { | |
26748 | return synthesize_cob_expression::process((*this), operation, branch); | |
26749 | } | |
26750 | else if (boc_optimisable(operation, branch)) | |
26751 | { | |
26752 | return synthesize_boc_expression::process((*this), operation, branch); | |
26753 | } | |
26754 | #ifndef exprtk_disable_enhanced_features | |
26755 | else if (cov_optimisable(operation, branch)) | |
26756 | { | |
26757 | return synthesize_cov_expression::process((*this), operation, branch); | |
26758 | } | |
26759 | #endif | |
26760 | else if (binext_optimisable(operation, branch)) | |
26761 | { | |
26762 | return synthesize_binary_ext_expression::process((*this), operation, branch); | |
26763 | } | |
26764 | else | |
26765 | return synthesize_expression<binary_node_t,2>(operation, branch); | |
26766 | } | |
26767 | ||
26768 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[3]) | |
26769 | { | |
26770 | if ( | |
26771 | (0 == branch[0]) || | |
26772 | (0 == branch[1]) || | |
26773 | (0 == branch[2]) | |
26774 | ) | |
26775 | { | |
26776 | details::free_all_nodes(*node_allocator_,branch); | |
26777 | ||
26778 | return error_node(); | |
26779 | } | |
26780 | else if (is_invalid_string_op(operation, branch)) | |
26781 | { | |
26782 | return error_node(); | |
26783 | } | |
26784 | else if (is_string_operation(operation, branch)) | |
26785 | { | |
26786 | return synthesize_string_expression(operation, branch); | |
26787 | } | |
26788 | else | |
26789 | return synthesize_expression<trinary_node_t,3>(operation, branch); | |
26790 | } | |
26791 | ||
26792 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr (&branch)[4]) | |
26793 | { | |
26794 | return synthesize_expression<quaternary_node_t,4>(operation,branch); | |
26795 | } | |
26796 | ||
26797 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr b0) | |
26798 | { | |
26799 | expression_node_ptr branch[1] = { b0 }; | |
26800 | return (*this)(operation,branch); | |
26801 | } | |
26802 | ||
26803 | inline expression_node_ptr operator() (const details::operator_type& operation, expression_node_ptr& b0, expression_node_ptr& b1) | |
26804 | { | |
26805 | expression_node_ptr result = error_node(); | |
26806 | ||
26807 | if ((0 != b0) && (0 != b1)) | |
26808 | { | |
26809 | expression_node_ptr branch[2] = { b0, b1 }; | |
26810 | result = expression_generator<Type>::operator()(operation, branch); | |
26811 | b0 = branch[0]; | |
26812 | b1 = branch[1]; | |
26813 | } | |
26814 | ||
26815 | return result; | |
26816 | } | |
26817 | ||
26818 | inline expression_node_ptr conditional(expression_node_ptr condition, | |
26819 | expression_node_ptr consequent, | |
26820 | expression_node_ptr alternative) const | |
26821 | { | |
26822 | if ((0 == condition) || (0 == consequent)) | |
26823 | { | |
26824 | free_node(*node_allocator_, condition); | |
26825 | free_node(*node_allocator_, consequent); | |
26826 | free_node(*node_allocator_, alternative); | |
26827 | ||
26828 | return error_node(); | |
26829 | } | |
26830 | // Can the condition be immediately evaluated? if so optimise. | |
26831 | else if (details::is_constant_node(condition)) | |
26832 | { | |
26833 | // True branch | |
26834 | if (details::is_true(condition)) | |
26835 | { | |
26836 | free_node(*node_allocator_, condition); | |
26837 | free_node(*node_allocator_, alternative); | |
26838 | ||
26839 | return consequent; | |
26840 | } | |
26841 | // False branch | |
26842 | else | |
26843 | { | |
26844 | free_node(*node_allocator_, condition); | |
26845 | free_node(*node_allocator_, consequent); | |
26846 | ||
26847 | if (alternative) | |
26848 | return alternative; | |
26849 | else | |
26850 | return node_allocator_->allocate<details::null_node<T> >(); | |
26851 | } | |
26852 | } | |
26853 | else if ((0 != consequent) && (0 != alternative)) | |
26854 | { | |
26855 | return node_allocator_-> | |
26856 | allocate<conditional_node_t>(condition, consequent, alternative); | |
26857 | } | |
26858 | else | |
26859 | return node_allocator_-> | |
26860 | allocate<cons_conditional_node_t>(condition, consequent); | |
26861 | } | |
26862 | ||
26863 | #ifndef exprtk_disable_string_capabilities | |
26864 | inline expression_node_ptr conditional_string(expression_node_ptr condition, | |
26865 | expression_node_ptr consequent, | |
26866 | expression_node_ptr alternative) const | |
26867 | { | |
26868 | if ((0 == condition) || (0 == consequent)) | |
26869 | { | |
26870 | free_node(*node_allocator_, condition); | |
26871 | free_node(*node_allocator_, consequent); | |
26872 | free_node(*node_allocator_, alternative); | |
26873 | ||
26874 | return error_node(); | |
26875 | } | |
26876 | // Can the condition be immediately evaluated? if so optimise. | |
26877 | else if (details::is_constant_node(condition)) | |
26878 | { | |
26879 | // True branch | |
26880 | if (details::is_true(condition)) | |
26881 | { | |
26882 | free_node(*node_allocator_, condition); | |
26883 | free_node(*node_allocator_, alternative); | |
26884 | ||
26885 | return consequent; | |
26886 | } | |
26887 | // False branch | |
26888 | else | |
26889 | { | |
26890 | free_node(*node_allocator_, condition); | |
26891 | free_node(*node_allocator_, consequent); | |
26892 | ||
26893 | if (alternative) | |
26894 | return alternative; | |
26895 | else | |
26896 | return node_allocator_-> | |
26897 | allocate_c<details::string_literal_node<Type> >(""); | |
26898 | } | |
26899 | } | |
26900 | else if ((0 != consequent) && (0 != alternative)) | |
26901 | return node_allocator_-> | |
26902 | allocate<conditional_string_node_t>(condition, consequent, alternative); | |
26903 | else | |
26904 | return error_node(); | |
26905 | } | |
26906 | #else | |
26907 | inline expression_node_ptr conditional_string(expression_node_ptr, | |
26908 | expression_node_ptr, | |
26909 | expression_node_ptr) const | |
26910 | { | |
26911 | return error_node(); | |
26912 | } | |
26913 | #endif | |
26914 | ||
26915 | inline expression_node_ptr while_loop(expression_node_ptr& condition, | |
26916 | expression_node_ptr& branch, | |
26917 | const bool brkcont = false) const | |
26918 | { | |
26919 | if (!brkcont && details::is_constant_node(condition)) | |
26920 | { | |
26921 | expression_node_ptr result = error_node(); | |
26922 | if (details::is_true(condition)) | |
26923 | // Infinite loops are not allowed. | |
26924 | result = error_node(); | |
26925 | else | |
26926 | result = node_allocator_->allocate<details::null_node<Type> >(); | |
26927 | ||
26928 | free_node(*node_allocator_, condition); | |
26929 | free_node(*node_allocator_, branch); | |
26930 | ||
26931 | return result; | |
26932 | } | |
26933 | else if (details::is_null_node(condition)) | |
26934 | { | |
26935 | free_node(*node_allocator_,condition); | |
26936 | ||
26937 | return branch; | |
26938 | } | |
26939 | else if (!brkcont) | |
26940 | return node_allocator_->allocate<while_loop_node_t>(condition,branch); | |
26941 | #ifndef exprtk_disable_break_continue | |
26942 | else | |
26943 | return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch); | |
26944 | #else | |
26945 | return error_node(); | |
26946 | #endif | |
26947 | } | |
26948 | ||
26949 | inline expression_node_ptr repeat_until_loop(expression_node_ptr& condition, | |
26950 | expression_node_ptr& branch, | |
26951 | const bool brkcont = false) const | |
26952 | { | |
26953 | if (!brkcont && details::is_constant_node(condition)) | |
26954 | { | |
26955 | if ( | |
26956 | details::is_true(condition) && | |
26957 | details::is_constant_node(branch) | |
26958 | ) | |
26959 | { | |
26960 | free_node(*node_allocator_,condition); | |
26961 | ||
26962 | return branch; | |
26963 | } | |
26964 | ||
26965 | free_node(*node_allocator_, condition); | |
26966 | free_node(*node_allocator_, branch); | |
26967 | ||
26968 | return error_node(); | |
26969 | } | |
26970 | else if (details::is_null_node(condition)) | |
26971 | { | |
26972 | free_node(*node_allocator_,condition); | |
26973 | ||
26974 | return branch; | |
26975 | } | |
26976 | else if (!brkcont) | |
26977 | return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch); | |
26978 | #ifndef exprtk_disable_break_continue | |
26979 | else | |
26980 | return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch); | |
26981 | #else | |
26982 | return error_node(); | |
26983 | #endif | |
26984 | } | |
26985 | ||
26986 | inline expression_node_ptr for_loop(expression_node_ptr& initialiser, | |
26987 | expression_node_ptr& condition, | |
26988 | expression_node_ptr& incrementor, | |
26989 | expression_node_ptr& loop_body, | |
26990 | bool brkcont = false) const | |
26991 | { | |
26992 | if (!brkcont && details::is_constant_node(condition)) | |
26993 | { | |
26994 | expression_node_ptr result = error_node(); | |
26995 | ||
26996 | if (details::is_true(condition)) | |
26997 | // Infinite loops are not allowed. | |
26998 | result = error_node(); | |
26999 | else | |
27000 | result = node_allocator_->allocate<details::null_node<Type> >(); | |
27001 | ||
27002 | free_node(*node_allocator_, initialiser); | |
27003 | free_node(*node_allocator_, condition); | |
27004 | free_node(*node_allocator_, incrementor); | |
27005 | free_node(*node_allocator_, loop_body); | |
27006 | ||
27007 | return result; | |
27008 | } | |
27009 | else if (details::is_null_node(condition) || (0 == condition)) | |
27010 | { | |
27011 | free_node(*node_allocator_, initialiser); | |
27012 | free_node(*node_allocator_, condition); | |
27013 | free_node(*node_allocator_, incrementor); | |
27014 | ||
27015 | return loop_body; | |
27016 | } | |
27017 | else if (!brkcont) | |
27018 | return node_allocator_->allocate<for_loop_node_t> | |
27019 | ( | |
27020 | initialiser, | |
27021 | condition, | |
27022 | incrementor, | |
27023 | loop_body | |
27024 | ); | |
27025 | ||
27026 | #ifndef exprtk_disable_break_continue | |
27027 | else | |
27028 | return node_allocator_->allocate<for_loop_bc_node_t> | |
27029 | ( | |
27030 | initialiser, | |
27031 | condition, | |
27032 | incrementor, | |
27033 | loop_body | |
27034 | ); | |
27035 | #else | |
27036 | return error_node(); | |
27037 | #endif | |
27038 | } | |
27039 | ||
27040 | template <typename Allocator, | |
27041 | template <typename, typename> class Sequence> | |
27042 | inline expression_node_ptr const_optimise_switch(Sequence<expression_node_ptr,Allocator>& arg_list) | |
27043 | { | |
27044 | expression_node_ptr result = error_node(); | |
27045 | ||
27046 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) | |
27047 | { | |
27048 | expression_node_ptr condition = arg_list[(2 * i) ]; | |
27049 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; | |
27050 | ||
27051 | if ((0 == result) && details::is_true(condition)) | |
27052 | { | |
27053 | result = consequent; | |
27054 | break; | |
27055 | } | |
27056 | } | |
27057 | ||
27058 | if (0 == result) | |
27059 | { | |
27060 | result = arg_list.back(); | |
27061 | } | |
27062 | ||
27063 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
27064 | { | |
27065 | expression_node_ptr current_expr = arg_list[i]; | |
27066 | ||
27067 | if (current_expr && (current_expr != result)) | |
27068 | { | |
27069 | free_node(*node_allocator_,current_expr); | |
27070 | } | |
27071 | } | |
27072 | ||
27073 | return result; | |
27074 | } | |
27075 | ||
27076 | template <typename Allocator, | |
27077 | template <typename, typename> class Sequence> | |
27078 | inline expression_node_ptr const_optimise_mswitch(Sequence<expression_node_ptr,Allocator>& arg_list) | |
27079 | { | |
27080 | expression_node_ptr result = error_node(); | |
27081 | ||
27082 | for (std::size_t i = 0; i < (arg_list.size() / 2); ++i) | |
27083 | { | |
27084 | expression_node_ptr condition = arg_list[(2 * i) ]; | |
27085 | expression_node_ptr consequent = arg_list[(2 * i) + 1]; | |
27086 | ||
27087 | if (details::is_true(condition)) | |
27088 | { | |
27089 | result = consequent; | |
27090 | } | |
27091 | } | |
27092 | ||
27093 | if (0 == result) | |
27094 | { | |
27095 | T zero = T(0); | |
27096 | result = node_allocator_->allocate<literal_node_t>(zero); | |
27097 | } | |
27098 | ||
27099 | for (std::size_t i = 0; i < arg_list.size(); ++i) | |
27100 | { | |
27101 | expression_node_ptr& current_expr = arg_list[i]; | |
27102 | ||
27103 | if (current_expr && (current_expr != result)) | |
27104 | { | |
27105 | free_node(*node_allocator_,current_expr); | |
27106 | } | |
27107 | } | |
27108 | ||
27109 | return result; | |
27110 | } | |
27111 | ||
27112 | struct switch_nodes | |
27113 | { | |
27114 | typedef std::vector<expression_node_ptr> arg_list_t; | |
27115 | ||
27116 | #define case_stmt(N) \ | |
27117 | if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \ | |
27118 | ||
27119 | struct switch_1 | |
27120 | { | |
27121 | static inline T process(const arg_list_t& arg) | |
27122 | { | |
27123 | case_stmt(0) | |
27124 | ||
27125 | return arg.back()->value(); | |
27126 | } | |
27127 | }; | |
27128 | ||
27129 | struct switch_2 | |
27130 | { | |
27131 | static inline T process(const arg_list_t& arg) | |
27132 | { | |
27133 | case_stmt(0) case_stmt(1) | |
27134 | ||
27135 | return arg.back()->value(); | |
27136 | } | |
27137 | }; | |
27138 | ||
27139 | struct switch_3 | |
27140 | { | |
27141 | static inline T process(const arg_list_t& arg) | |
27142 | { | |
27143 | case_stmt(0) case_stmt(1) | |
27144 | case_stmt(2) | |
27145 | ||
27146 | return arg.back()->value(); | |
27147 | } | |
27148 | }; | |
27149 | ||
27150 | struct switch_4 | |
27151 | { | |
27152 | static inline T process(const arg_list_t& arg) | |
27153 | { | |
27154 | case_stmt(0) case_stmt(1) | |
27155 | case_stmt(2) case_stmt(3) | |
27156 | ||
27157 | return arg.back()->value(); | |
27158 | } | |
27159 | }; | |
27160 | ||
27161 | struct switch_5 | |
27162 | { | |
27163 | static inline T process(const arg_list_t& arg) | |
27164 | { | |
27165 | case_stmt(0) case_stmt(1) | |
27166 | case_stmt(2) case_stmt(3) | |
27167 | case_stmt(4) | |
27168 | ||
27169 | return arg.back()->value(); | |
27170 | } | |
27171 | }; | |
27172 | ||
27173 | struct switch_6 | |
27174 | { | |
27175 | static inline T process(const arg_list_t& arg) | |
27176 | { | |
27177 | case_stmt(0) case_stmt(1) | |
27178 | case_stmt(2) case_stmt(3) | |
27179 | case_stmt(4) case_stmt(5) | |
27180 | ||
27181 | return arg.back()->value(); | |
27182 | } | |
27183 | }; | |
27184 | ||
27185 | struct switch_7 | |
27186 | { | |
27187 | static inline T process(const arg_list_t& arg) | |
27188 | { | |
27189 | case_stmt(0) case_stmt(1) | |
27190 | case_stmt(2) case_stmt(3) | |
27191 | case_stmt(4) case_stmt(5) | |
27192 | case_stmt(6) | |
27193 | ||
27194 | return arg.back()->value(); | |
27195 | } | |
27196 | }; | |
27197 | ||
27198 | #undef case_stmt | |
27199 | }; | |
27200 | ||
27201 | template <typename Allocator, | |
27202 | template <typename, typename> class Sequence> | |
27203 | inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) | |
27204 | { | |
27205 | if (arg_list.empty()) | |
27206 | return error_node(); | |
27207 | else if ( | |
27208 | !all_nodes_valid(arg_list) || | |
27209 | (arg_list.size() < 3) || | |
27210 | ((arg_list.size() % 2) != 1) | |
27211 | ) | |
27212 | { | |
27213 | details::free_all_nodes(*node_allocator_,arg_list); | |
27214 | ||
27215 | return error_node(); | |
27216 | } | |
27217 | else if (is_constant_foldable(arg_list)) | |
27218 | return const_optimise_switch(arg_list); | |
27219 | ||
27220 | switch ((arg_list.size() - 1) / 2) | |
27221 | { | |
27222 | #define case_stmt(N) \ | |
27223 | case N : \ | |
27224 | return node_allocator_-> \ | |
27225 | allocate<details::switch_n_node \ | |
27226 | <Type,typename switch_nodes::switch_##N> >(arg_list); \ | |
27227 | ||
27228 | case_stmt(1) | |
27229 | case_stmt(2) | |
27230 | case_stmt(3) | |
27231 | case_stmt(4) | |
27232 | case_stmt(5) | |
27233 | case_stmt(6) | |
27234 | case_stmt(7) | |
27235 | #undef case_stmt | |
27236 | ||
27237 | default : return node_allocator_->allocate<details::switch_node<Type> >(arg_list); | |
27238 | } | |
27239 | } | |
27240 | ||
27241 | template <typename Allocator, | |
27242 | template <typename, typename> class Sequence> | |
27243 | inline expression_node_ptr multi_switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) | |
27244 | { | |
27245 | if (!all_nodes_valid(arg_list)) | |
27246 | { | |
27247 | details::free_all_nodes(*node_allocator_,arg_list); | |
27248 | ||
27249 | return error_node(); | |
27250 | } | |
27251 | else if (is_constant_foldable(arg_list)) | |
27252 | return const_optimise_mswitch(arg_list); | |
27253 | else | |
27254 | return node_allocator_->allocate<details::multi_switch_node<Type> >(arg_list); | |
27255 | } | |
27256 | ||
27257 | #define unary_opr_switch_statements \ | |
27258 | case_stmt(details:: e_abs, details:: abs_op) \ | |
27259 | case_stmt(details:: e_acos, details:: acos_op) \ | |
27260 | case_stmt(details::e_acosh, details::acosh_op) \ | |
27261 | case_stmt(details:: e_asin, details:: asin_op) \ | |
27262 | case_stmt(details::e_asinh, details::asinh_op) \ | |
27263 | case_stmt(details:: e_atan, details:: atan_op) \ | |
27264 | case_stmt(details::e_atanh, details::atanh_op) \ | |
27265 | case_stmt(details:: e_ceil, details:: ceil_op) \ | |
27266 | case_stmt(details:: e_cos, details:: cos_op) \ | |
27267 | case_stmt(details:: e_cosh, details:: cosh_op) \ | |
27268 | case_stmt(details:: e_exp, details:: exp_op) \ | |
27269 | case_stmt(details::e_expm1, details::expm1_op) \ | |
27270 | case_stmt(details::e_floor, details::floor_op) \ | |
27271 | case_stmt(details:: e_log, details:: log_op) \ | |
27272 | case_stmt(details::e_log10, details::log10_op) \ | |
27273 | case_stmt(details:: e_log2, details:: log2_op) \ | |
27274 | case_stmt(details::e_log1p, details::log1p_op) \ | |
27275 | case_stmt(details:: e_neg, details:: neg_op) \ | |
27276 | case_stmt(details:: e_pos, details:: pos_op) \ | |
27277 | case_stmt(details::e_round, details::round_op) \ | |
27278 | case_stmt(details:: e_sin, details:: sin_op) \ | |
27279 | case_stmt(details:: e_sinc, details:: sinc_op) \ | |
27280 | case_stmt(details:: e_sinh, details:: sinh_op) \ | |
27281 | case_stmt(details:: e_sqrt, details:: sqrt_op) \ | |
27282 | case_stmt(details:: e_tan, details:: tan_op) \ | |
27283 | case_stmt(details:: e_tanh, details:: tanh_op) \ | |
27284 | case_stmt(details:: e_cot, details:: cot_op) \ | |
27285 | case_stmt(details:: e_sec, details:: sec_op) \ | |
27286 | case_stmt(details:: e_csc, details:: csc_op) \ | |
27287 | case_stmt(details:: e_r2d, details:: r2d_op) \ | |
27288 | case_stmt(details:: e_d2r, details:: d2r_op) \ | |
27289 | case_stmt(details:: e_d2g, details:: d2g_op) \ | |
27290 | case_stmt(details:: e_g2d, details:: g2d_op) \ | |
27291 | case_stmt(details:: e_notl, details:: notl_op) \ | |
27292 | case_stmt(details:: e_sgn, details:: sgn_op) \ | |
27293 | case_stmt(details:: e_erf, details:: erf_op) \ | |
27294 | case_stmt(details:: e_erfc, details:: erfc_op) \ | |
27295 | case_stmt(details:: e_ncdf, details:: ncdf_op) \ | |
27296 | case_stmt(details:: e_frac, details:: frac_op) \ | |
27297 | case_stmt(details::e_trunc, details::trunc_op) \ | |
27298 | ||
27299 | inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, | |
27300 | expression_node_ptr (&branch)[1]) | |
27301 | { | |
27302 | T& v = static_cast<details::variable_node<T>*>(branch[0])->ref(); | |
27303 | ||
27304 | switch (operation) | |
27305 | { | |
27306 | #define case_stmt(op0,op1) \ | |
27307 | case op0 : return node_allocator_-> \ | |
27308 | allocate<typename details::unary_variable_node<Type,op1<Type> > >(v); \ | |
27309 | ||
27310 | unary_opr_switch_statements | |
27311 | #undef case_stmt | |
27312 | default : return error_node(); | |
27313 | } | |
27314 | } | |
27315 | ||
27316 | inline expression_node_ptr synthesize_uvec_expression(const details::operator_type& operation, | |
27317 | expression_node_ptr (&branch)[1]) | |
27318 | { | |
27319 | switch (operation) | |
27320 | { | |
27321 | #define case_stmt(op0,op1) \ | |
27322 | case op0 : return node_allocator_-> \ | |
27323 | allocate<typename details::unary_vector_node<Type,op1<Type> > > \ | |
27324 | (operation, branch[0]); \ | |
27325 | ||
27326 | unary_opr_switch_statements | |
27327 | #undef case_stmt | |
27328 | default : return error_node(); | |
27329 | } | |
27330 | } | |
27331 | ||
27332 | inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, | |
27333 | expression_node_ptr (&branch)[1]) | |
27334 | { | |
27335 | switch (operation) | |
27336 | { | |
27337 | #define case_stmt(op0,op1) \ | |
27338 | case op0 : return node_allocator_-> \ | |
27339 | allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]); \ | |
27340 | ||
27341 | unary_opr_switch_statements | |
27342 | #undef case_stmt | |
27343 | default : return error_node(); | |
27344 | } | |
27345 | } | |
27346 | ||
27347 | inline expression_node_ptr const_optimise_sf3(const details::operator_type& operation, | |
27348 | expression_node_ptr (&branch)[3]) | |
27349 | { | |
27350 | expression_node_ptr temp_node = error_node(); | |
27351 | ||
27352 | switch (operation) | |
27353 | { | |
27354 | #define case_stmt(op) \ | |
27355 | case details::e_sf##op : temp_node = node_allocator_-> \ | |
27356 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ | |
27357 | (operation, branch); \ | |
27358 | break; \ | |
27359 | ||
27360 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) | |
27361 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) | |
27362 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) | |
27363 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) | |
27364 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) | |
27365 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) | |
27366 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) | |
27367 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) | |
27368 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) | |
27369 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) | |
27370 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) | |
27371 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) | |
27372 | #undef case_stmt | |
27373 | default : return error_node(); | |
27374 | } | |
27375 | ||
27376 | const T v = temp_node->value(); | |
27377 | ||
27378 | details::free_node(*node_allocator_,temp_node); | |
27379 | ||
27380 | return node_allocator_->allocate<literal_node_t>(v); | |
27381 | } | |
27382 | ||
27383 | inline expression_node_ptr varnode_optimise_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3]) | |
27384 | { | |
27385 | typedef details::variable_node<Type>* variable_ptr; | |
27386 | ||
27387 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); | |
27388 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); | |
27389 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); | |
27390 | ||
27391 | switch (operation) | |
27392 | { | |
27393 | #define case_stmt(op) \ | |
27394 | case details::e_sf##op : return node_allocator_-> \ | |
27395 | allocate_rrr<details::sf3_var_node<Type,details::sf##op##_op<Type> > > \ | |
27396 | (v0, v1, v2); \ | |
27397 | ||
27398 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) | |
27399 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) | |
27400 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) | |
27401 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) | |
27402 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) | |
27403 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) | |
27404 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) | |
27405 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) | |
27406 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) | |
27407 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) | |
27408 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) | |
27409 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) | |
27410 | #undef case_stmt | |
27411 | default : return error_node(); | |
27412 | } | |
27413 | } | |
27414 | ||
27415 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3]) | |
27416 | { | |
27417 | if (!all_nodes_valid(branch)) | |
27418 | return error_node(); | |
27419 | else if (is_constant_foldable(branch)) | |
27420 | return const_optimise_sf3(operation,branch); | |
27421 | else if (all_nodes_variables(branch)) | |
27422 | return varnode_optimise_sf3(operation,branch); | |
27423 | else | |
27424 | { | |
27425 | switch (operation) | |
27426 | { | |
27427 | #define case_stmt(op) \ | |
27428 | case details::e_sf##op : return node_allocator_-> \ | |
27429 | allocate<details::sf3_node<Type,details::sf##op##_op<Type> > > \ | |
27430 | (operation, branch); \ | |
27431 | ||
27432 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) | |
27433 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) | |
27434 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) | |
27435 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) | |
27436 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) | |
27437 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) | |
27438 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) | |
27439 | case_stmt(28) case_stmt(29) case_stmt(30) case_stmt(31) | |
27440 | case_stmt(32) case_stmt(33) case_stmt(34) case_stmt(35) | |
27441 | case_stmt(36) case_stmt(37) case_stmt(38) case_stmt(39) | |
27442 | case_stmt(40) case_stmt(41) case_stmt(42) case_stmt(43) | |
27443 | case_stmt(44) case_stmt(45) case_stmt(46) case_stmt(47) | |
27444 | #undef case_stmt | |
27445 | default : return error_node(); | |
27446 | } | |
27447 | } | |
27448 | } | |
27449 | ||
27450 | inline expression_node_ptr const_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) | |
27451 | { | |
27452 | expression_node_ptr temp_node = error_node(); | |
27453 | ||
27454 | switch (operation) | |
27455 | { | |
27456 | #define case_stmt(op) \ | |
27457 | case details::e_sf##op : temp_node = node_allocator_-> \ | |
27458 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ | |
27459 | (operation, branch); \ | |
27460 | break; \ | |
27461 | ||
27462 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) | |
27463 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) | |
27464 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) | |
27465 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) | |
27466 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) | |
27467 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) | |
27468 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) | |
27469 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) | |
27470 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) | |
27471 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) | |
27472 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) | |
27473 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) | |
27474 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) | |
27475 | #undef case_stmt | |
27476 | default : return error_node(); | |
27477 | } | |
27478 | ||
27479 | const T v = temp_node->value(); | |
27480 | ||
27481 | details::free_node(*node_allocator_,temp_node); | |
27482 | ||
27483 | return node_allocator_->allocate<literal_node_t>(v); | |
27484 | } | |
27485 | ||
27486 | inline expression_node_ptr varnode_optimise_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4]) | |
27487 | { | |
27488 | typedef details::variable_node<Type>* variable_ptr; | |
27489 | ||
27490 | const Type& v0 = static_cast<variable_ptr>(branch[0])->ref(); | |
27491 | const Type& v1 = static_cast<variable_ptr>(branch[1])->ref(); | |
27492 | const Type& v2 = static_cast<variable_ptr>(branch[2])->ref(); | |
27493 | const Type& v3 = static_cast<variable_ptr>(branch[3])->ref(); | |
27494 | ||
27495 | switch (operation) | |
27496 | { | |
27497 | #define case_stmt(op) \ | |
27498 | case details::e_sf##op : return node_allocator_-> \ | |
27499 | allocate_rrrr<details::sf4_var_node<Type,details::sf##op##_op<Type> > > \ | |
27500 | (v0, v1, v2, v3); \ | |
27501 | ||
27502 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) | |
27503 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) | |
27504 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) | |
27505 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) | |
27506 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) | |
27507 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) | |
27508 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) | |
27509 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) | |
27510 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) | |
27511 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) | |
27512 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) | |
27513 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) | |
27514 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) | |
27515 | #undef case_stmt | |
27516 | default : return error_node(); | |
27517 | } | |
27518 | } | |
27519 | ||
27520 | inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4]) | |
27521 | { | |
27522 | if (!all_nodes_valid(branch)) | |
27523 | return error_node(); | |
27524 | else if (is_constant_foldable(branch)) | |
27525 | return const_optimise_sf4(operation,branch); | |
27526 | else if (all_nodes_variables(branch)) | |
27527 | return varnode_optimise_sf4(operation,branch); | |
27528 | switch (operation) | |
27529 | { | |
27530 | #define case_stmt(op) \ | |
27531 | case details::e_sf##op : return node_allocator_-> \ | |
27532 | allocate<details::sf4_node<Type,details::sf##op##_op<Type> > > \ | |
27533 | (operation, branch); \ | |
27534 | ||
27535 | case_stmt(48) case_stmt(49) case_stmt(50) case_stmt(51) | |
27536 | case_stmt(52) case_stmt(53) case_stmt(54) case_stmt(55) | |
27537 | case_stmt(56) case_stmt(57) case_stmt(58) case_stmt(59) | |
27538 | case_stmt(60) case_stmt(61) case_stmt(62) case_stmt(63) | |
27539 | case_stmt(64) case_stmt(65) case_stmt(66) case_stmt(67) | |
27540 | case_stmt(68) case_stmt(69) case_stmt(70) case_stmt(71) | |
27541 | case_stmt(72) case_stmt(73) case_stmt(74) case_stmt(75) | |
27542 | case_stmt(76) case_stmt(77) case_stmt(78) case_stmt(79) | |
27543 | case_stmt(80) case_stmt(81) case_stmt(82) case_stmt(83) | |
27544 | case_stmt(84) case_stmt(85) case_stmt(86) case_stmt(87) | |
27545 | case_stmt(88) case_stmt(89) case_stmt(90) case_stmt(91) | |
27546 | case_stmt(92) case_stmt(93) case_stmt(94) case_stmt(95) | |
27547 | case_stmt(96) case_stmt(97) case_stmt(98) case_stmt(99) | |
27548 | #undef case_stmt | |
27549 | default : return error_node(); | |
27550 | } | |
27551 | } | |
27552 | ||
27553 | template <typename Allocator, | |
27554 | template <typename, typename> class Sequence> | |
27555 | inline expression_node_ptr const_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) | |
27556 | { | |
27557 | expression_node_ptr temp_node = error_node(); | |
27558 | ||
27559 | switch (operation) | |
27560 | { | |
27561 | #define case_stmt(op0,op1) \ | |
27562 | case op0 : temp_node = node_allocator_-> \ | |
27563 | allocate<details::vararg_node<Type,op1<Type> > > \ | |
27564 | (arg_list); \ | |
27565 | break; \ | |
27566 | ||
27567 | case_stmt(details::e_sum , details::vararg_add_op ) | |
27568 | case_stmt(details::e_prod , details::vararg_mul_op ) | |
27569 | case_stmt(details::e_avg , details::vararg_avg_op ) | |
27570 | case_stmt(details::e_min , details::vararg_min_op ) | |
27571 | case_stmt(details::e_max , details::vararg_max_op ) | |
27572 | case_stmt(details::e_mand , details::vararg_mand_op ) | |
27573 | case_stmt(details::e_mor , details::vararg_mor_op ) | |
27574 | case_stmt(details::e_multi , details::vararg_multi_op) | |
27575 | #undef case_stmt | |
27576 | default : return error_node(); | |
27577 | } | |
27578 | ||
27579 | const T v = temp_node->value(); | |
27580 | ||
27581 | details::free_node(*node_allocator_,temp_node); | |
27582 | ||
27583 | return node_allocator_->allocate<literal_node_t>(v); | |
27584 | } | |
27585 | ||
27586 | inline bool special_one_parameter_vararg(const details::operator_type& operation) const | |
27587 | { | |
27588 | return ( | |
27589 | (details::e_sum == operation) || | |
27590 | (details::e_prod == operation) || | |
27591 | (details::e_avg == operation) || | |
27592 | (details::e_min == operation) || | |
27593 | (details::e_max == operation) | |
27594 | ); | |
27595 | } | |
27596 | ||
27597 | template <typename Allocator, | |
27598 | template <typename, typename> class Sequence> | |
27599 | inline expression_node_ptr varnode_optimise_varargfunc(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) | |
27600 | { | |
27601 | switch (operation) | |
27602 | { | |
27603 | #define case_stmt(op0,op1) \ | |
27604 | case op0 : return node_allocator_-> \ | |
27605 | allocate<details::vararg_varnode<Type,op1<Type> > >(arg_list); \ | |
27606 | ||
27607 | case_stmt(details::e_sum , details::vararg_add_op ) | |
27608 | case_stmt(details::e_prod , details::vararg_mul_op ) | |
27609 | case_stmt(details::e_avg , details::vararg_avg_op ) | |
27610 | case_stmt(details::e_min , details::vararg_min_op ) | |
27611 | case_stmt(details::e_max , details::vararg_max_op ) | |
27612 | case_stmt(details::e_mand , details::vararg_mand_op ) | |
27613 | case_stmt(details::e_mor , details::vararg_mor_op ) | |
27614 | case_stmt(details::e_multi , details::vararg_multi_op) | |
27615 | #undef case_stmt | |
27616 | default : return error_node(); | |
27617 | } | |
27618 | } | |
27619 | ||
27620 | template <typename Allocator, | |
27621 | template <typename, typename> class Sequence> | |
27622 | inline expression_node_ptr vectorize_func(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) | |
27623 | { | |
27624 | if (1 == arg_list.size()) | |
27625 | { | |
27626 | switch (operation) | |
27627 | { | |
27628 | #define case_stmt(op0,op1) \ | |
27629 | case op0 : return node_allocator_-> \ | |
27630 | allocate<details::vectorize_node<Type,op1<Type> > >(arg_list[0]); \ | |
27631 | ||
27632 | case_stmt(details::e_sum , details::vec_add_op) | |
27633 | case_stmt(details::e_prod , details::vec_mul_op) | |
27634 | case_stmt(details::e_avg , details::vec_avg_op) | |
27635 | case_stmt(details::e_min , details::vec_min_op) | |
27636 | case_stmt(details::e_max , details::vec_max_op) | |
27637 | #undef case_stmt | |
27638 | default : return error_node(); | |
27639 | } | |
27640 | } | |
27641 | else | |
27642 | return error_node(); | |
27643 | } | |
27644 | ||
27645 | template <typename Allocator, | |
27646 | template <typename, typename> class Sequence> | |
27647 | inline expression_node_ptr vararg_function(const details::operator_type& operation, Sequence<expression_node_ptr,Allocator>& arg_list) | |
27648 | { | |
27649 | if (!all_nodes_valid(arg_list)) | |
27650 | { | |
27651 | details::free_all_nodes(*node_allocator_,arg_list); | |
27652 | ||
27653 | return error_node(); | |
27654 | } | |
27655 | else if (is_constant_foldable(arg_list)) | |
27656 | return const_optimise_varargfunc(operation,arg_list); | |
27657 | else if ((arg_list.size() == 1) && details::is_ivector_node(arg_list[0])) | |
27658 | return vectorize_func(operation,arg_list); | |
27659 | else if ((arg_list.size() == 1) && special_one_parameter_vararg(operation)) | |
27660 | return arg_list[0]; | |
27661 | else if (all_nodes_variables(arg_list)) | |
27662 | return varnode_optimise_varargfunc(operation,arg_list); | |
27663 | ||
27664 | #ifndef exprtk_disable_string_capabilities | |
27665 | if (details::e_smulti == operation) | |
27666 | { | |
27667 | return node_allocator_-> | |
27668 | allocate<details::str_vararg_node<Type,details::vararg_multi_op<Type> > >(arg_list); | |
27669 | } | |
27670 | else | |
27671 | #endif | |
27672 | { | |
27673 | switch (operation) | |
27674 | { | |
27675 | #define case_stmt(op0,op1) \ | |
27676 | case op0 : return node_allocator_-> \ | |
27677 | allocate<details::vararg_node<Type,op1<Type> > >(arg_list); \ | |
27678 | ||
27679 | case_stmt(details::e_sum , details::vararg_add_op ) | |
27680 | case_stmt(details::e_prod , details::vararg_mul_op ) | |
27681 | case_stmt(details::e_avg , details::vararg_avg_op ) | |
27682 | case_stmt(details::e_min , details::vararg_min_op ) | |
27683 | case_stmt(details::e_max , details::vararg_max_op ) | |
27684 | case_stmt(details::e_mand , details::vararg_mand_op ) | |
27685 | case_stmt(details::e_mor , details::vararg_mor_op ) | |
27686 | case_stmt(details::e_multi , details::vararg_multi_op) | |
27687 | #undef case_stmt | |
27688 | default : return error_node(); | |
27689 | } | |
27690 | } | |
27691 | } | |
27692 | ||
27693 | template <std::size_t N> | |
27694 | inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N]) | |
27695 | { | |
27696 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; | |
27697 | expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b); | |
27698 | ||
27699 | if (0 == result) | |
27700 | return error_node(); | |
27701 | else | |
27702 | { | |
27703 | // Can the function call be completely optimised? | |
27704 | if (details::is_constant_node(result)) | |
27705 | return result; | |
27706 | else if (!all_nodes_valid(b)) | |
27707 | return error_node(); | |
27708 | else if (N != f->param_count) | |
27709 | { | |
27710 | details::free_all_nodes(*node_allocator_,b); | |
27711 | ||
27712 | return error_node(); | |
27713 | } | |
27714 | ||
27715 | function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result); | |
27716 | ||
27717 | if (func_node_ptr->init_branches(b)) | |
27718 | return result; | |
27719 | else | |
27720 | { | |
27721 | details::free_all_nodes(*node_allocator_,b); | |
27722 | ||
27723 | return error_node(); | |
27724 | } | |
27725 | } | |
27726 | } | |
27727 | ||
27728 | inline expression_node_ptr function(ifunction_t* f) | |
27729 | { | |
27730 | typedef typename details::function_N_node<Type,ifunction_t,0> function_N_node_t; | |
27731 | return node_allocator_->allocate<function_N_node_t>(f); | |
27732 | } | |
27733 | ||
27734 | inline expression_node_ptr vararg_function_call(ivararg_function_t* vaf, | |
27735 | std::vector<expression_node_ptr>& arg_list) | |
27736 | { | |
27737 | if (!all_nodes_valid(arg_list)) | |
27738 | { | |
27739 | details::free_all_nodes(*node_allocator_,arg_list); | |
27740 | ||
27741 | return error_node(); | |
27742 | } | |
27743 | ||
27744 | typedef details::vararg_function_node<Type,ivararg_function_t> alloc_type; | |
27745 | ||
27746 | expression_node_ptr result = node_allocator_->allocate<alloc_type>(vaf,arg_list); | |
27747 | ||
27748 | if ( | |
27749 | !arg_list.empty() && | |
27750 | !vaf->has_side_effects() && | |
27751 | is_constant_foldable(arg_list) | |
27752 | ) | |
27753 | { | |
27754 | const Type v = result->value(); | |
27755 | details::free_node(*node_allocator_,result); | |
27756 | result = node_allocator_->allocate<literal_node_t>(v); | |
27757 | } | |
27758 | ||
27759 | parser_->state_.activate_side_effect("vararg_function_call()"); | |
27760 | ||
27761 | return result; | |
27762 | } | |
27763 | ||
27764 | inline expression_node_ptr generic_function_call(igeneric_function_t* gf, | |
27765 | std::vector<expression_node_ptr>& arg_list, | |
27766 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) | |
27767 | { | |
27768 | if (!all_nodes_valid(arg_list)) | |
27769 | { | |
27770 | details::free_all_nodes(*node_allocator_,arg_list); | |
27771 | return error_node(); | |
27772 | } | |
27773 | ||
27774 | typedef details::generic_function_node <Type,igeneric_function_t> alloc_type1; | |
27775 | typedef details::multimode_genfunction_node<Type,igeneric_function_t> alloc_type2; | |
27776 | ||
27777 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); | |
27778 | ||
27779 | expression_node_ptr result = error_node(); | |
27780 | ||
27781 | if (no_psi == param_seq_index) | |
27782 | result = node_allocator_->allocate<alloc_type1>(arg_list,gf); | |
27783 | else | |
27784 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); | |
27785 | ||
27786 | alloc_type1* genfunc_node_ptr = static_cast<alloc_type1*>(result); | |
27787 | ||
27788 | if ( | |
27789 | !arg_list.empty() && | |
27790 | !gf->has_side_effects() && | |
27791 | parser_->state_.type_check_enabled && | |
27792 | is_constant_foldable(arg_list) | |
27793 | ) | |
27794 | { | |
27795 | genfunc_node_ptr->init_branches(); | |
27796 | ||
27797 | const Type v = result->value(); | |
27798 | ||
27799 | details::free_node(*node_allocator_,result); | |
27800 | ||
27801 | return node_allocator_->allocate<literal_node_t>(v); | |
27802 | } | |
27803 | else if (genfunc_node_ptr->init_branches()) | |
27804 | { | |
27805 | parser_->state_.activate_side_effect("generic_function_call()"); | |
27806 | ||
27807 | return result; | |
27808 | } | |
27809 | else | |
27810 | { | |
27811 | details::free_node(*node_allocator_, result); | |
27812 | details::free_all_nodes(*node_allocator_, arg_list); | |
27813 | ||
27814 | return error_node(); | |
27815 | } | |
27816 | } | |
27817 | ||
27818 | #ifndef exprtk_disable_string_capabilities | |
27819 | inline expression_node_ptr string_function_call(igeneric_function_t* gf, | |
27820 | std::vector<expression_node_ptr>& arg_list, | |
27821 | const std::size_t& param_seq_index = std::numeric_limits<std::size_t>::max()) | |
27822 | { | |
27823 | if (!all_nodes_valid(arg_list)) | |
27824 | { | |
27825 | details::free_all_nodes(*node_allocator_,arg_list); | |
27826 | return error_node(); | |
27827 | } | |
27828 | ||
27829 | typedef details::string_function_node <Type,igeneric_function_t> alloc_type1; | |
27830 | typedef details::multimode_strfunction_node<Type,igeneric_function_t> alloc_type2; | |
27831 | ||
27832 | const std::size_t no_psi = std::numeric_limits<std::size_t>::max(); | |
27833 | ||
27834 | expression_node_ptr result = error_node(); | |
27835 | ||
27836 | if (no_psi == param_seq_index) | |
27837 | result = node_allocator_->allocate<alloc_type1>(gf,arg_list); | |
27838 | else | |
27839 | result = node_allocator_->allocate<alloc_type2>(gf, param_seq_index, arg_list); | |
27840 | ||
27841 | alloc_type1* strfunc_node_ptr = static_cast<alloc_type1*>(result); | |
27842 | ||
27843 | if ( | |
27844 | !arg_list.empty() && | |
27845 | !gf->has_side_effects() && | |
27846 | is_constant_foldable(arg_list) | |
27847 | ) | |
27848 | { | |
27849 | strfunc_node_ptr->init_branches(); | |
27850 | ||
27851 | const Type v = result->value(); | |
27852 | ||
27853 | details::free_node(*node_allocator_,result); | |
27854 | ||
27855 | return node_allocator_->allocate<literal_node_t>(v); | |
27856 | } | |
27857 | else if (strfunc_node_ptr->init_branches()) | |
27858 | { | |
27859 | parser_->state_.activate_side_effect("string_function_call()"); | |
27860 | ||
27861 | return result; | |
27862 | } | |
27863 | else | |
27864 | { | |
27865 | details::free_node (*node_allocator_,result ); | |
27866 | details::free_all_nodes(*node_allocator_,arg_list); | |
27867 | ||
27868 | return error_node(); | |
27869 | } | |
27870 | } | |
27871 | #endif | |
27872 | ||
27873 | #ifndef exprtk_disable_return_statement | |
27874 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>& arg_list) | |
27875 | { | |
27876 | if (!all_nodes_valid(arg_list)) | |
27877 | { | |
27878 | details::free_all_nodes(*node_allocator_,arg_list); | |
27879 | return error_node(); | |
27880 | } | |
27881 | ||
27882 | typedef details::return_node<Type> alloc_type; | |
27883 | ||
27884 | expression_node_ptr result = node_allocator_-> | |
27885 | allocate_rr<alloc_type>(arg_list,parser_->results_ctx()); | |
27886 | ||
27887 | alloc_type* return_node_ptr = static_cast<alloc_type*>(result); | |
27888 | ||
27889 | if (return_node_ptr->init_branches()) | |
27890 | { | |
27891 | parser_->state_.activate_side_effect("return_call()"); | |
27892 | ||
27893 | return result; | |
27894 | } | |
27895 | else | |
27896 | { | |
27897 | details::free_node (*node_allocator_,result ); | |
27898 | details::free_all_nodes(*node_allocator_,arg_list); | |
27899 | ||
27900 | return error_node(); | |
27901 | } | |
27902 | } | |
27903 | ||
27904 | inline expression_node_ptr return_envelope(expression_node_ptr body, | |
27905 | results_context_t* rc, | |
27906 | bool*& return_invoked) | |
27907 | { | |
27908 | typedef details::return_envelope_node<Type> alloc_type; | |
27909 | ||
27910 | expression_node_ptr result = node_allocator_-> | |
27911 | allocate_cr<alloc_type>(body,(*rc)); | |
27912 | ||
27913 | return_invoked = static_cast<alloc_type*>(result)->retinvk_ptr(); | |
27914 | ||
27915 | return result; | |
27916 | } | |
27917 | #else | |
27918 | inline expression_node_ptr return_call(std::vector<expression_node_ptr>&) | |
27919 | { | |
27920 | return error_node(); | |
27921 | } | |
27922 | ||
27923 | inline expression_node_ptr return_envelope(expression_node_ptr, | |
27924 | results_context_t*, | |
27925 | bool*&) | |
27926 | { | |
27927 | return error_node(); | |
27928 | } | |
27929 | #endif | |
27930 | ||
27931 | inline expression_node_ptr vector_element(const std::string& symbol, | |
27932 | vector_holder_ptr vector_base, | |
27933 | expression_node_ptr index) | |
27934 | { | |
27935 | expression_node_ptr result = error_node(); | |
27936 | ||
27937 | if (details::is_constant_node(index)) | |
27938 | { | |
27939 | std::size_t i = static_cast<std::size_t>(details::numeric::to_int64(index->value())); | |
27940 | ||
27941 | details::free_node(*node_allocator_,index); | |
27942 | ||
27943 | if (vector_base->rebaseable()) | |
27944 | { | |
27945 | return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base); | |
27946 | } | |
27947 | ||
27948 | scope_element& se = parser_->sem_.get_element(symbol,i); | |
27949 | ||
27950 | if (se.index == i) | |
27951 | { | |
27952 | result = se.var_node; | |
27953 | } | |
27954 | else | |
27955 | { | |
27956 | scope_element nse; | |
27957 | nse.name = symbol; | |
27958 | nse.active = true; | |
27959 | nse.ref_count = 1; | |
27960 | nse.type = scope_element::e_vecelem; | |
27961 | nse.index = i; | |
27962 | nse.depth = parser_->state_.scope_depth; | |
27963 | nse.data = 0; | |
27964 | nse.var_node = node_allocator_->allocate<variable_node_t>((*(*vector_base)[i])); | |
27965 | ||
27966 | if (!parser_->sem_.add_element(nse)) | |
27967 | { | |
27968 | parser_->set_synthesis_error("Failed to add new local vector element to SEM [1]"); | |
27969 | ||
27970 | parser_->sem_.free_element(nse); | |
27971 | ||
27972 | result = error_node(); | |
27973 | } | |
27974 | ||
27975 | exprtk_debug(("vector_element() - INFO - Added new local vector element: %s\n",nse.name.c_str())); | |
27976 | ||
27977 | parser_->state_.activate_side_effect("vector_element()"); | |
27978 | ||
27979 | result = nse.var_node; | |
27980 | } | |
27981 | } | |
27982 | else if (vector_base->rebaseable()) | |
27983 | result = node_allocator_->allocate<rebasevector_elem_node_t>(index,vector_base); | |
27984 | else | |
27985 | result = node_allocator_->allocate<vector_elem_node_t>(index,vector_base); | |
27986 | ||
27987 | return result; | |
27988 | } | |
27989 | ||
27990 | private: | |
27991 | ||
27992 | template <std::size_t N, typename NodePtr> | |
27993 | inline bool is_constant_foldable(NodePtr (&b)[N]) const | |
27994 | { | |
27995 | for (std::size_t i = 0; i < N; ++i) | |
27996 | { | |
27997 | if (0 == b[i]) | |
27998 | return false; | |
27999 | else if (!details::is_constant_node(b[i])) | |
28000 | return false; | |
28001 | } | |
28002 | ||
28003 | return true; | |
28004 | } | |
28005 | ||
28006 | template <typename NodePtr, | |
28007 | typename Allocator, | |
28008 | template <typename, typename> class Sequence> | |
28009 | inline bool is_constant_foldable(const Sequence<NodePtr,Allocator>& b) const | |
28010 | { | |
28011 | for (std::size_t i = 0; i < b.size(); ++i) | |
28012 | { | |
28013 | if (0 == b[i]) | |
28014 | return false; | |
28015 | else if (!details::is_constant_node(b[i])) | |
28016 | return false; | |
28017 | } | |
28018 | ||
28019 | return true; | |
28020 | } | |
28021 | ||
28022 | void lodge_assignment(symbol_type cst, expression_node_ptr node) | |
28023 | { | |
28024 | parser_->state_.activate_side_effect("lodge_assignment()"); | |
28025 | ||
28026 | if (!parser_->dec_.collect_assignments()) | |
28027 | return; | |
28028 | ||
28029 | std::string symbol_name; | |
28030 | ||
28031 | switch (cst) | |
28032 | { | |
28033 | case e_st_variable : symbol_name = parser_->symtab_store_ | |
28034 | .get_variable_name(node); | |
28035 | break; | |
28036 | ||
28037 | #ifndef exprtk_disable_string_capabilities | |
28038 | case e_st_string : symbol_name = parser_->symtab_store_ | |
28039 | .get_stringvar_name(node); | |
28040 | break; | |
28041 | #endif | |
28042 | ||
28043 | case e_st_vector : { | |
28044 | typedef details::vector_holder<T> vector_holder_t; | |
28045 | ||
28046 | vector_holder_t& vh = static_cast<vector_node_t*>(node)->vec_holder(); | |
28047 | ||
28048 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); | |
28049 | } | |
28050 | break; | |
28051 | ||
28052 | case e_st_vecelem : { | |
28053 | typedef details::vector_holder<T> vector_holder_t; | |
28054 | ||
28055 | vector_holder_t& vh = static_cast<vector_elem_node_t*>(node)->vec_holder(); | |
28056 | ||
28057 | symbol_name = parser_->symtab_store_.get_vector_name(&vh); | |
28058 | ||
28059 | cst = e_st_vector; | |
28060 | } | |
28061 | break; | |
28062 | ||
28063 | default : return; | |
28064 | } | |
28065 | ||
28066 | if (!symbol_name.empty()) | |
28067 | { | |
28068 | parser_->dec_.add_assignment(symbol_name,cst); | |
28069 | } | |
28070 | } | |
28071 | ||
28072 | inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) | |
28073 | { | |
28074 | if (details::is_variable_node(branch[0])) | |
28075 | { | |
28076 | lodge_assignment(e_st_variable,branch[0]); | |
28077 | ||
28078 | return synthesize_expression<assignment_node_t,2>(operation,branch); | |
28079 | } | |
28080 | else if (details::is_vector_elem_node(branch[0])) | |
28081 | { | |
28082 | lodge_assignment(e_st_vecelem,branch[0]); | |
28083 | ||
28084 | return synthesize_expression<assignment_vec_elem_node_t, 2>(operation, branch); | |
28085 | } | |
28086 | else if (details::is_rebasevector_elem_node(branch[0])) | |
28087 | { | |
28088 | lodge_assignment(e_st_vecelem,branch[0]); | |
28089 | ||
28090 | return synthesize_expression<assignment_rebasevec_elem_node_t, 2>(operation, branch); | |
28091 | } | |
28092 | else if (details::is_rebasevector_celem_node(branch[0])) | |
28093 | { | |
28094 | lodge_assignment(e_st_vecelem,branch[0]); | |
28095 | ||
28096 | return synthesize_expression<assignment_rebasevec_celem_node_t, 2>(operation, branch); | |
28097 | } | |
28098 | #ifndef exprtk_disable_string_capabilities | |
28099 | else if (details::is_string_node(branch[0])) | |
28100 | { | |
28101 | lodge_assignment(e_st_string,branch[0]); | |
28102 | ||
28103 | return synthesize_expression<assignment_string_node_t,2>(operation, branch); | |
28104 | } | |
28105 | else if (details::is_string_range_node(branch[0])) | |
28106 | { | |
28107 | lodge_assignment(e_st_string,branch[0]); | |
28108 | ||
28109 | return synthesize_expression<assignment_string_range_node_t,2>(operation, branch); | |
28110 | } | |
28111 | #endif | |
28112 | else if (details::is_vector_node(branch[0])) | |
28113 | { | |
28114 | lodge_assignment(e_st_vector,branch[0]); | |
28115 | ||
28116 | if (details::is_ivector_node(branch[1])) | |
28117 | return synthesize_expression<assignment_vecvec_node_t,2>(operation, branch); | |
28118 | else | |
28119 | return synthesize_expression<assignment_vec_node_t,2>(operation, branch); | |
28120 | } | |
28121 | else | |
28122 | { | |
28123 | parser_->set_synthesis_error("Invalid assignment operation.[1]"); | |
28124 | ||
28125 | return error_node(); | |
28126 | } | |
28127 | } | |
28128 | ||
28129 | inline expression_node_ptr synthesize_assignment_operation_expression(const details::operator_type& operation, | |
28130 | expression_node_ptr (&branch)[2]) | |
28131 | { | |
28132 | if (details::is_variable_node(branch[0])) | |
28133 | { | |
28134 | lodge_assignment(e_st_variable,branch[0]); | |
28135 | ||
28136 | switch (operation) | |
28137 | { | |
28138 | #define case_stmt(op0,op1) \ | |
28139 | case op0 : return node_allocator_-> \ | |
28140 | template allocate_rrr<typename details::assignment_op_node<Type,op1<Type> > > \ | |
28141 | (operation, branch[0], branch[1]); \ | |
28142 | ||
28143 | case_stmt(details::e_addass,details::add_op) | |
28144 | case_stmt(details::e_subass,details::sub_op) | |
28145 | case_stmt(details::e_mulass,details::mul_op) | |
28146 | case_stmt(details::e_divass,details::div_op) | |
28147 | case_stmt(details::e_modass,details::mod_op) | |
28148 | #undef case_stmt | |
28149 | default : return error_node(); | |
28150 | } | |
28151 | } | |
28152 | else if (details::is_vector_elem_node(branch[0])) | |
28153 | { | |
28154 | lodge_assignment(e_st_vecelem,branch[0]); | |
28155 | ||
28156 | switch (operation) | |
28157 | { | |
28158 | #define case_stmt(op0,op1) \ | |
28159 | case op0 : return node_allocator_-> \ | |
28160 | template allocate_rrr<typename details::assignment_vec_elem_op_node<Type,op1<Type> > > \ | |
28161 | (operation, branch[0], branch[1]); \ | |
28162 | ||
28163 | case_stmt(details::e_addass,details::add_op) | |
28164 | case_stmt(details::e_subass,details::sub_op) | |
28165 | case_stmt(details::e_mulass,details::mul_op) | |
28166 | case_stmt(details::e_divass,details::div_op) | |
28167 | case_stmt(details::e_modass,details::mod_op) | |
28168 | #undef case_stmt | |
28169 | default : return error_node(); | |
28170 | } | |
28171 | } | |
28172 | else if (details::is_rebasevector_elem_node(branch[0])) | |
28173 | { | |
28174 | lodge_assignment(e_st_vecelem,branch[0]); | |
28175 | ||
28176 | switch (operation) | |
28177 | { | |
28178 | #define case_stmt(op0,op1) \ | |
28179 | case op0 : return node_allocator_-> \ | |
28180 | template allocate_rrr<typename details::assignment_rebasevec_elem_op_node<Type,op1<Type> > > \ | |
28181 | (operation, branch[0], branch[1]); \ | |
28182 | ||
28183 | case_stmt(details::e_addass,details::add_op) | |
28184 | case_stmt(details::e_subass,details::sub_op) | |
28185 | case_stmt(details::e_mulass,details::mul_op) | |
28186 | case_stmt(details::e_divass,details::div_op) | |
28187 | case_stmt(details::e_modass,details::mod_op) | |
28188 | #undef case_stmt | |
28189 | default : return error_node(); | |
28190 | } | |
28191 | } | |
28192 | else if (details::is_rebasevector_celem_node(branch[0])) | |
28193 | { | |
28194 | lodge_assignment(e_st_vecelem,branch[0]); | |
28195 | ||
28196 | switch (operation) | |
28197 | { | |
28198 | #define case_stmt(op0,op1) \ | |
28199 | case op0 : return node_allocator_-> \ | |
28200 | template allocate_rrr<typename details::assignment_rebasevec_celem_op_node<Type,op1<Type> > > \ | |
28201 | (operation, branch[0], branch[1]); \ | |
28202 | ||
28203 | case_stmt(details::e_addass,details::add_op) | |
28204 | case_stmt(details::e_subass,details::sub_op) | |
28205 | case_stmt(details::e_mulass,details::mul_op) | |
28206 | case_stmt(details::e_divass,details::div_op) | |
28207 | case_stmt(details::e_modass,details::mod_op) | |
28208 | #undef case_stmt | |
28209 | default : return error_node(); | |
28210 | } | |
28211 | } | |
28212 | else if (details::is_vector_node(branch[0])) | |
28213 | { | |
28214 | lodge_assignment(e_st_vector,branch[0]); | |
28215 | ||
28216 | if (details::is_ivector_node(branch[1])) | |
28217 | { | |
28218 | switch (operation) | |
28219 | { | |
28220 | #define case_stmt(op0,op1) \ | |
28221 | case op0 : return node_allocator_-> \ | |
28222 | template allocate_rrr<typename details::assignment_vecvec_op_node<Type,op1<Type> > > \ | |
28223 | (operation, branch[0], branch[1]); \ | |
28224 | ||
28225 | case_stmt(details::e_addass,details::add_op) | |
28226 | case_stmt(details::e_subass,details::sub_op) | |
28227 | case_stmt(details::e_mulass,details::mul_op) | |
28228 | case_stmt(details::e_divass,details::div_op) | |
28229 | case_stmt(details::e_modass,details::mod_op) | |
28230 | #undef case_stmt | |
28231 | default : return error_node(); | |
28232 | } | |
28233 | } | |
28234 | else | |
28235 | { | |
28236 | switch (operation) | |
28237 | { | |
28238 | #define case_stmt(op0,op1) \ | |
28239 | case op0 : return node_allocator_-> \ | |
28240 | template allocate_rrr<typename details::assignment_vec_op_node<Type,op1<Type> > > \ | |
28241 | (operation, branch[0], branch[1]); \ | |
28242 | ||
28243 | case_stmt(details::e_addass,details::add_op) | |
28244 | case_stmt(details::e_subass,details::sub_op) | |
28245 | case_stmt(details::e_mulass,details::mul_op) | |
28246 | case_stmt(details::e_divass,details::div_op) | |
28247 | case_stmt(details::e_modass,details::mod_op) | |
28248 | #undef case_stmt | |
28249 | default : return error_node(); | |
28250 | } | |
28251 | } | |
28252 | } | |
28253 | #ifndef exprtk_disable_string_capabilities | |
28254 | else if ( | |
28255 | (details::e_addass == operation) && | |
28256 | details::is_string_node(branch[0]) | |
28257 | ) | |
28258 | { | |
28259 | typedef details::assignment_string_node<T,details::asn_addassignment> addass_t; | |
28260 | ||
28261 | lodge_assignment(e_st_string,branch[0]); | |
28262 | ||
28263 | return synthesize_expression<addass_t,2>(operation,branch); | |
28264 | } | |
28265 | #endif | |
28266 | else | |
28267 | { | |
28268 | parser_->set_synthesis_error("Invalid assignment operation[2]"); | |
28269 | ||
28270 | return error_node(); | |
28271 | } | |
28272 | } | |
28273 | ||
28274 | inline expression_node_ptr synthesize_veceqineqlogic_operation_expression(const details::operator_type& operation, | |
28275 | expression_node_ptr (&branch)[2]) | |
28276 | { | |
28277 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); | |
28278 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); | |
28279 | ||
28280 | #define batch_eqineq_logic_case \ | |
28281 | case_stmt(details:: e_lt, details:: lt_op) \ | |
28282 | case_stmt(details:: e_lte, details:: lte_op) \ | |
28283 | case_stmt(details:: e_gt, details:: gt_op) \ | |
28284 | case_stmt(details:: e_gte, details:: gte_op) \ | |
28285 | case_stmt(details:: e_eq, details:: eq_op) \ | |
28286 | case_stmt(details:: e_ne, details:: ne_op) \ | |
28287 | case_stmt(details::e_equal, details::equal_op) \ | |
28288 | case_stmt(details:: e_and, details:: and_op) \ | |
28289 | case_stmt(details:: e_nand, details:: nand_op) \ | |
28290 | case_stmt(details:: e_or, details:: or_op) \ | |
28291 | case_stmt(details:: e_nor, details:: nor_op) \ | |
28292 | case_stmt(details:: e_xor, details:: xor_op) \ | |
28293 | case_stmt(details:: e_xnor, details:: xnor_op) \ | |
28294 | ||
28295 | if (is_b0_ivec && is_b1_ivec) | |
28296 | { | |
28297 | switch (operation) | |
28298 | { | |
28299 | #define case_stmt(op0,op1) \ | |
28300 | case op0 : return node_allocator_-> \ | |
28301 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ | |
28302 | (operation, branch[0], branch[1]); \ | |
28303 | ||
28304 | batch_eqineq_logic_case | |
28305 | #undef case_stmt | |
28306 | default : return error_node(); | |
28307 | } | |
28308 | } | |
28309 | else if (is_b0_ivec && !is_b1_ivec) | |
28310 | { | |
28311 | switch (operation) | |
28312 | { | |
28313 | #define case_stmt(op0,op1) \ | |
28314 | case op0 : return node_allocator_-> \ | |
28315 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ | |
28316 | (operation, branch[0], branch[1]); \ | |
28317 | ||
28318 | batch_eqineq_logic_case | |
28319 | #undef case_stmt | |
28320 | default : return error_node(); | |
28321 | } | |
28322 | } | |
28323 | else if (!is_b0_ivec && is_b1_ivec) | |
28324 | { | |
28325 | switch (operation) | |
28326 | { | |
28327 | #define case_stmt(op0,op1) \ | |
28328 | case op0 : return node_allocator_-> \ | |
28329 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ | |
28330 | (operation, branch[0], branch[1]); \ | |
28331 | ||
28332 | batch_eqineq_logic_case | |
28333 | #undef case_stmt | |
28334 | default : return error_node(); | |
28335 | } | |
28336 | } | |
28337 | else | |
28338 | return error_node(); | |
28339 | ||
28340 | #undef batch_eqineq_logic_case | |
28341 | } | |
28342 | ||
28343 | inline expression_node_ptr synthesize_vecarithmetic_operation_expression(const details::operator_type& operation, | |
28344 | expression_node_ptr (&branch)[2]) | |
28345 | { | |
28346 | const bool is_b0_ivec = details::is_ivector_node(branch[0]); | |
28347 | const bool is_b1_ivec = details::is_ivector_node(branch[1]); | |
28348 | ||
28349 | #define vector_ops \ | |
28350 | case_stmt(details::e_add,details::add_op) \ | |
28351 | case_stmt(details::e_sub,details::sub_op) \ | |
28352 | case_stmt(details::e_mul,details::mul_op) \ | |
28353 | case_stmt(details::e_div,details::div_op) \ | |
28354 | case_stmt(details::e_mod,details::mod_op) \ | |
28355 | ||
28356 | if (is_b0_ivec && is_b1_ivec) | |
28357 | { | |
28358 | switch (operation) | |
28359 | { | |
28360 | #define case_stmt(op0,op1) \ | |
28361 | case op0 : return node_allocator_-> \ | |
28362 | template allocate_rrr<typename details::vec_binop_vecvec_node<Type,op1<Type> > > \ | |
28363 | (operation, branch[0], branch[1]); \ | |
28364 | ||
28365 | vector_ops | |
28366 | case_stmt(details::e_pow,details:: pow_op) | |
28367 | #undef case_stmt | |
28368 | default : return error_node(); | |
28369 | } | |
28370 | } | |
28371 | else if (is_b0_ivec && !is_b1_ivec) | |
28372 | { | |
28373 | switch (operation) | |
28374 | { | |
28375 | #define case_stmt(op0,op1) \ | |
28376 | case op0 : return node_allocator_-> \ | |
28377 | template allocate_rrr<typename details::vec_binop_vecval_node<Type,op1<Type> > > \ | |
28378 | (operation, branch[0], branch[1]); \ | |
28379 | ||
28380 | vector_ops | |
28381 | case_stmt(details::e_pow,details:: pow_op) | |
28382 | #undef case_stmt | |
28383 | default : return error_node(); | |
28384 | } | |
28385 | } | |
28386 | else if (!is_b0_ivec && is_b1_ivec) | |
28387 | { | |
28388 | switch (operation) | |
28389 | { | |
28390 | #define case_stmt(op0,op1) \ | |
28391 | case op0 : return node_allocator_-> \ | |
28392 | template allocate_rrr<typename details::vec_binop_valvec_node<Type,op1<Type> > > \ | |
28393 | (operation, branch[0], branch[1]); \ | |
28394 | ||
28395 | vector_ops | |
28396 | #undef case_stmt | |
28397 | default : return error_node(); | |
28398 | } | |
28399 | } | |
28400 | else | |
28401 | return error_node(); | |
28402 | ||
28403 | #undef vector_ops | |
28404 | } | |
28405 | ||
28406 | inline expression_node_ptr synthesize_swap_expression(expression_node_ptr (&branch)[2]) | |
28407 | { | |
28408 | const bool v0_is_ivar = details::is_ivariable_node(branch[0]); | |
28409 | const bool v1_is_ivar = details::is_ivariable_node(branch[1]); | |
28410 | ||
28411 | const bool v0_is_ivec = details::is_ivector_node (branch[0]); | |
28412 | const bool v1_is_ivec = details::is_ivector_node (branch[1]); | |
28413 | ||
28414 | #ifndef exprtk_disable_string_capabilities | |
28415 | const bool v0_is_str = details::is_generally_string_node(branch[0]); | |
28416 | const bool v1_is_str = details::is_generally_string_node(branch[1]); | |
28417 | #endif | |
28418 | ||
28419 | expression_node_ptr result = error_node(); | |
28420 | ||
28421 | if (v0_is_ivar && v1_is_ivar) | |
28422 | { | |
28423 | typedef details::variable_node<T>* variable_node_ptr; | |
28424 | ||
28425 | variable_node_ptr v0 = variable_node_ptr(0); | |
28426 | variable_node_ptr v1 = variable_node_ptr(0); | |
28427 | ||
28428 | if ( | |
28429 | (0 != (v0 = dynamic_cast<variable_node_ptr>(branch[0]))) && | |
28430 | (0 != (v1 = dynamic_cast<variable_node_ptr>(branch[1]))) | |
28431 | ) | |
28432 | { | |
28433 | result = node_allocator_->allocate<details::swap_node<T> >(v0,v1); | |
28434 | } | |
28435 | else | |
28436 | result = node_allocator_->allocate<details::swap_generic_node<T> >(branch[0],branch[1]); | |
28437 | } | |
28438 | else if (v0_is_ivec && v1_is_ivec) | |
28439 | { | |
28440 | result = node_allocator_->allocate<details::swap_vecvec_node<T> >(branch[0],branch[1]); | |
28441 | } | |
28442 | #ifndef exprtk_disable_string_capabilities | |
28443 | else if (v0_is_str && v1_is_str) | |
28444 | { | |
28445 | if (is_string_node(branch[0]) && is_string_node(branch[1])) | |
28446 | result = node_allocator_->allocate<details::swap_string_node<T> > | |
28447 | (branch[0], branch[1]); | |
28448 | else | |
28449 | result = node_allocator_->allocate<details::swap_genstrings_node<T> > | |
28450 | (branch[0], branch[1]); | |
28451 | } | |
28452 | #endif | |
28453 | else | |
28454 | { | |
28455 | parser_->set_synthesis_error("Only variables, strings, vectors or vector elements can be swapped"); | |
28456 | ||
28457 | return error_node(); | |
28458 | } | |
28459 | ||
28460 | parser_->state_.activate_side_effect("synthesize_swap_expression()"); | |
28461 | ||
28462 | return result; | |
28463 | } | |
28464 | ||
28465 | #ifndef exprtk_disable_sc_andor | |
28466 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) | |
28467 | { | |
28468 | expression_node_ptr result = error_node(); | |
28469 | ||
28470 | if (details::is_constant_node(branch[0])) | |
28471 | { | |
28472 | if ( | |
28473 | (details::e_scand == operation) && | |
28474 | std::equal_to<T>()(T(0),branch[0]->value()) | |
28475 | ) | |
28476 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); | |
28477 | else if ( | |
28478 | (details::e_scor == operation) && | |
28479 | std::not_equal_to<T>()(T(0),branch[0]->value()) | |
28480 | ) | |
28481 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); | |
28482 | } | |
28483 | ||
28484 | if (details::is_constant_node(branch[1]) && (0 == result)) | |
28485 | { | |
28486 | if ( | |
28487 | (details::e_scand == operation) && | |
28488 | std::equal_to<T>()(T(0),branch[1]->value()) | |
28489 | ) | |
28490 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); | |
28491 | else if ( | |
28492 | (details::e_scor == operation) && | |
28493 | std::not_equal_to<T>()(T(0),branch[1]->value()) | |
28494 | ) | |
28495 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); | |
28496 | } | |
28497 | ||
28498 | if (result) | |
28499 | { | |
28500 | free_node(*node_allocator_, branch[0]); | |
28501 | free_node(*node_allocator_, branch[1]); | |
28502 | ||
28503 | return result; | |
28504 | } | |
28505 | else if (details::e_scand == operation) | |
28506 | { | |
28507 | return synthesize_expression<scand_node_t,2>(operation, branch); | |
28508 | } | |
28509 | else if (details::e_scor == operation) | |
28510 | { | |
28511 | return synthesize_expression<scor_node_t,2>(operation, branch); | |
28512 | } | |
28513 | else | |
28514 | return error_node(); | |
28515 | } | |
28516 | #else | |
28517 | inline expression_node_ptr synthesize_shortcircuit_expression(const details::operator_type&, expression_node_ptr (&)[2]) | |
28518 | { | |
28519 | return error_node(); | |
28520 | } | |
28521 | #endif | |
28522 | ||
28523 | #define basic_opr_switch_statements \ | |
28524 | case_stmt(details::e_add, details::add_op) \ | |
28525 | case_stmt(details::e_sub, details::sub_op) \ | |
28526 | case_stmt(details::e_mul, details::mul_op) \ | |
28527 | case_stmt(details::e_div, details::div_op) \ | |
28528 | case_stmt(details::e_mod, details::mod_op) \ | |
28529 | case_stmt(details::e_pow, details::pow_op) \ | |
28530 | ||
28531 | #define extended_opr_switch_statements \ | |
28532 | case_stmt(details:: e_lt, details:: lt_op) \ | |
28533 | case_stmt(details:: e_lte, details:: lte_op) \ | |
28534 | case_stmt(details:: e_gt, details:: gt_op) \ | |
28535 | case_stmt(details:: e_gte, details:: gte_op) \ | |
28536 | case_stmt(details:: e_eq, details:: eq_op) \ | |
28537 | case_stmt(details:: e_ne, details:: ne_op) \ | |
28538 | case_stmt(details:: e_and, details:: and_op) \ | |
28539 | case_stmt(details::e_nand, details::nand_op) \ | |
28540 | case_stmt(details:: e_or, details:: or_op) \ | |
28541 | case_stmt(details:: e_nor, details:: nor_op) \ | |
28542 | case_stmt(details:: e_xor, details:: xor_op) \ | |
28543 | case_stmt(details::e_xnor, details::xnor_op) \ | |
28544 | ||
28545 | #ifndef exprtk_disable_cardinal_pow_optimisation | |
28546 | template <typename TType, template <typename, typename> class IPowNode> | |
28547 | inline expression_node_ptr cardinal_pow_optimisation_impl(const TType& v, const unsigned int& p) | |
28548 | { | |
28549 | switch (p) | |
28550 | { | |
28551 | #define case_stmt(cp) \ | |
28552 | case cp : return node_allocator_-> \ | |
28553 | allocate<IPowNode<T,details::numeric::fast_exp<T,cp> > >(v); \ | |
28554 | ||
28555 | case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4) | |
28556 | case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8) | |
28557 | case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12) | |
28558 | case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16) | |
28559 | case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20) | |
28560 | case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24) | |
28561 | case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28) | |
28562 | case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32) | |
28563 | case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36) | |
28564 | case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40) | |
28565 | case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44) | |
28566 | case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48) | |
28567 | case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52) | |
28568 | case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56) | |
28569 | case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60) | |
28570 | #undef case_stmt | |
28571 | default : return error_node(); | |
28572 | } | |
28573 | } | |
28574 | ||
28575 | inline expression_node_ptr cardinal_pow_optimisation(const T& v, const T& c) | |
28576 | { | |
28577 | const bool not_recipricol = (c >= T(0)); | |
28578 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); | |
28579 | ||
28580 | if (0 == p) | |
28581 | return node_allocator_->allocate_c<literal_node_t>(T(1)); | |
28582 | else if (std::equal_to<T>()(T(2),c)) | |
28583 | { | |
28584 | return node_allocator_-> | |
28585 | template allocate_rr<typename details::vov_node<Type,details::mul_op<Type> > >(v,v); | |
28586 | } | |
28587 | else | |
28588 | { | |
28589 | if (not_recipricol) | |
28590 | return cardinal_pow_optimisation_impl<T,details::ipow_node>(v,p); | |
28591 | else | |
28592 | return cardinal_pow_optimisation_impl<T,details::ipowinv_node>(v,p); | |
28593 | } | |
28594 | } | |
28595 | ||
28596 | inline bool cardinal_pow_optimisable(const details::operator_type& operation, const T& c) const | |
28597 | { | |
28598 | return (details::e_pow == operation) && (details::numeric::abs(c) <= T(60)) && details::numeric::is_integer(c); | |
28599 | } | |
28600 | ||
28601 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr (&branch)[2]) | |
28602 | { | |
28603 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
28604 | const bool not_recipricol = (c >= T(0)); | |
28605 | const unsigned int p = static_cast<unsigned int>(details::numeric::to_int32(details::numeric::abs(c))); | |
28606 | ||
28607 | node_allocator_->free(branch[1]); | |
28608 | ||
28609 | if (0 == p) | |
28610 | { | |
28611 | details::free_all_nodes(*node_allocator_, branch); | |
28612 | ||
28613 | return node_allocator_->allocate_c<literal_node_t>(T(1)); | |
28614 | } | |
28615 | else if (not_recipricol) | |
28616 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipow_node>(branch[0],p); | |
28617 | else | |
28618 | return cardinal_pow_optimisation_impl<expression_node_ptr,details::bipowninv_node>(branch[0],p); | |
28619 | } | |
28620 | #else | |
28621 | inline expression_node_ptr cardinal_pow_optimisation(T&, const T&) | |
28622 | { | |
28623 | return error_node(); | |
28624 | } | |
28625 | ||
28626 | inline bool cardinal_pow_optimisable(const details::operator_type&, const T&) | |
28627 | { | |
28628 | return false; | |
28629 | } | |
28630 | ||
28631 | inline expression_node_ptr cardinal_pow_optimisation(expression_node_ptr(&)[2]) | |
28632 | { | |
28633 | return error_node(); | |
28634 | } | |
28635 | #endif | |
28636 | ||
28637 | struct synthesize_binary_ext_expression | |
28638 | { | |
28639 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
28640 | const details::operator_type& operation, | |
28641 | expression_node_ptr (&branch)[2]) | |
28642 | { | |
28643 | const bool left_neg = is_neg_unary_node(branch[0]); | |
28644 | const bool right_neg = is_neg_unary_node(branch[1]); | |
28645 | ||
28646 | if (left_neg && right_neg) | |
28647 | { | |
28648 | if ( | |
28649 | (details::e_add == operation) || | |
28650 | (details::e_sub == operation) || | |
28651 | (details::e_mul == operation) || | |
28652 | (details::e_div == operation) | |
28653 | ) | |
28654 | { | |
28655 | if ( | |
28656 | !expr_gen.parser_->simplify_unary_negation_branch(branch[0]) || | |
28657 | !expr_gen.parser_->simplify_unary_negation_branch(branch[1]) | |
28658 | ) | |
28659 | { | |
28660 | details::free_all_nodes(*expr_gen.node_allocator_,branch); | |
28661 | ||
28662 | return error_node(); | |
28663 | } | |
28664 | } | |
28665 | ||
28666 | switch (operation) | |
28667 | { | |
28668 | // -f(x + 1) + -g(y + 1) --> -(f(x + 1) + g(y + 1)) | |
28669 | case details::e_add : return expr_gen(details::e_neg, | |
28670 | expr_gen.node_allocator_-> | |
28671 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > | |
28672 | (branch[0],branch[1])); | |
28673 | ||
28674 | // -f(x + 1) - -g(y + 1) --> g(y + 1) - f(x + 1) | |
28675 | case details::e_sub : return expr_gen.node_allocator_-> | |
28676 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > | |
28677 | (branch[1],branch[0]); | |
28678 | ||
28679 | default : break; | |
28680 | } | |
28681 | } | |
28682 | else if (left_neg && !right_neg) | |
28683 | { | |
28684 | if ( | |
28685 | (details::e_add == operation) || | |
28686 | (details::e_sub == operation) || | |
28687 | (details::e_mul == operation) || | |
28688 | (details::e_div == operation) | |
28689 | ) | |
28690 | { | |
28691 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[0])) | |
28692 | { | |
28693 | details::free_all_nodes(*expr_gen.node_allocator_,branch); | |
28694 | ||
28695 | return error_node(); | |
28696 | } | |
28697 | ||
28698 | switch (operation) | |
28699 | { | |
28700 | // -f(x + 1) + g(y + 1) --> g(y + 1) - f(x + 1) | |
28701 | case details::e_add : return expr_gen.node_allocator_-> | |
28702 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > | |
28703 | (branch[1], branch[0]); | |
28704 | ||
28705 | // -f(x + 1) - g(y + 1) --> -(f(x + 1) + g(y + 1)) | |
28706 | case details::e_sub : return expr_gen(details::e_neg, | |
28707 | expr_gen.node_allocator_-> | |
28708 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > | |
28709 | (branch[0], branch[1])); | |
28710 | ||
28711 | // -f(x + 1) * g(y + 1) --> -(f(x + 1) * g(y + 1)) | |
28712 | case details::e_mul : return expr_gen(details::e_neg, | |
28713 | expr_gen.node_allocator_-> | |
28714 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > | |
28715 | (branch[0], branch[1])); | |
28716 | ||
28717 | // -f(x + 1) / g(y + 1) --> -(f(x + 1) / g(y + 1)) | |
28718 | case details::e_div : return expr_gen(details::e_neg, | |
28719 | expr_gen.node_allocator_-> | |
28720 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > | |
28721 | (branch[0], branch[1])); | |
28722 | ||
28723 | default : return error_node(); | |
28724 | } | |
28725 | } | |
28726 | } | |
28727 | else if (!left_neg && right_neg) | |
28728 | { | |
28729 | if ( | |
28730 | (details::e_add == operation) || | |
28731 | (details::e_sub == operation) || | |
28732 | (details::e_mul == operation) || | |
28733 | (details::e_div == operation) | |
28734 | ) | |
28735 | { | |
28736 | if (!expr_gen.parser_->simplify_unary_negation_branch(branch[1])) | |
28737 | { | |
28738 | details::free_all_nodes(*expr_gen.node_allocator_,branch); | |
28739 | ||
28740 | return error_node(); | |
28741 | } | |
28742 | ||
28743 | switch (operation) | |
28744 | { | |
28745 | // f(x + 1) + -g(y + 1) --> f(x + 1) - g(y + 1) | |
28746 | case details::e_add : return expr_gen.node_allocator_-> | |
28747 | template allocate<typename details::binary_ext_node<Type,details::sub_op<Type> > > | |
28748 | (branch[0], branch[1]); | |
28749 | ||
28750 | // f(x + 1) - - g(y + 1) --> f(x + 1) + g(y + 1) | |
28751 | case details::e_sub : return expr_gen.node_allocator_-> | |
28752 | template allocate<typename details::binary_ext_node<Type,details::add_op<Type> > > | |
28753 | (branch[0], branch[1]); | |
28754 | ||
28755 | // f(x + 1) * -g(y + 1) --> -(f(x + 1) * g(y + 1)) | |
28756 | case details::e_mul : return expr_gen(details::e_neg, | |
28757 | expr_gen.node_allocator_-> | |
28758 | template allocate<typename details::binary_ext_node<Type,details::mul_op<Type> > > | |
28759 | (branch[0], branch[1])); | |
28760 | ||
28761 | // f(x + 1) / -g(y + 1) --> -(f(x + 1) / g(y + 1)) | |
28762 | case details::e_div : return expr_gen(details::e_neg, | |
28763 | expr_gen.node_allocator_-> | |
28764 | template allocate<typename details::binary_ext_node<Type,details::div_op<Type> > > | |
28765 | (branch[0], branch[1])); | |
28766 | ||
28767 | default : return error_node(); | |
28768 | } | |
28769 | } | |
28770 | } | |
28771 | ||
28772 | switch (operation) | |
28773 | { | |
28774 | #define case_stmt(op0,op1) \ | |
28775 | case op0 : return expr_gen.node_allocator_-> \ | |
28776 | template allocate<typename details::binary_ext_node<Type,op1<Type> > > \ | |
28777 | (branch[0], branch[1]); \ | |
28778 | ||
28779 | basic_opr_switch_statements | |
28780 | extended_opr_switch_statements | |
28781 | #undef case_stmt | |
28782 | default : return error_node(); | |
28783 | } | |
28784 | } | |
28785 | }; | |
28786 | ||
28787 | struct synthesize_vob_expression | |
28788 | { | |
28789 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
28790 | const details::operator_type& operation, | |
28791 | expression_node_ptr (&branch)[2]) | |
28792 | { | |
28793 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
28794 | ||
28795 | #ifndef exprtk_disable_enhanced_features | |
28796 | if (details::is_sf3ext_node(branch[1])) | |
28797 | { | |
28798 | expression_node_ptr result = error_node(); | |
28799 | ||
28800 | const bool synthesis_result = | |
28801 | synthesize_sf4ext_expression::template compile_right<vtype> | |
28802 | (expr_gen, v, operation, branch[1], result); | |
28803 | ||
28804 | if (synthesis_result) | |
28805 | { | |
28806 | free_node(*expr_gen.node_allocator_,branch[1]); | |
28807 | return result; | |
28808 | } | |
28809 | } | |
28810 | #endif | |
28811 | ||
28812 | if ( | |
28813 | (details::e_mul == operation) || | |
28814 | (details::e_div == operation) | |
28815 | ) | |
28816 | { | |
28817 | if (details::is_uv_node(branch[1])) | |
28818 | { | |
28819 | typedef details::uv_base_node<Type>* uvbn_ptr_t; | |
28820 | ||
28821 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[1])->operation(); | |
28822 | ||
28823 | if (details::e_neg == o) | |
28824 | { | |
28825 | const Type& v1 = static_cast<uvbn_ptr_t>(branch[1])->v(); | |
28826 | ||
28827 | free_node(*expr_gen.node_allocator_,branch[1]); | |
28828 | ||
28829 | switch (operation) | |
28830 | { | |
28831 | case details::e_mul : return expr_gen(details::e_neg, | |
28832 | expr_gen.node_allocator_-> | |
28833 | template allocate_rr<typename details:: | |
28834 | vov_node<Type,details::mul_op<Type> > >(v,v1)); | |
28835 | ||
28836 | case details::e_div : return expr_gen(details::e_neg, | |
28837 | expr_gen.node_allocator_-> | |
28838 | template allocate_rr<typename details:: | |
28839 | vov_node<Type,details::div_op<Type> > >(v,v1)); | |
28840 | ||
28841 | default : break; | |
28842 | } | |
28843 | } | |
28844 | } | |
28845 | } | |
28846 | ||
28847 | switch (operation) | |
28848 | { | |
28849 | #define case_stmt(op0,op1) \ | |
28850 | case op0 : return expr_gen.node_allocator_-> \ | |
28851 | template allocate_rc<typename details::vob_node<Type,op1<Type> > > \ | |
28852 | (v, branch[1]); \ | |
28853 | ||
28854 | basic_opr_switch_statements | |
28855 | extended_opr_switch_statements | |
28856 | #undef case_stmt | |
28857 | default : return error_node(); | |
28858 | } | |
28859 | } | |
28860 | }; | |
28861 | ||
28862 | struct synthesize_bov_expression | |
28863 | { | |
28864 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
28865 | const details::operator_type& operation, | |
28866 | expression_node_ptr (&branch)[2]) | |
28867 | { | |
28868 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
28869 | ||
28870 | #ifndef exprtk_disable_enhanced_features | |
28871 | if (details::is_sf3ext_node(branch[0])) | |
28872 | { | |
28873 | expression_node_ptr result = error_node(); | |
28874 | ||
28875 | const bool synthesis_result = | |
28876 | synthesize_sf4ext_expression::template compile_left<vtype> | |
28877 | (expr_gen, v, operation, branch[0], result); | |
28878 | ||
28879 | if (synthesis_result) | |
28880 | { | |
28881 | free_node(*expr_gen.node_allocator_, branch[0]); | |
28882 | ||
28883 | return result; | |
28884 | } | |
28885 | } | |
28886 | #endif | |
28887 | ||
28888 | if ( | |
28889 | (details::e_add == operation) || | |
28890 | (details::e_sub == operation) || | |
28891 | (details::e_mul == operation) || | |
28892 | (details::e_div == operation) | |
28893 | ) | |
28894 | { | |
28895 | if (details::is_uv_node(branch[0])) | |
28896 | { | |
28897 | typedef details::uv_base_node<Type>* uvbn_ptr_t; | |
28898 | ||
28899 | details::operator_type o = static_cast<uvbn_ptr_t>(branch[0])->operation(); | |
28900 | ||
28901 | if (details::e_neg == o) | |
28902 | { | |
28903 | const Type& v0 = static_cast<uvbn_ptr_t>(branch[0])->v(); | |
28904 | ||
28905 | free_node(*expr_gen.node_allocator_,branch[0]); | |
28906 | ||
28907 | switch (operation) | |
28908 | { | |
28909 | case details::e_add : return expr_gen.node_allocator_-> | |
28910 | template allocate_rr<typename details:: | |
28911 | vov_node<Type,details::sub_op<Type> > >(v,v0); | |
28912 | ||
28913 | case details::e_sub : return expr_gen(details::e_neg, | |
28914 | expr_gen.node_allocator_-> | |
28915 | template allocate_rr<typename details:: | |
28916 | vov_node<Type,details::add_op<Type> > >(v0,v)); | |
28917 | ||
28918 | case details::e_mul : return expr_gen(details::e_neg, | |
28919 | expr_gen.node_allocator_-> | |
28920 | template allocate_rr<typename details:: | |
28921 | vov_node<Type,details::mul_op<Type> > >(v0,v)); | |
28922 | ||
28923 | case details::e_div : return expr_gen(details::e_neg, | |
28924 | expr_gen.node_allocator_-> | |
28925 | template allocate_rr<typename details:: | |
28926 | vov_node<Type,details::div_op<Type> > >(v0,v)); | |
28927 | default : break; | |
28928 | } | |
28929 | } | |
28930 | } | |
28931 | } | |
28932 | ||
28933 | switch (operation) | |
28934 | { | |
28935 | #define case_stmt(op0,op1) \ | |
28936 | case op0 : return expr_gen.node_allocator_-> \ | |
28937 | template allocate_cr<typename details::bov_node<Type,op1<Type> > > \ | |
28938 | (branch[0], v); \ | |
28939 | ||
28940 | basic_opr_switch_statements | |
28941 | extended_opr_switch_statements | |
28942 | #undef case_stmt | |
28943 | default : return error_node(); | |
28944 | } | |
28945 | } | |
28946 | }; | |
28947 | ||
28948 | struct synthesize_cob_expression | |
28949 | { | |
28950 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
28951 | const details::operator_type& operation, | |
28952 | expression_node_ptr (&branch)[2]) | |
28953 | { | |
28954 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
28955 | ||
28956 | free_node(*expr_gen.node_allocator_,branch[0]); | |
28957 | ||
28958 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
28959 | { | |
28960 | free_node(*expr_gen.node_allocator_,branch[1]); | |
28961 | ||
28962 | return expr_gen(T(0)); | |
28963 | } | |
28964 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
28965 | { | |
28966 | free_node(*expr_gen.node_allocator_, branch[1]); | |
28967 | ||
28968 | return expr_gen(T(0)); | |
28969 | } | |
28970 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
28971 | return branch[1]; | |
28972 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
28973 | return branch[1]; | |
28974 | ||
28975 | if (details::is_cob_node(branch[1])) | |
28976 | { | |
28977 | // Simplify expressions of the form: | |
28978 | // 1. (1 * (2 * (3 * (4 * (5 * (6 * (7 * (8 * (9 + x))))))))) --> 40320 * (9 + x) | |
28979 | // 2. (1 + (2 + (3 + (4 + (5 + (6 + (7 + (8 + (9 + x))))))))) --> 45 + x | |
28980 | if ( | |
28981 | (operation == details::e_mul) || | |
28982 | (operation == details::e_add) | |
28983 | ) | |
28984 | { | |
28985 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); | |
28986 | ||
28987 | if (operation == cobnode->operation()) | |
28988 | { | |
28989 | switch (operation) | |
28990 | { | |
28991 | case details::e_add : cobnode->set_c(c + cobnode->c()); break; | |
28992 | case details::e_mul : cobnode->set_c(c * cobnode->c()); break; | |
28993 | default : return error_node(); | |
28994 | } | |
28995 | ||
28996 | return cobnode; | |
28997 | } | |
28998 | } | |
28999 | ||
29000 | if (operation == details::e_mul) | |
29001 | { | |
29002 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); | |
29003 | details::operator_type cob_opr = cobnode->operation(); | |
29004 | ||
29005 | if ( | |
29006 | (details::e_div == cob_opr) || | |
29007 | (details::e_mul == cob_opr) | |
29008 | ) | |
29009 | { | |
29010 | switch (cob_opr) | |
29011 | { | |
29012 | case details::e_div : cobnode->set_c(c * cobnode->c()); break; | |
29013 | case details::e_mul : cobnode->set_c(cobnode->c() / c); break; | |
29014 | default : return error_node(); | |
29015 | } | |
29016 | ||
29017 | return cobnode; | |
29018 | } | |
29019 | } | |
29020 | else if (operation == details::e_div) | |
29021 | { | |
29022 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); | |
29023 | details::operator_type cob_opr = cobnode->operation(); | |
29024 | ||
29025 | if ( | |
29026 | (details::e_div == cob_opr) || | |
29027 | (details::e_mul == cob_opr) | |
29028 | ) | |
29029 | { | |
29030 | details::expression_node<Type>* new_cobnode = error_node(); | |
29031 | ||
29032 | switch (cob_opr) | |
29033 | { | |
29034 | case details::e_div : new_cobnode = expr_gen.node_allocator_-> | |
29035 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > | |
29036 | (c / cobnode->c(), cobnode->move_branch(0)); | |
29037 | break; | |
29038 | ||
29039 | case details::e_mul : new_cobnode = expr_gen.node_allocator_-> | |
29040 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > | |
29041 | (c / cobnode->c(), cobnode->move_branch(0)); | |
29042 | break; | |
29043 | ||
29044 | default : return error_node(); | |
29045 | } | |
29046 | ||
29047 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29048 | ||
29049 | return new_cobnode; | |
29050 | } | |
29051 | } | |
29052 | } | |
29053 | #ifndef exprtk_disable_enhanced_features | |
29054 | else if (details::is_sf3ext_node(branch[1])) | |
29055 | { | |
29056 | expression_node_ptr result = error_node(); | |
29057 | ||
29058 | const bool synthesis_result = | |
29059 | synthesize_sf4ext_expression::template compile_right<ctype> | |
29060 | (expr_gen, c, operation, branch[1], result); | |
29061 | ||
29062 | if (synthesis_result) | |
29063 | { | |
29064 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29065 | ||
29066 | return result; | |
29067 | } | |
29068 | } | |
29069 | #endif | |
29070 | ||
29071 | switch (operation) | |
29072 | { | |
29073 | #define case_stmt(op0,op1) \ | |
29074 | case op0 : return expr_gen.node_allocator_-> \ | |
29075 | template allocate_tt<typename details::cob_node<Type,op1<Type> > > \ | |
29076 | (c, branch[1]); \ | |
29077 | ||
29078 | basic_opr_switch_statements | |
29079 | extended_opr_switch_statements | |
29080 | #undef case_stmt | |
29081 | default : return error_node(); | |
29082 | } | |
29083 | } | |
29084 | }; | |
29085 | ||
29086 | struct synthesize_boc_expression | |
29087 | { | |
29088 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29089 | const details::operator_type& operation, | |
29090 | expression_node_ptr (&branch)[2]) | |
29091 | { | |
29092 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
29093 | ||
29094 | details::free_node(*(expr_gen.node_allocator_), branch[1]); | |
29095 | ||
29096 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
29097 | { | |
29098 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29099 | ||
29100 | return expr_gen(T(0)); | |
29101 | } | |
29102 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
29103 | { | |
29104 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29105 | ||
29106 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); | |
29107 | } | |
29108 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
29109 | return branch[0]; | |
29110 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
29111 | return branch[0]; | |
29112 | ||
29113 | if (details::is_boc_node(branch[0])) | |
29114 | { | |
29115 | // Simplify expressions of the form: | |
29116 | // 1. (((((((((x + 9) * 8) * 7) * 6) * 5) * 4) * 3) * 2) * 1) --> (x + 9) * 40320 | |
29117 | // 2. (((((((((x + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) --> x + 45 | |
29118 | if ( | |
29119 | (operation == details::e_mul) || | |
29120 | (operation == details::e_add) | |
29121 | ) | |
29122 | { | |
29123 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); | |
29124 | ||
29125 | if (operation == bocnode->operation()) | |
29126 | { | |
29127 | switch (operation) | |
29128 | { | |
29129 | case details::e_add : bocnode->set_c(c + bocnode->c()); break; | |
29130 | case details::e_mul : bocnode->set_c(c * bocnode->c()); break; | |
29131 | default : return error_node(); | |
29132 | } | |
29133 | ||
29134 | return bocnode; | |
29135 | } | |
29136 | } | |
29137 | else if (operation == details::e_div) | |
29138 | { | |
29139 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); | |
29140 | details::operator_type boc_opr = bocnode->operation(); | |
29141 | ||
29142 | if ( | |
29143 | (details::e_div == boc_opr) || | |
29144 | (details::e_mul == boc_opr) | |
29145 | ) | |
29146 | { | |
29147 | switch (boc_opr) | |
29148 | { | |
29149 | case details::e_div : bocnode->set_c(c * bocnode->c()); break; | |
29150 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; | |
29151 | default : return error_node(); | |
29152 | } | |
29153 | ||
29154 | return bocnode; | |
29155 | } | |
29156 | } | |
29157 | else if (operation == details::e_pow) | |
29158 | { | |
29159 | // (v ^ c0) ^ c1 --> v ^(c0 * c1) | |
29160 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); | |
29161 | details::operator_type boc_opr = bocnode->operation(); | |
29162 | ||
29163 | if (details::e_pow == boc_opr) | |
29164 | { | |
29165 | bocnode->set_c(bocnode->c() * c); | |
29166 | ||
29167 | return bocnode; | |
29168 | } | |
29169 | } | |
29170 | } | |
29171 | ||
29172 | #ifndef exprtk_disable_enhanced_features | |
29173 | if (details::is_sf3ext_node(branch[0])) | |
29174 | { | |
29175 | expression_node_ptr result = error_node(); | |
29176 | ||
29177 | const bool synthesis_result = | |
29178 | synthesize_sf4ext_expression::template compile_left<ctype> | |
29179 | (expr_gen, c, operation, branch[0], result); | |
29180 | ||
29181 | if (synthesis_result) | |
29182 | { | |
29183 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29184 | ||
29185 | return result; | |
29186 | } | |
29187 | } | |
29188 | #endif | |
29189 | ||
29190 | switch (operation) | |
29191 | { | |
29192 | #define case_stmt(op0,op1) \ | |
29193 | case op0 : return expr_gen.node_allocator_-> \ | |
29194 | template allocate_cr<typename details::boc_node<Type,op1<Type> > > \ | |
29195 | (branch[0], c); \ | |
29196 | ||
29197 | basic_opr_switch_statements | |
29198 | extended_opr_switch_statements | |
29199 | #undef case_stmt | |
29200 | default : return error_node(); | |
29201 | } | |
29202 | } | |
29203 | }; | |
29204 | ||
29205 | struct synthesize_cocob_expression | |
29206 | { | |
29207 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29208 | const details::operator_type& operation, | |
29209 | expression_node_ptr (&branch)[2]) | |
29210 | { | |
29211 | expression_node_ptr result = error_node(); | |
29212 | ||
29213 | // (cob) o c --> cob | |
29214 | if (details::is_cob_node(branch[0])) | |
29215 | { | |
29216 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[0]); | |
29217 | ||
29218 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
29219 | ||
29220 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
29221 | { | |
29222 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29223 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29224 | ||
29225 | return expr_gen(T(0)); | |
29226 | } | |
29227 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
29228 | { | |
29229 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29230 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29231 | ||
29232 | return expr_gen(T(std::numeric_limits<T>::quiet_NaN())); | |
29233 | } | |
29234 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
29235 | { | |
29236 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29237 | ||
29238 | return branch[0]; | |
29239 | } | |
29240 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
29241 | { | |
29242 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29243 | ||
29244 | return branch[0]; | |
29245 | } | |
29246 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) | |
29247 | { | |
29248 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29249 | ||
29250 | return branch[0]; | |
29251 | } | |
29252 | ||
29253 | const bool op_addsub = (details::e_add == cobnode->operation()) || | |
29254 | (details::e_sub == cobnode->operation()) ; | |
29255 | ||
29256 | if (op_addsub) | |
29257 | { | |
29258 | switch (operation) | |
29259 | { | |
29260 | case details::e_add : cobnode->set_c(cobnode->c() + c); break; | |
29261 | case details::e_sub : cobnode->set_c(cobnode->c() - c); break; | |
29262 | default : return error_node(); | |
29263 | } | |
29264 | ||
29265 | result = cobnode; | |
29266 | } | |
29267 | else if (details::e_mul == cobnode->operation()) | |
29268 | { | |
29269 | switch (operation) | |
29270 | { | |
29271 | case details::e_mul : cobnode->set_c(cobnode->c() * c); break; | |
29272 | case details::e_div : cobnode->set_c(cobnode->c() / c); break; | |
29273 | default : return error_node(); | |
29274 | } | |
29275 | ||
29276 | result = cobnode; | |
29277 | } | |
29278 | else if (details::e_div == cobnode->operation()) | |
29279 | { | |
29280 | if (details::e_mul == operation) | |
29281 | { | |
29282 | cobnode->set_c(cobnode->c() * c); | |
29283 | result = cobnode; | |
29284 | } | |
29285 | else if (details::e_div == operation) | |
29286 | { | |
29287 | result = expr_gen.node_allocator_-> | |
29288 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > | |
29289 | (cobnode->c() / c, cobnode->move_branch(0)); | |
29290 | ||
29291 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29292 | } | |
29293 | } | |
29294 | ||
29295 | if (result) | |
29296 | { | |
29297 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29298 | } | |
29299 | } | |
29300 | ||
29301 | // c o (cob) --> cob | |
29302 | else if (details::is_cob_node(branch[1])) | |
29303 | { | |
29304 | details::cob_base_node<Type>* cobnode = static_cast<details::cob_base_node<Type>*>(branch[1]); | |
29305 | ||
29306 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
29307 | ||
29308 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
29309 | { | |
29310 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29311 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29312 | ||
29313 | return expr_gen(T(0)); | |
29314 | } | |
29315 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
29316 | { | |
29317 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29318 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29319 | ||
29320 | return expr_gen(T(0)); | |
29321 | } | |
29322 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
29323 | { | |
29324 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29325 | ||
29326 | return branch[1]; | |
29327 | } | |
29328 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
29329 | { | |
29330 | free_node(*expr_gen.node_allocator_, branch[0]); | |
29331 | ||
29332 | return branch[1]; | |
29333 | } | |
29334 | ||
29335 | if (details::e_add == cobnode->operation()) | |
29336 | { | |
29337 | if (details::e_add == operation) | |
29338 | { | |
29339 | cobnode->set_c(c + cobnode->c()); | |
29340 | result = cobnode; | |
29341 | } | |
29342 | else if (details::e_sub == operation) | |
29343 | { | |
29344 | result = expr_gen.node_allocator_-> | |
29345 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > | |
29346 | (c - cobnode->c(), cobnode->move_branch(0)); | |
29347 | ||
29348 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29349 | } | |
29350 | } | |
29351 | else if (details::e_sub == cobnode->operation()) | |
29352 | { | |
29353 | if (details::e_add == operation) | |
29354 | { | |
29355 | cobnode->set_c(c + cobnode->c()); | |
29356 | result = cobnode; | |
29357 | } | |
29358 | else if (details::e_sub == operation) | |
29359 | { | |
29360 | result = expr_gen.node_allocator_-> | |
29361 | template allocate_tt<typename details::cob_node<Type,details::add_op<Type> > > | |
29362 | (c - cobnode->c(), cobnode->move_branch(0)); | |
29363 | ||
29364 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29365 | } | |
29366 | } | |
29367 | else if (details::e_mul == cobnode->operation()) | |
29368 | { | |
29369 | if (details::e_mul == operation) | |
29370 | { | |
29371 | cobnode->set_c(c * cobnode->c()); | |
29372 | result = cobnode; | |
29373 | } | |
29374 | else if (details::e_div == operation) | |
29375 | { | |
29376 | result = expr_gen.node_allocator_-> | |
29377 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > | |
29378 | (c / cobnode->c(), cobnode->move_branch(0)); | |
29379 | ||
29380 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29381 | } | |
29382 | } | |
29383 | else if (details::e_div == cobnode->operation()) | |
29384 | { | |
29385 | if (details::e_mul == operation) | |
29386 | { | |
29387 | cobnode->set_c(c * cobnode->c()); | |
29388 | result = cobnode; | |
29389 | } | |
29390 | else if (details::e_div == operation) | |
29391 | { | |
29392 | result = expr_gen.node_allocator_-> | |
29393 | template allocate_tt<typename details::cob_node<Type,details::mul_op<Type> > > | |
29394 | (c / cobnode->c(), cobnode->move_branch(0)); | |
29395 | ||
29396 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29397 | } | |
29398 | } | |
29399 | ||
29400 | if (result) | |
29401 | { | |
29402 | free_node(*expr_gen.node_allocator_,branch[0]); | |
29403 | } | |
29404 | } | |
29405 | ||
29406 | return result; | |
29407 | } | |
29408 | }; | |
29409 | ||
29410 | struct synthesize_coboc_expression | |
29411 | { | |
29412 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29413 | const details::operator_type& operation, | |
29414 | expression_node_ptr (&branch)[2]) | |
29415 | { | |
29416 | expression_node_ptr result = error_node(); | |
29417 | ||
29418 | // (boc) o c --> boc | |
29419 | if (details::is_boc_node(branch[0])) | |
29420 | { | |
29421 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[0]); | |
29422 | ||
29423 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
29424 | ||
29425 | if (details::e_add == bocnode->operation()) | |
29426 | { | |
29427 | switch (operation) | |
29428 | { | |
29429 | case details::e_add : bocnode->set_c(bocnode->c() + c); break; | |
29430 | case details::e_sub : bocnode->set_c(bocnode->c() - c); break; | |
29431 | default : return error_node(); | |
29432 | } | |
29433 | ||
29434 | result = bocnode; | |
29435 | } | |
29436 | else if (details::e_mul == bocnode->operation()) | |
29437 | { | |
29438 | switch (operation) | |
29439 | { | |
29440 | case details::e_mul : bocnode->set_c(bocnode->c() * c); break; | |
29441 | case details::e_div : bocnode->set_c(bocnode->c() / c); break; | |
29442 | default : return error_node(); | |
29443 | } | |
29444 | ||
29445 | result = bocnode; | |
29446 | } | |
29447 | else if (details::e_sub == bocnode->operation()) | |
29448 | { | |
29449 | if (details::e_add == operation) | |
29450 | { | |
29451 | result = expr_gen.node_allocator_-> | |
29452 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > | |
29453 | (bocnode->move_branch(0), c - bocnode->c()); | |
29454 | ||
29455 | free_node(*expr_gen.node_allocator_,branch[0]); | |
29456 | } | |
29457 | else if (details::e_sub == operation) | |
29458 | { | |
29459 | bocnode->set_c(bocnode->c() + c); | |
29460 | result = bocnode; | |
29461 | } | |
29462 | } | |
29463 | else if (details::e_div == bocnode->operation()) | |
29464 | { | |
29465 | switch (operation) | |
29466 | { | |
29467 | case details::e_div : bocnode->set_c(bocnode->c() * c); break; | |
29468 | case details::e_mul : bocnode->set_c(bocnode->c() / c); break; | |
29469 | default : return error_node(); | |
29470 | } | |
29471 | ||
29472 | result = bocnode; | |
29473 | } | |
29474 | ||
29475 | if (result) | |
29476 | { | |
29477 | free_node(*expr_gen.node_allocator_, branch[1]); | |
29478 | } | |
29479 | } | |
29480 | ||
29481 | // c o (boc) --> boc | |
29482 | else if (details::is_boc_node(branch[1])) | |
29483 | { | |
29484 | details::boc_base_node<Type>* bocnode = static_cast<details::boc_base_node<Type>*>(branch[1]); | |
29485 | ||
29486 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
29487 | ||
29488 | if (details::e_add == bocnode->operation()) | |
29489 | { | |
29490 | if (details::e_add == operation) | |
29491 | { | |
29492 | bocnode->set_c(c + bocnode->c()); | |
29493 | result = bocnode; | |
29494 | } | |
29495 | else if (details::e_sub == operation) | |
29496 | { | |
29497 | result = expr_gen.node_allocator_-> | |
29498 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > | |
29499 | (c - bocnode->c(), bocnode->move_branch(0)); | |
29500 | ||
29501 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29502 | } | |
29503 | } | |
29504 | else if (details::e_sub == bocnode->operation()) | |
29505 | { | |
29506 | if (details::e_add == operation) | |
29507 | { | |
29508 | result = expr_gen.node_allocator_-> | |
29509 | template allocate_tt<typename details::boc_node<Type,details::add_op<Type> > > | |
29510 | (bocnode->move_branch(0), c - bocnode->c()); | |
29511 | ||
29512 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29513 | } | |
29514 | else if (details::e_sub == operation) | |
29515 | { | |
29516 | result = expr_gen.node_allocator_-> | |
29517 | template allocate_tt<typename details::cob_node<Type,details::sub_op<Type> > > | |
29518 | (c + bocnode->c(), bocnode->move_branch(0)); | |
29519 | ||
29520 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29521 | } | |
29522 | } | |
29523 | else if (details::e_mul == bocnode->operation()) | |
29524 | { | |
29525 | if (details::e_mul == operation) | |
29526 | { | |
29527 | bocnode->set_c(c * bocnode->c()); | |
29528 | result = bocnode; | |
29529 | } | |
29530 | else if (details::e_div == operation) | |
29531 | { | |
29532 | result = expr_gen.node_allocator_-> | |
29533 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > | |
29534 | (c / bocnode->c(), bocnode->move_branch(0)); | |
29535 | ||
29536 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29537 | } | |
29538 | } | |
29539 | else if (details::e_div == bocnode->operation()) | |
29540 | { | |
29541 | if (details::e_mul == operation) | |
29542 | { | |
29543 | bocnode->set_c(bocnode->c() / c); | |
29544 | result = bocnode; | |
29545 | } | |
29546 | else if (details::e_div == operation) | |
29547 | { | |
29548 | result = expr_gen.node_allocator_-> | |
29549 | template allocate_tt<typename details::cob_node<Type,details::div_op<Type> > > | |
29550 | (c * bocnode->c(), bocnode->move_branch(0)); | |
29551 | ||
29552 | free_node(*expr_gen.node_allocator_,branch[1]); | |
29553 | } | |
29554 | } | |
29555 | ||
29556 | if (result) | |
29557 | { | |
29558 | free_node(*expr_gen.node_allocator_,branch[0]); | |
29559 | } | |
29560 | } | |
29561 | ||
29562 | return result; | |
29563 | } | |
29564 | }; | |
29565 | ||
29566 | #ifndef exprtk_disable_enhanced_features | |
29567 | inline bool synthesize_expression(const details::operator_type& operation, | |
29568 | expression_node_ptr (&branch)[2], | |
29569 | expression_node_ptr& result) | |
29570 | { | |
29571 | result = error_node(); | |
29572 | ||
29573 | if (!operation_optimisable(operation)) | |
29574 | return false; | |
29575 | ||
29576 | const std::string node_id = branch_to_id(branch); | |
29577 | ||
29578 | const typename synthesize_map_t::iterator itr = synthesize_map_.find(node_id); | |
29579 | ||
29580 | if (synthesize_map_.end() != itr) | |
29581 | { | |
29582 | result = itr->second((*this), operation, branch); | |
29583 | ||
29584 | return true; | |
29585 | } | |
29586 | else | |
29587 | return false; | |
29588 | } | |
29589 | ||
29590 | struct synthesize_vov_expression | |
29591 | { | |
29592 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29593 | const details::operator_type& operation, | |
29594 | expression_node_ptr (&branch)[2]) | |
29595 | { | |
29596 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
29597 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
29598 | ||
29599 | switch (operation) | |
29600 | { | |
29601 | #define case_stmt(op0,op1) \ | |
29602 | case op0 : return expr_gen.node_allocator_-> \ | |
29603 | template allocate_rr<typename details::vov_node<Type,op1<Type> > > \ | |
29604 | (v1, v2); \ | |
29605 | ||
29606 | basic_opr_switch_statements | |
29607 | extended_opr_switch_statements | |
29608 | #undef case_stmt | |
29609 | default : return error_node(); | |
29610 | } | |
29611 | } | |
29612 | }; | |
29613 | ||
29614 | struct synthesize_cov_expression | |
29615 | { | |
29616 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29617 | const details::operator_type& operation, | |
29618 | expression_node_ptr (&branch)[2]) | |
29619 | { | |
29620 | const Type c = static_cast<details::literal_node<Type>*> (branch[0])->value(); | |
29621 | const Type& v = static_cast<details::variable_node<Type>*>(branch[1])->ref (); | |
29622 | ||
29623 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
29624 | ||
29625 | if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
29626 | return expr_gen(T(0)); | |
29627 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
29628 | return expr_gen(T(0)); | |
29629 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
29630 | return static_cast<details::variable_node<Type>*>(branch[1]); | |
29631 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
29632 | return static_cast<details::variable_node<Type>*>(branch[1]); | |
29633 | ||
29634 | switch (operation) | |
29635 | { | |
29636 | #define case_stmt(op0,op1) \ | |
29637 | case op0 : return expr_gen.node_allocator_-> \ | |
29638 | template allocate_cr<typename details::cov_node<Type,op1<Type> > > \ | |
29639 | (c, v); \ | |
29640 | ||
29641 | basic_opr_switch_statements | |
29642 | extended_opr_switch_statements | |
29643 | #undef case_stmt | |
29644 | default : return error_node(); | |
29645 | } | |
29646 | } | |
29647 | }; | |
29648 | ||
29649 | struct synthesize_voc_expression | |
29650 | { | |
29651 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29652 | const details::operator_type& operation, | |
29653 | expression_node_ptr (&branch)[2]) | |
29654 | { | |
29655 | const Type& v = static_cast<details::variable_node<Type>*>(branch[0])->ref (); | |
29656 | const Type c = static_cast<details::literal_node<Type>*> (branch[1])->value(); | |
29657 | ||
29658 | details::free_node(*(expr_gen.node_allocator_), branch[1]); | |
29659 | ||
29660 | if (expr_gen.cardinal_pow_optimisable(operation,c)) | |
29661 | { | |
29662 | if (std::equal_to<T>()(T(1),c)) | |
29663 | return branch[0]; | |
29664 | else | |
29665 | return expr_gen.cardinal_pow_optimisation(v,c); | |
29666 | } | |
29667 | else if (std::equal_to<T>()(T(0),c) && (details::e_mul == operation)) | |
29668 | return expr_gen(T(0)); | |
29669 | else if (std::equal_to<T>()(T(0),c) && (details::e_div == operation)) | |
29670 | return expr_gen(std::numeric_limits<T>::quiet_NaN()); | |
29671 | else if (std::equal_to<T>()(T(0),c) && (details::e_add == operation)) | |
29672 | return static_cast<details::variable_node<Type>*>(branch[0]); | |
29673 | else if (std::equal_to<T>()(T(1),c) && (details::e_mul == operation)) | |
29674 | return static_cast<details::variable_node<Type>*>(branch[0]); | |
29675 | else if (std::equal_to<T>()(T(1),c) && (details::e_div == operation)) | |
29676 | return static_cast<details::variable_node<Type>*>(branch[0]); | |
29677 | ||
29678 | switch (operation) | |
29679 | { | |
29680 | #define case_stmt(op0,op1) \ | |
29681 | case op0 : return expr_gen.node_allocator_-> \ | |
29682 | template allocate_rc<typename details::voc_node<Type,op1<Type> > > \ | |
29683 | (v, c); \ | |
29684 | ||
29685 | basic_opr_switch_statements | |
29686 | extended_opr_switch_statements | |
29687 | #undef case_stmt | |
29688 | default : return error_node(); | |
29689 | } | |
29690 | } | |
29691 | }; | |
29692 | ||
29693 | struct synthesize_sf3ext_expression | |
29694 | { | |
29695 | template <typename T0, typename T1, typename T2> | |
29696 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29697 | const details::operator_type& sf3opr, | |
29698 | T0 t0, T1 t1, T2 t2) | |
29699 | { | |
29700 | switch (sf3opr) | |
29701 | { | |
29702 | #define case_stmt(op) \ | |
29703 | case details::e_sf##op : return details::T0oT1oT2_sf3ext<T,T0,T1,T2,details::sf##op##_op<Type> >:: \ | |
29704 | allocate(*(expr_gen.node_allocator_), t0, t1, t2); \ | |
29705 | ||
29706 | case_stmt(00) case_stmt(01) case_stmt(02) case_stmt(03) | |
29707 | case_stmt(04) case_stmt(05) case_stmt(06) case_stmt(07) | |
29708 | case_stmt(08) case_stmt(09) case_stmt(10) case_stmt(11) | |
29709 | case_stmt(12) case_stmt(13) case_stmt(14) case_stmt(15) | |
29710 | case_stmt(16) case_stmt(17) case_stmt(18) case_stmt(19) | |
29711 | case_stmt(20) case_stmt(21) case_stmt(22) case_stmt(23) | |
29712 | case_stmt(24) case_stmt(25) case_stmt(26) case_stmt(27) | |
29713 | case_stmt(28) case_stmt(29) case_stmt(30) | |
29714 | #undef case_stmt | |
29715 | default : return error_node(); | |
29716 | } | |
29717 | } | |
29718 | ||
29719 | template <typename T0, typename T1, typename T2> | |
29720 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, | |
29721 | T0 t0, T1 t1, T2 t2, | |
29722 | expression_node_ptr& result) | |
29723 | { | |
29724 | details::operator_type sf3opr; | |
29725 | ||
29726 | if (!expr_gen.sf3_optimisable(id,sf3opr)) | |
29727 | return false; | |
29728 | else | |
29729 | result = synthesize_sf3ext_expression::template process<T0, T1, T2> | |
29730 | (expr_gen, sf3opr, t0, t1, t2); | |
29731 | ||
29732 | return true; | |
29733 | } | |
29734 | }; | |
29735 | ||
29736 | struct synthesize_sf4ext_expression | |
29737 | { | |
29738 | template <typename T0, typename T1, typename T2, typename T3> | |
29739 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29740 | const details::operator_type& sf4opr, | |
29741 | T0 t0, T1 t1, T2 t2, T3 t3) | |
29742 | { | |
29743 | switch (sf4opr) | |
29744 | { | |
29745 | #define case_stmt0(op) \ | |
29746 | case details::e_sf##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sf##op##_op<Type> >:: \ | |
29747 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ | |
29748 | ||
29749 | ||
29750 | #define case_stmt1(op) \ | |
29751 | case details::e_sf4ext##op : return details::T0oT1oT2oT3_sf4ext<Type,T0,T1,T2,T3,details::sfext##op##_op<Type> >:: \ | |
29752 | allocate(*(expr_gen.node_allocator_), t0, t1, t2, t3); \ | |
29753 | ||
29754 | case_stmt0(48) case_stmt0(49) case_stmt0(50) case_stmt0(51) | |
29755 | case_stmt0(52) case_stmt0(53) case_stmt0(54) case_stmt0(55) | |
29756 | case_stmt0(56) case_stmt0(57) case_stmt0(58) case_stmt0(59) | |
29757 | case_stmt0(60) case_stmt0(61) case_stmt0(62) case_stmt0(63) | |
29758 | case_stmt0(64) case_stmt0(65) case_stmt0(66) case_stmt0(67) | |
29759 | case_stmt0(68) case_stmt0(69) case_stmt0(70) case_stmt0(71) | |
29760 | case_stmt0(72) case_stmt0(73) case_stmt0(74) case_stmt0(75) | |
29761 | case_stmt0(76) case_stmt0(77) case_stmt0(78) case_stmt0(79) | |
29762 | case_stmt0(80) case_stmt0(81) case_stmt0(82) case_stmt0(83) | |
29763 | ||
29764 | case_stmt1(00) case_stmt1(01) case_stmt1(02) case_stmt1(03) | |
29765 | case_stmt1(04) case_stmt1(05) case_stmt1(06) case_stmt1(07) | |
29766 | case_stmt1(08) case_stmt1(09) case_stmt1(10) case_stmt1(11) | |
29767 | case_stmt1(12) case_stmt1(13) case_stmt1(14) case_stmt1(15) | |
29768 | case_stmt1(16) case_stmt1(17) case_stmt1(18) case_stmt1(19) | |
29769 | case_stmt1(20) case_stmt1(21) case_stmt1(22) case_stmt1(23) | |
29770 | case_stmt1(24) case_stmt1(25) case_stmt1(26) case_stmt1(27) | |
29771 | case_stmt1(28) case_stmt1(29) case_stmt1(30) case_stmt1(31) | |
29772 | case_stmt1(32) case_stmt1(33) case_stmt1(34) case_stmt1(35) | |
29773 | case_stmt1(36) case_stmt1(37) case_stmt1(38) case_stmt1(39) | |
29774 | case_stmt1(40) case_stmt1(41) case_stmt1(42) case_stmt1(43) | |
29775 | case_stmt1(44) case_stmt1(45) case_stmt1(46) case_stmt1(47) | |
29776 | case_stmt1(48) case_stmt1(49) case_stmt1(50) case_stmt1(51) | |
29777 | case_stmt1(52) case_stmt1(53) case_stmt1(54) case_stmt1(55) | |
29778 | case_stmt1(56) case_stmt1(57) case_stmt1(58) case_stmt1(59) | |
29779 | case_stmt1(60) case_stmt1(61) | |
29780 | ||
29781 | #undef case_stmt0 | |
29782 | #undef case_stmt1 | |
29783 | default : return error_node(); | |
29784 | } | |
29785 | } | |
29786 | ||
29787 | template <typename T0, typename T1, typename T2, typename T3> | |
29788 | static inline bool compile(expression_generator<Type>& expr_gen, const std::string& id, | |
29789 | T0 t0, T1 t1, T2 t2, T3 t3, | |
29790 | expression_node_ptr& result) | |
29791 | { | |
29792 | details::operator_type sf4opr; | |
29793 | ||
29794 | if (!expr_gen.sf4_optimisable(id,sf4opr)) | |
29795 | return false; | |
29796 | else | |
29797 | result = synthesize_sf4ext_expression::template process<T0, T1, T2, T3> | |
29798 | (expr_gen, sf4opr, t0, t1, t2, t3); | |
29799 | ||
29800 | return true; | |
29801 | } | |
29802 | ||
29803 | // T o (sf3ext) | |
29804 | template <typename ExternalType> | |
29805 | static inline bool compile_right(expression_generator<Type>& expr_gen, | |
29806 | ExternalType t, | |
29807 | const details::operator_type& operation, | |
29808 | expression_node_ptr& sf3node, | |
29809 | expression_node_ptr& result) | |
29810 | { | |
29811 | if (!details::is_sf3ext_node(sf3node)) | |
29812 | return false; | |
29813 | ||
29814 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; | |
29815 | ||
29816 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); | |
29817 | const std::string id = "t" + expr_gen.to_str(operation) + "(" + n->type_id() + ")"; | |
29818 | ||
29819 | switch (n->type()) | |
29820 | { | |
29821 | case details::expression_node<Type>::e_covoc : return compile_right_impl | |
29822 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> | |
29823 | (expr_gen, id, t, sf3node, result); | |
29824 | ||
29825 | case details::expression_node<Type>::e_covov : return compile_right_impl | |
29826 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> | |
29827 | (expr_gen, id, t, sf3node, result); | |
29828 | ||
29829 | case details::expression_node<Type>::e_vocov : return compile_right_impl | |
29830 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> | |
29831 | (expr_gen, id, t, sf3node, result); | |
29832 | ||
29833 | case details::expression_node<Type>::e_vovoc : return compile_right_impl | |
29834 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> | |
29835 | (expr_gen, id, t, sf3node, result); | |
29836 | ||
29837 | case details::expression_node<Type>::e_vovov : return compile_right_impl | |
29838 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> | |
29839 | (expr_gen, id, t, sf3node, result); | |
29840 | ||
29841 | default : return false; | |
29842 | } | |
29843 | } | |
29844 | ||
29845 | // (sf3ext) o T | |
29846 | template <typename ExternalType> | |
29847 | static inline bool compile_left(expression_generator<Type>& expr_gen, | |
29848 | ExternalType t, | |
29849 | const details::operator_type& operation, | |
29850 | expression_node_ptr& sf3node, | |
29851 | expression_node_ptr& result) | |
29852 | { | |
29853 | if (!details::is_sf3ext_node(sf3node)) | |
29854 | return false; | |
29855 | ||
29856 | typedef details::T0oT1oT2_base_node<Type>* sf3ext_base_ptr; | |
29857 | ||
29858 | sf3ext_base_ptr n = static_cast<sf3ext_base_ptr>(sf3node); | |
29859 | ||
29860 | const std::string id = "(" + n->type_id() + ")" + expr_gen.to_str(operation) + "t"; | |
29861 | ||
29862 | switch (n->type()) | |
29863 | { | |
29864 | case details::expression_node<Type>::e_covoc : return compile_left_impl | |
29865 | <typename covoc_t::sf3_type_node,ExternalType, ctype, vtype, ctype> | |
29866 | (expr_gen, id, t, sf3node, result); | |
29867 | ||
29868 | case details::expression_node<Type>::e_covov : return compile_left_impl | |
29869 | <typename covov_t::sf3_type_node,ExternalType, ctype, vtype, vtype> | |
29870 | (expr_gen, id, t, sf3node, result); | |
29871 | ||
29872 | case details::expression_node<Type>::e_vocov : return compile_left_impl | |
29873 | <typename vocov_t::sf3_type_node,ExternalType, vtype, ctype, vtype> | |
29874 | (expr_gen, id, t, sf3node, result); | |
29875 | ||
29876 | case details::expression_node<Type>::e_vovoc : return compile_left_impl | |
29877 | <typename vovoc_t::sf3_type_node,ExternalType, vtype, vtype, ctype> | |
29878 | (expr_gen, id, t, sf3node, result); | |
29879 | ||
29880 | case details::expression_node<Type>::e_vovov : return compile_left_impl | |
29881 | <typename vovov_t::sf3_type_node,ExternalType, vtype, vtype, vtype> | |
29882 | (expr_gen, id, t, sf3node, result); | |
29883 | ||
29884 | default : return false; | |
29885 | } | |
29886 | } | |
29887 | ||
29888 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> | |
29889 | static inline bool compile_right_impl(expression_generator<Type>& expr_gen, | |
29890 | const std::string& id, | |
29891 | ExternalType t, | |
29892 | expression_node_ptr& node, | |
29893 | expression_node_ptr& result) | |
29894 | { | |
29895 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); | |
29896 | ||
29897 | if (n) | |
29898 | { | |
29899 | T0 t0 = n->t0(); | |
29900 | T1 t1 = n->t1(); | |
29901 | T2 t2 = n->t2(); | |
29902 | ||
29903 | return synthesize_sf4ext_expression::template compile<ExternalType, T0, T1, T2> | |
29904 | (expr_gen, id, t, t0, t1, t2, result); | |
29905 | } | |
29906 | else | |
29907 | return false; | |
29908 | } | |
29909 | ||
29910 | template <typename SF3TypeNode, typename ExternalType, typename T0, typename T1, typename T2> | |
29911 | static inline bool compile_left_impl(expression_generator<Type>& expr_gen, | |
29912 | const std::string& id, | |
29913 | ExternalType t, | |
29914 | expression_node_ptr& node, | |
29915 | expression_node_ptr& result) | |
29916 | { | |
29917 | SF3TypeNode* n = dynamic_cast<SF3TypeNode*>(node); | |
29918 | ||
29919 | if (n) | |
29920 | { | |
29921 | T0 t0 = n->t0(); | |
29922 | T1 t1 = n->t1(); | |
29923 | T2 t2 = n->t2(); | |
29924 | ||
29925 | return synthesize_sf4ext_expression::template compile<T0, T1, T2, ExternalType> | |
29926 | (expr_gen, id, t0, t1, t2, t, result); | |
29927 | } | |
29928 | else | |
29929 | return false; | |
29930 | } | |
29931 | }; | |
29932 | ||
29933 | struct synthesize_vovov_expression0 | |
29934 | { | |
29935 | typedef typename vovov_t::type0 node_type; | |
29936 | typedef typename vovov_t::sf3_type sf3_type; | |
29937 | ||
29938 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
29939 | const details::operator_type& operation, | |
29940 | expression_node_ptr (&branch)[2]) | |
29941 | { | |
29942 | // (v0 o0 v1) o1 (v2) | |
29943 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); | |
29944 | const Type& v0 = vov->v0(); | |
29945 | const Type& v1 = vov->v1(); | |
29946 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
29947 | const details::operator_type o0 = vov->operation(); | |
29948 | const details::operator_type o1 = operation; | |
29949 | ||
29950 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
29951 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
29952 | ||
29953 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
29954 | ||
29955 | expression_node_ptr result = error_node(); | |
29956 | ||
29957 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
29958 | { | |
29959 | // (v0 / v1) / v2 --> (vovov) v0 / (v1 * v2) | |
29960 | if ((details::e_div == o0) && (details::e_div == o1)) | |
29961 | { | |
29962 | const bool synthesis_result = | |
29963 | synthesize_sf3ext_expression:: | |
29964 | template compile<vtype,vtype,vtype>(expr_gen, "t/(t*t)", v0, v1, v2, result); | |
29965 | ||
29966 | exprtk_debug(("(v0 / v1) / v2 --> (vovov) v0 / (v1 * v2)\n")); | |
29967 | ||
29968 | return (synthesis_result) ? result : error_node(); | |
29969 | } | |
29970 | } | |
29971 | ||
29972 | const bool synthesis_result = | |
29973 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> | |
29974 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); | |
29975 | ||
29976 | if (synthesis_result) | |
29977 | return result; | |
29978 | else if (!expr_gen.valid_operator(o0,f0)) | |
29979 | return error_node(); | |
29980 | else if (!expr_gen.valid_operator(o1,f1)) | |
29981 | return error_node(); | |
29982 | else | |
29983 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); | |
29984 | } | |
29985 | ||
29986 | static inline std::string id(expression_generator<Type>& expr_gen, | |
29987 | const details::operator_type o0, const details::operator_type o1) | |
29988 | { | |
29989 | return details::build_string() | |
29990 | << "(t" << expr_gen.to_str(o0) | |
29991 | << "t)" << expr_gen.to_str(o1) | |
29992 | << "t"; | |
29993 | } | |
29994 | }; | |
29995 | ||
29996 | struct synthesize_vovov_expression1 | |
29997 | { | |
29998 | typedef typename vovov_t::type1 node_type; | |
29999 | typedef typename vovov_t::sf3_type sf3_type; | |
30000 | ||
30001 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30002 | const details::operator_type& operation, | |
30003 | expression_node_ptr (&branch)[2]) | |
30004 | { | |
30005 | // (v0) o0 (v1 o1 v2) | |
30006 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); | |
30007 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
30008 | const Type& v1 = vov->v0(); | |
30009 | const Type& v2 = vov->v1(); | |
30010 | const details::operator_type o0 = operation; | |
30011 | const details::operator_type o1 = vov->operation(); | |
30012 | ||
30013 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30014 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30015 | ||
30016 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30017 | ||
30018 | expression_node_ptr result = error_node(); | |
30019 | ||
30020 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30021 | { | |
30022 | // v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1 | |
30023 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30024 | { | |
30025 | const bool synthesis_result = | |
30026 | synthesize_sf3ext_expression:: | |
30027 | template compile<vtype,vtype,vtype>(expr_gen, "(t*t)/t", v0, v2, v1, result); | |
30028 | ||
30029 | exprtk_debug(("v0 / (v1 / v2) --> (vovov) (v0 * v2) / v1\n")); | |
30030 | ||
30031 | return (synthesis_result) ? result : error_node(); | |
30032 | } | |
30033 | } | |
30034 | ||
30035 | const bool synthesis_result = | |
30036 | synthesize_sf3ext_expression::template compile<vtype, vtype, vtype> | |
30037 | (expr_gen, id(expr_gen, o0, o1), v0, v1, v2, result); | |
30038 | ||
30039 | if (synthesis_result) | |
30040 | return result; | |
30041 | else if (!expr_gen.valid_operator(o0,f0)) | |
30042 | return error_node(); | |
30043 | else if (!expr_gen.valid_operator(o1,f1)) | |
30044 | return error_node(); | |
30045 | else | |
30046 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, f0, f1); | |
30047 | } | |
30048 | ||
30049 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30050 | const details::operator_type o0, const details::operator_type o1) | |
30051 | { | |
30052 | return details::build_string() | |
30053 | << "t" << expr_gen.to_str(o0) | |
30054 | << "(t" << expr_gen.to_str(o1) | |
30055 | << "t)"; | |
30056 | } | |
30057 | }; | |
30058 | ||
30059 | struct synthesize_vovoc_expression0 | |
30060 | { | |
30061 | typedef typename vovoc_t::type0 node_type; | |
30062 | typedef typename vovoc_t::sf3_type sf3_type; | |
30063 | ||
30064 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30065 | const details::operator_type& operation, | |
30066 | expression_node_ptr (&branch)[2]) | |
30067 | { | |
30068 | // (v0 o0 v1) o1 (c) | |
30069 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); | |
30070 | const Type& v0 = vov->v0(); | |
30071 | const Type& v1 = vov->v1(); | |
30072 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
30073 | const details::operator_type o0 = vov->operation(); | |
30074 | const details::operator_type o1 = operation; | |
30075 | ||
30076 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30077 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30078 | ||
30079 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30080 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30081 | ||
30082 | expression_node_ptr result = error_node(); | |
30083 | ||
30084 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30085 | { | |
30086 | // (v0 / v1) / c --> (vovoc) v0 / (v1 * c) | |
30087 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30088 | { | |
30089 | const bool synthesis_result = | |
30090 | synthesize_sf3ext_expression:: | |
30091 | template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); | |
30092 | ||
30093 | exprtk_debug(("(v0 / v1) / c --> (vovoc) v0 / (v1 * c)\n")); | |
30094 | ||
30095 | return (synthesis_result) ? result : error_node(); | |
30096 | } | |
30097 | } | |
30098 | ||
30099 | const bool synthesis_result = | |
30100 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> | |
30101 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); | |
30102 | ||
30103 | if (synthesis_result) | |
30104 | return result; | |
30105 | else if (!expr_gen.valid_operator(o0,f0)) | |
30106 | return error_node(); | |
30107 | else if (!expr_gen.valid_operator(o1,f1)) | |
30108 | return error_node(); | |
30109 | else | |
30110 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); | |
30111 | } | |
30112 | ||
30113 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30114 | const details::operator_type o0, const details::operator_type o1) | |
30115 | { | |
30116 | return details::build_string() | |
30117 | << "(t" << expr_gen.to_str(o0) | |
30118 | << "t)" << expr_gen.to_str(o1) | |
30119 | << "t"; | |
30120 | } | |
30121 | }; | |
30122 | ||
30123 | struct synthesize_vovoc_expression1 | |
30124 | { | |
30125 | typedef typename vovoc_t::type1 node_type; | |
30126 | typedef typename vovoc_t::sf3_type sf3_type; | |
30127 | ||
30128 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30129 | const details::operator_type& operation, | |
30130 | expression_node_ptr (&branch)[2]) | |
30131 | { | |
30132 | // (v0) o0 (v1 o1 c) | |
30133 | const details::voc_base_node<Type>* voc = static_cast<const details::voc_base_node<Type>*>(branch[1]); | |
30134 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
30135 | const Type& v1 = voc->v(); | |
30136 | const Type c = voc->c(); | |
30137 | const details::operator_type o0 = operation; | |
30138 | const details::operator_type o1 = voc->operation(); | |
30139 | ||
30140 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30141 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30142 | ||
30143 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30144 | ||
30145 | expression_node_ptr result = error_node(); | |
30146 | ||
30147 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30148 | { | |
30149 | // v0 / (v1 / c) --> (vocov) (v0 * c) / v1 | |
30150 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30151 | { | |
30152 | const bool synthesis_result = | |
30153 | synthesize_sf3ext_expression:: | |
30154 | template compile<vtype,ctype,vtype>(expr_gen, "(t*t)/t", v0, c, v1, result); | |
30155 | ||
30156 | exprtk_debug(("v0 / (v1 / c) --> (vocov) (v0 * c) / v1\n")); | |
30157 | ||
30158 | return (synthesis_result) ? result : error_node(); | |
30159 | } | |
30160 | } | |
30161 | ||
30162 | const bool synthesis_result = | |
30163 | synthesize_sf3ext_expression::template compile<vtype, vtype, ctype> | |
30164 | (expr_gen, id(expr_gen, o0, o1), v0, v1, c, result); | |
30165 | ||
30166 | if (synthesis_result) | |
30167 | return result; | |
30168 | else if (!expr_gen.valid_operator(o0,f0)) | |
30169 | return error_node(); | |
30170 | else if (!expr_gen.valid_operator(o1,f1)) | |
30171 | return error_node(); | |
30172 | else | |
30173 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, f0, f1); | |
30174 | } | |
30175 | ||
30176 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30177 | const details::operator_type o0, const details::operator_type o1) | |
30178 | { | |
30179 | return details::build_string() | |
30180 | << "t" << expr_gen.to_str(o0) | |
30181 | << "(t" << expr_gen.to_str(o1) | |
30182 | << "t)"; | |
30183 | } | |
30184 | }; | |
30185 | ||
30186 | struct synthesize_vocov_expression0 | |
30187 | { | |
30188 | typedef typename vocov_t::type0 node_type; | |
30189 | typedef typename vocov_t::sf3_type sf3_type; | |
30190 | ||
30191 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30192 | const details::operator_type& operation, | |
30193 | expression_node_ptr (&branch)[2]) | |
30194 | { | |
30195 | // (v0 o0 c) o1 (v1) | |
30196 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); | |
30197 | const Type& v0 = voc->v(); | |
30198 | const Type c = voc->c(); | |
30199 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
30200 | const details::operator_type o0 = voc->operation(); | |
30201 | const details::operator_type o1 = operation; | |
30202 | ||
30203 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30204 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30205 | ||
30206 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30207 | ||
30208 | expression_node_ptr result = error_node(); | |
30209 | ||
30210 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30211 | { | |
30212 | // (v0 / c) / v1 --> (vovoc) v0 / (v1 * c) | |
30213 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30214 | { | |
30215 | const bool synthesis_result = | |
30216 | synthesize_sf3ext_expression:: | |
30217 | template compile<vtype,vtype,ctype>(expr_gen, "t/(t*t)", v0, v1, c, result); | |
30218 | ||
30219 | exprtk_debug(("(v0 / c) / v1 --> (vovoc) v0 / (v1 * c)\n")); | |
30220 | ||
30221 | return (synthesis_result) ? result : error_node(); | |
30222 | } | |
30223 | } | |
30224 | ||
30225 | const bool synthesis_result = | |
30226 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> | |
30227 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); | |
30228 | ||
30229 | if (synthesis_result) | |
30230 | return result; | |
30231 | else if (!expr_gen.valid_operator(o0,f0)) | |
30232 | return error_node(); | |
30233 | else if (!expr_gen.valid_operator(o1,f1)) | |
30234 | return error_node(); | |
30235 | else | |
30236 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); | |
30237 | } | |
30238 | ||
30239 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30240 | const details::operator_type o0, const details::operator_type o1) | |
30241 | { | |
30242 | return details::build_string() | |
30243 | << "(t" << expr_gen.to_str(o0) | |
30244 | << "t)" << expr_gen.to_str(o1) | |
30245 | << "t"; | |
30246 | } | |
30247 | }; | |
30248 | ||
30249 | struct synthesize_vocov_expression1 | |
30250 | { | |
30251 | typedef typename vocov_t::type1 node_type; | |
30252 | typedef typename vocov_t::sf3_type sf3_type; | |
30253 | ||
30254 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30255 | const details::operator_type& operation, | |
30256 | expression_node_ptr (&branch)[2]) | |
30257 | { | |
30258 | // (v0) o0 (c o1 v1) | |
30259 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); | |
30260 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
30261 | const Type c = cov->c(); | |
30262 | const Type& v1 = cov->v(); | |
30263 | const details::operator_type o0 = operation; | |
30264 | const details::operator_type o1 = cov->operation(); | |
30265 | ||
30266 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30267 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30268 | ||
30269 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30270 | ||
30271 | expression_node_ptr result = error_node(); | |
30272 | ||
30273 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30274 | { | |
30275 | // v0 / (c / v1) --> (vovoc) (v0 * v1) / c | |
30276 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30277 | { | |
30278 | const bool synthesis_result = | |
30279 | synthesize_sf3ext_expression:: | |
30280 | template compile<vtype, vtype, ctype>(expr_gen, "(t*t)/t", v0, v1, c, result); | |
30281 | ||
30282 | exprtk_debug(("v0 / (c / v1) --> (vovoc) (v0 * v1) / c\n")); | |
30283 | ||
30284 | return (synthesis_result) ? result : error_node(); | |
30285 | } | |
30286 | } | |
30287 | ||
30288 | const bool synthesis_result = | |
30289 | synthesize_sf3ext_expression::template compile<vtype, ctype, vtype> | |
30290 | (expr_gen, id(expr_gen, o0, o1), v0, c, v1, result); | |
30291 | ||
30292 | if (synthesis_result) | |
30293 | return result; | |
30294 | else if (!expr_gen.valid_operator(o0,f0)) | |
30295 | return error_node(); | |
30296 | else if (!expr_gen.valid_operator(o1,f1)) | |
30297 | return error_node(); | |
30298 | else | |
30299 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, f0, f1); | |
30300 | } | |
30301 | ||
30302 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30303 | const details::operator_type o0, const details::operator_type o1) | |
30304 | { | |
30305 | return details::build_string() | |
30306 | << "t" << expr_gen.to_str(o0) | |
30307 | << "(t" << expr_gen.to_str(o1) | |
30308 | << "t)"; | |
30309 | } | |
30310 | }; | |
30311 | ||
30312 | struct synthesize_covov_expression0 | |
30313 | { | |
30314 | typedef typename covov_t::type0 node_type; | |
30315 | typedef typename covov_t::sf3_type sf3_type; | |
30316 | ||
30317 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30318 | const details::operator_type& operation, | |
30319 | expression_node_ptr (&branch)[2]) | |
30320 | { | |
30321 | // (c o0 v0) o1 (v1) | |
30322 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); | |
30323 | const Type c = cov->c(); | |
30324 | const Type& v0 = cov->v(); | |
30325 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
30326 | const details::operator_type o0 = cov->operation(); | |
30327 | const details::operator_type o1 = operation; | |
30328 | ||
30329 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30330 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30331 | ||
30332 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30333 | ||
30334 | expression_node_ptr result = error_node(); | |
30335 | ||
30336 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30337 | { | |
30338 | // (c / v0) / v1 --> (covov) c / (v0 * v1) | |
30339 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30340 | { | |
30341 | const bool synthesis_result = | |
30342 | synthesize_sf3ext_expression:: | |
30343 | template compile<ctype, vtype, vtype>(expr_gen, "t/(t*t)", c, v0, v1, result); | |
30344 | ||
30345 | exprtk_debug(("(c / v0) / v1 --> (covov) c / (v0 * v1)\n")); | |
30346 | ||
30347 | return (synthesis_result) ? result : error_node(); | |
30348 | } | |
30349 | } | |
30350 | ||
30351 | const bool synthesis_result = | |
30352 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> | |
30353 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); | |
30354 | ||
30355 | if (synthesis_result) | |
30356 | return result; | |
30357 | else if (!expr_gen.valid_operator(o0,f0)) | |
30358 | return error_node(); | |
30359 | else if (!expr_gen.valid_operator(o1,f1)) | |
30360 | return error_node(); | |
30361 | else | |
30362 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); | |
30363 | } | |
30364 | ||
30365 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30366 | const details::operator_type o0, const details::operator_type o1) | |
30367 | { | |
30368 | return details::build_string() | |
30369 | << "(t" << expr_gen.to_str(o0) | |
30370 | << "t)" << expr_gen.to_str(o1) | |
30371 | << "t"; | |
30372 | } | |
30373 | }; | |
30374 | ||
30375 | struct synthesize_covov_expression1 | |
30376 | { | |
30377 | typedef typename covov_t::type1 node_type; | |
30378 | typedef typename covov_t::sf3_type sf3_type; | |
30379 | ||
30380 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30381 | const details::operator_type& operation, | |
30382 | expression_node_ptr (&branch)[2]) | |
30383 | { | |
30384 | // (c) o0 (v0 o1 v1) | |
30385 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); | |
30386 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
30387 | const Type& v0 = vov->v0(); | |
30388 | const Type& v1 = vov->v1(); | |
30389 | const details::operator_type o0 = operation; | |
30390 | const details::operator_type o1 = vov->operation(); | |
30391 | ||
30392 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30393 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30394 | ||
30395 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30396 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30397 | ||
30398 | expression_node_ptr result = error_node(); | |
30399 | ||
30400 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30401 | { | |
30402 | // c / (v0 / v1) --> (covov) (c * v1) / v0 | |
30403 | if ((details::e_div == o0) && (details::e_div == o1)) | |
30404 | { | |
30405 | const bool synthesis_result = | |
30406 | synthesize_sf3ext_expression:: | |
30407 | template compile<ctype, vtype, vtype>(expr_gen, "(t*t)/t", c, v1, v0, result); | |
30408 | ||
30409 | exprtk_debug(("c / (v0 / v1) --> (covov) (c * v1) / v0\n")); | |
30410 | ||
30411 | return (synthesis_result) ? result : error_node(); | |
30412 | } | |
30413 | } | |
30414 | ||
30415 | const bool synthesis_result = | |
30416 | synthesize_sf3ext_expression::template compile<ctype, vtype, vtype> | |
30417 | (expr_gen, id(expr_gen, o0, o1), c, v0, v1, result); | |
30418 | ||
30419 | if (synthesis_result) | |
30420 | return result; | |
30421 | else if (!expr_gen.valid_operator(o0,f0)) | |
30422 | return error_node(); | |
30423 | else if (!expr_gen.valid_operator(o1,f1)) | |
30424 | return error_node(); | |
30425 | else | |
30426 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, f0, f1); | |
30427 | } | |
30428 | ||
30429 | static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1) | |
30430 | { | |
30431 | return details::build_string() | |
30432 | << "t" << expr_gen.to_str(o0) | |
30433 | << "(t" << expr_gen.to_str(o1) | |
30434 | << "t)"; | |
30435 | } | |
30436 | }; | |
30437 | ||
30438 | struct synthesize_covoc_expression0 | |
30439 | { | |
30440 | typedef typename covoc_t::type0 node_type; | |
30441 | typedef typename covoc_t::sf3_type sf3_type; | |
30442 | ||
30443 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30444 | const details::operator_type& operation, | |
30445 | expression_node_ptr (&branch)[2]) | |
30446 | { | |
30447 | // (c0 o0 v) o1 (c1) | |
30448 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); | |
30449 | const Type c0 = cov->c(); | |
30450 | const Type& v = cov->v(); | |
30451 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
30452 | const details::operator_type o0 = cov->operation(); | |
30453 | const details::operator_type o1 = operation; | |
30454 | ||
30455 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30456 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30457 | ||
30458 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30459 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30460 | ||
30461 | expression_node_ptr result = error_node(); | |
30462 | ||
30463 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30464 | { | |
30465 | // (c0 + v) + c1 --> (cov) (c0 + c1) + v | |
30466 | if ((details::e_add == o0) && (details::e_add == o1)) | |
30467 | { | |
30468 | exprtk_debug(("(c0 + v) + c1 --> (cov) (c0 + c1) + v\n")); | |
30469 | ||
30470 | return expr_gen.node_allocator_-> | |
30471 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); | |
30472 | } | |
30473 | // (c0 + v) - c1 --> (cov) (c0 - c1) + v | |
30474 | else if ((details::e_add == o0) && (details::e_sub == o1)) | |
30475 | { | |
30476 | exprtk_debug(("(c0 + v) - c1 --> (cov) (c0 - c1) + v\n")); | |
30477 | ||
30478 | return expr_gen.node_allocator_-> | |
30479 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); | |
30480 | } | |
30481 | // (c0 - v) + c1 --> (cov) (c0 + c1) - v | |
30482 | else if ((details::e_sub == o0) && (details::e_add == o1)) | |
30483 | { | |
30484 | exprtk_debug(("(c0 - v) + c1 --> (cov) (c0 + c1) - v\n")); | |
30485 | ||
30486 | return expr_gen.node_allocator_-> | |
30487 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); | |
30488 | } | |
30489 | // (c0 - v) - c1 --> (cov) (c0 - c1) - v | |
30490 | else if ((details::e_sub == o0) && (details::e_sub == o1)) | |
30491 | { | |
30492 | exprtk_debug(("(c0 - v) - c1 --> (cov) (c0 - c1) - v\n")); | |
30493 | ||
30494 | return expr_gen.node_allocator_-> | |
30495 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); | |
30496 | } | |
30497 | // (c0 * v) * c1 --> (cov) (c0 * c1) * v | |
30498 | else if ((details::e_mul == o0) && (details::e_mul == o1)) | |
30499 | { | |
30500 | exprtk_debug(("(c0 * v) * c1 --> (cov) (c0 * c1) * v\n")); | |
30501 | ||
30502 | return expr_gen.node_allocator_-> | |
30503 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); | |
30504 | } | |
30505 | // (c0 * v) / c1 --> (cov) (c0 / c1) * v | |
30506 | else if ((details::e_mul == o0) && (details::e_div == o1)) | |
30507 | { | |
30508 | exprtk_debug(("(c0 * v) / c1 --> (cov) (c0 / c1) * v\n")); | |
30509 | ||
30510 | return expr_gen.node_allocator_-> | |
30511 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); | |
30512 | } | |
30513 | // (c0 / v) * c1 --> (cov) (c0 * c1) / v | |
30514 | else if ((details::e_div == o0) && (details::e_mul == o1)) | |
30515 | { | |
30516 | exprtk_debug(("(c0 / v) * c1 --> (cov) (c0 * c1) / v\n")); | |
30517 | ||
30518 | return expr_gen.node_allocator_-> | |
30519 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); | |
30520 | } | |
30521 | // (c0 / v) / c1 --> (cov) (c0 / c1) / v | |
30522 | else if ((details::e_div == o0) && (details::e_div == o1)) | |
30523 | { | |
30524 | exprtk_debug(("(c0 / v) / c1 --> (cov) (c0 / c1) / v\n")); | |
30525 | ||
30526 | return expr_gen.node_allocator_-> | |
30527 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); | |
30528 | } | |
30529 | } | |
30530 | ||
30531 | const bool synthesis_result = | |
30532 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> | |
30533 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); | |
30534 | ||
30535 | if (synthesis_result) | |
30536 | return result; | |
30537 | else if (!expr_gen.valid_operator(o0,f0)) | |
30538 | return error_node(); | |
30539 | else if (!expr_gen.valid_operator(o1,f1)) | |
30540 | return error_node(); | |
30541 | else | |
30542 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); | |
30543 | } | |
30544 | ||
30545 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30546 | const details::operator_type o0, const details::operator_type o1) | |
30547 | { | |
30548 | return details::build_string() | |
30549 | << "(t" << expr_gen.to_str(o0) | |
30550 | << "t)" << expr_gen.to_str(o1) | |
30551 | << "t"; | |
30552 | } | |
30553 | }; | |
30554 | ||
30555 | struct synthesize_covoc_expression1 | |
30556 | { | |
30557 | typedef typename covoc_t::type1 node_type; | |
30558 | typedef typename covoc_t::sf3_type sf3_type; | |
30559 | ||
30560 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30561 | const details::operator_type& operation, | |
30562 | expression_node_ptr (&branch)[2]) | |
30563 | { | |
30564 | // (c0) o0 (v o1 c1) | |
30565 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); | |
30566 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
30567 | const Type& v = voc->v(); | |
30568 | const Type c1 = voc->c(); | |
30569 | const details::operator_type o0 = operation; | |
30570 | const details::operator_type o1 = voc->operation(); | |
30571 | ||
30572 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30573 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30574 | ||
30575 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30576 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30577 | ||
30578 | expression_node_ptr result = error_node(); | |
30579 | ||
30580 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30581 | { | |
30582 | // (c0) + (v + c1) --> (cov) (c0 + c1) + v | |
30583 | if ((details::e_add == o0) && (details::e_add == o1)) | |
30584 | { | |
30585 | exprtk_debug(("(c0) + (v + c1) --> (cov) (c0 + c1) + v\n")); | |
30586 | ||
30587 | return expr_gen.node_allocator_-> | |
30588 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); | |
30589 | } | |
30590 | // (c0) + (v - c1) --> (cov) (c0 - c1) + v | |
30591 | else if ((details::e_add == o0) && (details::e_sub == o1)) | |
30592 | { | |
30593 | exprtk_debug(("(c0) + (v - c1) --> (cov) (c0 - c1) + v\n")); | |
30594 | ||
30595 | return expr_gen.node_allocator_-> | |
30596 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); | |
30597 | } | |
30598 | // (c0) - (v + c1) --> (cov) (c0 - c1) - v | |
30599 | else if ((details::e_sub == o0) && (details::e_add == o1)) | |
30600 | { | |
30601 | exprtk_debug(("(c0) - (v + c1) --> (cov) (c0 - c1) - v\n")); | |
30602 | ||
30603 | return expr_gen.node_allocator_-> | |
30604 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); | |
30605 | } | |
30606 | // (c0) - (v - c1) --> (cov) (c0 + c1) - v | |
30607 | else if ((details::e_sub == o0) && (details::e_sub == o1)) | |
30608 | { | |
30609 | exprtk_debug(("(c0) - (v - c1) --> (cov) (c0 + c1) - v\n")); | |
30610 | ||
30611 | return expr_gen.node_allocator_-> | |
30612 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); | |
30613 | } | |
30614 | // (c0) * (v * c1) --> (voc) v * (c0 * c1) | |
30615 | else if ((details::e_mul == o0) && (details::e_mul == o1)) | |
30616 | { | |
30617 | exprtk_debug(("(c0) * (v * c1) --> (voc) v * (c0 * c1)\n")); | |
30618 | ||
30619 | return expr_gen.node_allocator_-> | |
30620 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); | |
30621 | } | |
30622 | // (c0) * (v / c1) --> (cov) (c0 / c1) * v | |
30623 | else if ((details::e_mul == o0) && (details::e_div == o1)) | |
30624 | { | |
30625 | exprtk_debug(("(c0) * (v / c1) --> (cov) (c0 / c1) * v\n")); | |
30626 | ||
30627 | return expr_gen.node_allocator_-> | |
30628 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); | |
30629 | } | |
30630 | // (c0) / (v * c1) --> (cov) (c0 / c1) / v | |
30631 | else if ((details::e_div == o0) && (details::e_mul == o1)) | |
30632 | { | |
30633 | exprtk_debug(("(c0) / (v * c1) --> (cov) (c0 / c1) / v\n")); | |
30634 | ||
30635 | return expr_gen.node_allocator_-> | |
30636 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); | |
30637 | } | |
30638 | // (c0) / (v / c1) --> (cov) (c0 * c1) / v | |
30639 | else if ((details::e_div == o0) && (details::e_div == o1)) | |
30640 | { | |
30641 | exprtk_debug(("(c0) / (v / c1) --> (cov) (c0 * c1) / v\n")); | |
30642 | ||
30643 | return expr_gen.node_allocator_-> | |
30644 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); | |
30645 | } | |
30646 | } | |
30647 | ||
30648 | const bool synthesis_result = | |
30649 | synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> | |
30650 | (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); | |
30651 | ||
30652 | if (synthesis_result) | |
30653 | return result; | |
30654 | else if (!expr_gen.valid_operator(o0,f0)) | |
30655 | return error_node(); | |
30656 | else if (!expr_gen.valid_operator(o1,f1)) | |
30657 | return error_node(); | |
30658 | else | |
30659 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v, c1, f0, f1); | |
30660 | } | |
30661 | ||
30662 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30663 | const details::operator_type o0, const details::operator_type o1) | |
30664 | { | |
30665 | return details::build_string() | |
30666 | << "t" << expr_gen.to_str(o0) | |
30667 | << "(t" << expr_gen.to_str(o1) | |
30668 | << "t)"; | |
30669 | } | |
30670 | }; | |
30671 | ||
30672 | struct synthesize_cocov_expression0 | |
30673 | { | |
30674 | typedef typename cocov_t::type0 node_type; | |
30675 | static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) | |
30676 | { | |
30677 | // (c0 o0 c1) o1 (v) - Not possible. | |
30678 | return error_node(); | |
30679 | } | |
30680 | }; | |
30681 | ||
30682 | struct synthesize_cocov_expression1 | |
30683 | { | |
30684 | typedef typename cocov_t::type1 node_type; | |
30685 | typedef typename cocov_t::sf3_type sf3_type; | |
30686 | ||
30687 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30688 | const details::operator_type& operation, | |
30689 | expression_node_ptr (&branch)[2]) | |
30690 | { | |
30691 | // (c0) o0 (c1 o1 v) | |
30692 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); | |
30693 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
30694 | const Type c1 = cov->c(); | |
30695 | const Type& v = cov->v(); | |
30696 | const details::operator_type o0 = operation; | |
30697 | const details::operator_type o1 = cov->operation(); | |
30698 | ||
30699 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30700 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30701 | ||
30702 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30703 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30704 | ||
30705 | expression_node_ptr result = error_node(); | |
30706 | ||
30707 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30708 | { | |
30709 | // (c0) + (c1 + v) --> (cov) (c0 + c1) + v | |
30710 | if ((details::e_add == o0) && (details::e_add == o1)) | |
30711 | { | |
30712 | exprtk_debug(("(c0) + (c1 + v) --> (cov) (c0 + c1) + v\n")); | |
30713 | ||
30714 | return expr_gen.node_allocator_-> | |
30715 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 + c1, v); | |
30716 | } | |
30717 | // (c0) + (c1 - v) --> (cov) (c0 + c1) - v | |
30718 | else if ((details::e_add == o0) && (details::e_sub == o1)) | |
30719 | { | |
30720 | exprtk_debug(("(c0) + (c1 - v) --> (cov) (c0 + c1) - v\n")); | |
30721 | ||
30722 | return expr_gen.node_allocator_-> | |
30723 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 + c1, v); | |
30724 | } | |
30725 | // (c0) - (c1 + v) --> (cov) (c0 - c1) - v | |
30726 | else if ((details::e_sub == o0) && (details::e_add == o1)) | |
30727 | { | |
30728 | exprtk_debug(("(c0) - (c1 + v) --> (cov) (c0 - c1) - v\n")); | |
30729 | ||
30730 | return expr_gen.node_allocator_-> | |
30731 | template allocate_cr<typename details::cov_node<Type,details::sub_op<Type> > >(c0 - c1, v); | |
30732 | } | |
30733 | // (c0) - (c1 - v) --> (cov) (c0 - c1) + v | |
30734 | else if ((details::e_sub == o0) && (details::e_sub == o1)) | |
30735 | { | |
30736 | exprtk_debug(("(c0) - (c1 - v) --> (cov) (c0 - c1) + v\n")); | |
30737 | ||
30738 | return expr_gen.node_allocator_-> | |
30739 | template allocate_cr<typename details::cov_node<Type,details::add_op<Type> > >(c0 - c1, v); | |
30740 | } | |
30741 | // (c0) * (c1 * v) --> (cov) (c0 * c1) * v | |
30742 | else if ((details::e_mul == o0) && (details::e_mul == o1)) | |
30743 | { | |
30744 | exprtk_debug(("(c0) * (c1 * v) --> (cov) (c0 * c1) * v\n")); | |
30745 | ||
30746 | return expr_gen.node_allocator_-> | |
30747 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 * c1, v); | |
30748 | } | |
30749 | // (c0) * (c1 / v) --> (cov) (c0 * c1) / v | |
30750 | else if ((details::e_mul == o0) && (details::e_div == o1)) | |
30751 | { | |
30752 | exprtk_debug(("(c0) * (c1 / v) --> (cov) (c0 * c1) / v\n")); | |
30753 | ||
30754 | return expr_gen.node_allocator_-> | |
30755 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 * c1, v); | |
30756 | } | |
30757 | // (c0) / (c1 * v) --> (cov) (c0 / c1) / v | |
30758 | else if ((details::e_div == o0) && (details::e_mul == o1)) | |
30759 | { | |
30760 | exprtk_debug(("(c0) / (c1 * v) --> (cov) (c0 / c1) / v\n")); | |
30761 | ||
30762 | return expr_gen.node_allocator_-> | |
30763 | template allocate_cr<typename details::cov_node<Type,details::div_op<Type> > >(c0 / c1, v); | |
30764 | } | |
30765 | // (c0) / (c1 / v) --> (cov) (c0 / c1) * v | |
30766 | else if ((details::e_div == o0) && (details::e_div == o1)) | |
30767 | { | |
30768 | exprtk_debug(("(c0) / (c1 / v) --> (cov) (c0 / c1) * v\n")); | |
30769 | ||
30770 | return expr_gen.node_allocator_-> | |
30771 | template allocate_cr<typename details::cov_node<Type,details::mul_op<Type> > >(c0 / c1, v); | |
30772 | } | |
30773 | } | |
30774 | ||
30775 | const bool synthesis_result = | |
30776 | synthesize_sf3ext_expression::template compile<ctype, ctype, vtype> | |
30777 | (expr_gen, id(expr_gen, o0, o1), c0, c1, v, result); | |
30778 | ||
30779 | if (synthesis_result) | |
30780 | return result; | |
30781 | else if (!expr_gen.valid_operator(o0,f0)) | |
30782 | return error_node(); | |
30783 | else if (!expr_gen.valid_operator(o1,f1)) | |
30784 | return error_node(); | |
30785 | else | |
30786 | return node_type::allocate(*(expr_gen.node_allocator_), c0, c1, v, f0, f1); | |
30787 | } | |
30788 | ||
30789 | static inline std::string id(expression_generator<Type>& expr_gen, const details::operator_type o0, const details::operator_type o1) | |
30790 | { | |
30791 | return details::build_string() | |
30792 | << "t" << expr_gen.to_str(o0) | |
30793 | << "(t" << expr_gen.to_str(o1) | |
30794 | << "t)"; | |
30795 | } | |
30796 | }; | |
30797 | ||
30798 | struct synthesize_vococ_expression0 | |
30799 | { | |
30800 | typedef typename vococ_t::type0 node_type; | |
30801 | typedef typename vococ_t::sf3_type sf3_type; | |
30802 | ||
30803 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30804 | const details::operator_type& operation, | |
30805 | expression_node_ptr (&branch)[2]) | |
30806 | { | |
30807 | // (v o0 c0) o1 (c1) | |
30808 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); | |
30809 | const Type& v = voc->v(); | |
30810 | const Type& c0 = voc->c(); | |
30811 | const Type& c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
30812 | const details::operator_type o0 = voc->operation(); | |
30813 | const details::operator_type o1 = operation; | |
30814 | ||
30815 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30816 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30817 | ||
30818 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30819 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30820 | ||
30821 | expression_node_ptr result = error_node(); | |
30822 | ||
30823 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30824 | { | |
30825 | // (v + c0) + c1 --> (voc) v + (c0 + c1) | |
30826 | if ((details::e_add == o0) && (details::e_add == o1)) | |
30827 | { | |
30828 | exprtk_debug(("(v + c0) + c1 --> (voc) v + (c0 + c1)\n")); | |
30829 | ||
30830 | return expr_gen.node_allocator_-> | |
30831 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 + c1); | |
30832 | } | |
30833 | // (v + c0) - c1 --> (voc) v + (c0 - c1) | |
30834 | else if ((details::e_add == o0) && (details::e_sub == o1)) | |
30835 | { | |
30836 | exprtk_debug(("(v + c0) - c1 --> (voc) v + (c0 - c1)\n")); | |
30837 | ||
30838 | return expr_gen.node_allocator_-> | |
30839 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c0 - c1); | |
30840 | } | |
30841 | // (v - c0) + c1 --> (voc) v - (c0 + c1) | |
30842 | else if ((details::e_sub == o0) && (details::e_add == o1)) | |
30843 | { | |
30844 | exprtk_debug(("(v - c0) + c1 --> (voc) v - (c0 + c1)\n")); | |
30845 | ||
30846 | return expr_gen.node_allocator_-> | |
30847 | template allocate_rc<typename details::voc_node<Type,details::add_op<Type> > >(v, c1 - c0); | |
30848 | } | |
30849 | // (v - c0) - c1 --> (voc) v - (c0 + c1) | |
30850 | else if ((details::e_sub == o0) && (details::e_sub == o1)) | |
30851 | { | |
30852 | exprtk_debug(("(v - c0) - c1 --> (voc) v - (c0 + c1)\n")); | |
30853 | ||
30854 | return expr_gen.node_allocator_-> | |
30855 | template allocate_rc<typename details::voc_node<Type,details::sub_op<Type> > >(v, c0 + c1); | |
30856 | } | |
30857 | // (v * c0) * c1 --> (voc) v * (c0 * c1) | |
30858 | else if ((details::e_mul == o0) && (details::e_mul == o1)) | |
30859 | { | |
30860 | exprtk_debug(("(v * c0) * c1 --> (voc) v * (c0 * c1)\n")); | |
30861 | ||
30862 | return expr_gen.node_allocator_-> | |
30863 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 * c1); | |
30864 | } | |
30865 | // (v * c0) / c1 --> (voc) v * (c0 / c1) | |
30866 | else if ((details::e_mul == o0) && (details::e_div == o1)) | |
30867 | { | |
30868 | exprtk_debug(("(v * c0) / c1 --> (voc) v * (c0 / c1)\n")); | |
30869 | ||
30870 | return expr_gen.node_allocator_-> | |
30871 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c0 / c1); | |
30872 | } | |
30873 | // (v / c0) * c1 --> (voc) v * (c1 / c0) | |
30874 | else if ((details::e_div == o0) && (details::e_mul == o1)) | |
30875 | { | |
30876 | exprtk_debug(("(v / c0) * c1 --> (voc) v * (c1 / c0)\n")); | |
30877 | ||
30878 | return expr_gen.node_allocator_-> | |
30879 | template allocate_rc<typename details::voc_node<Type,details::mul_op<Type> > >(v, c1 / c0); | |
30880 | } | |
30881 | // (v / c0) / c1 --> (voc) v / (c0 * c1) | |
30882 | else if ((details::e_div == o0) && (details::e_div == o1)) | |
30883 | { | |
30884 | exprtk_debug(("(v / c0) / c1 --> (voc) v / (c0 * c1)\n")); | |
30885 | ||
30886 | return expr_gen.node_allocator_-> | |
30887 | template allocate_rc<typename details::voc_node<Type,details::div_op<Type> > >(v, c0 * c1); | |
30888 | } | |
30889 | // (v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1) | |
30890 | else if ((details::e_pow == o0) && (details::e_pow == o1)) | |
30891 | { | |
30892 | exprtk_debug(("(v ^ c0) ^ c1 --> (voc) v ^ (c0 * c1)\n")); | |
30893 | ||
30894 | return expr_gen.node_allocator_-> | |
30895 | template allocate_rc<typename details::voc_node<Type,details::pow_op<Type> > >(v, c0 * c1); | |
30896 | } | |
30897 | } | |
30898 | ||
30899 | const bool synthesis_result = | |
30900 | synthesize_sf3ext_expression::template compile<vtype, ctype, ctype> | |
30901 | (expr_gen, id(expr_gen, o0, o1), v, c0, c1, result); | |
30902 | ||
30903 | if (synthesis_result) | |
30904 | return result; | |
30905 | else if (!expr_gen.valid_operator(o0,f0)) | |
30906 | return error_node(); | |
30907 | else if (!expr_gen.valid_operator(o1,f1)) | |
30908 | return error_node(); | |
30909 | else | |
30910 | return node_type::allocate(*(expr_gen.node_allocator_), v, c0, c1, f0, f1); | |
30911 | } | |
30912 | ||
30913 | static inline std::string id(expression_generator<Type>& expr_gen, | |
30914 | const details::operator_type o0, const details::operator_type o1) | |
30915 | { | |
30916 | return details::build_string() | |
30917 | << "(t" << expr_gen.to_str(o0) | |
30918 | << "t)" << expr_gen.to_str(o1) | |
30919 | << "t"; | |
30920 | } | |
30921 | }; | |
30922 | ||
30923 | struct synthesize_vococ_expression1 | |
30924 | { | |
30925 | typedef typename vococ_t::type0 node_type; | |
30926 | ||
30927 | static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) | |
30928 | { | |
30929 | // (v) o0 (c0 o1 c1) - Not possible. | |
30930 | exprtk_debug(("(v) o0 (c0 o1 c1) - Not possible.\n")); | |
30931 | return error_node(); | |
30932 | } | |
30933 | }; | |
30934 | ||
30935 | struct synthesize_vovovov_expression0 | |
30936 | { | |
30937 | typedef typename vovovov_t::type0 node_type; | |
30938 | typedef typename vovovov_t::sf4_type sf4_type; | |
30939 | typedef typename node_type::T0 T0; | |
30940 | typedef typename node_type::T1 T1; | |
30941 | typedef typename node_type::T2 T2; | |
30942 | typedef typename node_type::T3 T3; | |
30943 | ||
30944 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
30945 | const details::operator_type& operation, | |
30946 | expression_node_ptr (&branch)[2]) | |
30947 | { | |
30948 | // (v0 o0 v1) o1 (v2 o2 v3) | |
30949 | const details::vov_base_node<Type>* vov0 = static_cast<details::vov_base_node<Type>*>(branch[0]); | |
30950 | const details::vov_base_node<Type>* vov1 = static_cast<details::vov_base_node<Type>*>(branch[1]); | |
30951 | const Type& v0 = vov0->v0(); | |
30952 | const Type& v1 = vov0->v1(); | |
30953 | const Type& v2 = vov1->v0(); | |
30954 | const Type& v3 = vov1->v1(); | |
30955 | const details::operator_type o0 = vov0->operation(); | |
30956 | const details::operator_type o1 = operation; | |
30957 | const details::operator_type o2 = vov1->operation(); | |
30958 | ||
30959 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
30960 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
30961 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
30962 | ||
30963 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
30964 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
30965 | ||
30966 | expression_node_ptr result = error_node(); | |
30967 | ||
30968 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
30969 | { | |
30970 | // (v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3) | |
30971 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
30972 | { | |
30973 | const bool synthesis_result = | |
30974 | synthesize_sf4ext_expression:: | |
30975 | template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, v3, result); | |
30976 | ||
30977 | exprtk_debug(("(v0 / v1) * (v2 / v3) --> (vovovov) (v0 * v2) / (v1 * v3)\n")); | |
30978 | ||
30979 | return (synthesis_result) ? result : error_node(); | |
30980 | } | |
30981 | // (v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2) | |
30982 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
30983 | { | |
30984 | const bool synthesis_result = | |
30985 | synthesize_sf4ext_expression:: | |
30986 | template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v3, v1, v2, result); | |
30987 | ||
30988 | exprtk_debug(("(v0 / v1) / (v2 / v3) --> (vovovov) (v0 * v3) / (v1 * v2)\n")); | |
30989 | ||
30990 | return (synthesis_result) ? result : error_node(); | |
30991 | } | |
30992 | // (v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) | |
30993 | else if ((details::e_add == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
30994 | { | |
30995 | const bool synthesis_result = | |
30996 | synthesize_sf4ext_expression:: | |
30997 | template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t+t)*(t/t)", v0, v1, v3, v2, result); | |
30998 | ||
30999 | exprtk_debug(("(v0 + v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2)\n")); | |
31000 | ||
31001 | return (synthesis_result) ? result : error_node(); | |
31002 | } | |
31003 | // (v0 - v1) / (v2 / v3) --> (vovovov) (v0 + v1) * (v3 / v2) | |
31004 | else if ((details::e_sub == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31005 | { | |
31006 | const bool synthesis_result = | |
31007 | synthesize_sf4ext_expression:: | |
31008 | template compile<vtype,vtype,vtype,vtype>(expr_gen, "(t-t)*(t/t)", v0, v1, v3, v2, result); | |
31009 | ||
31010 | exprtk_debug(("(v0 - v1) / (v2 / v3) --> (vovovov) (v0 - v1) * (v3 / v2)\n")); | |
31011 | ||
31012 | return (synthesis_result) ? result : error_node(); | |
31013 | } | |
31014 | // (v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2 | |
31015 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31016 | { | |
31017 | const bool synthesis_result = | |
31018 | synthesize_sf4ext_expression:: | |
31019 | template compile<vtype,vtype,vtype,vtype>(expr_gen, "((t*t)*t)/t", v0, v1, v3, v2, result); | |
31020 | ||
31021 | exprtk_debug(("(v0 * v1) / (v2 / v3) --> (vovovov) ((v0 * v1) * v3) / v2\n")); | |
31022 | ||
31023 | return (synthesis_result) ? result : error_node(); | |
31024 | } | |
31025 | } | |
31026 | ||
31027 | const bool synthesis_result = | |
31028 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31029 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); | |
31030 | ||
31031 | if (synthesis_result) | |
31032 | return result; | |
31033 | else if (!expr_gen.valid_operator(o0,f0)) | |
31034 | return error_node(); | |
31035 | else if (!expr_gen.valid_operator(o1,f1)) | |
31036 | return error_node(); | |
31037 | else if (!expr_gen.valid_operator(o2,f2)) | |
31038 | return error_node(); | |
31039 | else | |
31040 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); | |
31041 | } | |
31042 | ||
31043 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31044 | const details::operator_type o0, | |
31045 | const details::operator_type o1, | |
31046 | const details::operator_type o2) | |
31047 | { | |
31048 | return details::build_string() | |
31049 | << "(t" << expr_gen.to_str(o0) | |
31050 | << "t)" << expr_gen.to_str(o1) | |
31051 | << "(t" << expr_gen.to_str(o2) | |
31052 | << "t)"; | |
31053 | } | |
31054 | }; | |
31055 | ||
31056 | struct synthesize_vovovoc_expression0 | |
31057 | { | |
31058 | typedef typename vovovoc_t::type0 node_type; | |
31059 | typedef typename vovovoc_t::sf4_type sf4_type; | |
31060 | typedef typename node_type::T0 T0; | |
31061 | typedef typename node_type::T1 T1; | |
31062 | typedef typename node_type::T2 T2; | |
31063 | typedef typename node_type::T3 T3; | |
31064 | ||
31065 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31066 | const details::operator_type& operation, | |
31067 | expression_node_ptr (&branch)[2]) | |
31068 | { | |
31069 | // (v0 o0 v1) o1 (v2 o2 c) | |
31070 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); | |
31071 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); | |
31072 | const Type& v0 = vov->v0(); | |
31073 | const Type& v1 = vov->v1(); | |
31074 | const Type& v2 = voc->v (); | |
31075 | const Type c = voc->c (); | |
31076 | const details::operator_type o0 = vov->operation(); | |
31077 | const details::operator_type o1 = operation; | |
31078 | const details::operator_type o2 = voc->operation(); | |
31079 | ||
31080 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31081 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31082 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31083 | ||
31084 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31085 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31086 | ||
31087 | expression_node_ptr result = error_node(); | |
31088 | ||
31089 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31090 | { | |
31091 | // (v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c) | |
31092 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31093 | { | |
31094 | const bool synthesis_result = | |
31095 | synthesize_sf4ext_expression:: | |
31096 | template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); | |
31097 | ||
31098 | exprtk_debug(("(v0 / v1) * (v2 / c) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); | |
31099 | ||
31100 | return (synthesis_result) ? result : error_node(); | |
31101 | } | |
31102 | // (v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2) | |
31103 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31104 | { | |
31105 | const bool synthesis_result = | |
31106 | synthesize_sf4ext_expression:: | |
31107 | template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); | |
31108 | ||
31109 | exprtk_debug(("(v0 / v1) / (v2 / c) --> (vocovov) (v0 * c) / (v1 * v2)\n")); | |
31110 | ||
31111 | return (synthesis_result) ? result : error_node(); | |
31112 | } | |
31113 | } | |
31114 | ||
31115 | const bool synthesis_result = | |
31116 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31117 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); | |
31118 | ||
31119 | if (synthesis_result) | |
31120 | return result; | |
31121 | else if (!expr_gen.valid_operator(o0,f0)) | |
31122 | return error_node(); | |
31123 | else if (!expr_gen.valid_operator(o1,f1)) | |
31124 | return error_node(); | |
31125 | else if (!expr_gen.valid_operator(o2,f2)) | |
31126 | return error_node(); | |
31127 | else | |
31128 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); | |
31129 | } | |
31130 | ||
31131 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31132 | const details::operator_type o0, | |
31133 | const details::operator_type o1, | |
31134 | const details::operator_type o2) | |
31135 | { | |
31136 | return details::build_string() | |
31137 | << "(t" << expr_gen.to_str(o0) | |
31138 | << "t)" << expr_gen.to_str(o1) | |
31139 | << "(t" << expr_gen.to_str(o2) | |
31140 | << "t)"; | |
31141 | } | |
31142 | }; | |
31143 | ||
31144 | struct synthesize_vovocov_expression0 | |
31145 | { | |
31146 | typedef typename vovocov_t::type0 node_type; | |
31147 | typedef typename vovocov_t::sf4_type sf4_type; | |
31148 | typedef typename node_type::T0 T0; | |
31149 | typedef typename node_type::T1 T1; | |
31150 | typedef typename node_type::T2 T2; | |
31151 | typedef typename node_type::T3 T3; | |
31152 | ||
31153 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31154 | const details::operator_type& operation, | |
31155 | expression_node_ptr (&branch)[2]) | |
31156 | { | |
31157 | // (v0 o0 v1) o1 (c o2 v2) | |
31158 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[0]); | |
31159 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); | |
31160 | const Type& v0 = vov->v0(); | |
31161 | const Type& v1 = vov->v1(); | |
31162 | const Type& v2 = cov->v (); | |
31163 | const Type c = cov->c (); | |
31164 | const details::operator_type o0 = vov->operation(); | |
31165 | const details::operator_type o1 = operation; | |
31166 | const details::operator_type o2 = cov->operation(); | |
31167 | ||
31168 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31169 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31170 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31171 | ||
31172 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31173 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31174 | ||
31175 | expression_node_ptr result = error_node(); | |
31176 | ||
31177 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31178 | { | |
31179 | // (v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2) | |
31180 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31181 | { | |
31182 | const bool synthesis_result = | |
31183 | synthesize_sf4ext_expression:: | |
31184 | template compile<vtype,ctype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", v0, c, v1, v2, result); | |
31185 | ||
31186 | exprtk_debug(("(v0 / v1) * (c / v2) --> (vocovov) (v0 * c) / (v1 * v2)\n")); | |
31187 | ||
31188 | return (synthesis_result) ? result : error_node(); | |
31189 | } | |
31190 | // (v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c) | |
31191 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31192 | { | |
31193 | const bool synthesis_result = | |
31194 | synthesize_sf4ext_expression:: | |
31195 | template compile<vtype,vtype,vtype,ctype>(expr_gen, "(t*t)/(t*t)", v0, v2, v1, c, result); | |
31196 | ||
31197 | exprtk_debug(("(v0 / v1) / (c / v2) --> (vovovoc) (v0 * v2) / (v1 * c)\n")); | |
31198 | ||
31199 | return (synthesis_result) ? result : error_node(); | |
31200 | } | |
31201 | } | |
31202 | ||
31203 | const bool synthesis_result = | |
31204 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31205 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); | |
31206 | ||
31207 | if (synthesis_result) | |
31208 | return result; | |
31209 | else if (!expr_gen.valid_operator(o0,f0)) | |
31210 | return error_node(); | |
31211 | else if (!expr_gen.valid_operator(o1,f1)) | |
31212 | return error_node(); | |
31213 | else if (!expr_gen.valid_operator(o2,f2)) | |
31214 | return error_node(); | |
31215 | else | |
31216 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); | |
31217 | } | |
31218 | ||
31219 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31220 | const details::operator_type o0, | |
31221 | const details::operator_type o1, | |
31222 | const details::operator_type o2) | |
31223 | { | |
31224 | return details::build_string() | |
31225 | << "(t" << expr_gen.to_str(o0) | |
31226 | << "t)" << expr_gen.to_str(o1) | |
31227 | << "(t" << expr_gen.to_str(o2) | |
31228 | << "t)"; | |
31229 | } | |
31230 | }; | |
31231 | ||
31232 | struct synthesize_vocovov_expression0 | |
31233 | { | |
31234 | typedef typename vocovov_t::type0 node_type; | |
31235 | typedef typename vocovov_t::sf4_type sf4_type; | |
31236 | typedef typename node_type::T0 T0; | |
31237 | typedef typename node_type::T1 T1; | |
31238 | typedef typename node_type::T2 T2; | |
31239 | typedef typename node_type::T3 T3; | |
31240 | ||
31241 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31242 | const details::operator_type& operation, | |
31243 | expression_node_ptr (&branch)[2]) | |
31244 | { | |
31245 | // (v0 o0 c) o1 (v1 o2 v2) | |
31246 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); | |
31247 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); | |
31248 | const Type c = voc->c (); | |
31249 | const Type& v0 = voc->v (); | |
31250 | const Type& v1 = vov->v0(); | |
31251 | const Type& v2 = vov->v1(); | |
31252 | const details::operator_type o0 = voc->operation(); | |
31253 | const details::operator_type o1 = operation; | |
31254 | const details::operator_type o2 = vov->operation(); | |
31255 | ||
31256 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31257 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31258 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31259 | ||
31260 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31261 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31262 | ||
31263 | expression_node_ptr result = error_node(); | |
31264 | ||
31265 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31266 | { | |
31267 | // (v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2) | |
31268 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31269 | { | |
31270 | const bool synthesis_result = | |
31271 | synthesize_sf4ext_expression:: | |
31272 | template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v1, c, v2, result); | |
31273 | ||
31274 | exprtk_debug(("(v0 / c) * (v1 / v2) --> (vovocov) (v0 * v1) / (c * v2)\n")); | |
31275 | ||
31276 | return (synthesis_result) ? result : error_node(); | |
31277 | } | |
31278 | // (v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1) | |
31279 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31280 | { | |
31281 | const bool synthesis_result = | |
31282 | synthesize_sf4ext_expression:: | |
31283 | template compile<vtype,vtype,ctype,vtype>(expr_gen, "(t*t)/(t*t)", v0, v2, c, v1, result); | |
31284 | ||
31285 | exprtk_debug(("(v0 / c) / (v1 / v2) --> (vovocov) (v0 * v2) / (c * v1)\n")); | |
31286 | ||
31287 | return (synthesis_result) ? result : error_node(); | |
31288 | } | |
31289 | } | |
31290 | ||
31291 | const bool synthesis_result = | |
31292 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31293 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); | |
31294 | ||
31295 | if (synthesis_result) | |
31296 | return result; | |
31297 | else if (!expr_gen.valid_operator(o0,f0)) | |
31298 | return error_node(); | |
31299 | else if (!expr_gen.valid_operator(o1,f1)) | |
31300 | return error_node(); | |
31301 | else if (!expr_gen.valid_operator(o2,f2)) | |
31302 | return error_node(); | |
31303 | else | |
31304 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); | |
31305 | } | |
31306 | ||
31307 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31308 | const details::operator_type o0, | |
31309 | const details::operator_type o1, | |
31310 | const details::operator_type o2) | |
31311 | { | |
31312 | return details::build_string() | |
31313 | << "(t" << expr_gen.to_str(o0) | |
31314 | << "t)" << expr_gen.to_str(o1) | |
31315 | << "(t" << expr_gen.to_str(o2) | |
31316 | << "t)"; | |
31317 | } | |
31318 | }; | |
31319 | ||
31320 | struct synthesize_covovov_expression0 | |
31321 | { | |
31322 | typedef typename covovov_t::type0 node_type; | |
31323 | typedef typename covovov_t::sf4_type sf4_type; | |
31324 | typedef typename node_type::T0 T0; | |
31325 | typedef typename node_type::T1 T1; | |
31326 | typedef typename node_type::T2 T2; | |
31327 | typedef typename node_type::T3 T3; | |
31328 | ||
31329 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31330 | const details::operator_type& operation, | |
31331 | expression_node_ptr (&branch)[2]) | |
31332 | { | |
31333 | // (c o0 v0) o1 (v1 o2 v2) | |
31334 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); | |
31335 | const details::vov_base_node<Type>* vov = static_cast<details::vov_base_node<Type>*>(branch[1]); | |
31336 | const Type c = cov->c (); | |
31337 | const Type& v0 = cov->v (); | |
31338 | const Type& v1 = vov->v0(); | |
31339 | const Type& v2 = vov->v1(); | |
31340 | const details::operator_type o0 = cov->operation(); | |
31341 | const details::operator_type o1 = operation; | |
31342 | const details::operator_type o2 = vov->operation(); | |
31343 | ||
31344 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31345 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31346 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31347 | ||
31348 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31349 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31350 | ||
31351 | expression_node_ptr result = error_node(); | |
31352 | ||
31353 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31354 | { | |
31355 | // (c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2) | |
31356 | if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31357 | { | |
31358 | const bool synthesis_result = | |
31359 | synthesize_sf4ext_expression:: | |
31360 | template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v1, v0, v2, result); | |
31361 | ||
31362 | exprtk_debug(("(c / v0) * (v1 / v2) --> (covovov) (c * v1) / (v0 * v2)\n")); | |
31363 | ||
31364 | return (synthesis_result) ? result : error_node(); | |
31365 | } | |
31366 | // (c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1) | |
31367 | if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31368 | { | |
31369 | const bool synthesis_result = | |
31370 | synthesize_sf4ext_expression:: | |
31371 | template compile<ctype,vtype,vtype,vtype>(expr_gen, "(t*t)/(t*t)", c, v2, v0, v1, result); | |
31372 | ||
31373 | exprtk_debug(("(c / v0) / (v1 / v2) --> (covovov) (c * v2) / (v0 * v1)\n")); | |
31374 | ||
31375 | return (synthesis_result) ? result : error_node(); | |
31376 | } | |
31377 | } | |
31378 | ||
31379 | const bool synthesis_result = | |
31380 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31381 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); | |
31382 | ||
31383 | if (synthesis_result) | |
31384 | return result; | |
31385 | else if (!expr_gen.valid_operator(o0,f0)) | |
31386 | return error_node(); | |
31387 | else if (!expr_gen.valid_operator(o1,f1)) | |
31388 | return error_node(); | |
31389 | else if (!expr_gen.valid_operator(o2,f2)) | |
31390 | return error_node(); | |
31391 | else | |
31392 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); | |
31393 | } | |
31394 | ||
31395 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31396 | const details::operator_type o0, | |
31397 | const details::operator_type o1, | |
31398 | const details::operator_type o2) | |
31399 | { | |
31400 | return details::build_string() | |
31401 | << "(t" << expr_gen.to_str(o0) | |
31402 | << "t)" << expr_gen.to_str(o1) | |
31403 | << "(t" << expr_gen.to_str(o2) | |
31404 | << "t)"; | |
31405 | } | |
31406 | }; | |
31407 | ||
31408 | struct synthesize_covocov_expression0 | |
31409 | { | |
31410 | typedef typename covocov_t::type0 node_type; | |
31411 | typedef typename covocov_t::sf4_type sf4_type; | |
31412 | typedef typename node_type::T0 T0; | |
31413 | typedef typename node_type::T1 T1; | |
31414 | typedef typename node_type::T2 T2; | |
31415 | typedef typename node_type::T3 T3; | |
31416 | ||
31417 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31418 | const details::operator_type& operation, | |
31419 | expression_node_ptr (&branch)[2]) | |
31420 | { | |
31421 | // (c0 o0 v0) o1 (c1 o2 v1) | |
31422 | const details::cov_base_node<Type>* cov0 = static_cast<details::cov_base_node<Type>*>(branch[0]); | |
31423 | const details::cov_base_node<Type>* cov1 = static_cast<details::cov_base_node<Type>*>(branch[1]); | |
31424 | const Type c0 = cov0->c(); | |
31425 | const Type& v0 = cov0->v(); | |
31426 | const Type c1 = cov1->c(); | |
31427 | const Type& v1 = cov1->v(); | |
31428 | const details::operator_type o0 = cov0->operation(); | |
31429 | const details::operator_type o1 = operation; | |
31430 | const details::operator_type o2 = cov1->operation(); | |
31431 | ||
31432 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31433 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31434 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31435 | ||
31436 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31437 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31438 | ||
31439 | expression_node_ptr result = error_node(); | |
31440 | ||
31441 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31442 | { | |
31443 | // (c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 | |
31444 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) | |
31445 | { | |
31446 | const bool synthesis_result = | |
31447 | synthesize_sf3ext_expression:: | |
31448 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); | |
31449 | ||
31450 | exprtk_debug(("(c0 + v0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); | |
31451 | ||
31452 | return (synthesis_result) ? result : error_node(); | |
31453 | } | |
31454 | // (c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 | |
31455 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) | |
31456 | { | |
31457 | const bool synthesis_result = | |
31458 | synthesize_sf3ext_expression:: | |
31459 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); | |
31460 | ||
31461 | exprtk_debug(("(c0 + v0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); | |
31462 | ||
31463 | return (synthesis_result) ? result : error_node(); | |
31464 | } | |
31465 | // (c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1 | |
31466 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) | |
31467 | { | |
31468 | const bool synthesis_result = | |
31469 | synthesize_sf3ext_expression:: | |
31470 | template compile<ctype,vtype,vtype>(expr_gen, "(t-t)+t", (c0 - c1), v0, v1, result); | |
31471 | ||
31472 | exprtk_debug(("(c0 - v0) - (c1 - v1) --> (covov) (c0 - c1) - v0 + v1\n")); | |
31473 | ||
31474 | return (synthesis_result) ? result : error_node(); | |
31475 | } | |
31476 | // (c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 | |
31477 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) | |
31478 | { | |
31479 | const bool synthesis_result = | |
31480 | synthesize_sf3ext_expression:: | |
31481 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); | |
31482 | ||
31483 | exprtk_debug(("(c0 * v0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); | |
31484 | ||
31485 | return (synthesis_result) ? result : error_node(); | |
31486 | } | |
31487 | // (c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1) | |
31488 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31489 | { | |
31490 | const bool synthesis_result = | |
31491 | synthesize_sf3ext_expression:: | |
31492 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); | |
31493 | ||
31494 | exprtk_debug(("(c0 * v0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 / v1)\n")); | |
31495 | ||
31496 | return (synthesis_result) ? result : error_node(); | |
31497 | } | |
31498 | // (c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1) | |
31499 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31500 | { | |
31501 | const bool synthesis_result = | |
31502 | synthesize_sf3ext_expression:: | |
31503 | template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); | |
31504 | ||
31505 | exprtk_debug(("(c0 / v0) * (c1 / v1) --> (covov) (c0 * c1) / (v0 * v1)\n")); | |
31506 | ||
31507 | return (synthesis_result) ? result : error_node(); | |
31508 | } | |
31509 | // (c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0 | |
31510 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31511 | { | |
31512 | const bool synthesis_result = | |
31513 | synthesize_sf3ext_expression:: | |
31514 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v1, v0, result); | |
31515 | ||
31516 | exprtk_debug(("(c0 / v0) / (c1 / v1) --> (covov) ((c0 / c1) * v1) / v0\n")); | |
31517 | ||
31518 | return (synthesis_result) ? result : error_node(); | |
31519 | } | |
31520 | // (c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) | |
31521 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31522 | { | |
31523 | const bool synthesis_result = | |
31524 | synthesize_sf3ext_expression:: | |
31525 | template compile<ctype,vtype,vtype>(expr_gen, "t*(t*t)", (c0 / c1), v0, v1, result); | |
31526 | ||
31527 | exprtk_debug(("(c0 * v0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); | |
31528 | ||
31529 | return (synthesis_result) ? result : error_node(); | |
31530 | } | |
31531 | // (c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1) | |
31532 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31533 | { | |
31534 | const bool synthesis_result = | |
31535 | synthesize_sf3ext_expression:: | |
31536 | template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); | |
31537 | ||
31538 | exprtk_debug(("(c0 / v0) / (c1 * v1) --> (covov) (c0 / c1) / (v0 * v1)\n")); | |
31539 | ||
31540 | return (synthesis_result) ? result : error_node(); | |
31541 | } | |
31542 | // (c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1) | |
31543 | else if ( | |
31544 | (std::equal_to<T>()(c0,c1)) && | |
31545 | (details::e_mul == o0) && | |
31546 | (details::e_mul == o2) && | |
31547 | ( | |
31548 | (details::e_add == o1) || | |
31549 | (details::e_sub == o1) | |
31550 | ) | |
31551 | ) | |
31552 | { | |
31553 | std::string specfunc; | |
31554 | ||
31555 | switch (o1) | |
31556 | { | |
31557 | case details::e_add : specfunc = "t*(t+t)"; break; | |
31558 | case details::e_sub : specfunc = "t*(t-t)"; break; | |
31559 | default : return error_node(); | |
31560 | } | |
31561 | ||
31562 | const bool synthesis_result = | |
31563 | synthesize_sf3ext_expression:: | |
31564 | template compile<ctype, vtype, vtype>(expr_gen, specfunc, c0, v0, v1, result); | |
31565 | ||
31566 | exprtk_debug(("(c * v0) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); | |
31567 | ||
31568 | return (synthesis_result) ? result : error_node(); | |
31569 | } | |
31570 | } | |
31571 | ||
31572 | const bool synthesis_result = | |
31573 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31574 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); | |
31575 | ||
31576 | if (synthesis_result) | |
31577 | return result; | |
31578 | else if (!expr_gen.valid_operator(o0,f0)) | |
31579 | return error_node(); | |
31580 | else if (!expr_gen.valid_operator(o1,f1)) | |
31581 | return error_node(); | |
31582 | else if (!expr_gen.valid_operator(o2,f2)) | |
31583 | return error_node(); | |
31584 | else | |
31585 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); | |
31586 | } | |
31587 | ||
31588 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31589 | const details::operator_type o0, | |
31590 | const details::operator_type o1, | |
31591 | const details::operator_type o2) | |
31592 | { | |
31593 | return details::build_string() | |
31594 | << "(t" << expr_gen.to_str(o0) | |
31595 | << "t)" << expr_gen.to_str(o1) | |
31596 | << "(t" << expr_gen.to_str(o2) | |
31597 | << "t)"; | |
31598 | } | |
31599 | }; | |
31600 | ||
31601 | struct synthesize_vocovoc_expression0 | |
31602 | { | |
31603 | typedef typename vocovoc_t::type0 node_type; | |
31604 | typedef typename vocovoc_t::sf4_type sf4_type; | |
31605 | typedef typename node_type::T0 T0; | |
31606 | typedef typename node_type::T1 T1; | |
31607 | typedef typename node_type::T2 T2; | |
31608 | typedef typename node_type::T3 T3; | |
31609 | ||
31610 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31611 | const details::operator_type& operation, | |
31612 | expression_node_ptr (&branch)[2]) | |
31613 | { | |
31614 | // (v0 o0 c0) o1 (v1 o2 c1) | |
31615 | const details::voc_base_node<Type>* voc0 = static_cast<details::voc_base_node<Type>*>(branch[0]); | |
31616 | const details::voc_base_node<Type>* voc1 = static_cast<details::voc_base_node<Type>*>(branch[1]); | |
31617 | const Type c0 = voc0->c(); | |
31618 | const Type& v0 = voc0->v(); | |
31619 | const Type c1 = voc1->c(); | |
31620 | const Type& v1 = voc1->v(); | |
31621 | const details::operator_type o0 = voc0->operation(); | |
31622 | const details::operator_type o1 = operation; | |
31623 | const details::operator_type o2 = voc1->operation(); | |
31624 | ||
31625 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31626 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31627 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31628 | ||
31629 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31630 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31631 | ||
31632 | expression_node_ptr result = error_node(); | |
31633 | ||
31634 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31635 | { | |
31636 | // (v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 | |
31637 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) | |
31638 | { | |
31639 | const bool synthesis_result = | |
31640 | synthesize_sf3ext_expression:: | |
31641 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); | |
31642 | ||
31643 | exprtk_debug(("(v0 + c0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); | |
31644 | ||
31645 | return (synthesis_result) ? result : error_node(); | |
31646 | } | |
31647 | // (v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 | |
31648 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) | |
31649 | { | |
31650 | const bool synthesis_result = | |
31651 | synthesize_sf3ext_expression:: | |
31652 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); | |
31653 | ||
31654 | exprtk_debug(("(v0 + c0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); | |
31655 | ||
31656 | return (synthesis_result) ? result : error_node(); | |
31657 | } | |
31658 | // (v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1 | |
31659 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) | |
31660 | { | |
31661 | const bool synthesis_result = | |
31662 | synthesize_sf3ext_expression:: | |
31663 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c1 - c0), v0, v1, result); | |
31664 | ||
31665 | exprtk_debug(("(v0 - c0) - (v1 - c1) --> (covov) (c1 - c0) + v0 - v1\n")); | |
31666 | ||
31667 | return (synthesis_result) ? result : error_node(); | |
31668 | } | |
31669 | // (v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 | |
31670 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) | |
31671 | { | |
31672 | const bool synthesis_result = | |
31673 | synthesize_sf3ext_expression:: | |
31674 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); | |
31675 | ||
31676 | exprtk_debug(("(v0 * c0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); | |
31677 | ||
31678 | return (synthesis_result) ? result : error_node(); | |
31679 | } | |
31680 | // (v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) | |
31681 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31682 | { | |
31683 | const bool synthesis_result = | |
31684 | synthesize_sf3ext_expression:: | |
31685 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); | |
31686 | ||
31687 | exprtk_debug(("(v0 * c0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); | |
31688 | ||
31689 | return (synthesis_result) ? result : error_node(); | |
31690 | } | |
31691 | // (v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1 | |
31692 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31693 | { | |
31694 | const bool synthesis_result = | |
31695 | synthesize_sf3ext_expression:: | |
31696 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", Type(1) / (c0 * c1), v0, v1, result); | |
31697 | ||
31698 | exprtk_debug(("(v0 / c0) * (v1 / c1) --> (covov) (1 / (c0 * c1)) * v0 * v1\n")); | |
31699 | ||
31700 | return (synthesis_result) ? result : error_node(); | |
31701 | } | |
31702 | // (v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1 | |
31703 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31704 | { | |
31705 | const bool synthesis_result = | |
31706 | synthesize_sf3ext_expression:: | |
31707 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); | |
31708 | ||
31709 | exprtk_debug(("(v0 / c0) / (v1 / c1) --> (covov) ((c1 / c0) * v0) / v1\n")); | |
31710 | ||
31711 | return (synthesis_result) ? result : error_node(); | |
31712 | } | |
31713 | // (v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) | |
31714 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31715 | { | |
31716 | const bool synthesis_result = | |
31717 | synthesize_sf3ext_expression:: | |
31718 | template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 * c1), v0, v1, result); | |
31719 | ||
31720 | exprtk_debug(("(v0 * c0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); | |
31721 | ||
31722 | return (synthesis_result) ? result : error_node(); | |
31723 | } | |
31724 | // (v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1 | |
31725 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31726 | { | |
31727 | const bool synthesis_result = | |
31728 | synthesize_sf3ext_expression:: | |
31729 | template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", Type(1) / (c0 * c1), v0, v1, result); | |
31730 | ||
31731 | exprtk_debug(("(v0 / c0) / (v1 * c1) --> (covov) (1 / (c0 * c1)) * v0 / v1\n")); | |
31732 | ||
31733 | return (synthesis_result) ? result : error_node(); | |
31734 | } | |
31735 | // (v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1) | |
31736 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_add == o2)) | |
31737 | { | |
31738 | const bool synthesis_result = | |
31739 | synthesize_sf4ext_expression:: | |
31740 | template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t+t)", v0, T(1) / c0, v1, c1, result); | |
31741 | ||
31742 | exprtk_debug(("(v0 / c0) * (v1 + c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 + c1)\n")); | |
31743 | ||
31744 | return (synthesis_result) ? result : error_node(); | |
31745 | } | |
31746 | // (v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1) | |
31747 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_sub == o2)) | |
31748 | { | |
31749 | const bool synthesis_result = | |
31750 | synthesize_sf4ext_expression:: | |
31751 | template compile<vtype,ctype,vtype,ctype>(expr_gen, "(t*t)*(t-t)", v0, T(1) / c0, v1, c1, result); | |
31752 | ||
31753 | exprtk_debug(("(v0 / c0) * (v1 - c1) --> (vocovoc) (v0 * (1 / c0)) * (v1 - c1)\n")); | |
31754 | ||
31755 | return (synthesis_result) ? result : error_node(); | |
31756 | } | |
31757 | // (v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1) | |
31758 | else if ( | |
31759 | (std::equal_to<T>()(c0,c1)) && | |
31760 | (details::e_mul == o0) && | |
31761 | (details::e_mul == o2) && | |
31762 | ( | |
31763 | (details::e_add == o1) || | |
31764 | (details::e_sub == o1) | |
31765 | ) | |
31766 | ) | |
31767 | { | |
31768 | std::string specfunc; | |
31769 | ||
31770 | switch (o1) | |
31771 | { | |
31772 | case details::e_add : specfunc = "t*(t+t)"; break; | |
31773 | case details::e_sub : specfunc = "t*(t-t)"; break; | |
31774 | default : return error_node(); | |
31775 | } | |
31776 | ||
31777 | const bool synthesis_result = | |
31778 | synthesize_sf3ext_expression:: | |
31779 | template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result); | |
31780 | ||
31781 | exprtk_debug(("(v0 * c) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); | |
31782 | ||
31783 | return (synthesis_result) ? result : error_node(); | |
31784 | } | |
31785 | // (v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c | |
31786 | else if ( | |
31787 | (std::equal_to<T>()(c0,c1)) && | |
31788 | (details::e_div == o0) && | |
31789 | (details::e_div == o2) && | |
31790 | ( | |
31791 | (details::e_add == o1) || | |
31792 | (details::e_sub == o1) | |
31793 | ) | |
31794 | ) | |
31795 | { | |
31796 | std::string specfunc; | |
31797 | ||
31798 | switch (o1) | |
31799 | { | |
31800 | case details::e_add : specfunc = "(t+t)/t"; break; | |
31801 | case details::e_sub : specfunc = "(t-t)/t"; break; | |
31802 | default : return error_node(); | |
31803 | } | |
31804 | ||
31805 | const bool synthesis_result = | |
31806 | synthesize_sf3ext_expression:: | |
31807 | template compile<vtype,vtype,ctype>(expr_gen, specfunc, v0, v1, c0, result); | |
31808 | ||
31809 | exprtk_debug(("(v0 / c) +/- (v1 / c) --> (vovoc) (v0 +/- v1) / c\n")); | |
31810 | ||
31811 | return (synthesis_result) ? result : error_node(); | |
31812 | } | |
31813 | } | |
31814 | ||
31815 | const bool synthesis_result = | |
31816 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
31817 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); | |
31818 | ||
31819 | if (synthesis_result) | |
31820 | return result; | |
31821 | else if (!expr_gen.valid_operator(o0,f0)) | |
31822 | return error_node(); | |
31823 | else if (!expr_gen.valid_operator(o1,f1)) | |
31824 | return error_node(); | |
31825 | else if (!expr_gen.valid_operator(o2,f2)) | |
31826 | return error_node(); | |
31827 | else | |
31828 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); | |
31829 | } | |
31830 | ||
31831 | static inline std::string id(expression_generator<Type>& expr_gen, | |
31832 | const details::operator_type o0, | |
31833 | const details::operator_type o1, | |
31834 | const details::operator_type o2) | |
31835 | { | |
31836 | return details::build_string() | |
31837 | << "(t" << expr_gen.to_str(o0) | |
31838 | << "t)" << expr_gen.to_str(o1) | |
31839 | << "(t" << expr_gen.to_str(o2) | |
31840 | << "t)"; | |
31841 | } | |
31842 | }; | |
31843 | ||
31844 | struct synthesize_covovoc_expression0 | |
31845 | { | |
31846 | typedef typename covovoc_t::type0 node_type; | |
31847 | typedef typename covovoc_t::sf4_type sf4_type; | |
31848 | typedef typename node_type::T0 T0; | |
31849 | typedef typename node_type::T1 T1; | |
31850 | typedef typename node_type::T2 T2; | |
31851 | typedef typename node_type::T3 T3; | |
31852 | ||
31853 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
31854 | const details::operator_type& operation, | |
31855 | expression_node_ptr (&branch)[2]) | |
31856 | { | |
31857 | // (c0 o0 v0) o1 (v1 o2 c1) | |
31858 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[0]); | |
31859 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[1]); | |
31860 | const Type c0 = cov->c(); | |
31861 | const Type& v0 = cov->v(); | |
31862 | const Type c1 = voc->c(); | |
31863 | const Type& v1 = voc->v(); | |
31864 | const details::operator_type o0 = cov->operation(); | |
31865 | const details::operator_type o1 = operation; | |
31866 | const details::operator_type o2 = voc->operation(); | |
31867 | ||
31868 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
31869 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
31870 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
31871 | ||
31872 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
31873 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
31874 | ||
31875 | expression_node_ptr result = error_node(); | |
31876 | ||
31877 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
31878 | { | |
31879 | // (c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1 | |
31880 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) | |
31881 | { | |
31882 | const bool synthesis_result = | |
31883 | synthesize_sf3ext_expression:: | |
31884 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); | |
31885 | ||
31886 | exprtk_debug(("(c0 + v0) + (v1 + c1) --> (covov) (c0 + c1) + v0 + v1\n")); | |
31887 | ||
31888 | return (synthesis_result) ? result : error_node(); | |
31889 | } | |
31890 | // (c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1 | |
31891 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) | |
31892 | { | |
31893 | const bool synthesis_result = | |
31894 | synthesize_sf3ext_expression:: | |
31895 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); | |
31896 | ||
31897 | exprtk_debug(("(c0 + v0) - (v1 + c1) --> (covov) (c0 - c1) + v0 - v1\n")); | |
31898 | ||
31899 | return (synthesis_result) ? result : error_node(); | |
31900 | } | |
31901 | // (c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1 | |
31902 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) | |
31903 | { | |
31904 | const bool synthesis_result = | |
31905 | synthesize_sf3ext_expression:: | |
31906 | template compile<ctype,vtype,vtype>(expr_gen, "t-(t+t)", (c0 + c1), v0, v1, result); | |
31907 | ||
31908 | exprtk_debug(("(c0 - v0) - (v1 - c1) --> (covov) (c0 + c1) - v0 - v1\n")); | |
31909 | ||
31910 | return (synthesis_result) ? result : error_node(); | |
31911 | } | |
31912 | // (c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1 | |
31913 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) | |
31914 | { | |
31915 | const bool synthesis_result = | |
31916 | synthesize_sf3ext_expression:: | |
31917 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); | |
31918 | ||
31919 | exprtk_debug(("(c0 * v0) * (v1 * c1) --> (covov) (c0 * c1) * v0 * v1\n")); | |
31920 | ||
31921 | return (synthesis_result) ? result : error_node(); | |
31922 | } | |
31923 | // (c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1) | |
31924 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31925 | { | |
31926 | const bool synthesis_result = | |
31927 | synthesize_sf3ext_expression:: | |
31928 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); | |
31929 | ||
31930 | exprtk_debug(("(c0 * v0) / (v1 * c1) --> (covov) (c0 / c1) * (v0 / v1)\n")); | |
31931 | ||
31932 | return (synthesis_result) ? result : error_node(); | |
31933 | } | |
31934 | // (c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0) | |
31935 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
31936 | { | |
31937 | const bool synthesis_result = | |
31938 | synthesize_sf3ext_expression:: | |
31939 | template compile<ctype,vtype,vtype>(expr_gen, "t*(t/t)", (c0 / c1), v1, v0, result); | |
31940 | ||
31941 | exprtk_debug(("(c0 / v0) * (v1 / c1) --> (covov) (c0 / c1) * (v1 / v0)\n")); | |
31942 | ||
31943 | return (synthesis_result) ? result : error_node(); | |
31944 | } | |
31945 | // (c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1) | |
31946 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31947 | { | |
31948 | const bool synthesis_result = | |
31949 | synthesize_sf3ext_expression:: | |
31950 | template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 * c1), v0, v1, result); | |
31951 | ||
31952 | exprtk_debug(("(c0 / v0) / (v1 / c1) --> (covov) (c0 * c1) / (v0 * v1)\n")); | |
31953 | ||
31954 | return (synthesis_result) ? result : error_node(); | |
31955 | } | |
31956 | // (c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1) | |
31957 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
31958 | { | |
31959 | const bool synthesis_result = | |
31960 | synthesize_sf3ext_expression:: | |
31961 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 * c1), v0, v1, result); | |
31962 | ||
31963 | exprtk_debug(("(c0 * v0) / (v1 / c1) --> (covov) (c0 * c1) * (v0 / v1)\n")); | |
31964 | ||
31965 | return (synthesis_result) ? result : error_node(); | |
31966 | } | |
31967 | // (c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1) | |
31968 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
31969 | { | |
31970 | const bool synthesis_result = | |
31971 | synthesize_sf3ext_expression:: | |
31972 | template compile<ctype,vtype,vtype>(expr_gen, "t/(t*t)", (c0 / c1), v0, v1, result); | |
31973 | ||
31974 | exprtk_debug(("(c0 / v0) / (v1 * c1) --> (covov) (c0 / c1) / (v0 * v1)\n")); | |
31975 | ||
31976 | return (synthesis_result) ? result : error_node(); | |
31977 | } | |
31978 | // (c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1) | |
31979 | else if ( | |
31980 | (std::equal_to<T>()(c0,c1)) && | |
31981 | (details::e_mul == o0) && | |
31982 | (details::e_mul == o2) && | |
31983 | ( | |
31984 | (details::e_add == o1) || | |
31985 | (details::e_sub == o1) | |
31986 | ) | |
31987 | ) | |
31988 | { | |
31989 | std::string specfunc; | |
31990 | ||
31991 | switch (o1) | |
31992 | { | |
31993 | case details::e_add : specfunc = "t*(t+t)"; break; | |
31994 | case details::e_sub : specfunc = "t*(t-t)"; break; | |
31995 | default : return error_node(); | |
31996 | } | |
31997 | ||
31998 | const bool synthesis_result = | |
31999 | synthesize_sf3ext_expression:: | |
32000 | template compile<ctype,vtype,vtype>(expr_gen,specfunc, c0, v0, v1, result); | |
32001 | ||
32002 | exprtk_debug(("(c * v0) +/- (v1 * c) --> (covov) c * (v0 +/- v1)\n")); | |
32003 | ||
32004 | return (synthesis_result) ? result : error_node(); | |
32005 | } | |
32006 | } | |
32007 | ||
32008 | const bool synthesis_result = | |
32009 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32010 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); | |
32011 | ||
32012 | if (synthesis_result) | |
32013 | return result; | |
32014 | else if (!expr_gen.valid_operator(o0,f0)) | |
32015 | return error_node(); | |
32016 | else if (!expr_gen.valid_operator(o1,f1)) | |
32017 | return error_node(); | |
32018 | else if (!expr_gen.valid_operator(o2,f2)) | |
32019 | return error_node(); | |
32020 | else | |
32021 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); | |
32022 | } | |
32023 | ||
32024 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32025 | const details::operator_type o0, | |
32026 | const details::operator_type o1, | |
32027 | const details::operator_type o2) | |
32028 | { | |
32029 | return details::build_string() | |
32030 | << "(t" << expr_gen.to_str(o0) | |
32031 | << "t)" << expr_gen.to_str(o1) | |
32032 | << "(t" << expr_gen.to_str(o2) | |
32033 | << "t)"; | |
32034 | } | |
32035 | }; | |
32036 | ||
32037 | struct synthesize_vococov_expression0 | |
32038 | { | |
32039 | typedef typename vococov_t::type0 node_type; | |
32040 | typedef typename vococov_t::sf4_type sf4_type; | |
32041 | typedef typename node_type::T0 T0; | |
32042 | typedef typename node_type::T1 T1; | |
32043 | typedef typename node_type::T2 T2; | |
32044 | typedef typename node_type::T3 T3; | |
32045 | ||
32046 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32047 | const details::operator_type& operation, | |
32048 | expression_node_ptr (&branch)[2]) | |
32049 | { | |
32050 | // (v0 o0 c0) o1 (c1 o2 v1) | |
32051 | const details::voc_base_node<Type>* voc = static_cast<details::voc_base_node<Type>*>(branch[0]); | |
32052 | const details::cov_base_node<Type>* cov = static_cast<details::cov_base_node<Type>*>(branch[1]); | |
32053 | const Type c0 = voc->c(); | |
32054 | const Type& v0 = voc->v(); | |
32055 | const Type c1 = cov->c(); | |
32056 | const Type& v1 = cov->v(); | |
32057 | const details::operator_type o0 = voc->operation(); | |
32058 | const details::operator_type o1 = operation; | |
32059 | const details::operator_type o2 = cov->operation(); | |
32060 | ||
32061 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32062 | binary_functor_t f1 = reinterpret_cast<binary_functor_t>(0); | |
32063 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
32064 | ||
32065 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
32066 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32067 | ||
32068 | expression_node_ptr result = error_node(); | |
32069 | ||
32070 | if (expr_gen.parser_->settings_.strength_reduction_enabled()) | |
32071 | { | |
32072 | // (v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1 | |
32073 | if ((details::e_add == o0) && (details::e_add == o1) && (details::e_add == o2)) | |
32074 | { | |
32075 | const bool synthesis_result = | |
32076 | synthesize_sf3ext_expression:: | |
32077 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)+t", (c0 + c1), v0, v1, result); | |
32078 | ||
32079 | exprtk_debug(("(v0 + c0) + (c1 + v1) --> (covov) (c0 + c1) + v0 + v1\n")); | |
32080 | ||
32081 | return (synthesis_result) ? result : error_node(); | |
32082 | } | |
32083 | // (v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1 | |
32084 | else if ((details::e_add == o0) && (details::e_sub == o1) && (details::e_add == o2)) | |
32085 | { | |
32086 | const bool synthesis_result = | |
32087 | synthesize_sf3ext_expression:: | |
32088 | template compile<ctype,vtype,vtype>(expr_gen, "(t+t)-t", (c0 - c1), v0, v1, result); | |
32089 | ||
32090 | exprtk_debug(("(v0 + c0) - (c1 + v1) --> (covov) (c0 - c1) + v0 - v1\n")); | |
32091 | ||
32092 | return (synthesis_result) ? result : error_node(); | |
32093 | } | |
32094 | // (v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0) | |
32095 | else if ((details::e_sub == o0) && (details::e_sub == o1) && (details::e_sub == o2)) | |
32096 | { | |
32097 | const bool synthesis_result = | |
32098 | synthesize_sf3ext_expression:: | |
32099 | template compile<vtype,vtype,ctype>(expr_gen, "(t+t)-t", v0, v1, (c1 + c0), result); | |
32100 | ||
32101 | exprtk_debug(("(v0 - c0) - (c1 - v1) --> (vovoc) v0 + v1 - (c1 + c0)\n")); | |
32102 | ||
32103 | return (synthesis_result) ? result : error_node(); | |
32104 | } | |
32105 | // (v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1 | |
32106 | else if ((details::e_mul == o0) && (details::e_mul == o1) && (details::e_mul == o2)) | |
32107 | { | |
32108 | const bool synthesis_result = | |
32109 | synthesize_sf3ext_expression:: | |
32110 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 * c1), v0, v1, result); | |
32111 | ||
32112 | exprtk_debug(("(v0 * c0) * (c1 * v1) --> (covov) (c0 * c1) * v0 * v1\n")); | |
32113 | ||
32114 | return (synthesis_result) ? result : error_node(); | |
32115 | } | |
32116 | // (v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1) | |
32117 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
32118 | { | |
32119 | const bool synthesis_result = | |
32120 | synthesize_sf3ext_expression:: | |
32121 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c0 / c1), v0, v1, result); | |
32122 | ||
32123 | exprtk_debug(("(v0 * c0) / (c1 * v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); | |
32124 | ||
32125 | return (synthesis_result) ? result : error_node(); | |
32126 | } | |
32127 | // (v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1) | |
32128 | else if ((details::e_div == o0) && (details::e_mul == o1) && (details::e_div == o2)) | |
32129 | { | |
32130 | const bool synthesis_result = | |
32131 | synthesize_sf3ext_expression:: | |
32132 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", (c1 / c0), v0, v1, result); | |
32133 | ||
32134 | exprtk_debug(("(v0 / c0) * (c1 / v1) --> (covov) (c1 / c0) * (v0 / v1)\n")); | |
32135 | ||
32136 | return (synthesis_result) ? result : error_node(); | |
32137 | } | |
32138 | // (v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1) | |
32139 | else if ((details::e_mul == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
32140 | { | |
32141 | const bool synthesis_result = | |
32142 | synthesize_sf3ext_expression:: | |
32143 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)*t", (c0 / c1), v0, v1, result); | |
32144 | ||
32145 | exprtk_debug(("(v0 * c0) / (c1 / v1) --> (covov) (c0 / c1) * (v0 * v1)\n")); | |
32146 | ||
32147 | return (synthesis_result) ? result : error_node(); | |
32148 | } | |
32149 | // (v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1) | |
32150 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_mul == o2)) | |
32151 | { | |
32152 | const bool synthesis_result = | |
32153 | synthesize_sf3ext_expression:: | |
32154 | template compile<ctype,vtype,vtype>(expr_gen, "(t*t)/t", Type(1) / (c0 * c1), v0, v1, result); | |
32155 | ||
32156 | exprtk_debug(("(v0 / c0) / (c1 * v1) --> (covov) (1 / (c0 * c1)) * (v0 / v1)\n")); | |
32157 | ||
32158 | return (synthesis_result) ? result : error_node(); | |
32159 | } | |
32160 | // (v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1)) | |
32161 | else if ((details::e_div == o0) && (details::e_div == o1) && (details::e_div == o2)) | |
32162 | { | |
32163 | const bool synthesis_result = | |
32164 | synthesize_sf3ext_expression:: | |
32165 | template compile<vtype,vtype,ctype>(expr_gen, "(t*t)*t", v0, v1, Type(1) / (c0 * c1), result); | |
32166 | ||
32167 | exprtk_debug(("(v0 / c0) / (c1 / v1) --> (vovoc) (v0 * v1) * (1 / (c0 * c1))\n")); | |
32168 | ||
32169 | return (synthesis_result) ? result : error_node(); | |
32170 | } | |
32171 | // (v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1) | |
32172 | else if ( | |
32173 | (std::equal_to<T>()(c0,c1)) && | |
32174 | (details::e_mul == o0) && | |
32175 | (details::e_mul == o2) && | |
32176 | ( | |
32177 | (details::e_add == o1) || (details::e_sub == o1) | |
32178 | ) | |
32179 | ) | |
32180 | { | |
32181 | std::string specfunc; | |
32182 | ||
32183 | switch (o1) | |
32184 | { | |
32185 | case details::e_add : specfunc = "t*(t+t)"; break; | |
32186 | case details::e_sub : specfunc = "t*(t-t)"; break; | |
32187 | default : return error_node(); | |
32188 | } | |
32189 | ||
32190 | const bool synthesis_result = | |
32191 | synthesize_sf3ext_expression:: | |
32192 | template compile<ctype,vtype,vtype>(expr_gen, specfunc, c0, v0, v1, result); | |
32193 | ||
32194 | exprtk_debug(("(v0 * c) +/- (c * v1) --> (covov) c * (v0 +/- v1)\n")); | |
32195 | ||
32196 | return (synthesis_result) ? result : error_node(); | |
32197 | } | |
32198 | } | |
32199 | ||
32200 | const bool synthesis_result = | |
32201 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32202 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); | |
32203 | ||
32204 | if (synthesis_result) | |
32205 | return result; | |
32206 | else if (!expr_gen.valid_operator(o0,f0)) | |
32207 | return error_node(); | |
32208 | else if (!expr_gen.valid_operator(o1,f1)) | |
32209 | return error_node(); | |
32210 | else if (!expr_gen.valid_operator(o2,f2)) | |
32211 | return error_node(); | |
32212 | else | |
32213 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); | |
32214 | } | |
32215 | ||
32216 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32217 | const details::operator_type o0, | |
32218 | const details::operator_type o1, | |
32219 | const details::operator_type o2) | |
32220 | { | |
32221 | return details::build_string() | |
32222 | << "(t" << expr_gen.to_str(o0) | |
32223 | << "t)" << expr_gen.to_str(o1) | |
32224 | << "(t" << expr_gen.to_str(o2) | |
32225 | << "t)"; | |
32226 | } | |
32227 | }; | |
32228 | ||
32229 | struct synthesize_vovovov_expression1 | |
32230 | { | |
32231 | typedef typename vovovov_t::type1 node_type; | |
32232 | typedef typename vovovov_t::sf4_type sf4_type; | |
32233 | typedef typename node_type::T0 T0; | |
32234 | typedef typename node_type::T1 T1; | |
32235 | typedef typename node_type::T2 T2; | |
32236 | typedef typename node_type::T3 T3; | |
32237 | ||
32238 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32239 | const details::operator_type& operation, | |
32240 | expression_node_ptr (&branch)[2]) | |
32241 | { | |
32242 | // v0 o0 (v1 o1 (v2 o2 v3)) | |
32243 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; | |
32244 | ||
32245 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); | |
32246 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32247 | const Type& v1 = vovov->t0(); | |
32248 | const Type& v2 = vovov->t1(); | |
32249 | const Type& v3 = vovov->t2(); | |
32250 | const details::operator_type o0 = operation; | |
32251 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); | |
32252 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); | |
32253 | ||
32254 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32255 | binary_functor_t f1 = vovov->f0(); | |
32256 | binary_functor_t f2 = vovov->f1(); | |
32257 | ||
32258 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32259 | ||
32260 | expression_node_ptr result = error_node(); | |
32261 | ||
32262 | if (synthesize_sf4ext_expression::template compile<T0,T1,T2,T3>(expr_gen,id(expr_gen,o0,o1,o2),v0,v1,v2,v3,result)) | |
32263 | return result; | |
32264 | else if (!expr_gen.valid_operator(o0,f0)) | |
32265 | return error_node(); | |
32266 | ||
32267 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 v3))\n")); | |
32268 | ||
32269 | return node_type::allocate(*(expr_gen.node_allocator_),v0,v1,v2,v3,f0,f1,f2); | |
32270 | } | |
32271 | ||
32272 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32273 | const details::operator_type o0, | |
32274 | const details::operator_type o1, | |
32275 | const details::operator_type o2) | |
32276 | { | |
32277 | return details::build_string() | |
32278 | << "t" << expr_gen.to_str(o0) | |
32279 | << "(t" << expr_gen.to_str(o1) | |
32280 | << "(t" << expr_gen.to_str(o2) | |
32281 | << "t))"; | |
32282 | } | |
32283 | }; | |
32284 | ||
32285 | struct synthesize_vovovoc_expression1 | |
32286 | { | |
32287 | typedef typename vovovoc_t::type1 node_type; | |
32288 | typedef typename vovovoc_t::sf4_type sf4_type; | |
32289 | typedef typename node_type::T0 T0; | |
32290 | typedef typename node_type::T1 T1; | |
32291 | typedef typename node_type::T2 T2; | |
32292 | typedef typename node_type::T3 T3; | |
32293 | ||
32294 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32295 | const details::operator_type& operation, | |
32296 | expression_node_ptr (&branch)[2]) | |
32297 | { | |
32298 | // v0 o0 (v1 o1 (v2 o2 c)) | |
32299 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; | |
32300 | ||
32301 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); | |
32302 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32303 | const Type& v1 = vovoc->t0(); | |
32304 | const Type& v2 = vovoc->t1(); | |
32305 | const Type c = vovoc->t2(); | |
32306 | const details::operator_type o0 = operation; | |
32307 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); | |
32308 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); | |
32309 | ||
32310 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32311 | binary_functor_t f1 = vovoc->f0(); | |
32312 | binary_functor_t f2 = vovoc->f1(); | |
32313 | ||
32314 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32315 | ||
32316 | expression_node_ptr result = error_node(); | |
32317 | ||
32318 | const bool synthesis_result = | |
32319 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32320 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); | |
32321 | ||
32322 | if (synthesis_result) | |
32323 | return result; | |
32324 | else if (!expr_gen.valid_operator(o0,f0)) | |
32325 | return error_node(); | |
32326 | ||
32327 | exprtk_debug(("v0 o0 (v1 o1 (v2 o2 c))\n")); | |
32328 | ||
32329 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); | |
32330 | } | |
32331 | ||
32332 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32333 | const details::operator_type o0, | |
32334 | const details::operator_type o1, | |
32335 | const details::operator_type o2) | |
32336 | { | |
32337 | return details::build_string() | |
32338 | << "t" << expr_gen.to_str(o0) | |
32339 | << "(t" << expr_gen.to_str(o1) | |
32340 | << "(t" << expr_gen.to_str(o2) | |
32341 | << "t))"; | |
32342 | } | |
32343 | }; | |
32344 | ||
32345 | struct synthesize_vovocov_expression1 | |
32346 | { | |
32347 | typedef typename vovocov_t::type1 node_type; | |
32348 | typedef typename vovocov_t::sf4_type sf4_type; | |
32349 | typedef typename node_type::T0 T0; | |
32350 | typedef typename node_type::T1 T1; | |
32351 | typedef typename node_type::T2 T2; | |
32352 | typedef typename node_type::T3 T3; | |
32353 | ||
32354 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32355 | const details::operator_type& operation, | |
32356 | expression_node_ptr (&branch)[2]) | |
32357 | { | |
32358 | // v0 o0 (v1 o1 (c o2 v2)) | |
32359 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; | |
32360 | ||
32361 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); | |
32362 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32363 | const Type& v1 = vocov->t0(); | |
32364 | const Type c = vocov->t1(); | |
32365 | const Type& v2 = vocov->t2(); | |
32366 | const details::operator_type o0 = operation; | |
32367 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); | |
32368 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); | |
32369 | ||
32370 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32371 | binary_functor_t f1 = vocov->f0(); | |
32372 | binary_functor_t f2 = vocov->f1(); | |
32373 | ||
32374 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32375 | ||
32376 | expression_node_ptr result = error_node(); | |
32377 | ||
32378 | const bool synthesis_result = | |
32379 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32380 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); | |
32381 | ||
32382 | if (synthesis_result) | |
32383 | return result; | |
32384 | if (!expr_gen.valid_operator(o0,f0)) | |
32385 | return error_node(); | |
32386 | ||
32387 | exprtk_debug(("v0 o0 (v1 o1 (c o2 v2))\n")); | |
32388 | ||
32389 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); | |
32390 | } | |
32391 | ||
32392 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32393 | const details::operator_type o0, | |
32394 | const details::operator_type o1, | |
32395 | const details::operator_type o2) | |
32396 | { | |
32397 | return details::build_string() | |
32398 | << "t" << expr_gen.to_str(o0) | |
32399 | << "(t" << expr_gen.to_str(o1) | |
32400 | << "(t" << expr_gen.to_str(o2) | |
32401 | << "t))"; | |
32402 | } | |
32403 | }; | |
32404 | ||
32405 | struct synthesize_vocovov_expression1 | |
32406 | { | |
32407 | typedef typename vocovov_t::type1 node_type; | |
32408 | typedef typename vocovov_t::sf4_type sf4_type; | |
32409 | typedef typename node_type::T0 T0; | |
32410 | typedef typename node_type::T1 T1; | |
32411 | typedef typename node_type::T2 T2; | |
32412 | typedef typename node_type::T3 T3; | |
32413 | ||
32414 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32415 | const details::operator_type& operation, | |
32416 | expression_node_ptr (&branch)[2]) | |
32417 | { | |
32418 | // v0 o0 (c o1 (v1 o2 v2)) | |
32419 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; | |
32420 | ||
32421 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); | |
32422 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32423 | const Type c = covov->t0(); | |
32424 | const Type& v1 = covov->t1(); | |
32425 | const Type& v2 = covov->t2(); | |
32426 | const details::operator_type o0 = operation; | |
32427 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); | |
32428 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); | |
32429 | ||
32430 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32431 | binary_functor_t f1 = covov->f0(); | |
32432 | binary_functor_t f2 = covov->f1(); | |
32433 | ||
32434 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32435 | ||
32436 | expression_node_ptr result = error_node(); | |
32437 | ||
32438 | const bool synthesis_result = | |
32439 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32440 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); | |
32441 | ||
32442 | if (synthesis_result) | |
32443 | return result; | |
32444 | else if (!expr_gen.valid_operator(o0,f0)) | |
32445 | return error_node(); | |
32446 | ||
32447 | exprtk_debug(("v0 o0 (c o1 (v1 o2 v2))\n")); | |
32448 | ||
32449 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); | |
32450 | } | |
32451 | ||
32452 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32453 | const details::operator_type o0, | |
32454 | const details::operator_type o1, | |
32455 | const details::operator_type o2) | |
32456 | { | |
32457 | return details::build_string() | |
32458 | << "t" << expr_gen.to_str(o0) | |
32459 | << "(t" << expr_gen.to_str(o1) | |
32460 | << "(t" << expr_gen.to_str(o2) | |
32461 | << "t))"; | |
32462 | } | |
32463 | }; | |
32464 | ||
32465 | struct synthesize_covovov_expression1 | |
32466 | { | |
32467 | typedef typename covovov_t::type1 node_type; | |
32468 | typedef typename covovov_t::sf4_type sf4_type; | |
32469 | typedef typename node_type::T0 T0; | |
32470 | typedef typename node_type::T1 T1; | |
32471 | typedef typename node_type::T2 T2; | |
32472 | typedef typename node_type::T3 T3; | |
32473 | ||
32474 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32475 | const details::operator_type& operation, | |
32476 | expression_node_ptr (&branch)[2]) | |
32477 | { | |
32478 | // c o0 (v0 o1 (v1 o2 v2)) | |
32479 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; | |
32480 | ||
32481 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); | |
32482 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
32483 | const Type& v0 = vovov->t0(); | |
32484 | const Type& v1 = vovov->t1(); | |
32485 | const Type& v2 = vovov->t2(); | |
32486 | const details::operator_type o0 = operation; | |
32487 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); | |
32488 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); | |
32489 | ||
32490 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32491 | binary_functor_t f1 = vovov->f0(); | |
32492 | binary_functor_t f2 = vovov->f1(); | |
32493 | ||
32494 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
32495 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32496 | ||
32497 | expression_node_ptr result = error_node(); | |
32498 | ||
32499 | const bool synthesis_result = | |
32500 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32501 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); | |
32502 | ||
32503 | if (synthesis_result) | |
32504 | return result; | |
32505 | if (!expr_gen.valid_operator(o0,f0)) | |
32506 | return error_node(); | |
32507 | ||
32508 | exprtk_debug(("c o0 (v0 o1 (v1 o2 v2))\n")); | |
32509 | ||
32510 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); | |
32511 | } | |
32512 | ||
32513 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32514 | const details::operator_type o0, | |
32515 | const details::operator_type o1, | |
32516 | const details::operator_type o2) | |
32517 | { | |
32518 | return details::build_string() | |
32519 | << "t" << expr_gen.to_str(o0) | |
32520 | << "(t" << expr_gen.to_str(o1) | |
32521 | << "(t" << expr_gen.to_str(o2) | |
32522 | << "t))"; | |
32523 | } | |
32524 | }; | |
32525 | ||
32526 | struct synthesize_covocov_expression1 | |
32527 | { | |
32528 | typedef typename covocov_t::type1 node_type; | |
32529 | typedef typename covocov_t::sf4_type sf4_type; | |
32530 | typedef typename node_type::T0 T0; | |
32531 | typedef typename node_type::T1 T1; | |
32532 | typedef typename node_type::T2 T2; | |
32533 | typedef typename node_type::T3 T3; | |
32534 | ||
32535 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32536 | const details::operator_type& operation, | |
32537 | expression_node_ptr (&branch)[2]) | |
32538 | { | |
32539 | // c0 o0 (v0 o1 (c1 o2 v1)) | |
32540 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; | |
32541 | ||
32542 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); | |
32543 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
32544 | const Type& v0 = vocov->t0(); | |
32545 | const Type c1 = vocov->t1(); | |
32546 | const Type& v1 = vocov->t2(); | |
32547 | const details::operator_type o0 = operation; | |
32548 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); | |
32549 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); | |
32550 | ||
32551 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32552 | binary_functor_t f1 = vocov->f0(); | |
32553 | binary_functor_t f2 = vocov->f1(); | |
32554 | ||
32555 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
32556 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32557 | ||
32558 | expression_node_ptr result = error_node(); | |
32559 | ||
32560 | const bool synthesis_result = | |
32561 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32562 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); | |
32563 | ||
32564 | if (synthesis_result) | |
32565 | return result; | |
32566 | else if (!expr_gen.valid_operator(o0,f0)) | |
32567 | return error_node(); | |
32568 | ||
32569 | exprtk_debug(("c0 o0 (v0 o1 (c1 o2 v1))\n")); | |
32570 | ||
32571 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); | |
32572 | } | |
32573 | ||
32574 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32575 | const details::operator_type o0, | |
32576 | const details::operator_type o1, | |
32577 | const details::operator_type o2) | |
32578 | { | |
32579 | return details::build_string() | |
32580 | << "t" << expr_gen.to_str(o0) | |
32581 | << "(t" << expr_gen.to_str(o1) | |
32582 | << "(t" << expr_gen.to_str(o2) | |
32583 | << "t))"; | |
32584 | } | |
32585 | }; | |
32586 | ||
32587 | struct synthesize_vocovoc_expression1 | |
32588 | { | |
32589 | typedef typename vocovoc_t::type1 node_type; | |
32590 | typedef typename vocovoc_t::sf4_type sf4_type; | |
32591 | typedef typename node_type::T0 T0; | |
32592 | typedef typename node_type::T1 T1; | |
32593 | typedef typename node_type::T2 T2; | |
32594 | typedef typename node_type::T3 T3; | |
32595 | ||
32596 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32597 | const details::operator_type& operation, | |
32598 | expression_node_ptr (&branch)[2]) | |
32599 | { | |
32600 | // v0 o0 (c0 o1 (v1 o2 c2)) | |
32601 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; | |
32602 | ||
32603 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); | |
32604 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32605 | const Type c0 = covoc->t0(); | |
32606 | const Type& v1 = covoc->t1(); | |
32607 | const Type c1 = covoc->t2(); | |
32608 | const details::operator_type o0 = operation; | |
32609 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); | |
32610 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); | |
32611 | ||
32612 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32613 | binary_functor_t f1 = covoc->f0(); | |
32614 | binary_functor_t f2 = covoc->f1(); | |
32615 | ||
32616 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32617 | ||
32618 | expression_node_ptr result = error_node(); | |
32619 | ||
32620 | const bool synthesis_result = | |
32621 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32622 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); | |
32623 | ||
32624 | if (synthesis_result) | |
32625 | return result; | |
32626 | else if (!expr_gen.valid_operator(o0,f0)) | |
32627 | return error_node(); | |
32628 | ||
32629 | exprtk_debug(("v0 o0 (c0 o1 (v1 o2 c2))\n")); | |
32630 | ||
32631 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); | |
32632 | } | |
32633 | ||
32634 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32635 | const details::operator_type o0, | |
32636 | const details::operator_type o1, | |
32637 | const details::operator_type o2) | |
32638 | { | |
32639 | return details::build_string() | |
32640 | << "t" << expr_gen.to_str(o0) | |
32641 | << "(t" << expr_gen.to_str(o1) | |
32642 | << "(t" << expr_gen.to_str(o2) | |
32643 | << "t))"; | |
32644 | } | |
32645 | }; | |
32646 | ||
32647 | struct synthesize_covovoc_expression1 | |
32648 | { | |
32649 | typedef typename covovoc_t::type1 node_type; | |
32650 | typedef typename covovoc_t::sf4_type sf4_type; | |
32651 | typedef typename node_type::T0 T0; | |
32652 | typedef typename node_type::T1 T1; | |
32653 | typedef typename node_type::T2 T2; | |
32654 | typedef typename node_type::T3 T3; | |
32655 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32656 | const details::operator_type& operation, | |
32657 | expression_node_ptr (&branch)[2]) | |
32658 | { | |
32659 | // c0 o0 (v0 o1 (v1 o2 c1)) | |
32660 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; | |
32661 | ||
32662 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); | |
32663 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
32664 | const Type& v0 = vovoc->t0(); | |
32665 | const Type& v1 = vovoc->t1(); | |
32666 | const Type c1 = vovoc->t2(); | |
32667 | const details::operator_type o0 = operation; | |
32668 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); | |
32669 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); | |
32670 | ||
32671 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32672 | binary_functor_t f1 = vovoc->f0(); | |
32673 | binary_functor_t f2 = vovoc->f1(); | |
32674 | ||
32675 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
32676 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32677 | ||
32678 | expression_node_ptr result = error_node(); | |
32679 | ||
32680 | const bool synthesis_result = | |
32681 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32682 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); | |
32683 | ||
32684 | if (synthesis_result) | |
32685 | return result; | |
32686 | else if (!expr_gen.valid_operator(o0,f0)) | |
32687 | return error_node(); | |
32688 | ||
32689 | exprtk_debug(("c0 o0 (v0 o1 (v1 o2 c1))\n")); | |
32690 | ||
32691 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); | |
32692 | } | |
32693 | ||
32694 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32695 | const details::operator_type o0, | |
32696 | const details::operator_type o1, | |
32697 | const details::operator_type o2) | |
32698 | { | |
32699 | return details::build_string() | |
32700 | << "t" << expr_gen.to_str(o0) | |
32701 | << "(t" << expr_gen.to_str(o1) | |
32702 | << "(t" << expr_gen.to_str(o2) | |
32703 | << "t))"; | |
32704 | } | |
32705 | }; | |
32706 | ||
32707 | struct synthesize_vococov_expression1 | |
32708 | { | |
32709 | typedef typename vococov_t::type1 node_type; | |
32710 | typedef typename vococov_t::sf4_type sf4_type; | |
32711 | typedef typename node_type::T0 T0; | |
32712 | typedef typename node_type::T1 T1; | |
32713 | typedef typename node_type::T2 T2; | |
32714 | typedef typename node_type::T3 T3; | |
32715 | ||
32716 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32717 | const details::operator_type& operation, | |
32718 | expression_node_ptr (&branch)[2]) | |
32719 | { | |
32720 | // v0 o0 (c0 o1 (c1 o2 v1)) | |
32721 | typedef typename synthesize_cocov_expression1::node_type lcl_cocov_t; | |
32722 | ||
32723 | const lcl_cocov_t* cocov = static_cast<const lcl_cocov_t*>(branch[1]); | |
32724 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32725 | const Type c0 = cocov->t0(); | |
32726 | const Type c1 = cocov->t1(); | |
32727 | const Type& v1 = cocov->t2(); | |
32728 | const details::operator_type o0 = operation; | |
32729 | const details::operator_type o1 = expr_gen.get_operator(cocov->f0()); | |
32730 | const details::operator_type o2 = expr_gen.get_operator(cocov->f1()); | |
32731 | ||
32732 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32733 | binary_functor_t f1 = cocov->f0(); | |
32734 | binary_functor_t f2 = cocov->f1(); | |
32735 | ||
32736 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32737 | ||
32738 | expression_node_ptr result = error_node(); | |
32739 | ||
32740 | const bool synthesis_result = | |
32741 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32742 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); | |
32743 | ||
32744 | if (synthesis_result) | |
32745 | return result; | |
32746 | else if (!expr_gen.valid_operator(o0,f0)) | |
32747 | return error_node(); | |
32748 | ||
32749 | exprtk_debug(("v0 o0 (c0 o1 (c1 o2 v1))\n")); | |
32750 | ||
32751 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); | |
32752 | } | |
32753 | ||
32754 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32755 | const details::operator_type o0, | |
32756 | const details::operator_type o1, | |
32757 | const details::operator_type o2) | |
32758 | { | |
32759 | return details::build_string() | |
32760 | << "t" << expr_gen.to_str(o0) | |
32761 | << "(t" << expr_gen.to_str(o1) | |
32762 | << "(t" << expr_gen.to_str(o2) | |
32763 | << "t))"; | |
32764 | } | |
32765 | }; | |
32766 | ||
32767 | struct synthesize_vovovov_expression2 | |
32768 | { | |
32769 | typedef typename vovovov_t::type2 node_type; | |
32770 | typedef typename vovovov_t::sf4_type sf4_type; | |
32771 | typedef typename node_type::T0 T0; | |
32772 | typedef typename node_type::T1 T1; | |
32773 | typedef typename node_type::T2 T2; | |
32774 | typedef typename node_type::T3 T3; | |
32775 | ||
32776 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32777 | const details::operator_type& operation, | |
32778 | expression_node_ptr (&branch)[2]) | |
32779 | { | |
32780 | // v0 o0 ((v1 o1 v2) o2 v3) | |
32781 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; | |
32782 | ||
32783 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); | |
32784 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32785 | const Type& v1 = vovov->t0(); | |
32786 | const Type& v2 = vovov->t1(); | |
32787 | const Type& v3 = vovov->t2(); | |
32788 | const details::operator_type o0 = operation; | |
32789 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); | |
32790 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); | |
32791 | ||
32792 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32793 | binary_functor_t f1 = vovov->f0(); | |
32794 | binary_functor_t f2 = vovov->f1(); | |
32795 | ||
32796 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32797 | ||
32798 | expression_node_ptr result = error_node(); | |
32799 | ||
32800 | const bool synthesis_result = | |
32801 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32802 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); | |
32803 | ||
32804 | if (synthesis_result) | |
32805 | return result; | |
32806 | else if (!expr_gen.valid_operator(o0,f0)) | |
32807 | return error_node(); | |
32808 | ||
32809 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 v3)\n")); | |
32810 | ||
32811 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); | |
32812 | } | |
32813 | ||
32814 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32815 | const details::operator_type o0, | |
32816 | const details::operator_type o1, | |
32817 | const details::operator_type o2) | |
32818 | { | |
32819 | return details::build_string() | |
32820 | << "t" << expr_gen.to_str(o0) | |
32821 | << "((t" << expr_gen.to_str(o1) | |
32822 | << "t)" << expr_gen.to_str(o2) | |
32823 | << "t)"; | |
32824 | } | |
32825 | }; | |
32826 | ||
32827 | struct synthesize_vovovoc_expression2 | |
32828 | { | |
32829 | typedef typename vovovoc_t::type2 node_type; | |
32830 | typedef typename vovovoc_t::sf4_type sf4_type; | |
32831 | typedef typename node_type::T0 T0; | |
32832 | typedef typename node_type::T1 T1; | |
32833 | typedef typename node_type::T2 T2; | |
32834 | typedef typename node_type::T3 T3; | |
32835 | ||
32836 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32837 | const details::operator_type& operation, | |
32838 | expression_node_ptr (&branch)[2]) | |
32839 | { | |
32840 | // v0 o0 ((v1 o1 v2) o2 c) | |
32841 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; | |
32842 | ||
32843 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); | |
32844 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32845 | const Type& v1 = vovoc->t0(); | |
32846 | const Type& v2 = vovoc->t1(); | |
32847 | const Type c = vovoc->t2(); | |
32848 | const details::operator_type o0 = operation; | |
32849 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); | |
32850 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); | |
32851 | ||
32852 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32853 | binary_functor_t f1 = vovoc->f0(); | |
32854 | binary_functor_t f2 = vovoc->f1(); | |
32855 | ||
32856 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32857 | ||
32858 | expression_node_ptr result = error_node(); | |
32859 | ||
32860 | const bool synthesis_result = | |
32861 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32862 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); | |
32863 | ||
32864 | if (synthesis_result) | |
32865 | return result; | |
32866 | else if (!expr_gen.valid_operator(o0,f0)) | |
32867 | return error_node(); | |
32868 | ||
32869 | exprtk_debug(("v0 o0 ((v1 o1 v2) o2 c)\n")); | |
32870 | ||
32871 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); | |
32872 | } | |
32873 | ||
32874 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32875 | const details::operator_type o0, | |
32876 | const details::operator_type o1, | |
32877 | const details::operator_type o2) | |
32878 | { | |
32879 | return details::build_string() | |
32880 | << "t" << expr_gen.to_str(o0) | |
32881 | << "((t" << expr_gen.to_str(o1) | |
32882 | << "t)" << expr_gen.to_str(o2) | |
32883 | << "t)"; | |
32884 | } | |
32885 | }; | |
32886 | ||
32887 | struct synthesize_vovocov_expression2 | |
32888 | { | |
32889 | typedef typename vovocov_t::type2 node_type; | |
32890 | typedef typename vovocov_t::sf4_type sf4_type; | |
32891 | typedef typename node_type::T0 T0; | |
32892 | typedef typename node_type::T1 T1; | |
32893 | typedef typename node_type::T2 T2; | |
32894 | typedef typename node_type::T3 T3; | |
32895 | ||
32896 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32897 | const details::operator_type& operation, | |
32898 | expression_node_ptr (&branch)[2]) | |
32899 | { | |
32900 | // v0 o0 ((v1 o1 c) o2 v2) | |
32901 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; | |
32902 | ||
32903 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); | |
32904 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32905 | const Type& v1 = vocov->t0(); | |
32906 | const Type c = vocov->t1(); | |
32907 | const Type& v2 = vocov->t2(); | |
32908 | const details::operator_type o0 = operation; | |
32909 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); | |
32910 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); | |
32911 | ||
32912 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32913 | binary_functor_t f1 = vocov->f0(); | |
32914 | binary_functor_t f2 = vocov->f1(); | |
32915 | ||
32916 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32917 | ||
32918 | expression_node_ptr result = error_node(); | |
32919 | ||
32920 | const bool synthesis_result = | |
32921 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32922 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); | |
32923 | ||
32924 | if (synthesis_result) | |
32925 | return result; | |
32926 | else if (!expr_gen.valid_operator(o0,f0)) | |
32927 | return error_node(); | |
32928 | ||
32929 | exprtk_debug(("v0 o0 ((v1 o1 c) o2 v2)\n")); | |
32930 | ||
32931 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); | |
32932 | } | |
32933 | ||
32934 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32935 | const details::operator_type o0, | |
32936 | const details::operator_type o1, | |
32937 | const details::operator_type o2) | |
32938 | { | |
32939 | return details::build_string() | |
32940 | << "t" << expr_gen.to_str(o0) | |
32941 | << "((t" << expr_gen.to_str(o1) | |
32942 | << "t)" << expr_gen.to_str(o2) | |
32943 | << "t)"; | |
32944 | } | |
32945 | }; | |
32946 | ||
32947 | struct synthesize_vocovov_expression2 | |
32948 | { | |
32949 | typedef typename vocovov_t::type2 node_type; | |
32950 | typedef typename vocovov_t::sf4_type sf4_type; | |
32951 | typedef typename node_type::T0 T0; | |
32952 | typedef typename node_type::T1 T1; | |
32953 | typedef typename node_type::T2 T2; | |
32954 | typedef typename node_type::T3 T3; | |
32955 | ||
32956 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
32957 | const details::operator_type& operation, | |
32958 | expression_node_ptr (&branch)[2]) | |
32959 | { | |
32960 | // v0 o0 ((c o1 v1) o2 v2) | |
32961 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; | |
32962 | ||
32963 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[1]); | |
32964 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
32965 | const Type c = covov->t0(); | |
32966 | const Type& v1 = covov->t1(); | |
32967 | const Type& v2 = covov->t2(); | |
32968 | const details::operator_type o0 = operation; | |
32969 | const details::operator_type o1 = expr_gen.get_operator(covov->f0()); | |
32970 | const details::operator_type o2 = expr_gen.get_operator(covov->f1()); | |
32971 | ||
32972 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
32973 | binary_functor_t f1 = covov->f0(); | |
32974 | binary_functor_t f2 = covov->f1(); | |
32975 | ||
32976 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
32977 | ||
32978 | expression_node_ptr result = error_node(); | |
32979 | ||
32980 | const bool synthesis_result = | |
32981 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
32982 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); | |
32983 | ||
32984 | if (synthesis_result) | |
32985 | return result; | |
32986 | else if (!expr_gen.valid_operator(o0,f0)) | |
32987 | return error_node(); | |
32988 | ||
32989 | exprtk_debug(("v0 o0 ((c o1 v1) o2 v2)\n")); | |
32990 | ||
32991 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); | |
32992 | } | |
32993 | ||
32994 | static inline std::string id(expression_generator<Type>& expr_gen, | |
32995 | const details::operator_type o0, | |
32996 | const details::operator_type o1, | |
32997 | const details::operator_type o2) | |
32998 | { | |
32999 | return details::build_string() | |
33000 | << "t" << expr_gen.to_str(o0) | |
33001 | << "((t" << expr_gen.to_str(o1) | |
33002 | << "t)" << expr_gen.to_str(o2) | |
33003 | << "t)"; | |
33004 | } | |
33005 | }; | |
33006 | ||
33007 | struct synthesize_covovov_expression2 | |
33008 | { | |
33009 | typedef typename covovov_t::type2 node_type; | |
33010 | typedef typename covovov_t::sf4_type sf4_type; | |
33011 | typedef typename node_type::T0 T0; | |
33012 | typedef typename node_type::T1 T1; | |
33013 | typedef typename node_type::T2 T2; | |
33014 | typedef typename node_type::T3 T3; | |
33015 | ||
33016 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33017 | const details::operator_type& operation, | |
33018 | expression_node_ptr (&branch)[2]) | |
33019 | { | |
33020 | // c o0 ((v1 o1 v2) o2 v3) | |
33021 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; | |
33022 | ||
33023 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[1]); | |
33024 | const Type c = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
33025 | const Type& v0 = vovov->t0(); | |
33026 | const Type& v1 = vovov->t1(); | |
33027 | const Type& v2 = vovov->t2(); | |
33028 | const details::operator_type o0 = operation; | |
33029 | const details::operator_type o1 = expr_gen.get_operator(vovov->f0()); | |
33030 | const details::operator_type o2 = expr_gen.get_operator(vovov->f1()); | |
33031 | ||
33032 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
33033 | binary_functor_t f1 = vovov->f0(); | |
33034 | binary_functor_t f2 = vovov->f1(); | |
33035 | ||
33036 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33037 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33038 | ||
33039 | expression_node_ptr result = error_node(); | |
33040 | ||
33041 | const bool synthesis_result = | |
33042 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33043 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); | |
33044 | ||
33045 | if (synthesis_result) | |
33046 | return result; | |
33047 | else if (!expr_gen.valid_operator(o0,f0)) | |
33048 | return error_node(); | |
33049 | ||
33050 | exprtk_debug(("c o0 ((v1 o1 v2) o2 v3)\n")); | |
33051 | ||
33052 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); | |
33053 | } | |
33054 | ||
33055 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33056 | const details::operator_type o0, | |
33057 | const details::operator_type o1, | |
33058 | const details::operator_type o2) | |
33059 | { | |
33060 | return details::build_string() | |
33061 | << "t" << expr_gen.to_str(o0) | |
33062 | << "((t" << expr_gen.to_str(o1) | |
33063 | << "t)" << expr_gen.to_str(o2) | |
33064 | << "t)"; | |
33065 | } | |
33066 | }; | |
33067 | ||
33068 | struct synthesize_covocov_expression2 | |
33069 | { | |
33070 | typedef typename covocov_t::type2 node_type; | |
33071 | typedef typename covocov_t::sf4_type sf4_type; | |
33072 | typedef typename node_type::T0 T0; | |
33073 | typedef typename node_type::T1 T1; | |
33074 | typedef typename node_type::T2 T2; | |
33075 | typedef typename node_type::T3 T3; | |
33076 | ||
33077 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33078 | const details::operator_type& operation, | |
33079 | expression_node_ptr (&branch)[2]) | |
33080 | { | |
33081 | // c0 o0 ((v0 o1 c1) o2 v1) | |
33082 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; | |
33083 | ||
33084 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[1]); | |
33085 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
33086 | const Type& v0 = vocov->t0(); | |
33087 | const Type c1 = vocov->t1(); | |
33088 | const Type& v1 = vocov->t2(); | |
33089 | const details::operator_type o0 = operation; | |
33090 | const details::operator_type o1 = expr_gen.get_operator(vocov->f0()); | |
33091 | const details::operator_type o2 = expr_gen.get_operator(vocov->f1()); | |
33092 | ||
33093 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
33094 | binary_functor_t f1 = vocov->f0(); | |
33095 | binary_functor_t f2 = vocov->f1(); | |
33096 | ||
33097 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33098 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33099 | ||
33100 | expression_node_ptr result = error_node(); | |
33101 | ||
33102 | const bool synthesis_result = | |
33103 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33104 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); | |
33105 | ||
33106 | if (synthesis_result) | |
33107 | return result; | |
33108 | else if (!expr_gen.valid_operator(o0,f0)) | |
33109 | return error_node(); | |
33110 | ||
33111 | exprtk_debug(("c0 o0 ((v0 o1 c1) o2 v1)\n")); | |
33112 | ||
33113 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); | |
33114 | } | |
33115 | ||
33116 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33117 | const details::operator_type o0, | |
33118 | const details::operator_type o1, | |
33119 | const details::operator_type o2) | |
33120 | { | |
33121 | return details::build_string() | |
33122 | << "t" << expr_gen.to_str(o0) | |
33123 | << "((t" << expr_gen.to_str(o1) | |
33124 | << "t)" << expr_gen.to_str(o2) | |
33125 | << "t)"; | |
33126 | } | |
33127 | }; | |
33128 | ||
33129 | struct synthesize_vocovoc_expression2 | |
33130 | { | |
33131 | typedef typename vocovoc_t::type2 node_type; | |
33132 | typedef typename vocovoc_t::sf4_type sf4_type; | |
33133 | typedef typename node_type::T0 T0; | |
33134 | typedef typename node_type::T1 T1; | |
33135 | typedef typename node_type::T2 T2; | |
33136 | typedef typename node_type::T3 T3; | |
33137 | ||
33138 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33139 | const details::operator_type& operation, | |
33140 | expression_node_ptr (&branch)[2]) | |
33141 | { | |
33142 | // v0 o0 ((c0 o1 v1) o2 c1) | |
33143 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; | |
33144 | ||
33145 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[1]); | |
33146 | const Type& v0 = static_cast<details::variable_node<Type>*>(branch[0])->ref(); | |
33147 | const Type c0 = covoc->t0(); | |
33148 | const Type& v1 = covoc->t1(); | |
33149 | const Type c1 = covoc->t2(); | |
33150 | const details::operator_type o0 = operation; | |
33151 | const details::operator_type o1 = expr_gen.get_operator(covoc->f0()); | |
33152 | const details::operator_type o2 = expr_gen.get_operator(covoc->f1()); | |
33153 | ||
33154 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
33155 | binary_functor_t f1 = covoc->f0(); | |
33156 | binary_functor_t f2 = covoc->f1(); | |
33157 | ||
33158 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33159 | ||
33160 | expression_node_ptr result = error_node(); | |
33161 | ||
33162 | const bool synthesis_result = | |
33163 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33164 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); | |
33165 | ||
33166 | if (synthesis_result) | |
33167 | return result; | |
33168 | else if (!expr_gen.valid_operator(o0,f0)) | |
33169 | return error_node(); | |
33170 | ||
33171 | exprtk_debug(("v0 o0 ((c0 o1 v1) o2 c1)\n")); | |
33172 | ||
33173 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); | |
33174 | } | |
33175 | ||
33176 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33177 | const details::operator_type o0, | |
33178 | const details::operator_type o1, | |
33179 | const details::operator_type o2) | |
33180 | { | |
33181 | return details::build_string() | |
33182 | << "t" << expr_gen.to_str(o0) | |
33183 | << "((t" << expr_gen.to_str(o1) | |
33184 | << "t)" << expr_gen.to_str(o2) | |
33185 | << "t)"; | |
33186 | } | |
33187 | }; | |
33188 | ||
33189 | struct synthesize_covovoc_expression2 | |
33190 | { | |
33191 | typedef typename covovoc_t::type2 node_type; | |
33192 | typedef typename covovoc_t::sf4_type sf4_type; | |
33193 | typedef typename node_type::T0 T0; | |
33194 | typedef typename node_type::T1 T1; | |
33195 | typedef typename node_type::T2 T2; | |
33196 | typedef typename node_type::T3 T3; | |
33197 | ||
33198 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33199 | const details::operator_type& operation, | |
33200 | expression_node_ptr (&branch)[2]) | |
33201 | { | |
33202 | // c0 o0 ((v0 o1 v1) o2 c1) | |
33203 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; | |
33204 | ||
33205 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[1]); | |
33206 | const Type c0 = static_cast<details::literal_node<Type>*>(branch[0])->value(); | |
33207 | const Type& v0 = vovoc->t0(); | |
33208 | const Type& v1 = vovoc->t1(); | |
33209 | const Type c1 = vovoc->t2(); | |
33210 | const details::operator_type o0 = operation; | |
33211 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f0()); | |
33212 | const details::operator_type o2 = expr_gen.get_operator(vovoc->f1()); | |
33213 | ||
33214 | binary_functor_t f0 = reinterpret_cast<binary_functor_t>(0); | |
33215 | binary_functor_t f1 = vovoc->f0(); | |
33216 | binary_functor_t f2 = vovoc->f1(); | |
33217 | ||
33218 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33219 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33220 | ||
33221 | expression_node_ptr result = error_node(); | |
33222 | ||
33223 | const bool synthesis_result = | |
33224 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33225 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); | |
33226 | ||
33227 | if (synthesis_result) | |
33228 | return result; | |
33229 | else if (!expr_gen.valid_operator(o0,f0)) | |
33230 | return error_node(); | |
33231 | ||
33232 | exprtk_debug(("c0 o0 ((v0 o1 v1) o2 c1)\n")); | |
33233 | ||
33234 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); | |
33235 | } | |
33236 | ||
33237 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33238 | const details::operator_type o0, | |
33239 | const details::operator_type o1, | |
33240 | const details::operator_type o2) | |
33241 | { | |
33242 | return details::build_string() | |
33243 | << "t" << expr_gen.to_str(o0) | |
33244 | << "((t" << expr_gen.to_str(o1) | |
33245 | << "t)" << expr_gen.to_str(o2) | |
33246 | << "t)"; | |
33247 | } | |
33248 | }; | |
33249 | ||
33250 | struct synthesize_vococov_expression2 | |
33251 | { | |
33252 | typedef typename vococov_t::type2 node_type; | |
33253 | static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) | |
33254 | { | |
33255 | // v0 o0 ((c0 o1 c1) o2 v1) - Not possible | |
33256 | exprtk_debug(("v0 o0 ((c0 o1 c1) o2 v1) - Not possible\n")); | |
33257 | return error_node(); | |
33258 | } | |
33259 | ||
33260 | static inline std::string id(expression_generator<Type>&, | |
33261 | const details::operator_type, const details::operator_type, const details::operator_type) | |
33262 | { | |
33263 | return "INVALID"; | |
33264 | } | |
33265 | }; | |
33266 | ||
33267 | struct synthesize_vovovov_expression3 | |
33268 | { | |
33269 | typedef typename vovovov_t::type3 node_type; | |
33270 | typedef typename vovovov_t::sf4_type sf4_type; | |
33271 | typedef typename node_type::T0 T0; | |
33272 | typedef typename node_type::T1 T1; | |
33273 | typedef typename node_type::T2 T2; | |
33274 | typedef typename node_type::T3 T3; | |
33275 | ||
33276 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33277 | const details::operator_type& operation, | |
33278 | expression_node_ptr (&branch)[2]) | |
33279 | { | |
33280 | // ((v0 o0 v1) o1 v2) o2 v3 | |
33281 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; | |
33282 | ||
33283 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); | |
33284 | const Type& v0 = vovov->t0(); | |
33285 | const Type& v1 = vovov->t1(); | |
33286 | const Type& v2 = vovov->t2(); | |
33287 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33288 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); | |
33289 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); | |
33290 | const details::operator_type o2 = operation; | |
33291 | ||
33292 | binary_functor_t f0 = vovov->f0(); | |
33293 | binary_functor_t f1 = vovov->f1(); | |
33294 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33295 | ||
33296 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33297 | ||
33298 | expression_node_ptr result = error_node(); | |
33299 | ||
33300 | const bool synthesis_result = | |
33301 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33302 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); | |
33303 | ||
33304 | if (synthesis_result) | |
33305 | return result; | |
33306 | else if (!expr_gen.valid_operator(o2,f2)) | |
33307 | return error_node(); | |
33308 | ||
33309 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 v3\n")); | |
33310 | ||
33311 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); | |
33312 | } | |
33313 | ||
33314 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33315 | const details::operator_type o0, | |
33316 | const details::operator_type o1, | |
33317 | const details::operator_type o2) | |
33318 | { | |
33319 | return details::build_string() | |
33320 | << "((t" << expr_gen.to_str(o0) | |
33321 | << "t)" << expr_gen.to_str(o1) | |
33322 | << "t)" << expr_gen.to_str(o2) | |
33323 | << "t"; | |
33324 | } | |
33325 | }; | |
33326 | ||
33327 | struct synthesize_vovovoc_expression3 | |
33328 | { | |
33329 | typedef typename vovovoc_t::type3 node_type; | |
33330 | typedef typename vovovoc_t::sf4_type sf4_type; | |
33331 | typedef typename node_type::T0 T0; | |
33332 | typedef typename node_type::T1 T1; | |
33333 | typedef typename node_type::T2 T2; | |
33334 | typedef typename node_type::T3 T3; | |
33335 | ||
33336 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33337 | const details::operator_type& operation, | |
33338 | expression_node_ptr (&branch)[2]) | |
33339 | { | |
33340 | // ((v0 o0 v1) o1 v2) o2 c | |
33341 | typedef typename synthesize_vovov_expression0::node_type lcl_vovov_t; | |
33342 | ||
33343 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); | |
33344 | const Type& v0 = vovov->t0(); | |
33345 | const Type& v1 = vovov->t1(); | |
33346 | const Type& v2 = vovov->t2(); | |
33347 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
33348 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); | |
33349 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); | |
33350 | const details::operator_type o2 = operation; | |
33351 | ||
33352 | binary_functor_t f0 = vovov->f0(); | |
33353 | binary_functor_t f1 = vovov->f1(); | |
33354 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33355 | ||
33356 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33357 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33358 | ||
33359 | expression_node_ptr result = error_node(); | |
33360 | ||
33361 | const bool synthesis_result = | |
33362 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33363 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); | |
33364 | ||
33365 | if (synthesis_result) | |
33366 | return result; | |
33367 | else if (!expr_gen.valid_operator(o2,f2)) | |
33368 | return error_node(); | |
33369 | ||
33370 | exprtk_debug(("((v0 o0 v1) o1 v2) o2 c\n")); | |
33371 | ||
33372 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); | |
33373 | } | |
33374 | ||
33375 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33376 | const details::operator_type o0, | |
33377 | const details::operator_type o1, | |
33378 | const details::operator_type o2) | |
33379 | { | |
33380 | return details::build_string() | |
33381 | << "((t" << expr_gen.to_str(o0) | |
33382 | << "t)" << expr_gen.to_str(o1) | |
33383 | << "t)" << expr_gen.to_str(o2) | |
33384 | << "t"; | |
33385 | } | |
33386 | }; | |
33387 | ||
33388 | struct synthesize_vovocov_expression3 | |
33389 | { | |
33390 | typedef typename vovocov_t::type3 node_type; | |
33391 | typedef typename vovocov_t::sf4_type sf4_type; | |
33392 | typedef typename node_type::T0 T0; | |
33393 | typedef typename node_type::T1 T1; | |
33394 | typedef typename node_type::T2 T2; | |
33395 | typedef typename node_type::T3 T3; | |
33396 | ||
33397 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33398 | const details::operator_type& operation, | |
33399 | expression_node_ptr (&branch)[2]) | |
33400 | { | |
33401 | // ((v0 o0 v1) o1 c) o2 v2 | |
33402 | typedef typename synthesize_vovoc_expression0::node_type lcl_vovoc_t; | |
33403 | ||
33404 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); | |
33405 | const Type& v0 = vovoc->t0(); | |
33406 | const Type& v1 = vovoc->t1(); | |
33407 | const Type c = vovoc->t2(); | |
33408 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33409 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); | |
33410 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); | |
33411 | const details::operator_type o2 = operation; | |
33412 | ||
33413 | binary_functor_t f0 = vovoc->f0(); | |
33414 | binary_functor_t f1 = vovoc->f1(); | |
33415 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33416 | ||
33417 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33418 | ||
33419 | expression_node_ptr result = error_node(); | |
33420 | ||
33421 | const bool synthesis_result = | |
33422 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33423 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); | |
33424 | ||
33425 | if (synthesis_result) | |
33426 | return result; | |
33427 | else if (!expr_gen.valid_operator(o2,f2)) | |
33428 | return error_node(); | |
33429 | ||
33430 | exprtk_debug(("((v0 o0 v1) o1 c) o2 v2\n")); | |
33431 | ||
33432 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); | |
33433 | } | |
33434 | ||
33435 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33436 | const details::operator_type o0, | |
33437 | const details::operator_type o1, | |
33438 | const details::operator_type o2) | |
33439 | { | |
33440 | return details::build_string() | |
33441 | << "((t" << expr_gen.to_str(o0) | |
33442 | << "t)" << expr_gen.to_str(o1) | |
33443 | << "t)" << expr_gen.to_str(o2) | |
33444 | << "t"; | |
33445 | } | |
33446 | }; | |
33447 | ||
33448 | struct synthesize_vocovov_expression3 | |
33449 | { | |
33450 | typedef typename vocovov_t::type3 node_type; | |
33451 | typedef typename vocovov_t::sf4_type sf4_type; | |
33452 | typedef typename node_type::T0 T0; | |
33453 | typedef typename node_type::T1 T1; | |
33454 | typedef typename node_type::T2 T2; | |
33455 | typedef typename node_type::T3 T3; | |
33456 | ||
33457 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33458 | const details::operator_type& operation, | |
33459 | expression_node_ptr (&branch)[2]) | |
33460 | { | |
33461 | // ((v0 o0 c) o1 v1) o2 v2 | |
33462 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; | |
33463 | ||
33464 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); | |
33465 | const Type& v0 = vocov->t0(); | |
33466 | const Type c = vocov->t1(); | |
33467 | const Type& v1 = vocov->t2(); | |
33468 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33469 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); | |
33470 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); | |
33471 | const details::operator_type o2 = operation; | |
33472 | ||
33473 | binary_functor_t f0 = vocov->f0(); | |
33474 | binary_functor_t f1 = vocov->f1(); | |
33475 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33476 | ||
33477 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33478 | ||
33479 | expression_node_ptr result = error_node(); | |
33480 | ||
33481 | const bool synthesis_result = | |
33482 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33483 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); | |
33484 | ||
33485 | if (synthesis_result) | |
33486 | return result; | |
33487 | else if (!expr_gen.valid_operator(o2,f2)) | |
33488 | return error_node(); | |
33489 | ||
33490 | exprtk_debug(("((v0 o0 c) o1 v1) o2 v2\n")); | |
33491 | ||
33492 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); | |
33493 | } | |
33494 | ||
33495 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33496 | const details::operator_type o0, | |
33497 | const details::operator_type o1, | |
33498 | const details::operator_type o2) | |
33499 | { | |
33500 | return details::build_string() | |
33501 | << "((t" << expr_gen.to_str(o0) | |
33502 | << "t)" << expr_gen.to_str(o1) | |
33503 | << "t)" << expr_gen.to_str(o2) | |
33504 | << "t"; | |
33505 | } | |
33506 | }; | |
33507 | ||
33508 | struct synthesize_covovov_expression3 | |
33509 | { | |
33510 | typedef typename covovov_t::type3 node_type; | |
33511 | typedef typename covovov_t::sf4_type sf4_type; | |
33512 | typedef typename node_type::T0 T0; | |
33513 | typedef typename node_type::T1 T1; | |
33514 | typedef typename node_type::T2 T2; | |
33515 | typedef typename node_type::T3 T3; | |
33516 | ||
33517 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33518 | const details::operator_type& operation, | |
33519 | expression_node_ptr (&branch)[2]) | |
33520 | { | |
33521 | // ((c o0 v0) o1 v1) o2 v2 | |
33522 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; | |
33523 | ||
33524 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); | |
33525 | const Type c = covov->t0(); | |
33526 | const Type& v0 = covov->t1(); | |
33527 | const Type& v1 = covov->t2(); | |
33528 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33529 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); | |
33530 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); | |
33531 | const details::operator_type o2 = operation; | |
33532 | ||
33533 | binary_functor_t f0 = covov->f0(); | |
33534 | binary_functor_t f1 = covov->f1(); | |
33535 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33536 | ||
33537 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33538 | ||
33539 | expression_node_ptr result = error_node(); | |
33540 | ||
33541 | const bool synthesis_result = | |
33542 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33543 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); | |
33544 | ||
33545 | if (synthesis_result) | |
33546 | return result; | |
33547 | else if (!expr_gen.valid_operator(o2,f2)) | |
33548 | return error_node(); | |
33549 | ||
33550 | exprtk_debug(("((c o0 v0) o1 v1) o2 v2\n")); | |
33551 | ||
33552 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); | |
33553 | } | |
33554 | ||
33555 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33556 | const details::operator_type o0, | |
33557 | const details::operator_type o1, | |
33558 | const details::operator_type o2) | |
33559 | { | |
33560 | return details::build_string() | |
33561 | << "((t" << expr_gen.to_str(o0) | |
33562 | << "t)" << expr_gen.to_str(o1) | |
33563 | << "t)" << expr_gen.to_str(o2) | |
33564 | << "t"; | |
33565 | } | |
33566 | }; | |
33567 | ||
33568 | struct synthesize_covocov_expression3 | |
33569 | { | |
33570 | typedef typename covocov_t::type3 node_type; | |
33571 | typedef typename covocov_t::sf4_type sf4_type; | |
33572 | typedef typename node_type::T0 T0; | |
33573 | typedef typename node_type::T1 T1; | |
33574 | typedef typename node_type::T2 T2; | |
33575 | typedef typename node_type::T3 T3; | |
33576 | ||
33577 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33578 | const details::operator_type& operation, | |
33579 | expression_node_ptr (&branch)[2]) | |
33580 | { | |
33581 | // ((c0 o0 v0) o1 c1) o2 v1 | |
33582 | typedef typename synthesize_covoc_expression0::node_type lcl_covoc_t; | |
33583 | ||
33584 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); | |
33585 | const Type c0 = covoc->t0(); | |
33586 | const Type& v0 = covoc->t1(); | |
33587 | const Type c1 = covoc->t2(); | |
33588 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33589 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); | |
33590 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); | |
33591 | const details::operator_type o2 = operation; | |
33592 | ||
33593 | binary_functor_t f0 = covoc->f0(); | |
33594 | binary_functor_t f1 = covoc->f1(); | |
33595 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33596 | ||
33597 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33598 | ||
33599 | expression_node_ptr result = error_node(); | |
33600 | ||
33601 | const bool synthesis_result = | |
33602 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33603 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); | |
33604 | ||
33605 | if (synthesis_result) | |
33606 | return result; | |
33607 | else if (!expr_gen.valid_operator(o2,f2)) | |
33608 | return error_node(); | |
33609 | ||
33610 | exprtk_debug(("((c0 o0 v0) o1 c1) o2 v1\n")); | |
33611 | ||
33612 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); | |
33613 | } | |
33614 | ||
33615 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33616 | const details::operator_type o0, | |
33617 | const details::operator_type o1, | |
33618 | const details::operator_type o2) | |
33619 | { | |
33620 | return details::build_string() | |
33621 | << "((t" << expr_gen.to_str(o0) | |
33622 | << "t)" << expr_gen.to_str(o1) | |
33623 | << "t)" << expr_gen.to_str(o2) | |
33624 | << "t"; | |
33625 | } | |
33626 | }; | |
33627 | ||
33628 | struct synthesize_vocovoc_expression3 | |
33629 | { | |
33630 | typedef typename vocovoc_t::type3 node_type; | |
33631 | typedef typename vocovoc_t::sf4_type sf4_type; | |
33632 | typedef typename node_type::T0 T0; | |
33633 | typedef typename node_type::T1 T1; | |
33634 | typedef typename node_type::T2 T2; | |
33635 | typedef typename node_type::T3 T3; | |
33636 | ||
33637 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33638 | const details::operator_type& operation, | |
33639 | expression_node_ptr (&branch)[2]) | |
33640 | { | |
33641 | // ((v0 o0 c0) o1 v1) o2 c1 | |
33642 | typedef typename synthesize_vocov_expression0::node_type lcl_vocov_t; | |
33643 | ||
33644 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); | |
33645 | const Type& v0 = vocov->t0(); | |
33646 | const Type c0 = vocov->t1(); | |
33647 | const Type& v1 = vocov->t2(); | |
33648 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
33649 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); | |
33650 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); | |
33651 | const details::operator_type o2 = operation; | |
33652 | ||
33653 | binary_functor_t f0 = vocov->f0(); | |
33654 | binary_functor_t f1 = vocov->f1(); | |
33655 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33656 | ||
33657 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33658 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33659 | ||
33660 | expression_node_ptr result = error_node(); | |
33661 | ||
33662 | const bool synthesis_result = | |
33663 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33664 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); | |
33665 | ||
33666 | if (synthesis_result) | |
33667 | return result; | |
33668 | else if (!expr_gen.valid_operator(o2,f2)) | |
33669 | return error_node(); | |
33670 | ||
33671 | exprtk_debug(("((v0 o0 c0) o1 v1) o2 c1\n")); | |
33672 | ||
33673 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); | |
33674 | } | |
33675 | ||
33676 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33677 | const details::operator_type o0, | |
33678 | const details::operator_type o1, | |
33679 | const details::operator_type o2) | |
33680 | { | |
33681 | return details::build_string() | |
33682 | << "((t" << expr_gen.to_str(o0) | |
33683 | << "t)" << expr_gen.to_str(o1) | |
33684 | << "t)" << expr_gen.to_str(o2) | |
33685 | << "t"; | |
33686 | } | |
33687 | }; | |
33688 | ||
33689 | struct synthesize_covovoc_expression3 | |
33690 | { | |
33691 | typedef typename covovoc_t::type3 node_type; | |
33692 | typedef typename covovoc_t::sf4_type sf4_type; | |
33693 | typedef typename node_type::T0 T0; | |
33694 | typedef typename node_type::T1 T1; | |
33695 | typedef typename node_type::T2 T2; | |
33696 | typedef typename node_type::T3 T3; | |
33697 | ||
33698 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33699 | const details::operator_type& operation, | |
33700 | expression_node_ptr (&branch)[2]) | |
33701 | { | |
33702 | // ((c0 o0 v0) o1 v1) o2 c1 | |
33703 | typedef typename synthesize_covov_expression0::node_type lcl_covov_t; | |
33704 | ||
33705 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); | |
33706 | const Type c0 = covov->t0(); | |
33707 | const Type& v0 = covov->t1(); | |
33708 | const Type& v1 = covov->t2(); | |
33709 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
33710 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); | |
33711 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); | |
33712 | const details::operator_type o2 = operation; | |
33713 | ||
33714 | binary_functor_t f0 = covov->f0(); | |
33715 | binary_functor_t f1 = covov->f1(); | |
33716 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33717 | ||
33718 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33719 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33720 | ||
33721 | expression_node_ptr result = error_node(); | |
33722 | ||
33723 | const bool synthesis_result = | |
33724 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33725 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); | |
33726 | ||
33727 | if (synthesis_result) | |
33728 | return result; | |
33729 | else if (!expr_gen.valid_operator(o2,f2)) | |
33730 | return error_node(); | |
33731 | ||
33732 | exprtk_debug(("((c0 o0 v0) o1 v1) o2 c1\n")); | |
33733 | ||
33734 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); | |
33735 | } | |
33736 | ||
33737 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33738 | const details::operator_type o0, | |
33739 | const details::operator_type o1, | |
33740 | const details::operator_type o2) | |
33741 | { | |
33742 | return details::build_string() | |
33743 | << "((t" << expr_gen.to_str(o0) | |
33744 | << "t)" << expr_gen.to_str(o1) | |
33745 | << "t)" << expr_gen.to_str(o2) | |
33746 | << "t"; | |
33747 | } | |
33748 | }; | |
33749 | ||
33750 | struct synthesize_vococov_expression3 | |
33751 | { | |
33752 | typedef typename vococov_t::type3 node_type; | |
33753 | typedef typename vococov_t::sf4_type sf4_type; | |
33754 | typedef typename node_type::T0 T0; | |
33755 | typedef typename node_type::T1 T1; | |
33756 | typedef typename node_type::T2 T2; | |
33757 | typedef typename node_type::T3 T3; | |
33758 | ||
33759 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33760 | const details::operator_type& operation, | |
33761 | expression_node_ptr (&branch)[2]) | |
33762 | { | |
33763 | // ((v0 o0 c0) o1 c1) o2 v1 | |
33764 | typedef typename synthesize_vococ_expression0::node_type lcl_vococ_t; | |
33765 | ||
33766 | const lcl_vococ_t* vococ = static_cast<const lcl_vococ_t*>(branch[0]); | |
33767 | const Type& v0 = vococ->t0(); | |
33768 | const Type c0 = vococ->t1(); | |
33769 | const Type c1 = vococ->t2(); | |
33770 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33771 | const details::operator_type o0 = expr_gen.get_operator(vococ->f0()); | |
33772 | const details::operator_type o1 = expr_gen.get_operator(vococ->f1()); | |
33773 | const details::operator_type o2 = operation; | |
33774 | ||
33775 | binary_functor_t f0 = vococ->f0(); | |
33776 | binary_functor_t f1 = vococ->f1(); | |
33777 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33778 | ||
33779 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33780 | ||
33781 | expression_node_ptr result = error_node(); | |
33782 | ||
33783 | const bool synthesis_result = | |
33784 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33785 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, c1, v1, result); | |
33786 | ||
33787 | if (synthesis_result) | |
33788 | return result; | |
33789 | else if (!expr_gen.valid_operator(o2,f2)) | |
33790 | return error_node(); | |
33791 | ||
33792 | exprtk_debug(("((v0 o0 c0) o1 c1) o2 v1\n")); | |
33793 | ||
33794 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, c1, v1, f0, f1, f2); | |
33795 | } | |
33796 | ||
33797 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33798 | const details::operator_type o0, | |
33799 | const details::operator_type o1, | |
33800 | const details::operator_type o2) | |
33801 | { | |
33802 | return details::build_string() | |
33803 | << "((t" << expr_gen.to_str(o0) | |
33804 | << "t)" << expr_gen.to_str(o1) | |
33805 | << "t)" << expr_gen.to_str(o2) | |
33806 | << "t"; | |
33807 | } | |
33808 | }; | |
33809 | ||
33810 | struct synthesize_vovovov_expression4 | |
33811 | { | |
33812 | typedef typename vovovov_t::type4 node_type; | |
33813 | typedef typename vovovov_t::sf4_type sf4_type; | |
33814 | typedef typename node_type::T0 T0; | |
33815 | typedef typename node_type::T1 T1; | |
33816 | typedef typename node_type::T2 T2; | |
33817 | typedef typename node_type::T3 T3; | |
33818 | ||
33819 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33820 | const details::operator_type& operation, | |
33821 | expression_node_ptr (&branch)[2]) | |
33822 | { | |
33823 | // (v0 o0 (v1 o1 v2)) o2 v3 | |
33824 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; | |
33825 | ||
33826 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); | |
33827 | const Type& v0 = vovov->t0(); | |
33828 | const Type& v1 = vovov->t1(); | |
33829 | const Type& v2 = vovov->t2(); | |
33830 | const Type& v3 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33831 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); | |
33832 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); | |
33833 | const details::operator_type o2 = operation; | |
33834 | ||
33835 | binary_functor_t f0 = vovov->f0(); | |
33836 | binary_functor_t f1 = vovov->f1(); | |
33837 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33838 | ||
33839 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33840 | ||
33841 | expression_node_ptr result = error_node(); | |
33842 | ||
33843 | const bool synthesis_result = | |
33844 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33845 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); | |
33846 | ||
33847 | if (synthesis_result) | |
33848 | return result; | |
33849 | else if (!expr_gen.valid_operator(o2,f2)) | |
33850 | return error_node(); | |
33851 | ||
33852 | exprtk_debug(("(v0 o0 (v1 o1 v2)) o2 v3\n")); | |
33853 | ||
33854 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, v3, f0, f1, f2); | |
33855 | } | |
33856 | ||
33857 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33858 | const details::operator_type o0, | |
33859 | const details::operator_type o1, | |
33860 | const details::operator_type o2) | |
33861 | { | |
33862 | return details::build_string() | |
33863 | << "(t" << expr_gen.to_str(o0) | |
33864 | << "(t" << expr_gen.to_str(o1) | |
33865 | << "t)" << expr_gen.to_str(o2) | |
33866 | << "t"; | |
33867 | } | |
33868 | }; | |
33869 | ||
33870 | struct synthesize_vovovoc_expression4 | |
33871 | { | |
33872 | typedef typename vovovoc_t::type4 node_type; | |
33873 | typedef typename vovovoc_t::sf4_type sf4_type; | |
33874 | typedef typename node_type::T0 T0; | |
33875 | typedef typename node_type::T1 T1; | |
33876 | typedef typename node_type::T2 T2; | |
33877 | typedef typename node_type::T3 T3; | |
33878 | ||
33879 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33880 | const details::operator_type& operation, | |
33881 | expression_node_ptr (&branch)[2]) | |
33882 | { | |
33883 | // ((v0 o0 (v1 o1 v2)) o2 c) | |
33884 | typedef typename synthesize_vovov_expression1::node_type lcl_vovov_t; | |
33885 | ||
33886 | const lcl_vovov_t* vovov = static_cast<const lcl_vovov_t*>(branch[0]); | |
33887 | const Type& v0 = vovov->t0(); | |
33888 | const Type& v1 = vovov->t1(); | |
33889 | const Type& v2 = vovov->t2(); | |
33890 | const Type c = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
33891 | const details::operator_type o0 = expr_gen.get_operator(vovov->f0()); | |
33892 | const details::operator_type o1 = expr_gen.get_operator(vovov->f1()); | |
33893 | const details::operator_type o2 = operation; | |
33894 | ||
33895 | binary_functor_t f0 = vovov->f0(); | |
33896 | binary_functor_t f1 = vovov->f1(); | |
33897 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33898 | ||
33899 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33900 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
33901 | ||
33902 | expression_node_ptr result = error_node(); | |
33903 | ||
33904 | const bool synthesis_result = | |
33905 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33906 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, c, result); | |
33907 | ||
33908 | if (synthesis_result) | |
33909 | return result; | |
33910 | else if (!expr_gen.valid_operator(o2,f2)) | |
33911 | return error_node(); | |
33912 | ||
33913 | exprtk_debug(("((v0 o0 (v1 o1 v2)) o2 c)\n")); | |
33914 | ||
33915 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, v2, c, f0, f1, f2); | |
33916 | } | |
33917 | ||
33918 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33919 | const details::operator_type o0, | |
33920 | const details::operator_type o1, | |
33921 | const details::operator_type o2) | |
33922 | { | |
33923 | return details::build_string() | |
33924 | << "(t" << expr_gen.to_str(o0) | |
33925 | << "(t" << expr_gen.to_str(o1) | |
33926 | << "t)" << expr_gen.to_str(o2) | |
33927 | << "t"; | |
33928 | } | |
33929 | }; | |
33930 | ||
33931 | struct synthesize_vovocov_expression4 | |
33932 | { | |
33933 | typedef typename vovocov_t::type4 node_type; | |
33934 | typedef typename vovocov_t::sf4_type sf4_type; | |
33935 | typedef typename node_type::T0 T0; | |
33936 | typedef typename node_type::T1 T1; | |
33937 | typedef typename node_type::T2 T2; | |
33938 | typedef typename node_type::T3 T3; | |
33939 | ||
33940 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
33941 | const details::operator_type& operation, | |
33942 | expression_node_ptr (&branch)[2]) | |
33943 | { | |
33944 | // ((v0 o0 (v1 o1 c)) o2 v1) | |
33945 | typedef typename synthesize_vovoc_expression1::node_type lcl_vovoc_t; | |
33946 | ||
33947 | const lcl_vovoc_t* vovoc = static_cast<const lcl_vovoc_t*>(branch[0]); | |
33948 | const Type& v0 = vovoc->t0(); | |
33949 | const Type& v1 = vovoc->t1(); | |
33950 | const Type c = vovoc->t2(); | |
33951 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
33952 | const details::operator_type o0 = expr_gen.get_operator(vovoc->f0()); | |
33953 | const details::operator_type o1 = expr_gen.get_operator(vovoc->f1()); | |
33954 | const details::operator_type o2 = operation; | |
33955 | ||
33956 | binary_functor_t f0 = vovoc->f0(); | |
33957 | binary_functor_t f1 = vovoc->f1(); | |
33958 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
33959 | ||
33960 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
33961 | ||
33962 | expression_node_ptr result = error_node(); | |
33963 | ||
33964 | const bool synthesis_result = | |
33965 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
33966 | (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, c, v2, result); | |
33967 | ||
33968 | if (synthesis_result) | |
33969 | return result; | |
33970 | else if (!expr_gen.valid_operator(o2,f2)) | |
33971 | return error_node(); | |
33972 | ||
33973 | exprtk_debug(("((v0 o0 (v1 o1 c)) o2 v1)\n")); | |
33974 | ||
33975 | return node_type::allocate(*(expr_gen.node_allocator_), v0, v1, c, v2, f0, f1, f2); | |
33976 | } | |
33977 | ||
33978 | static inline std::string id(expression_generator<Type>& expr_gen, | |
33979 | const details::operator_type o0, | |
33980 | const details::operator_type o1, | |
33981 | const details::operator_type o2) | |
33982 | { | |
33983 | return details::build_string() | |
33984 | << "(t" << expr_gen.to_str(o0) | |
33985 | << "(t" << expr_gen.to_str(o1) | |
33986 | << "t)" << expr_gen.to_str(o2) | |
33987 | << "t"; | |
33988 | } | |
33989 | }; | |
33990 | ||
33991 | struct synthesize_vocovov_expression4 | |
33992 | { | |
33993 | typedef typename vocovov_t::type4 node_type; | |
33994 | typedef typename vocovov_t::sf4_type sf4_type; | |
33995 | typedef typename node_type::T0 T0; | |
33996 | typedef typename node_type::T1 T1; | |
33997 | typedef typename node_type::T2 T2; | |
33998 | typedef typename node_type::T3 T3; | |
33999 | ||
34000 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
34001 | const details::operator_type& operation, | |
34002 | expression_node_ptr (&branch)[2]) | |
34003 | { | |
34004 | // ((v0 o0 (c o1 v1)) o2 v2) | |
34005 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; | |
34006 | ||
34007 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); | |
34008 | const Type& v0 = vocov->t0(); | |
34009 | const Type c = vocov->t1(); | |
34010 | const Type& v1 = vocov->t2(); | |
34011 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
34012 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); | |
34013 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); | |
34014 | const details::operator_type o2 = operation; | |
34015 | ||
34016 | binary_functor_t f0 = vocov->f0(); | |
34017 | binary_functor_t f1 = vocov->f1(); | |
34018 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
34019 | ||
34020 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
34021 | expression_node_ptr result = error_node(); | |
34022 | ||
34023 | const bool synthesis_result = | |
34024 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
34025 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c, v1, v2, result); | |
34026 | ||
34027 | if (synthesis_result) | |
34028 | return result; | |
34029 | else if (!expr_gen.valid_operator(o2,f2)) | |
34030 | return error_node(); | |
34031 | ||
34032 | exprtk_debug(("((v0 o0 (c o1 v1)) o2 v2)\n")); | |
34033 | ||
34034 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c, v1, v2, f0, f1, f2); | |
34035 | } | |
34036 | ||
34037 | static inline std::string id(expression_generator<Type>& expr_gen, | |
34038 | const details::operator_type o0, | |
34039 | const details::operator_type o1, | |
34040 | const details::operator_type o2) | |
34041 | { | |
34042 | return details::build_string() | |
34043 | << "(t" << expr_gen.to_str(o0) | |
34044 | << "(t" << expr_gen.to_str(o1) | |
34045 | << "t)" << expr_gen.to_str(o2) | |
34046 | << "t"; | |
34047 | } | |
34048 | }; | |
34049 | ||
34050 | struct synthesize_covovov_expression4 | |
34051 | { | |
34052 | typedef typename covovov_t::type4 node_type; | |
34053 | typedef typename covovov_t::sf4_type sf4_type; | |
34054 | typedef typename node_type::T0 T0; | |
34055 | typedef typename node_type::T1 T1; | |
34056 | typedef typename node_type::T2 T2; | |
34057 | typedef typename node_type::T3 T3; | |
34058 | ||
34059 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
34060 | const details::operator_type& operation, | |
34061 | expression_node_ptr (&branch)[2]) | |
34062 | { | |
34063 | // ((c o0 (v0 o1 v1)) o2 v2) | |
34064 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; | |
34065 | ||
34066 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); | |
34067 | const Type c = covov->t0(); | |
34068 | const Type& v0 = covov->t1(); | |
34069 | const Type& v1 = covov->t2(); | |
34070 | const Type& v2 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
34071 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); | |
34072 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); | |
34073 | const details::operator_type o2 = operation; | |
34074 | ||
34075 | binary_functor_t f0 = covov->f0(); | |
34076 | binary_functor_t f1 = covov->f1(); | |
34077 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
34078 | ||
34079 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
34080 | ||
34081 | expression_node_ptr result = error_node(); | |
34082 | ||
34083 | const bool synthesis_result = | |
34084 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
34085 | (expr_gen, id(expr_gen, o0, o1, o2), c, v0, v1, v2, result); | |
34086 | ||
34087 | if (synthesis_result) | |
34088 | return result; | |
34089 | else if (!expr_gen.valid_operator(o2,f2)) | |
34090 | return error_node(); | |
34091 | ||
34092 | exprtk_debug(("((c o0 (v0 o1 v1)) o2 v2)\n")); | |
34093 | ||
34094 | return node_type::allocate(*(expr_gen.node_allocator_), c, v0, v1, v2, f0, f1, f2); | |
34095 | } | |
34096 | ||
34097 | static inline std::string id(expression_generator<Type>& expr_gen, | |
34098 | const details::operator_type o0, | |
34099 | const details::operator_type o1, | |
34100 | const details::operator_type o2) | |
34101 | { | |
34102 | return details::build_string() | |
34103 | << "(t" << expr_gen.to_str(o0) | |
34104 | << "(t" << expr_gen.to_str(o1) | |
34105 | << "t)" << expr_gen.to_str(o2) | |
34106 | << "t"; | |
34107 | } | |
34108 | }; | |
34109 | ||
34110 | struct synthesize_covocov_expression4 | |
34111 | { | |
34112 | typedef typename covocov_t::type4 node_type; | |
34113 | typedef typename covocov_t::sf4_type sf4_type; | |
34114 | typedef typename node_type::T0 T0; | |
34115 | typedef typename node_type::T1 T1; | |
34116 | typedef typename node_type::T2 T2; | |
34117 | typedef typename node_type::T3 T3; | |
34118 | ||
34119 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
34120 | const details::operator_type& operation, | |
34121 | expression_node_ptr (&branch)[2]) | |
34122 | { | |
34123 | // ((c0 o0 (v0 o1 c1)) o2 v1) | |
34124 | typedef typename synthesize_covoc_expression1::node_type lcl_covoc_t; | |
34125 | ||
34126 | const lcl_covoc_t* covoc = static_cast<const lcl_covoc_t*>(branch[0]); | |
34127 | const Type c0 = covoc->t0(); | |
34128 | const Type& v0 = covoc->t1(); | |
34129 | const Type c1 = covoc->t2(); | |
34130 | const Type& v1 = static_cast<details::variable_node<Type>*>(branch[1])->ref(); | |
34131 | const details::operator_type o0 = expr_gen.get_operator(covoc->f0()); | |
34132 | const details::operator_type o1 = expr_gen.get_operator(covoc->f1()); | |
34133 | const details::operator_type o2 = operation; | |
34134 | ||
34135 | binary_functor_t f0 = covoc->f0(); | |
34136 | binary_functor_t f1 = covoc->f1(); | |
34137 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
34138 | ||
34139 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
34140 | ||
34141 | expression_node_ptr result = error_node(); | |
34142 | ||
34143 | const bool synthesis_result = | |
34144 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
34145 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, c1, v1, result); | |
34146 | ||
34147 | if (synthesis_result) | |
34148 | return result; | |
34149 | else if (!expr_gen.valid_operator(o2,f2)) | |
34150 | return error_node(); | |
34151 | ||
34152 | exprtk_debug(("((c0 o0 (v0 o1 c1)) o2 v1)\n")); | |
34153 | ||
34154 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, c1, v1, f0, f1, f2); | |
34155 | } | |
34156 | ||
34157 | static inline std::string id(expression_generator<Type>& expr_gen, | |
34158 | const details::operator_type o0, | |
34159 | const details::operator_type o1, | |
34160 | const details::operator_type o2) | |
34161 | { | |
34162 | return details::build_string() | |
34163 | << "(t" << expr_gen.to_str(o0) | |
34164 | << "(t" << expr_gen.to_str(o1) | |
34165 | << "t)" << expr_gen.to_str(o2) | |
34166 | << "t"; | |
34167 | } | |
34168 | }; | |
34169 | ||
34170 | struct synthesize_vocovoc_expression4 | |
34171 | { | |
34172 | typedef typename vocovoc_t::type4 node_type; | |
34173 | typedef typename vocovoc_t::sf4_type sf4_type; | |
34174 | typedef typename node_type::T0 T0; | |
34175 | typedef typename node_type::T1 T1; | |
34176 | typedef typename node_type::T2 T2; | |
34177 | typedef typename node_type::T3 T3; | |
34178 | ||
34179 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
34180 | const details::operator_type& operation, | |
34181 | expression_node_ptr (&branch)[2]) | |
34182 | { | |
34183 | // ((v0 o0 (c0 o1 v1)) o2 c1) | |
34184 | typedef typename synthesize_vocov_expression1::node_type lcl_vocov_t; | |
34185 | ||
34186 | const lcl_vocov_t* vocov = static_cast<const lcl_vocov_t*>(branch[0]); | |
34187 | const Type& v0 = vocov->t0(); | |
34188 | const Type c0 = vocov->t1(); | |
34189 | const Type& v1 = vocov->t2(); | |
34190 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
34191 | const details::operator_type o0 = expr_gen.get_operator(vocov->f0()); | |
34192 | const details::operator_type o1 = expr_gen.get_operator(vocov->f1()); | |
34193 | const details::operator_type o2 = operation; | |
34194 | ||
34195 | binary_functor_t f0 = vocov->f0(); | |
34196 | binary_functor_t f1 = vocov->f1(); | |
34197 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
34198 | ||
34199 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
34200 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
34201 | ||
34202 | expression_node_ptr result = error_node(); | |
34203 | ||
34204 | const bool synthesis_result = | |
34205 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
34206 | (expr_gen, id(expr_gen, o0, o1, o2), v0, c0, v1, c1, result); | |
34207 | ||
34208 | if (synthesis_result) | |
34209 | return result; | |
34210 | else if (!expr_gen.valid_operator(o2,f2)) | |
34211 | return error_node(); | |
34212 | ||
34213 | exprtk_debug(("((v0 o0 (c0 o1 v1)) o2 c1)\n")); | |
34214 | ||
34215 | return node_type::allocate(*(expr_gen.node_allocator_), v0, c0, v1, c1, f0, f1, f2); | |
34216 | } | |
34217 | ||
34218 | static inline std::string id(expression_generator<Type>& expr_gen, | |
34219 | const details::operator_type o0, | |
34220 | const details::operator_type o1, | |
34221 | const details::operator_type o2) | |
34222 | { | |
34223 | return details::build_string() | |
34224 | << "(t" << expr_gen.to_str(o0) | |
34225 | << "(t" << expr_gen.to_str(o1) | |
34226 | << "t)" << expr_gen.to_str(o2) | |
34227 | << "t"; | |
34228 | } | |
34229 | }; | |
34230 | ||
34231 | struct synthesize_covovoc_expression4 | |
34232 | { | |
34233 | typedef typename covovoc_t::type4 node_type; | |
34234 | typedef typename covovoc_t::sf4_type sf4_type; | |
34235 | typedef typename node_type::T0 T0; | |
34236 | typedef typename node_type::T1 T1; | |
34237 | typedef typename node_type::T2 T2; | |
34238 | typedef typename node_type::T3 T3; | |
34239 | ||
34240 | static inline expression_node_ptr process(expression_generator<Type>& expr_gen, | |
34241 | const details::operator_type& operation, | |
34242 | expression_node_ptr (&branch)[2]) | |
34243 | { | |
34244 | // ((c0 o0 (v0 o1 v1)) o2 c1) | |
34245 | typedef typename synthesize_covov_expression1::node_type lcl_covov_t; | |
34246 | ||
34247 | const lcl_covov_t* covov = static_cast<const lcl_covov_t*>(branch[0]); | |
34248 | const Type c0 = covov->t0(); | |
34249 | const Type& v0 = covov->t1(); | |
34250 | const Type& v1 = covov->t2(); | |
34251 | const Type c1 = static_cast<details::literal_node<Type>*>(branch[1])->value(); | |
34252 | const details::operator_type o0 = expr_gen.get_operator(covov->f0()); | |
34253 | const details::operator_type o1 = expr_gen.get_operator(covov->f1()); | |
34254 | const details::operator_type o2 = operation; | |
34255 | ||
34256 | binary_functor_t f0 = covov->f0(); | |
34257 | binary_functor_t f1 = covov->f1(); | |
34258 | binary_functor_t f2 = reinterpret_cast<binary_functor_t>(0); | |
34259 | ||
34260 | details::free_node(*(expr_gen.node_allocator_),branch[0]); | |
34261 | details::free_node(*(expr_gen.node_allocator_),branch[1]); | |
34262 | ||
34263 | expression_node_ptr result = error_node(); | |
34264 | ||
34265 | const bool synthesis_result = | |
34266 | synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> | |
34267 | (expr_gen, id(expr_gen, o0, o1, o2), c0, v0, v1, c1, result); | |
34268 | ||
34269 | if (synthesis_result) | |
34270 | return result; | |
34271 | else if (!expr_gen.valid_operator(o2,f2)) | |
34272 | return error_node(); | |
34273 | ||
34274 | exprtk_debug(("((c0 o0 (v0 o1 v1)) o2 c1)\n")); | |
34275 | ||
34276 | return node_type::allocate(*(expr_gen.node_allocator_), c0, v0, v1, c1, f0, f1, f2); | |
34277 | } | |
34278 | ||
34279 | static inline std::string id(expression_generator<Type>& expr_gen, | |
34280 | const details::operator_type o0, | |
34281 | const details::operator_type o1, | |
34282 | const details::operator_type o2) | |
34283 | { | |
34284 | return details::build_string() | |
34285 | << "(t" << expr_gen.to_str(o0) | |
34286 | << "(t" << expr_gen.to_str(o1) | |
34287 | << "t)" << expr_gen.to_str(o2) | |
34288 | << "t"; | |
34289 | } | |
34290 | }; | |
34291 | ||
34292 | struct synthesize_vococov_expression4 | |
34293 | { | |
34294 | typedef typename vococov_t::type4 node_type; | |
34295 | static inline expression_node_ptr process(expression_generator<Type>&, const details::operator_type&, expression_node_ptr (&)[2]) | |
34296 | { | |
34297 | // ((v0 o0 (c0 o1 c1)) o2 v1) - Not possible | |
34298 | exprtk_debug(("((v0 o0 (c0 o1 c1)) o2 v1) - Not possible\n")); | |
34299 | return error_node(); | |
34300 | } | |
34301 | ||
34302 | static inline std::string id(expression_generator<Type>&, | |
34303 | const details::operator_type, const details::operator_type, const details::operator_type) | |
34304 | { | |
34305 | return "INVALID"; | |
34306 | } | |
34307 | }; | |
34308 | #endif | |
34309 | ||
34310 | inline expression_node_ptr synthesize_uvouv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) | |
34311 | { | |
34312 | // Definition: uv o uv | |
34313 | details::operator_type o0 = static_cast<details::uv_base_node<Type>*>(branch[0])->operation(); | |
34314 | details::operator_type o1 = static_cast<details::uv_base_node<Type>*>(branch[1])->operation(); | |
34315 | const Type& v0 = static_cast<details::uv_base_node<Type>*>(branch[0])->v(); | |
34316 | const Type& v1 = static_cast<details::uv_base_node<Type>*>(branch[1])->v(); | |
34317 | unary_functor_t u0 = reinterpret_cast<unary_functor_t> (0); | |
34318 | unary_functor_t u1 = reinterpret_cast<unary_functor_t> (0); | |
34319 | binary_functor_t f = reinterpret_cast<binary_functor_t>(0); | |
34320 | ||
34321 | if (!valid_operator(o0,u0)) | |
34322 | return error_node(); | |
34323 | else if (!valid_operator(o1,u1)) | |
34324 | return error_node(); | |
34325 | else if (!valid_operator(operation,f)) | |
34326 | return error_node(); | |
34327 | ||
34328 | expression_node_ptr result = error_node(); | |
34329 | ||
34330 | if ( | |
34331 | (details::e_neg == o0) && | |
34332 | (details::e_neg == o1) | |
34333 | ) | |
34334 | { | |
34335 | switch (operation) | |
34336 | { | |
34337 | // (-v0 + -v1) --> -(v0 + v1) | |
34338 | case details::e_add : result = (*this)(details::e_neg, | |
34339 | node_allocator_-> | |
34340 | allocate_rr<typename details:: | |
34341 | vov_node<Type,details::add_op<Type> > >(v0, v1)); | |
34342 | exprtk_debug(("(-v0 + -v1) --> -(v0 + v1)\n")); | |
34343 | break; | |
34344 | ||
34345 | // (-v0 - -v1) --> (v1 - v0) | |
34346 | case details::e_sub : result = node_allocator_-> | |
34347 | allocate_rr<typename details:: | |
34348 | vov_node<Type,details::sub_op<Type> > >(v1, v0); | |
34349 | exprtk_debug(("(-v0 - -v1) --> (v1 - v0)\n")); | |
34350 | break; | |
34351 | ||
34352 | // (-v0 * -v1) --> (v0 * v1) | |
34353 | case details::e_mul : result = node_allocator_-> | |
34354 | allocate_rr<typename details:: | |
34355 | vov_node<Type,details::mul_op<Type> > >(v0, v1); | |
34356 | exprtk_debug(("(-v0 * -v1) --> (v0 * v1)\n")); | |
34357 | break; | |
34358 | ||
34359 | // (-v0 / -v1) --> (v0 / v1) | |
34360 | case details::e_div : result = node_allocator_-> | |
34361 | allocate_rr<typename details:: | |
34362 | vov_node<Type,details::div_op<Type> > >(v0, v1); | |
34363 | exprtk_debug(("(-v0 / -v1) --> (v0 / v1)\n")); | |
34364 | break; | |
34365 | ||
34366 | default : break; | |
34367 | } | |
34368 | } | |
34369 | ||
34370 | if (0 == result) | |
34371 | { | |
34372 | result = node_allocator_-> | |
34373 | allocate_rrrrr<typename details::uvouv_node<Type> >(v0, v1, u0, u1, f); | |
34374 | } | |
34375 | ||
34376 | details::free_all_nodes(*node_allocator_,branch); | |
34377 | return result; | |
34378 | } | |
34379 | ||
34380 | #undef basic_opr_switch_statements | |
34381 | #undef extended_opr_switch_statements | |
34382 | #undef unary_opr_switch_statements | |
34383 | ||
34384 | #ifndef exprtk_disable_string_capabilities | |
34385 | ||
34386 | #define string_opr_switch_statements \ | |
34387 | case_stmt(details:: e_lt ,details:: lt_op) \ | |
34388 | case_stmt(details:: e_lte ,details:: lte_op) \ | |
34389 | case_stmt(details:: e_gt ,details:: gt_op) \ | |
34390 | case_stmt(details:: e_gte ,details:: gte_op) \ | |
34391 | case_stmt(details:: e_eq ,details:: eq_op) \ | |
34392 | case_stmt(details:: e_ne ,details:: ne_op) \ | |
34393 | case_stmt(details::e_in ,details:: in_op) \ | |
34394 | case_stmt(details::e_like ,details:: like_op) \ | |
34395 | case_stmt(details::e_ilike,details::ilike_op) \ | |
34396 | ||
34397 | template <typename T0, typename T1> | |
34398 | inline expression_node_ptr synthesize_str_xrox_expression_impl(const details::operator_type& opr, | |
34399 | T0 s0, T1 s1, | |
34400 | range_t rp0) | |
34401 | { | |
34402 | switch (opr) | |
34403 | { | |
34404 | #define case_stmt(op0,op1) \ | |
34405 | case op0 : return node_allocator_-> \ | |
34406 | allocate_ttt<typename details::str_xrox_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ | |
34407 | (s0, s1, rp0); \ | |
34408 | ||
34409 | string_opr_switch_statements | |
34410 | #undef case_stmt | |
34411 | default : return error_node(); | |
34412 | } | |
34413 | } | |
34414 | ||
34415 | template <typename T0, typename T1> | |
34416 | inline expression_node_ptr synthesize_str_xoxr_expression_impl(const details::operator_type& opr, | |
34417 | T0 s0, T1 s1, | |
34418 | range_t rp1) | |
34419 | { | |
34420 | switch (opr) | |
34421 | { | |
34422 | #define case_stmt(op0,op1) \ | |
34423 | case op0 : return node_allocator_-> \ | |
34424 | allocate_ttt<typename details::str_xoxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ | |
34425 | (s0, s1, rp1); \ | |
34426 | ||
34427 | string_opr_switch_statements | |
34428 | #undef case_stmt | |
34429 | default : return error_node(); | |
34430 | } | |
34431 | } | |
34432 | ||
34433 | template <typename T0, typename T1> | |
34434 | inline expression_node_ptr synthesize_str_xroxr_expression_impl(const details::operator_type& opr, | |
34435 | T0 s0, T1 s1, | |
34436 | range_t rp0, range_t rp1) | |
34437 | { | |
34438 | switch (opr) | |
34439 | { | |
34440 | #define case_stmt(op0,op1) \ | |
34441 | case op0 : return node_allocator_-> \ | |
34442 | allocate_tttt<typename details::str_xroxr_node<Type,T0,T1,range_t,op1<Type> >,T0,T1> \ | |
34443 | (s0, s1, rp0, rp1); \ | |
34444 | ||
34445 | string_opr_switch_statements | |
34446 | #undef case_stmt | |
34447 | default : return error_node(); | |
34448 | } | |
34449 | } | |
34450 | ||
34451 | template <typename T0, typename T1> | |
34452 | inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1) | |
34453 | { | |
34454 | switch (opr) | |
34455 | { | |
34456 | #define case_stmt(op0,op1) \ | |
34457 | case op0 : return node_allocator_-> \ | |
34458 | allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0, s1); \ | |
34459 | ||
34460 | string_opr_switch_statements | |
34461 | #undef case_stmt | |
34462 | default : return error_node(); | |
34463 | } | |
34464 | } | |
34465 | ||
34466 | inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34467 | { | |
34468 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); | |
34469 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); | |
34470 | ||
34471 | return synthesize_sos_expression_impl<std::string&,std::string&>(opr, s0, s1); | |
34472 | } | |
34473 | ||
34474 | inline expression_node_ptr synthesize_sros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34475 | { | |
34476 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); | |
34477 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); | |
34478 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); | |
34479 | ||
34480 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34481 | ||
34482 | free_node(*node_allocator_,branch[0]); | |
34483 | ||
34484 | return synthesize_str_xrox_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0); | |
34485 | } | |
34486 | ||
34487 | inline expression_node_ptr synthesize_sosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34488 | { | |
34489 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); | |
34490 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); | |
34491 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); | |
34492 | ||
34493 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34494 | ||
34495 | free_node(*node_allocator_,branch[1]); | |
34496 | ||
34497 | return synthesize_str_xoxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp1); | |
34498 | } | |
34499 | ||
34500 | inline expression_node_ptr synthesize_socsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34501 | { | |
34502 | std::string& s0 = static_cast<details::stringvar_node<Type>*> (branch[0])->ref (); | |
34503 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); | |
34504 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); | |
34505 | ||
34506 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34507 | ||
34508 | free_node(*node_allocator_,branch[1]); | |
34509 | ||
34510 | return synthesize_str_xoxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp1); | |
34511 | } | |
34512 | ||
34513 | inline expression_node_ptr synthesize_srosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34514 | { | |
34515 | std::string& s0 = static_cast<details::string_range_node<Type>*>(branch[0])->ref (); | |
34516 | std::string& s1 = static_cast<details::string_range_node<Type>*>(branch[1])->ref (); | |
34517 | range_t rp0 = static_cast<details::string_range_node<Type>*>(branch[0])->range(); | |
34518 | range_t rp1 = static_cast<details::string_range_node<Type>*>(branch[1])->range(); | |
34519 | ||
34520 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34521 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34522 | ||
34523 | details::free_node(*node_allocator_,branch[0]); | |
34524 | details::free_node(*node_allocator_,branch[1]); | |
34525 | ||
34526 | return synthesize_str_xroxr_expression_impl<std::string&,std::string&>(opr, s0, s1, rp0, rp1); | |
34527 | } | |
34528 | ||
34529 | inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34530 | { | |
34531 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); | |
34532 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); | |
34533 | ||
34534 | details::free_node(*node_allocator_,branch[1]); | |
34535 | ||
34536 | return synthesize_sos_expression_impl<std::string&, const std::string>(opr, s0, s1); | |
34537 | } | |
34538 | ||
34539 | inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34540 | { | |
34541 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); | |
34542 | std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); | |
34543 | ||
34544 | details::free_node(*node_allocator_,branch[0]); | |
34545 | ||
34546 | return synthesize_sos_expression_impl<const std::string,std::string&>(opr, s0, s1); | |
34547 | } | |
34548 | ||
34549 | inline expression_node_ptr synthesize_csosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34550 | { | |
34551 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str (); | |
34552 | std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref (); | |
34553 | range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); | |
34554 | ||
34555 | static_cast<details::string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34556 | ||
34557 | details::free_node(*node_allocator_,branch[0]); | |
34558 | details::free_node(*node_allocator_,branch[1]); | |
34559 | ||
34560 | return synthesize_str_xoxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp1); | |
34561 | } | |
34562 | ||
34563 | inline expression_node_ptr synthesize_srocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34564 | { | |
34565 | std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref (); | |
34566 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str (); | |
34567 | range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range(); | |
34568 | ||
34569 | static_cast<details::string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34570 | ||
34571 | details::free_node(*node_allocator_,branch[0]); | |
34572 | details::free_node(*node_allocator_,branch[1]); | |
34573 | ||
34574 | return synthesize_str_xrox_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0); | |
34575 | } | |
34576 | ||
34577 | inline expression_node_ptr synthesize_srocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34578 | { | |
34579 | std::string& s0 = static_cast<details::string_range_node<Type>*> (branch[0])->ref (); | |
34580 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); | |
34581 | range_t rp0 = static_cast<details::string_range_node<Type>*> (branch[0])->range(); | |
34582 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); | |
34583 | ||
34584 | static_cast<details::string_range_node<Type>*> (branch[0])->range_ref().clear(); | |
34585 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34586 | ||
34587 | details::free_node(*node_allocator_,branch[0]); | |
34588 | details::free_node(*node_allocator_,branch[1]); | |
34589 | ||
34590 | return synthesize_str_xroxr_expression_impl<std::string&, const std::string>(opr, s0, s1, rp0, rp1); | |
34591 | } | |
34592 | ||
34593 | inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34594 | { | |
34595 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); | |
34596 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); | |
34597 | ||
34598 | expression_node_ptr result = error_node(); | |
34599 | ||
34600 | if (details::e_add == opr) | |
34601 | result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1); | |
34602 | else if (details::e_in == opr) | |
34603 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op <Type>::process(s0,s1)); | |
34604 | else if (details::e_like == opr) | |
34605 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op <Type>::process(s0,s1)); | |
34606 | else if (details::e_ilike == opr) | |
34607 | result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1)); | |
34608 | else | |
34609 | { | |
34610 | expression_node_ptr temp = synthesize_sos_expression_impl<const std::string, const std::string>(opr, s0, s1); | |
34611 | ||
34612 | const Type v = temp->value(); | |
34613 | ||
34614 | details::free_node(*node_allocator_,temp); | |
34615 | ||
34616 | result = node_allocator_->allocate<literal_node_t>(v); | |
34617 | } | |
34618 | ||
34619 | details::free_all_nodes(*node_allocator_,branch); | |
34620 | ||
34621 | return result; | |
34622 | } | |
34623 | ||
34624 | inline expression_node_ptr synthesize_csocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34625 | { | |
34626 | const std::string s0 = static_cast<details::string_literal_node<Type>*> (branch[0])->str (); | |
34627 | std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); | |
34628 | range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); | |
34629 | ||
34630 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34631 | ||
34632 | free_node(*node_allocator_,branch[0]); | |
34633 | free_node(*node_allocator_,branch[1]); | |
34634 | ||
34635 | return synthesize_str_xoxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp1); | |
34636 | } | |
34637 | ||
34638 | inline expression_node_ptr synthesize_csros_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34639 | { | |
34640 | std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); | |
34641 | std::string& s1 = static_cast<details::stringvar_node<Type>*> (branch[1])->ref (); | |
34642 | range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); | |
34643 | ||
34644 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34645 | ||
34646 | free_node(*node_allocator_,branch[0]); | |
34647 | ||
34648 | return synthesize_str_xrox_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0); | |
34649 | } | |
34650 | ||
34651 | inline expression_node_ptr synthesize_csrosr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34652 | { | |
34653 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); | |
34654 | std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref (); | |
34655 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); | |
34656 | const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); | |
34657 | ||
34658 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34659 | static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); | |
34660 | ||
34661 | free_node(*node_allocator_,branch[0]); | |
34662 | free_node(*node_allocator_,branch[1]); | |
34663 | ||
34664 | return synthesize_str_xroxr_expression_impl<const std::string,std::string&>(opr, s0, s1, rp0, rp1); | |
34665 | } | |
34666 | ||
34667 | inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34668 | { | |
34669 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); | |
34670 | const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str (); | |
34671 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); | |
34672 | ||
34673 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34674 | ||
34675 | details::free_all_nodes(*node_allocator_,branch); | |
34676 | ||
34677 | return synthesize_str_xrox_expression_impl<const std::string,std::string>(opr, s0, s1, rp0); | |
34678 | } | |
34679 | ||
34680 | inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34681 | { | |
34682 | const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); | |
34683 | const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); | |
34684 | const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); | |
34685 | const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); | |
34686 | ||
34687 | static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); | |
34688 | static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); | |
34689 | ||
34690 | details::free_all_nodes(*node_allocator_,branch); | |
34691 | ||
34692 | return synthesize_str_xroxr_expression_impl<const std::string, const std::string>(opr, s0, s1, rp0, rp1); | |
34693 | } | |
34694 | ||
34695 | inline expression_node_ptr synthesize_strogen_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34696 | { | |
34697 | switch (opr) | |
34698 | { | |
34699 | #define case_stmt(op0,op1) \ | |
34700 | case op0 : return node_allocator_-> \ | |
34701 | allocate_ttt<typename details::str_sogens_node<Type,op1<Type> > > \ | |
34702 | (opr, branch[0], branch[1]); \ | |
34703 | ||
34704 | string_opr_switch_statements | |
34705 | #undef case_stmt | |
34706 | default : return error_node(); | |
34707 | } | |
34708 | } | |
34709 | #endif | |
34710 | ||
34711 | #ifndef exprtk_disable_string_capabilities | |
34712 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) | |
34713 | { | |
34714 | if ((0 == branch[0]) || (0 == branch[1])) | |
34715 | { | |
34716 | details::free_all_nodes(*node_allocator_,branch); | |
34717 | ||
34718 | return error_node(); | |
34719 | } | |
34720 | ||
34721 | const bool b0_is_s = details::is_string_node (branch[0]); | |
34722 | const bool b0_is_cs = details::is_const_string_node (branch[0]); | |
34723 | const bool b0_is_sr = details::is_string_range_node (branch[0]); | |
34724 | const bool b0_is_csr = details::is_const_string_range_node(branch[0]); | |
34725 | ||
34726 | const bool b1_is_s = details::is_string_node (branch[1]); | |
34727 | const bool b1_is_cs = details::is_const_string_node (branch[1]); | |
34728 | const bool b1_is_sr = details::is_string_range_node (branch[1]); | |
34729 | const bool b1_is_csr = details::is_const_string_range_node(branch[1]); | |
34730 | ||
34731 | const bool b0_is_gen = details::is_string_assignment_node (branch[0]) || | |
34732 | details::is_genricstring_range_node(branch[0]) || | |
34733 | details::is_string_concat_node (branch[0]) || | |
34734 | details::is_string_function_node (branch[0]) || | |
34735 | details::is_string_condition_node (branch[0]) || | |
34736 | details::is_string_ccondition_node (branch[0]) || | |
34737 | details::is_string_vararg_node (branch[0]) ; | |
34738 | ||
34739 | const bool b1_is_gen = details::is_string_assignment_node (branch[1]) || | |
34740 | details::is_genricstring_range_node(branch[1]) || | |
34741 | details::is_string_concat_node (branch[1]) || | |
34742 | details::is_string_function_node (branch[1]) || | |
34743 | details::is_string_condition_node (branch[1]) || | |
34744 | details::is_string_ccondition_node (branch[1]) || | |
34745 | details::is_string_vararg_node (branch[1]) ; | |
34746 | ||
34747 | if (details::e_add == opr) | |
34748 | { | |
34749 | if (!b0_is_cs || !b1_is_cs) | |
34750 | { | |
34751 | return synthesize_expression<string_concat_node_t,2>(opr,branch); | |
34752 | } | |
34753 | } | |
34754 | ||
34755 | if (b0_is_gen || b1_is_gen) | |
34756 | { | |
34757 | return synthesize_strogen_expression(opr,branch); | |
34758 | } | |
34759 | else if (b0_is_s) | |
34760 | { | |
34761 | if (b1_is_s ) return synthesize_sos_expression (opr,branch); | |
34762 | else if (b1_is_cs ) return synthesize_socs_expression (opr,branch); | |
34763 | else if (b1_is_sr ) return synthesize_sosr_expression (opr,branch); | |
34764 | else if (b1_is_csr) return synthesize_socsr_expression (opr,branch); | |
34765 | } | |
34766 | else if (b0_is_cs) | |
34767 | { | |
34768 | if (b1_is_s ) return synthesize_csos_expression (opr,branch); | |
34769 | else if (b1_is_cs ) return synthesize_csocs_expression (opr,branch); | |
34770 | else if (b1_is_sr ) return synthesize_csosr_expression (opr,branch); | |
34771 | else if (b1_is_csr) return synthesize_csocsr_expression(opr,branch); | |
34772 | } | |
34773 | else if (b0_is_sr) | |
34774 | { | |
34775 | if (b1_is_s ) return synthesize_sros_expression (opr,branch); | |
34776 | else if (b1_is_sr ) return synthesize_srosr_expression (opr,branch); | |
34777 | else if (b1_is_cs ) return synthesize_srocs_expression (opr,branch); | |
34778 | else if (b1_is_csr) return synthesize_srocsr_expression(opr,branch); | |
34779 | } | |
34780 | else if (b0_is_csr) | |
34781 | { | |
34782 | if (b1_is_s ) return synthesize_csros_expression (opr,branch); | |
34783 | else if (b1_is_sr ) return synthesize_csrosr_expression (opr,branch); | |
34784 | else if (b1_is_cs ) return synthesize_csrocs_expression (opr,branch); | |
34785 | else if (b1_is_csr) return synthesize_csrocsr_expression(opr,branch); | |
34786 | } | |
34787 | ||
34788 | return error_node(); | |
34789 | } | |
34790 | #else | |
34791 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[2]) | |
34792 | { | |
34793 | details::free_all_nodes(*node_allocator_,branch); | |
34794 | return error_node(); | |
34795 | } | |
34796 | #endif | |
34797 | ||
34798 | #ifndef exprtk_disable_string_capabilities | |
34799 | inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3]) | |
34800 | { | |
34801 | if (details::e_inrange != opr) | |
34802 | return error_node(); | |
34803 | else if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2])) | |
34804 | { | |
34805 | details::free_all_nodes(*node_allocator_,branch); | |
34806 | ||
34807 | return error_node(); | |
34808 | } | |
34809 | else if ( | |
34810 | details::is_const_string_node(branch[0]) && | |
34811 | details::is_const_string_node(branch[1]) && | |
34812 | details::is_const_string_node(branch[2]) | |
34813 | ) | |
34814 | { | |
34815 | const std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); | |
34816 | const std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); | |
34817 | const std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); | |
34818 | ||
34819 | const Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0)); | |
34820 | ||
34821 | details::free_all_nodes(*node_allocator_,branch); | |
34822 | ||
34823 | return node_allocator_->allocate_c<details::literal_node<Type> >(v); | |
34824 | } | |
34825 | else if ( | |
34826 | details::is_string_node(branch[0]) && | |
34827 | details::is_string_node(branch[1]) && | |
34828 | details::is_string_node(branch[2]) | |
34829 | ) | |
34830 | { | |
34831 | std::string& s0 = static_cast<details::stringvar_node<Type>*>(branch[0])->ref(); | |
34832 | std::string& s1 = static_cast<details::stringvar_node<Type>*>(branch[1])->ref(); | |
34833 | std::string& s2 = static_cast<details::stringvar_node<Type>*>(branch[2])->ref(); | |
34834 | ||
34835 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string&, details::inrange_op<Type> > inrange_t; | |
34836 | ||
34837 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string&>(s0, s1, s2); | |
34838 | } | |
34839 | else if ( | |
34840 | details::is_const_string_node(branch[0]) && | |
34841 | details::is_string_node(branch[1]) && | |
34842 | details::is_const_string_node(branch[2]) | |
34843 | ) | |
34844 | { | |
34845 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); | |
34846 | std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); | |
34847 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); | |
34848 | ||
34849 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string, details::inrange_op<Type> > inrange_t; | |
34850 | ||
34851 | details::free_node(*node_allocator_,branch[0]); | |
34852 | details::free_node(*node_allocator_,branch[2]); | |
34853 | ||
34854 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string>(s0, s1, s2); | |
34855 | } | |
34856 | else if ( | |
34857 | details::is_string_node(branch[0]) && | |
34858 | details::is_const_string_node(branch[1]) && | |
34859 | details::is_string_node(branch[2]) | |
34860 | ) | |
34861 | { | |
34862 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); | |
34863 | std::string s1 = static_cast<details::string_literal_node<Type>*>(branch[1])->str(); | |
34864 | std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref(); | |
34865 | ||
34866 | typedef typename details::sosos_node<Type, std::string&, std::string, std::string&, details::inrange_op<Type> > inrange_t; | |
34867 | ||
34868 | details::free_node(*node_allocator_,branch[1]); | |
34869 | ||
34870 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string, std::string&>(s0, s1, s2); | |
34871 | } | |
34872 | else if ( | |
34873 | details::is_string_node(branch[0]) && | |
34874 | details::is_string_node(branch[1]) && | |
34875 | details::is_const_string_node(branch[2]) | |
34876 | ) | |
34877 | { | |
34878 | std::string& s0 = static_cast< details::stringvar_node<Type>*>(branch[0])->ref(); | |
34879 | std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); | |
34880 | std::string s2 = static_cast<details::string_literal_node<Type>*>(branch[2])->str(); | |
34881 | ||
34882 | typedef typename details::sosos_node<Type, std::string&, std::string&, std::string, details::inrange_op<Type> > inrange_t; | |
34883 | ||
34884 | details::free_node(*node_allocator_,branch[2]); | |
34885 | ||
34886 | return node_allocator_->allocate_type<inrange_t, std::string&, std::string&, std::string>(s0, s1, s2); | |
34887 | } | |
34888 | else if ( | |
34889 | details::is_const_string_node(branch[0]) && | |
34890 | details:: is_string_node(branch[1]) && | |
34891 | details:: is_string_node(branch[2]) | |
34892 | ) | |
34893 | { | |
34894 | std::string s0 = static_cast<details::string_literal_node<Type>*>(branch[0])->str(); | |
34895 | std::string& s1 = static_cast< details::stringvar_node<Type>*>(branch[1])->ref(); | |
34896 | std::string& s2 = static_cast< details::stringvar_node<Type>*>(branch[2])->ref(); | |
34897 | ||
34898 | typedef typename details::sosos_node<Type, std::string, std::string&, std::string&, details::inrange_op<Type> > inrange_t; | |
34899 | ||
34900 | details::free_node(*node_allocator_,branch[0]); | |
34901 | ||
34902 | return node_allocator_->allocate_type<inrange_t, std::string, std::string&, std::string&>(s0, s1, s2); | |
34903 | } | |
34904 | else | |
34905 | return error_node(); | |
34906 | } | |
34907 | #else | |
34908 | inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&branch)[3]) | |
34909 | { | |
34910 | details::free_all_nodes(*node_allocator_,branch); | |
34911 | return error_node(); | |
34912 | } | |
34913 | #endif | |
34914 | ||
34915 | inline expression_node_ptr synthesize_null_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2]) | |
34916 | { | |
34917 | /* | |
34918 | Note: The following are the type promotion rules | |
34919 | that relate to operations that include 'null': | |
34920 | 0. null ==/!= null --> true false | |
34921 | 1. null operation null --> null | |
34922 | 2. x ==/!= null --> true/false | |
34923 | 3. null ==/!= x --> true/false | |
34924 | 4. x operation null --> x | |
34925 | 5. null operation x --> x | |
34926 | */ | |
34927 | ||
34928 | typedef typename details::null_eq_node<T> nulleq_node_t; | |
34929 | ||
34930 | const bool b0_null = details::is_null_node(branch[0]); | |
34931 | const bool b1_null = details::is_null_node(branch[1]); | |
34932 | ||
34933 | if (b0_null && b1_null) | |
34934 | { | |
34935 | expression_node_ptr result = error_node(); | |
34936 | ||
34937 | if (details::e_eq == operation) | |
34938 | result = node_allocator_->allocate_c<literal_node_t>(T(1)); | |
34939 | else if (details::e_ne == operation) | |
34940 | result = node_allocator_->allocate_c<literal_node_t>(T(0)); | |
34941 | ||
34942 | if (result) | |
34943 | { | |
34944 | details::free_node(*node_allocator_,branch[0]); | |
34945 | details::free_node(*node_allocator_,branch[1]); | |
34946 | ||
34947 | return result; | |
34948 | } | |
34949 | ||
34950 | details::free_node(*node_allocator_,branch[1]); | |
34951 | ||
34952 | return branch[0]; | |
34953 | } | |
34954 | else if (details::e_eq == operation) | |
34955 | { | |
34956 | expression_node_ptr result = node_allocator_-> | |
34957 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],true); | |
34958 | ||
34959 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); | |
34960 | ||
34961 | return result; | |
34962 | } | |
34963 | else if (details::e_ne == operation) | |
34964 | { | |
34965 | expression_node_ptr result = node_allocator_-> | |
34966 | allocate_rc<nulleq_node_t>(branch[b0_null ? 0 : 1],false); | |
34967 | ||
34968 | details::free_node(*node_allocator_,branch[b0_null ? 1 : 0]); | |
34969 | ||
34970 | return result; | |
34971 | } | |
34972 | else if (b0_null) | |
34973 | { | |
34974 | details::free_node(*node_allocator_,branch[0]); | |
34975 | branch[0] = branch[1]; | |
34976 | branch[1] = error_node(); | |
34977 | } | |
34978 | else if (b1_null) | |
34979 | { | |
34980 | details::free_node(*node_allocator_,branch[1]); | |
34981 | branch[1] = error_node(); | |
34982 | } | |
34983 | ||
34984 | if ( | |
34985 | (details::e_add == operation) || (details::e_sub == operation) || | |
34986 | (details::e_mul == operation) || (details::e_div == operation) || | |
34987 | (details::e_mod == operation) || (details::e_pow == operation) | |
34988 | ) | |
34989 | { | |
34990 | return branch[0]; | |
34991 | } | |
34992 | else if ( | |
34993 | (details::e_lt == operation) || (details::e_lte == operation) || | |
34994 | (details::e_gt == operation) || (details::e_gte == operation) || | |
34995 | (details::e_and == operation) || (details::e_nand == operation) || | |
34996 | (details::e_or == operation) || (details::e_nor == operation) || | |
34997 | (details::e_xor == operation) || (details::e_xnor == operation) || | |
34998 | (details::e_in == operation) || (details::e_like == operation) || | |
34999 | (details::e_ilike == operation) | |
35000 | ) | |
35001 | { | |
35002 | return node_allocator_->allocate_c<literal_node_t>(T(0)); | |
35003 | } | |
35004 | ||
35005 | details::free_node(*node_allocator_,branch[0]); | |
35006 | ||
35007 | return node_allocator_->allocate<details::null_node<Type> >(); | |
35008 | } | |
35009 | ||
35010 | template <typename NodeType, std::size_t N> | |
35011 | inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N]) | |
35012 | { | |
35013 | if ( | |
35014 | (details::e_in == operation) || | |
35015 | (details::e_like == operation) || | |
35016 | (details::e_ilike == operation) | |
35017 | ) | |
35018 | { | |
35019 | free_all_nodes(*node_allocator_,branch); | |
35020 | ||
35021 | return error_node(); | |
35022 | } | |
35023 | else if (!details::all_nodes_valid<N>(branch)) | |
35024 | { | |
35025 | free_all_nodes(*node_allocator_,branch); | |
35026 | ||
35027 | return error_node(); | |
35028 | } | |
35029 | else if ((details::e_default != operation)) | |
35030 | { | |
35031 | // Attempt simple constant folding optimisation. | |
35032 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch); | |
35033 | ||
35034 | if (is_constant_foldable<N>(branch)) | |
35035 | { | |
35036 | const Type v = expression_point->value(); | |
35037 | details::free_node(*node_allocator_,expression_point); | |
35038 | ||
35039 | return node_allocator_->allocate<literal_node_t>(v); | |
35040 | } | |
35041 | else | |
35042 | return expression_point; | |
35043 | } | |
35044 | else | |
35045 | return error_node(); | |
35046 | } | |
35047 | ||
35048 | template <typename NodeType, std::size_t N> | |
35049 | inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N]) | |
35050 | { | |
35051 | if (!details::all_nodes_valid<N>(branch)) | |
35052 | { | |
35053 | free_all_nodes(*node_allocator_,branch); | |
35054 | ||
35055 | return error_node(); | |
35056 | } | |
35057 | ||
35058 | typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t; | |
35059 | ||
35060 | // Attempt simple constant folding optimisation. | |
35061 | ||
35062 | expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f); | |
35063 | function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(expression_point); | |
35064 | ||
35065 | if (0 == func_node_ptr) | |
35066 | { | |
35067 | free_all_nodes(*node_allocator_,branch); | |
35068 | ||
35069 | return error_node(); | |
35070 | } | |
35071 | else | |
35072 | func_node_ptr->init_branches(branch); | |
35073 | ||
35074 | if (is_constant_foldable<N>(branch) && !f->has_side_effects()) | |
35075 | { | |
35076 | Type v = expression_point->value(); | |
35077 | details::free_node(*node_allocator_,expression_point); | |
35078 | ||
35079 | return node_allocator_->allocate<literal_node_t>(v); | |
35080 | } | |
35081 | ||
35082 | parser_->state_.activate_side_effect("synthesize_expression(function<NT,N>)"); | |
35083 | ||
35084 | return expression_point; | |
35085 | } | |
35086 | ||
35087 | bool strength_reduction_enabled_; | |
35088 | details::node_allocator* node_allocator_; | |
35089 | synthesize_map_t synthesize_map_; | |
35090 | unary_op_map_t* unary_op_map_; | |
35091 | binary_op_map_t* binary_op_map_; | |
35092 | inv_binary_op_map_t* inv_binary_op_map_; | |
35093 | sf3_map_t* sf3_map_; | |
35094 | sf4_map_t* sf4_map_; | |
35095 | parser_t* parser_; | |
35096 | }; | |
35097 | ||
35098 | inline void set_error(const parser_error::type& error_type) | |
35099 | { | |
35100 | error_list_.push_back(error_type); | |
35101 | } | |
35102 | ||
35103 | inline void remove_last_error() | |
35104 | { | |
35105 | if (!error_list_.empty()) | |
35106 | { | |
35107 | error_list_.pop_back(); | |
35108 | } | |
35109 | } | |
35110 | ||
35111 | inline void set_synthesis_error(const std::string& synthesis_error_message) | |
35112 | { | |
35113 | if (synthesis_error_.empty()) | |
35114 | { | |
35115 | synthesis_error_ = synthesis_error_message; | |
35116 | } | |
35117 | } | |
35118 | ||
35119 | inline void register_local_vars(expression<T>& e) | |
35120 | { | |
35121 | for (std::size_t i = 0; i < sem_.size(); ++i) | |
35122 | { | |
35123 | scope_element& se = sem_.get_element(i); | |
35124 | ||
35125 | if ( | |
35126 | (scope_element::e_variable == se.type) || | |
35127 | (scope_element::e_vecelem == se.type) | |
35128 | ) | |
35129 | { | |
35130 | if (se.var_node) | |
35131 | { | |
35132 | e.register_local_var(se.var_node); | |
35133 | } | |
35134 | ||
35135 | if (se.data) | |
35136 | { | |
35137 | e.register_local_data(se.data, 1, 0); | |
35138 | } | |
35139 | } | |
35140 | else if (scope_element::e_vector == se.type) | |
35141 | { | |
35142 | if (se.vec_node) | |
35143 | { | |
35144 | e.register_local_var(se.vec_node); | |
35145 | } | |
35146 | ||
35147 | if (se.data) | |
35148 | { | |
35149 | e.register_local_data(se.data, se.size, 1); | |
35150 | } | |
35151 | } | |
35152 | #ifndef exprtk_disable_string_capabilities | |
35153 | else if (scope_element::e_string == se.type) | |
35154 | { | |
35155 | if (se.str_node) | |
35156 | { | |
35157 | e.register_local_var(se.str_node); | |
35158 | } | |
35159 | ||
35160 | if (se.data) | |
35161 | { | |
35162 | e.register_local_data(se.data, se.size, 2); | |
35163 | } | |
35164 | } | |
35165 | #endif | |
35166 | ||
35167 | se.var_node = 0; | |
35168 | se.vec_node = 0; | |
35169 | #ifndef exprtk_disable_string_capabilities | |
35170 | se.str_node = 0; | |
35171 | #endif | |
35172 | se.data = 0; | |
35173 | se.ref_count = 0; | |
35174 | se.active = false; | |
35175 | } | |
35176 | } | |
35177 | ||
35178 | inline void register_return_results(expression<T>& e) | |
35179 | { | |
35180 | e.register_return_results(results_context_); | |
35181 | results_context_ = 0; | |
35182 | } | |
35183 | ||
35184 | inline void load_unary_operations_map(unary_op_map_t& m) | |
35185 | { | |
35186 | #define register_unary_op(Op,UnaryFunctor) \ | |
35187 | m.insert(std::make_pair(Op,UnaryFunctor<T>::process)); \ | |
35188 | ||
35189 | register_unary_op(details:: e_abs, details:: abs_op) | |
35190 | register_unary_op(details:: e_acos, details:: acos_op) | |
35191 | register_unary_op(details::e_acosh, details::acosh_op) | |
35192 | register_unary_op(details:: e_asin, details:: asin_op) | |
35193 | register_unary_op(details::e_asinh, details::asinh_op) | |
35194 | register_unary_op(details::e_atanh, details::atanh_op) | |
35195 | register_unary_op(details:: e_ceil, details:: ceil_op) | |
35196 | register_unary_op(details:: e_cos, details:: cos_op) | |
35197 | register_unary_op(details:: e_cosh, details:: cosh_op) | |
35198 | register_unary_op(details:: e_exp, details:: exp_op) | |
35199 | register_unary_op(details::e_expm1, details::expm1_op) | |
35200 | register_unary_op(details::e_floor, details::floor_op) | |
35201 | register_unary_op(details:: e_log, details:: log_op) | |
35202 | register_unary_op(details::e_log10, details::log10_op) | |
35203 | register_unary_op(details:: e_log2, details:: log2_op) | |
35204 | register_unary_op(details::e_log1p, details::log1p_op) | |
35205 | register_unary_op(details:: e_neg, details:: neg_op) | |
35206 | register_unary_op(details:: e_pos, details:: pos_op) | |
35207 | register_unary_op(details::e_round, details::round_op) | |
35208 | register_unary_op(details:: e_sin, details:: sin_op) | |
35209 | register_unary_op(details:: e_sinc, details:: sinc_op) | |
35210 | register_unary_op(details:: e_sinh, details:: sinh_op) | |
35211 | register_unary_op(details:: e_sqrt, details:: sqrt_op) | |
35212 | register_unary_op(details:: e_tan, details:: tan_op) | |
35213 | register_unary_op(details:: e_tanh, details:: tanh_op) | |
35214 | register_unary_op(details:: e_cot, details:: cot_op) | |
35215 | register_unary_op(details:: e_sec, details:: sec_op) | |
35216 | register_unary_op(details:: e_csc, details:: csc_op) | |
35217 | register_unary_op(details:: e_r2d, details:: r2d_op) | |
35218 | register_unary_op(details:: e_d2r, details:: d2r_op) | |
35219 | register_unary_op(details:: e_d2g, details:: d2g_op) | |
35220 | register_unary_op(details:: e_g2d, details:: g2d_op) | |
35221 | register_unary_op(details:: e_notl, details:: notl_op) | |
35222 | register_unary_op(details:: e_sgn, details:: sgn_op) | |
35223 | register_unary_op(details:: e_erf, details:: erf_op) | |
35224 | register_unary_op(details:: e_erfc, details:: erfc_op) | |
35225 | register_unary_op(details:: e_ncdf, details:: ncdf_op) | |
35226 | register_unary_op(details:: e_frac, details:: frac_op) | |
35227 | register_unary_op(details::e_trunc, details::trunc_op) | |
35228 | #undef register_unary_op | |
35229 | } | |
35230 | ||
35231 | inline void load_binary_operations_map(binary_op_map_t& m) | |
35232 | { | |
35233 | typedef typename binary_op_map_t::value_type value_type; | |
35234 | ||
35235 | #define register_binary_op(Op,BinaryFunctor) \ | |
35236 | m.insert(value_type(Op,BinaryFunctor<T>::process)); \ | |
35237 | ||
35238 | register_binary_op(details:: e_add, details:: add_op) | |
35239 | register_binary_op(details:: e_sub, details:: sub_op) | |
35240 | register_binary_op(details:: e_mul, details:: mul_op) | |
35241 | register_binary_op(details:: e_div, details:: div_op) | |
35242 | register_binary_op(details:: e_mod, details:: mod_op) | |
35243 | register_binary_op(details:: e_pow, details:: pow_op) | |
35244 | register_binary_op(details:: e_lt, details:: lt_op) | |
35245 | register_binary_op(details:: e_lte, details:: lte_op) | |
35246 | register_binary_op(details:: e_gt, details:: gt_op) | |
35247 | register_binary_op(details:: e_gte, details:: gte_op) | |
35248 | register_binary_op(details:: e_eq, details:: eq_op) | |
35249 | register_binary_op(details:: e_ne, details:: ne_op) | |
35250 | register_binary_op(details:: e_and, details:: and_op) | |
35251 | register_binary_op(details::e_nand, details::nand_op) | |
35252 | register_binary_op(details:: e_or, details:: or_op) | |
35253 | register_binary_op(details:: e_nor, details:: nor_op) | |
35254 | register_binary_op(details:: e_xor, details:: xor_op) | |
35255 | register_binary_op(details::e_xnor, details::xnor_op) | |
35256 | #undef register_binary_op | |
35257 | } | |
35258 | ||
35259 | inline void load_inv_binary_operations_map(inv_binary_op_map_t& m) | |
35260 | { | |
35261 | typedef typename inv_binary_op_map_t::value_type value_type; | |
35262 | ||
35263 | #define register_binary_op(Op,BinaryFunctor) \ | |
35264 | m.insert(value_type(BinaryFunctor<T>::process,Op)); \ | |
35265 | ||
35266 | register_binary_op(details:: e_add, details:: add_op) | |
35267 | register_binary_op(details:: e_sub, details:: sub_op) | |
35268 | register_binary_op(details:: e_mul, details:: mul_op) | |
35269 | register_binary_op(details:: e_div, details:: div_op) | |
35270 | register_binary_op(details:: e_mod, details:: mod_op) | |
35271 | register_binary_op(details:: e_pow, details:: pow_op) | |
35272 | register_binary_op(details:: e_lt, details:: lt_op) | |
35273 | register_binary_op(details:: e_lte, details:: lte_op) | |
35274 | register_binary_op(details:: e_gt, details:: gt_op) | |
35275 | register_binary_op(details:: e_gte, details:: gte_op) | |
35276 | register_binary_op(details:: e_eq, details:: eq_op) | |
35277 | register_binary_op(details:: e_ne, details:: ne_op) | |
35278 | register_binary_op(details:: e_and, details:: and_op) | |
35279 | register_binary_op(details::e_nand, details::nand_op) | |
35280 | register_binary_op(details:: e_or, details:: or_op) | |
35281 | register_binary_op(details:: e_nor, details:: nor_op) | |
35282 | register_binary_op(details:: e_xor, details:: xor_op) | |
35283 | register_binary_op(details::e_xnor, details::xnor_op) | |
35284 | #undef register_binary_op | |
35285 | } | |
35286 | ||
35287 | inline void load_sf3_map(sf3_map_t& sf3_map) | |
35288 | { | |
35289 | typedef std::pair<trinary_functor_t,details::operator_type> pair_t; | |
35290 | ||
35291 | #define register_sf3(Op) \ | |
35292 | sf3_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ | |
35293 | ||
35294 | register_sf3(00) register_sf3(01) register_sf3(02) register_sf3(03) | |
35295 | register_sf3(04) register_sf3(05) register_sf3(06) register_sf3(07) | |
35296 | register_sf3(08) register_sf3(09) register_sf3(10) register_sf3(11) | |
35297 | register_sf3(12) register_sf3(13) register_sf3(14) register_sf3(15) | |
35298 | register_sf3(16) register_sf3(17) register_sf3(18) register_sf3(19) | |
35299 | register_sf3(20) register_sf3(21) register_sf3(22) register_sf3(23) | |
35300 | register_sf3(24) register_sf3(25) register_sf3(26) register_sf3(27) | |
35301 | register_sf3(28) register_sf3(29) register_sf3(30) | |
35302 | #undef register_sf3 | |
35303 | ||
35304 | #define register_sf3_extid(Id, Op) \ | |
35305 | sf3_map[Id] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ | |
35306 | ||
35307 | register_sf3_extid("(t-t)-t",23) // (t-t)-t --> t-(t+t) | |
35308 | #undef register_sf3_extid | |
35309 | } | |
35310 | ||
35311 | inline void load_sf4_map(sf4_map_t& sf4_map) | |
35312 | { | |
35313 | typedef std::pair<quaternary_functor_t,details::operator_type> pair_t; | |
35314 | ||
35315 | #define register_sf4(Op) \ | |
35316 | sf4_map[details::sf##Op##_op<T>::id()] = pair_t(details::sf##Op##_op<T>::process,details::e_sf##Op); \ | |
35317 | ||
35318 | register_sf4(48) register_sf4(49) register_sf4(50) register_sf4(51) | |
35319 | register_sf4(52) register_sf4(53) register_sf4(54) register_sf4(55) | |
35320 | register_sf4(56) register_sf4(57) register_sf4(58) register_sf4(59) | |
35321 | register_sf4(60) register_sf4(61) register_sf4(62) register_sf4(63) | |
35322 | register_sf4(64) register_sf4(65) register_sf4(66) register_sf4(67) | |
35323 | register_sf4(68) register_sf4(69) register_sf4(70) register_sf4(71) | |
35324 | register_sf4(72) register_sf4(73) register_sf4(74) register_sf4(75) | |
35325 | register_sf4(76) register_sf4(77) register_sf4(78) register_sf4(79) | |
35326 | register_sf4(80) register_sf4(81) register_sf4(82) register_sf4(83) | |
35327 | #undef register_sf4 | |
35328 | ||
35329 | #define register_sf4ext(Op) \ | |
35330 | sf4_map[details::sfext##Op##_op<T>::id()] = pair_t(details::sfext##Op##_op<T>::process,details::e_sf4ext##Op); \ | |
35331 | ||
35332 | register_sf4ext(00) register_sf4ext(01) register_sf4ext(02) register_sf4ext(03) | |
35333 | register_sf4ext(04) register_sf4ext(05) register_sf4ext(06) register_sf4ext(07) | |
35334 | register_sf4ext(08) register_sf4ext(09) register_sf4ext(10) register_sf4ext(11) | |
35335 | register_sf4ext(12) register_sf4ext(13) register_sf4ext(14) register_sf4ext(15) | |
35336 | register_sf4ext(16) register_sf4ext(17) register_sf4ext(18) register_sf4ext(19) | |
35337 | register_sf4ext(20) register_sf4ext(21) register_sf4ext(22) register_sf4ext(23) | |
35338 | register_sf4ext(24) register_sf4ext(25) register_sf4ext(26) register_sf4ext(27) | |
35339 | register_sf4ext(28) register_sf4ext(29) register_sf4ext(30) register_sf4ext(31) | |
35340 | register_sf4ext(32) register_sf4ext(33) register_sf4ext(34) register_sf4ext(35) | |
35341 | register_sf4ext(36) register_sf4ext(36) register_sf4ext(38) register_sf4ext(39) | |
35342 | register_sf4ext(40) register_sf4ext(41) register_sf4ext(42) register_sf4ext(43) | |
35343 | register_sf4ext(44) register_sf4ext(45) register_sf4ext(46) register_sf4ext(47) | |
35344 | register_sf4ext(48) register_sf4ext(49) register_sf4ext(50) register_sf4ext(51) | |
35345 | register_sf4ext(52) register_sf4ext(53) register_sf4ext(54) register_sf4ext(55) | |
35346 | register_sf4ext(56) register_sf4ext(57) register_sf4ext(58) register_sf4ext(59) | |
35347 | register_sf4ext(60) register_sf4ext(61) | |
35348 | #undef register_sf4ext | |
35349 | } | |
35350 | ||
35351 | inline results_context_t& results_ctx() | |
35352 | { | |
35353 | if (0 == results_context_) | |
35354 | { | |
35355 | results_context_ = new results_context_t(); | |
35356 | } | |
35357 | ||
35358 | return (*results_context_); | |
35359 | } | |
35360 | ||
35361 | inline void return_cleanup() | |
35362 | { | |
35363 | #ifndef exprtk_disable_return_statement | |
35364 | if (results_context_) | |
35365 | { | |
35366 | delete results_context_; | |
35367 | results_context_ = 0; | |
35368 | } | |
35369 | ||
35370 | state_.return_stmt_present = false; | |
35371 | #endif | |
35372 | } | |
35373 | ||
35374 | private: | |
35375 | ||
35376 | parser(const parser<T>&); | |
35377 | parser<T>& operator=(const parser<T>&); | |
35378 | ||
35379 | settings_store settings_; | |
35380 | expression_generator<T> expression_generator_; | |
35381 | details::node_allocator node_allocator_; | |
35382 | symtab_store symtab_store_; | |
35383 | dependent_entity_collector dec_; | |
35384 | std::deque<parser_error::type> error_list_; | |
35385 | std::deque<bool> brkcnt_list_; | |
35386 | parser_state state_; | |
35387 | bool resolve_unknown_symbol_; | |
35388 | results_context_t* results_context_; | |
35389 | unknown_symbol_resolver* unknown_symbol_resolver_; | |
35390 | unknown_symbol_resolver default_usr_; | |
35391 | base_ops_map_t base_ops_map_; | |
35392 | unary_op_map_t unary_op_map_; | |
35393 | binary_op_map_t binary_op_map_; | |
35394 | inv_binary_op_map_t inv_binary_op_map_; | |
35395 | sf3_map_t sf3_map_; | |
35396 | sf4_map_t sf4_map_; | |
35397 | std::string synthesis_error_; | |
35398 | scope_element_manager sem_; | |
35399 | ||
35400 | lexer::helper::helper_assembly helper_assembly_; | |
35401 | ||
35402 | lexer::helper::commutative_inserter commutative_inserter_; | |
35403 | lexer::helper::operator_joiner operator_joiner_2_; | |
35404 | lexer::helper::operator_joiner operator_joiner_3_; | |
35405 | lexer::helper::symbol_replacer symbol_replacer_; | |
35406 | lexer::helper::bracket_checker bracket_checker_; | |
35407 | lexer::helper::numeric_checker numeric_checker_; | |
35408 | lexer::helper::sequence_validator sequence_validator_; | |
35409 | lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; | |
35410 | ||
35411 | template <typename ParserType> | |
35412 | friend void details::disable_type_checking(ParserType& p); | |
35413 | }; | |
35414 | ||
35415 | namespace details | |
35416 | { | |
35417 | template <typename T> | |
35418 | struct collector_helper | |
35419 | { | |
35420 | typedef exprtk::symbol_table<T> symbol_table_t; | |
35421 | typedef exprtk::expression<T> expression_t; | |
35422 | typedef exprtk::parser<T> parser_t; | |
35423 | typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; | |
35424 | typedef typename parser_t::unknown_symbol_resolver usr_t; | |
35425 | ||
35426 | struct resolve_as_vector : public parser_t::unknown_symbol_resolver | |
35427 | { | |
35428 | typedef exprtk::parser<T> parser_t; | |
35429 | ||
35430 | resolve_as_vector() | |
35431 | : usr_t(usr_t::e_usrmode_extended) | |
35432 | {} | |
35433 | ||
35434 | virtual bool process(const std::string& unknown_symbol, | |
35435 | symbol_table_t& symbol_table, | |
35436 | std::string&) | |
35437 | { | |
35438 | static T v[1]; | |
35439 | symbol_table.add_vector(unknown_symbol,v); | |
35440 | return true; | |
35441 | } | |
35442 | }; | |
35443 | ||
35444 | static inline bool collection_pass(const std::string& expression_string, | |
35445 | std::set<std::string>& symbol_set, | |
35446 | const bool collect_variables, | |
35447 | const bool collect_functions, | |
35448 | const bool vector_pass, | |
35449 | symbol_table_t& ext_symbol_table) | |
35450 | { | |
35451 | symbol_table_t symbol_table; | |
35452 | expression_t expression; | |
35453 | parser_t parser; | |
35454 | ||
35455 | resolve_as_vector vect_resolver; | |
35456 | ||
35457 | expression.register_symbol_table(symbol_table ); | |
35458 | expression.register_symbol_table(ext_symbol_table); | |
35459 | ||
35460 | if (vector_pass) | |
35461 | parser.enable_unknown_symbol_resolver(&vect_resolver); | |
35462 | else | |
35463 | parser.enable_unknown_symbol_resolver(); | |
35464 | ||
35465 | if (collect_variables) | |
35466 | parser.dec().collect_variables() = true; | |
35467 | ||
35468 | if (collect_functions) | |
35469 | parser.dec().collect_functions() = true; | |
35470 | ||
35471 | bool pass_result = false; | |
35472 | ||
35473 | details::disable_type_checking(parser); | |
35474 | ||
35475 | if (parser.compile(expression_string, expression)) | |
35476 | { | |
35477 | pass_result = true; | |
35478 | ||
35479 | std::deque<symbol_t> symb_list; | |
35480 | parser.dec().symbols(symb_list); | |
35481 | ||
35482 | for (std::size_t i = 0; i < symb_list.size(); ++i) | |
35483 | { | |
35484 | symbol_set.insert(symb_list[i].first); | |
35485 | } | |
35486 | } | |
35487 | ||
35488 | return pass_result; | |
35489 | } | |
35490 | }; | |
35491 | } | |
35492 | ||
35493 | template <typename Allocator, | |
35494 | template <typename, typename> class Sequence> | |
35495 | inline bool collect_variables(const std::string& expression, | |
35496 | Sequence<std::string, Allocator>& symbol_list) | |
35497 | { | |
35498 | typedef double T; | |
35499 | typedef details::collector_helper<T> collect_t; | |
35500 | ||
35501 | collect_t::symbol_table_t null_symbol_table; | |
35502 | ||
35503 | std::set<std::string> symbol_set; | |
35504 | ||
35505 | const bool variable_pass = collect_t::collection_pass | |
35506 | (expression, symbol_set, true, false, false, null_symbol_table); | |
35507 | const bool vector_pass = collect_t::collection_pass | |
35508 | (expression, symbol_set, true, false, true, null_symbol_table); | |
35509 | ||
35510 | if (!variable_pass && !vector_pass) | |
35511 | return false; | |
35512 | ||
35513 | std::set<std::string>::iterator itr = symbol_set.begin(); | |
35514 | ||
35515 | while (symbol_set.end() != itr) | |
35516 | { | |
35517 | symbol_list.push_back(*itr); | |
35518 | ++itr; | |
35519 | } | |
35520 | ||
35521 | return true; | |
35522 | } | |
35523 | ||
35524 | template <typename T, | |
35525 | typename Allocator, | |
35526 | template <typename, typename> class Sequence> | |
35527 | inline bool collect_variables(const std::string& expression, | |
35528 | exprtk::symbol_table<T>& extrnl_symbol_table, | |
35529 | Sequence<std::string, Allocator>& symbol_list) | |
35530 | { | |
35531 | typedef details::collector_helper<T> collect_t; | |
35532 | ||
35533 | std::set<std::string> symbol_set; | |
35534 | ||
35535 | const bool variable_pass = collect_t::collection_pass | |
35536 | (expression, symbol_set, true, false, false, extrnl_symbol_table); | |
35537 | const bool vector_pass = collect_t::collection_pass | |
35538 | (expression, symbol_set, true, false, true, extrnl_symbol_table); | |
35539 | ||
35540 | if (!variable_pass && !vector_pass) | |
35541 | return false; | |
35542 | ||
35543 | std::set<std::string>::iterator itr = symbol_set.begin(); | |
35544 | ||
35545 | while (symbol_set.end() != itr) | |
35546 | { | |
35547 | symbol_list.push_back(*itr); | |
35548 | ++itr; | |
35549 | } | |
35550 | ||
35551 | return true; | |
35552 | } | |
35553 | ||
35554 | template <typename Allocator, | |
35555 | template <typename, typename> class Sequence> | |
35556 | inline bool collect_functions(const std::string& expression, | |
35557 | Sequence<std::string, Allocator>& symbol_list) | |
35558 | { | |
35559 | typedef double T; | |
35560 | typedef details::collector_helper<T> collect_t; | |
35561 | ||
35562 | collect_t::symbol_table_t null_symbol_table; | |
35563 | ||
35564 | std::set<std::string> symbol_set; | |
35565 | ||
35566 | const bool variable_pass = collect_t::collection_pass | |
35567 | (expression, symbol_set, false, true, false, null_symbol_table); | |
35568 | const bool vector_pass = collect_t::collection_pass | |
35569 | (expression, symbol_set, false, true, true, null_symbol_table); | |
35570 | ||
35571 | if (!variable_pass && !vector_pass) | |
35572 | return false; | |
35573 | ||
35574 | std::set<std::string>::iterator itr = symbol_set.begin(); | |
35575 | ||
35576 | while (symbol_set.end() != itr) | |
35577 | { | |
35578 | symbol_list.push_back(*itr); | |
35579 | ++itr; | |
35580 | } | |
35581 | ||
35582 | return true; | |
35583 | } | |
35584 | ||
35585 | template <typename T, | |
35586 | typename Allocator, | |
35587 | template <typename, typename> class Sequence> | |
35588 | inline bool collect_functions(const std::string& expression, | |
35589 | exprtk::symbol_table<T>& extrnl_symbol_table, | |
35590 | Sequence<std::string, Allocator>& symbol_list) | |
35591 | { | |
35592 | typedef details::collector_helper<T> collect_t; | |
35593 | ||
35594 | std::set<std::string> symbol_set; | |
35595 | ||
35596 | const bool variable_pass = collect_t::collection_pass | |
35597 | (expression, symbol_set, false, true, false, extrnl_symbol_table); | |
35598 | const bool vector_pass = collect_t::collection_pass | |
35599 | (expression, symbol_set, false, true, true, extrnl_symbol_table); | |
35600 | ||
35601 | if (!variable_pass && !vector_pass) | |
35602 | return false; | |
35603 | ||
35604 | std::set<std::string>::iterator itr = symbol_set.begin(); | |
35605 | ||
35606 | while (symbol_set.end() != itr) | |
35607 | { | |
35608 | symbol_list.push_back(*itr); | |
35609 | ++itr; | |
35610 | } | |
35611 | ||
35612 | return true; | |
35613 | } | |
35614 | ||
35615 | template <typename T> | |
35616 | inline T integrate(const expression<T>& e, | |
35617 | T& x, | |
35618 | const T& r0, const T& r1, | |
35619 | const std::size_t number_of_intervals = 1000000) | |
35620 | { | |
35621 | if (r0 > r1) | |
35622 | return T(0); | |
35623 | ||
35624 | const T h = (r1 - r0) / (T(2) * number_of_intervals); | |
35625 | T total_area = T(0); | |
35626 | ||
35627 | for (std::size_t i = 0; i < number_of_intervals; ++i) | |
35628 | { | |
35629 | x = r0 + T(2) * i * h; | |
35630 | const T y0 = e.value(); x += h; | |
35631 | const T y1 = e.value(); x += h; | |
35632 | const T y2 = e.value(); x += h; | |
35633 | total_area += h * (y0 + T(4) * y1 + y2) / T(3); | |
35634 | } | |
35635 | ||
35636 | return total_area; | |
35637 | } | |
35638 | ||
35639 | template <typename T> | |
35640 | inline T integrate(const expression<T>& e, | |
35641 | const std::string& variable_name, | |
35642 | const T& r0, const T& r1, | |
35643 | const std::size_t number_of_intervals = 1000000) | |
35644 | { | |
35645 | const symbol_table<T>& sym_table = e.get_symbol_table(); | |
35646 | ||
35647 | if (!sym_table.valid()) | |
35648 | return std::numeric_limits<T>::quiet_NaN(); | |
35649 | ||
35650 | details::variable_node<T>* var = sym_table.get_variable(variable_name); | |
35651 | ||
35652 | if (var) | |
35653 | { | |
35654 | T& x = var->ref(); | |
35655 | T x_original = x; | |
35656 | T result = integrate(e, x, r0, r1, number_of_intervals); | |
35657 | x = x_original; | |
35658 | ||
35659 | return result; | |
35660 | } | |
35661 | else | |
35662 | return std::numeric_limits<T>::quiet_NaN(); | |
35663 | } | |
35664 | ||
35665 | template <typename T> | |
35666 | inline T derivative(const expression<T>& e, | |
35667 | T& x, | |
35668 | const T& h = T(0.00000001)) | |
35669 | { | |
35670 | const T x_init = x; | |
35671 | const T _2h = T(2) * h; | |
35672 | ||
35673 | x = x_init + _2h; | |
35674 | const T y0 = e.value(); | |
35675 | x = x_init + h; | |
35676 | const T y1 = e.value(); | |
35677 | x = x_init - h; | |
35678 | const T y2 = e.value(); | |
35679 | x = x_init - _2h; | |
35680 | const T y3 = e.value(); | |
35681 | x = x_init; | |
35682 | ||
35683 | return (-y0 + T(8) * (y1 - y2) + y3) / (T(12) * h); | |
35684 | } | |
35685 | ||
35686 | template <typename T> | |
35687 | inline T second_derivative(const expression<T>& e, | |
35688 | T& x, | |
35689 | const T& h = T(0.00001)) | |
35690 | { | |
35691 | const T x_init = x; | |
35692 | const T _2h = T(2) * h; | |
35693 | ||
35694 | const T y = e.value(); | |
35695 | x = x_init + _2h; | |
35696 | const T y0 = e.value(); | |
35697 | x = x_init + h; | |
35698 | const T y1 = e.value(); | |
35699 | x = x_init - h; | |
35700 | const T y2 = e.value(); | |
35701 | x = x_init - _2h; | |
35702 | const T y3 = e.value(); | |
35703 | x = x_init; | |
35704 | ||
35705 | return (-y0 + T(16) * (y1 + y2) - T(30) * y - y3) / (T(12) * h * h); | |
35706 | } | |
35707 | ||
35708 | template <typename T> | |
35709 | inline T third_derivative(const expression<T>& e, | |
35710 | T& x, | |
35711 | const T& h = T(0.0001)) | |
35712 | { | |
35713 | const T x_init = x; | |
35714 | const T _2h = T(2) * h; | |
35715 | ||
35716 | x = x_init + _2h; | |
35717 | const T y0 = e.value(); | |
35718 | x = x_init + h; | |
35719 | const T y1 = e.value(); | |
35720 | x = x_init - h; | |
35721 | const T y2 = e.value(); | |
35722 | x = x_init - _2h; | |
35723 | const T y3 = e.value(); | |
35724 | x = x_init; | |
35725 | ||
35726 | return (y0 + T(2) * (y2 - y1) - y3) / (T(2) * h * h * h); | |
35727 | } | |
35728 | ||
35729 | template <typename T> | |
35730 | inline T derivative(const expression<T>& e, | |
35731 | const std::string& variable_name, | |
35732 | const T& h = T(0.00000001)) | |
35733 | { | |
35734 | const symbol_table<T>& sym_table = e.get_symbol_table(); | |
35735 | ||
35736 | if (!sym_table.valid()) | |
35737 | { | |
35738 | return std::numeric_limits<T>::quiet_NaN(); | |
35739 | } | |
35740 | ||
35741 | details::variable_node<T>* var = sym_table.get_variable(variable_name); | |
35742 | ||
35743 | if (var) | |
35744 | { | |
35745 | T& x = var->ref(); | |
35746 | T x_original = x; | |
35747 | T result = derivative(e, x, h); | |
35748 | x = x_original; | |
35749 | ||
35750 | return result; | |
35751 | } | |
35752 | else | |
35753 | return std::numeric_limits<T>::quiet_NaN(); | |
35754 | } | |
35755 | ||
35756 | template <typename T> | |
35757 | inline T second_derivative(const expression<T>& e, | |
35758 | const std::string& variable_name, | |
35759 | const T& h = T(0.00001)) | |
35760 | { | |
35761 | const symbol_table<T>& sym_table = e.get_symbol_table(); | |
35762 | ||
35763 | if (!sym_table.valid()) | |
35764 | { | |
35765 | return std::numeric_limits<T>::quiet_NaN(); | |
35766 | } | |
35767 | ||
35768 | details::variable_node<T>* var = sym_table.get_variable(variable_name); | |
35769 | ||
35770 | if (var) | |
35771 | { | |
35772 | T& x = var->ref(); | |
35773 | const T x_original = x; | |
35774 | const T result = second_derivative(e, x, h); | |
35775 | x = x_original; | |
35776 | ||
35777 | return result; | |
35778 | } | |
35779 | else | |
35780 | return std::numeric_limits<T>::quiet_NaN(); | |
35781 | } | |
35782 | ||
35783 | template <typename T> | |
35784 | inline T third_derivative(const expression<T>& e, | |
35785 | const std::string& variable_name, | |
35786 | const T& h = T(0.0001)) | |
35787 | { | |
35788 | const symbol_table<T>& sym_table = e.get_symbol_table(); | |
35789 | ||
35790 | if (!sym_table.valid()) | |
35791 | { | |
35792 | return std::numeric_limits<T>::quiet_NaN(); | |
35793 | } | |
35794 | ||
35795 | details::variable_node<T>* var = sym_table.get_variable(variable_name); | |
35796 | ||
35797 | if (var) | |
35798 | { | |
35799 | T& x = var->ref(); | |
35800 | const T x_original = x; | |
35801 | const T result = third_derivative(e, x, h); | |
35802 | x = x_original; | |
35803 | ||
35804 | return result; | |
35805 | } | |
35806 | else | |
35807 | return std::numeric_limits<T>::quiet_NaN(); | |
35808 | } | |
35809 | ||
35810 | /* | |
35811 | Note: The following 'compute' routines are simple helpers, | |
35812 | for quickly setting up the required pieces of code in order | |
35813 | to evaluate an expression. By virtue of how they operate | |
35814 | there will be an overhead with regards to their setup and | |
35815 | teardown and hence should not be used in time critical | |
35816 | sections of code. | |
35817 | Furthermore they only assume a small sub set of variables, | |
35818 | no string variables or user defined functions. | |
35819 | */ | |
35820 | template <typename T> | |
35821 | inline bool compute(const std::string& expression_string, T& result) | |
35822 | { | |
35823 | // No variables | |
35824 | symbol_table<T> symbol_table; | |
35825 | symbol_table.add_constants(); | |
35826 | ||
35827 | expression<T> expression; | |
35828 | expression.register_symbol_table(symbol_table); | |
35829 | ||
35830 | parser<T> parser; | |
35831 | ||
35832 | if (parser.compile(expression_string,expression)) | |
35833 | { | |
35834 | result = expression.value(); | |
35835 | ||
35836 | return true; | |
35837 | } | |
35838 | else | |
35839 | return false; | |
35840 | } | |
35841 | ||
35842 | template <typename T> | |
35843 | inline bool compute(const std::string& expression_string, | |
35844 | const T& x, | |
35845 | T& result) | |
35846 | { | |
35847 | // Only 'x' | |
35848 | static const std::string x_var("x"); | |
35849 | ||
35850 | symbol_table<T> symbol_table; | |
35851 | symbol_table.add_constants(); | |
35852 | symbol_table.add_constant(x_var,x); | |
35853 | ||
35854 | expression<T> expression; | |
35855 | expression.register_symbol_table(symbol_table); | |
35856 | ||
35857 | parser<T> parser; | |
35858 | ||
35859 | if (parser.compile(expression_string,expression)) | |
35860 | { | |
35861 | result = expression.value(); | |
35862 | ||
35863 | return true; | |
35864 | } | |
35865 | else | |
35866 | return false; | |
35867 | } | |
35868 | ||
35869 | template <typename T> | |
35870 | inline bool compute(const std::string& expression_string, | |
35871 | const T&x, const T& y, | |
35872 | T& result) | |
35873 | { | |
35874 | // Only 'x' and 'y' | |
35875 | static const std::string x_var("x"); | |
35876 | static const std::string y_var("y"); | |
35877 | ||
35878 | symbol_table<T> symbol_table; | |
35879 | symbol_table.add_constants(); | |
35880 | symbol_table.add_constant(x_var,x); | |
35881 | symbol_table.add_constant(y_var,y); | |
35882 | ||
35883 | expression<T> expression; | |
35884 | expression.register_symbol_table(symbol_table); | |
35885 | ||
35886 | parser<T> parser; | |
35887 | ||
35888 | if (parser.compile(expression_string,expression)) | |
35889 | { | |
35890 | result = expression.value(); | |
35891 | ||
35892 | return true; | |
35893 | } | |
35894 | else | |
35895 | return false; | |
35896 | } | |
35897 | ||
35898 | template <typename T> | |
35899 | inline bool compute(const std::string& expression_string, | |
35900 | const T& x, const T& y, const T& z, | |
35901 | T& result) | |
35902 | { | |
35903 | // Only 'x', 'y' or 'z' | |
35904 | static const std::string x_var("x"); | |
35905 | static const std::string y_var("y"); | |
35906 | static const std::string z_var("z"); | |
35907 | ||
35908 | symbol_table<T> symbol_table; | |
35909 | symbol_table.add_constants(); | |
35910 | symbol_table.add_constant(x_var,x); | |
35911 | symbol_table.add_constant(y_var,y); | |
35912 | symbol_table.add_constant(z_var,z); | |
35913 | ||
35914 | expression<T> expression; | |
35915 | expression.register_symbol_table(symbol_table); | |
35916 | ||
35917 | parser<T> parser; | |
35918 | ||
35919 | if (parser.compile(expression_string,expression)) | |
35920 | { | |
35921 | result = expression.value(); | |
35922 | ||
35923 | return true; | |
35924 | } | |
35925 | else | |
35926 | return false; | |
35927 | } | |
35928 | ||
35929 | template <typename T, std::size_t N> | |
35930 | class polynomial : public ifunction<T> | |
35931 | { | |
35932 | private: | |
35933 | ||
35934 | template <typename Type, std::size_t NumberOfCoefficients> | |
35935 | struct poly_impl { }; | |
35936 | ||
35937 | template <typename Type> | |
35938 | struct poly_impl <Type,12> | |
35939 | { | |
35940 | static inline T evaluate(const Type x, | |
35941 | const Type c12, const Type c11, const Type c10, const Type c9, const Type c8, | |
35942 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, | |
35943 | const Type c2, const Type c1, const Type c0) | |
35944 | { | |
35945 | // p(x) = c_12x^12 + c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
35946 | return ((((((((((((c12 * x + c11) * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
35947 | } | |
35948 | }; | |
35949 | ||
35950 | template <typename Type> | |
35951 | struct poly_impl <Type,11> | |
35952 | { | |
35953 | static inline T evaluate(const Type x, | |
35954 | const Type c11, const Type c10, const Type c9, const Type c8, const Type c7, | |
35955 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, | |
35956 | const Type c1, const Type c0) | |
35957 | { | |
35958 | // p(x) = c_11x^11 + c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
35959 | return (((((((((((c11 * x + c10) * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
35960 | } | |
35961 | }; | |
35962 | ||
35963 | template <typename Type> | |
35964 | struct poly_impl <Type,10> | |
35965 | { | |
35966 | static inline T evaluate(const Type x, | |
35967 | const Type c10, const Type c9, const Type c8, const Type c7, const Type c6, | |
35968 | const Type c5, const Type c4, const Type c3, const Type c2, const Type c1, | |
35969 | const Type c0) | |
35970 | { | |
35971 | // p(x) = c_10x^10 + c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
35972 | return ((((((((((c10 * x + c9) * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
35973 | } | |
35974 | }; | |
35975 | ||
35976 | template <typename Type> | |
35977 | struct poly_impl <Type,9> | |
35978 | { | |
35979 | static inline T evaluate(const Type x, | |
35980 | const Type c9, const Type c8, const Type c7, const Type c6, const Type c5, | |
35981 | const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) | |
35982 | { | |
35983 | // p(x) = c_9x^9 + c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
35984 | return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
35985 | } | |
35986 | }; | |
35987 | ||
35988 | template <typename Type> | |
35989 | struct poly_impl <Type,8> | |
35990 | { | |
35991 | static inline T evaluate(const Type x, | |
35992 | const Type c8, const Type c7, const Type c6, const Type c5, const Type c4, | |
35993 | const Type c3, const Type c2, const Type c1, const Type c0) | |
35994 | { | |
35995 | // p(x) = c_8x^8 + c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
35996 | return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
35997 | } | |
35998 | }; | |
35999 | ||
36000 | template <typename Type> | |
36001 | struct poly_impl <Type,7> | |
36002 | { | |
36003 | static inline T evaluate(const Type x, | |
36004 | const Type c7, const Type c6, const Type c5, const Type c4, const Type c3, | |
36005 | const Type c2, const Type c1, const Type c0) | |
36006 | { | |
36007 | // p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
36008 | return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
36009 | } | |
36010 | }; | |
36011 | ||
36012 | template <typename Type> | |
36013 | struct poly_impl <Type,6> | |
36014 | { | |
36015 | static inline T evaluate(const Type x, | |
36016 | const Type c6, const Type c5, const Type c4, const Type c3, const Type c2, | |
36017 | const Type c1, const Type c0) | |
36018 | { | |
36019 | // p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
36020 | return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
36021 | } | |
36022 | }; | |
36023 | ||
36024 | template <typename Type> | |
36025 | struct poly_impl <Type,5> | |
36026 | { | |
36027 | static inline T evaluate(const Type x, | |
36028 | const Type c5, const Type c4, const Type c3, const Type c2, | |
36029 | const Type c1, const Type c0) | |
36030 | { | |
36031 | // p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
36032 | return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0); | |
36033 | } | |
36034 | }; | |
36035 | ||
36036 | template <typename Type> | |
36037 | struct poly_impl <Type,4> | |
36038 | { | |
36039 | static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0) | |
36040 | { | |
36041 | // p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
36042 | return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0); | |
36043 | } | |
36044 | }; | |
36045 | ||
36046 | template <typename Type> | |
36047 | struct poly_impl <Type,3> | |
36048 | { | |
36049 | static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0) | |
36050 | { | |
36051 | // p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0x^0 | |
36052 | return (((c3 * x + c2) * x + c1) * x + c0); | |
36053 | } | |
36054 | }; | |
36055 | ||
36056 | template <typename Type> | |
36057 | struct poly_impl <Type,2> | |
36058 | { | |
36059 | static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0) | |
36060 | { | |
36061 | // p(x) = c_2x^2 + c_1x^1 + c_0x^0 | |
36062 | return ((c2 * x + c1) * x + c0); | |
36063 | } | |
36064 | }; | |
36065 | ||
36066 | template <typename Type> | |
36067 | struct poly_impl <Type,1> | |
36068 | { | |
36069 | static inline T evaluate(const Type x, const Type c1, const Type c0) | |
36070 | { | |
36071 | // p(x) = c_1x^1 + c_0x^0 | |
36072 | return (c1 * x + c0); | |
36073 | } | |
36074 | }; | |
36075 | ||
36076 | public: | |
36077 | ||
36078 | using ifunction<T>::operator(); | |
36079 | ||
36080 | polynomial() | |
36081 | : ifunction<T>((N+2 <= 20) ? (N + 2) : std::numeric_limits<std::size_t>::max()) | |
36082 | { | |
36083 | disable_has_side_effects(*this); | |
36084 | } | |
36085 | ||
36086 | virtual ~polynomial() | |
36087 | {} | |
36088 | ||
36089 | #define poly_rtrn(NN) \ | |
36090 | return (NN != N) ? std::numeric_limits<T>::quiet_NaN() : | |
36091 | ||
36092 | inline virtual T operator() (const T& x, const T& c1, const T& c0) | |
36093 | { | |
36094 | poly_rtrn(1) poly_impl<T,1>::evaluate(x, c1, c0); | |
36095 | } | |
36096 | ||
36097 | inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) | |
36098 | { | |
36099 | poly_rtrn(2) poly_impl<T,2>::evaluate(x, c2, c1, c0); | |
36100 | } | |
36101 | ||
36102 | inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) | |
36103 | { | |
36104 | poly_rtrn(3) poly_impl<T,3>::evaluate(x, c3, c2, c1, c0); | |
36105 | } | |
36106 | ||
36107 | inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36108 | { | |
36109 | poly_rtrn(4) poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0); | |
36110 | } | |
36111 | ||
36112 | inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36113 | { | |
36114 | poly_rtrn(5) poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0); | |
36115 | } | |
36116 | ||
36117 | inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36118 | { | |
36119 | poly_rtrn(6) poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0); | |
36120 | } | |
36121 | ||
36122 | inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36123 | { | |
36124 | poly_rtrn(7) poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0); | |
36125 | } | |
36126 | ||
36127 | inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36128 | { | |
36129 | poly_rtrn(8) poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0); | |
36130 | } | |
36131 | ||
36132 | inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36133 | { | |
36134 | poly_rtrn(9) poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0); | |
36135 | } | |
36136 | ||
36137 | inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36138 | { | |
36139 | poly_rtrn(10) poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0); | |
36140 | } | |
36141 | ||
36142 | inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36143 | { | |
36144 | poly_rtrn(11) poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0); | |
36145 | } | |
36146 | ||
36147 | inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) | |
36148 | { | |
36149 | poly_rtrn(12) poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0); | |
36150 | } | |
36151 | ||
36152 | #undef poly_rtrn | |
36153 | ||
36154 | inline virtual T operator() () | |
36155 | { | |
36156 | return std::numeric_limits<T>::quiet_NaN(); | |
36157 | } | |
36158 | ||
36159 | inline virtual T operator() (const T&) | |
36160 | { | |
36161 | return std::numeric_limits<T>::quiet_NaN(); | |
36162 | } | |
36163 | ||
36164 | inline virtual T operator() (const T&, const T&) | |
36165 | { | |
36166 | return std::numeric_limits<T>::quiet_NaN(); | |
36167 | } | |
36168 | }; | |
36169 | ||
36170 | template <typename T> | |
36171 | class function_compositor | |
36172 | { | |
36173 | public: | |
36174 | ||
36175 | typedef exprtk::expression<T> expression_t; | |
36176 | typedef exprtk::symbol_table<T> symbol_table_t; | |
36177 | typedef exprtk::parser<T> parser_t; | |
36178 | typedef typename parser_t::settings_store settings_t; | |
36179 | ||
36180 | struct function | |
36181 | { | |
36182 | function() | |
36183 | {} | |
36184 | ||
36185 | function(const std::string& n) | |
36186 | : name_(n) | |
36187 | {} | |
36188 | ||
36189 | function(const std::string& name, | |
36190 | const std::string& expression) | |
36191 | : name_(name), | |
36192 | expression_(expression) | |
36193 | {} | |
36194 | ||
36195 | function(const std::string& name, | |
36196 | const std::string& expression, | |
36197 | const std::string& v0) | |
36198 | : name_(name), | |
36199 | expression_(expression) | |
36200 | { | |
36201 | v_.push_back(v0); | |
36202 | } | |
36203 | ||
36204 | function(const std::string& name, | |
36205 | const std::string& expression, | |
36206 | const std::string& v0, const std::string& v1) | |
36207 | : name_(name), | |
36208 | expression_(expression) | |
36209 | { | |
36210 | v_.push_back(v0); v_.push_back(v1); | |
36211 | } | |
36212 | ||
36213 | function(const std::string& name, | |
36214 | const std::string& expression, | |
36215 | const std::string& v0, const std::string& v1, | |
36216 | const std::string& v2) | |
36217 | : name_(name), | |
36218 | expression_(expression) | |
36219 | { | |
36220 | v_.push_back(v0); v_.push_back(v1); | |
36221 | v_.push_back(v2); | |
36222 | } | |
36223 | ||
36224 | function(const std::string& name, | |
36225 | const std::string& expression, | |
36226 | const std::string& v0, const std::string& v1, | |
36227 | const std::string& v2, const std::string& v3) | |
36228 | : name_(name), | |
36229 | expression_(expression) | |
36230 | { | |
36231 | v_.push_back(v0); v_.push_back(v1); | |
36232 | v_.push_back(v2); v_.push_back(v3); | |
36233 | } | |
36234 | ||
36235 | function(const std::string& name, | |
36236 | const std::string& expression, | |
36237 | const std::string& v0, const std::string& v1, | |
36238 | const std::string& v2, const std::string& v3, | |
36239 | const std::string& v4) | |
36240 | : name_(name), | |
36241 | expression_(expression) | |
36242 | { | |
36243 | v_.push_back(v0); v_.push_back(v1); | |
36244 | v_.push_back(v2); v_.push_back(v3); | |
36245 | v_.push_back(v4); | |
36246 | } | |
36247 | ||
36248 | inline function& name(const std::string& n) | |
36249 | { | |
36250 | name_ = n; | |
36251 | return (*this); | |
36252 | } | |
36253 | ||
36254 | inline function& expression(const std::string& e) | |
36255 | { | |
36256 | expression_ = e; | |
36257 | return (*this); | |
36258 | } | |
36259 | ||
36260 | inline function& var(const std::string& v) | |
36261 | { | |
36262 | v_.push_back(v); | |
36263 | return (*this); | |
36264 | } | |
36265 | ||
36266 | std::string name_; | |
36267 | std::string expression_; | |
36268 | std::deque<std::string> v_; | |
36269 | }; | |
36270 | ||
36271 | private: | |
36272 | ||
36273 | struct base_func : public exprtk::ifunction<T> | |
36274 | { | |
36275 | typedef const T& type; | |
36276 | typedef exprtk::ifunction<T> function_t; | |
36277 | typedef std::vector<T*> varref_t; | |
36278 | typedef std::vector<T> var_t; | |
36279 | typedef std::pair<T*,std::size_t> lvarref_t; | |
36280 | typedef std::vector<lvarref_t> lvr_vec_t; | |
36281 | ||
36282 | using exprtk::ifunction<T>::operator(); | |
36283 | ||
36284 | base_func(const std::size_t& pc = 0) | |
36285 | : exprtk::ifunction<T>(pc), | |
36286 | local_var_stack_size(0), | |
36287 | stack_depth(0) | |
36288 | { | |
36289 | v.resize(pc); | |
36290 | } | |
36291 | ||
36292 | virtual ~base_func() | |
36293 | {} | |
36294 | ||
36295 | inline void update(const T& v0) | |
36296 | { | |
36297 | (*v[0]) = v0; | |
36298 | } | |
36299 | ||
36300 | inline void update(const T& v0, const T& v1) | |
36301 | { | |
36302 | (*v[0]) = v0; (*v[1]) = v1; | |
36303 | } | |
36304 | ||
36305 | inline void update(const T& v0, const T& v1, const T& v2) | |
36306 | { | |
36307 | (*v[0]) = v0; (*v[1]) = v1; | |
36308 | (*v[2]) = v2; | |
36309 | } | |
36310 | ||
36311 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3) | |
36312 | { | |
36313 | (*v[0]) = v0; (*v[1]) = v1; | |
36314 | (*v[2]) = v2; (*v[3]) = v3; | |
36315 | } | |
36316 | ||
36317 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) | |
36318 | { | |
36319 | (*v[0]) = v0; (*v[1]) = v1; | |
36320 | (*v[2]) = v2; (*v[3]) = v3; | |
36321 | (*v[4]) = v4; | |
36322 | } | |
36323 | ||
36324 | inline void update(const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) | |
36325 | { | |
36326 | (*v[0]) = v0; (*v[1]) = v1; | |
36327 | (*v[2]) = v2; (*v[3]) = v3; | |
36328 | (*v[4]) = v4; (*v[5]) = v5; | |
36329 | } | |
36330 | ||
36331 | inline function_t& setup(expression_t& expr) | |
36332 | { | |
36333 | expression = expr; | |
36334 | ||
36335 | typedef typename expression_t::control_block::local_data_list_t ldl_t; | |
36336 | ||
36337 | ldl_t ldl = expr.local_data_list(); | |
36338 | ||
36339 | std::vector<std::size_t> index_list; | |
36340 | ||
36341 | for (std::size_t i = 0; i < ldl.size(); ++i) | |
36342 | { | |
36343 | if (ldl[i].size) | |
36344 | { | |
36345 | index_list.push_back(i); | |
36346 | } | |
36347 | } | |
36348 | ||
36349 | std::size_t input_param_count = 0; | |
36350 | ||
36351 | for (std::size_t i = 0; i < index_list.size(); ++i) | |
36352 | { | |
36353 | const std::size_t index = index_list[i]; | |
36354 | ||
36355 | if (i < (index_list.size() - v.size())) | |
36356 | { | |
36357 | lv.push_back( | |
36358 | std::make_pair( | |
36359 | reinterpret_cast<T*>(ldl[index].pointer), | |
36360 | ldl[index].size)); | |
36361 | ||
36362 | local_var_stack_size += ldl[index].size; | |
36363 | } | |
36364 | else | |
36365 | v[input_param_count++] = reinterpret_cast<T*>(ldl[index].pointer); | |
36366 | } | |
36367 | ||
36368 | clear_stack(); | |
36369 | ||
36370 | return (*this); | |
36371 | } | |
36372 | ||
36373 | inline void pre() | |
36374 | { | |
36375 | if (stack_depth++) | |
36376 | { | |
36377 | if (!v.empty()) | |
36378 | { | |
36379 | var_t var_stack(v.size(),T(0)); | |
36380 | copy(v,var_stack); | |
36381 | param_stack.push_back(var_stack); | |
36382 | } | |
36383 | ||
36384 | if (!lv.empty()) | |
36385 | { | |
36386 | var_t local_var_stack(local_var_stack_size,T(0)); | |
36387 | copy(lv,local_var_stack); | |
36388 | local_stack.push_back(local_var_stack); | |
36389 | } | |
36390 | } | |
36391 | } | |
36392 | ||
36393 | inline void post() | |
36394 | { | |
36395 | if (--stack_depth) | |
36396 | { | |
36397 | if (!v.empty()) | |
36398 | { | |
36399 | copy(param_stack.back(),v); | |
36400 | param_stack.pop_back(); | |
36401 | } | |
36402 | ||
36403 | if (!lv.empty()) | |
36404 | { | |
36405 | copy(local_stack.back(),lv); | |
36406 | local_stack.pop_back(); | |
36407 | } | |
36408 | } | |
36409 | } | |
36410 | ||
36411 | void copy(const varref_t& src_v, var_t& dest_v) | |
36412 | { | |
36413 | for (std::size_t i = 0; i < src_v.size(); ++i) | |
36414 | { | |
36415 | dest_v[i] = (*src_v[i]); | |
36416 | } | |
36417 | } | |
36418 | ||
36419 | void copy(const var_t& src_v, varref_t& dest_v) | |
36420 | { | |
36421 | for (std::size_t i = 0; i < src_v.size(); ++i) | |
36422 | { | |
36423 | (*dest_v[i]) = src_v[i]; | |
36424 | } | |
36425 | } | |
36426 | ||
36427 | void copy(const lvr_vec_t& src_v, var_t& dest_v) | |
36428 | { | |
36429 | typename var_t::iterator itr = dest_v.begin(); | |
36430 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; | |
36431 | ||
36432 | for (std::size_t i = 0; i < src_v.size(); ++i) | |
36433 | { | |
36434 | lvarref_t vr = src_v[i]; | |
36435 | ||
36436 | if (1 == vr.second) | |
36437 | *itr++ = (*vr.first); | |
36438 | else | |
36439 | { | |
36440 | std::copy(vr.first, vr.first + vr.second, itr); | |
36441 | itr += static_cast<diff_t>(vr.second); | |
36442 | } | |
36443 | } | |
36444 | } | |
36445 | ||
36446 | void copy(const var_t& src_v, lvr_vec_t& dest_v) | |
36447 | { | |
36448 | typename var_t::const_iterator itr = src_v.begin(); | |
36449 | typedef typename std::iterator_traits<typename var_t::iterator>::difference_type diff_t; | |
36450 | ||
36451 | for (std::size_t i = 0; i < src_v.size(); ++i) | |
36452 | { | |
36453 | lvarref_t vr = dest_v[i]; | |
36454 | ||
36455 | if (1 == vr.second) | |
36456 | (*vr.first) = *itr++; | |
36457 | else | |
36458 | { | |
36459 | std::copy(itr, itr + static_cast<diff_t>(vr.second), vr.first); | |
36460 | itr += static_cast<diff_t>(vr.second); | |
36461 | } | |
36462 | } | |
36463 | } | |
36464 | ||
36465 | inline void clear_stack() | |
36466 | { | |
36467 | for (std::size_t i = 0; i < v.size(); ++i) | |
36468 | { | |
36469 | (*v[i]) = 0; | |
36470 | } | |
36471 | } | |
36472 | ||
36473 | inline virtual T value(expression_t& e) | |
36474 | { | |
36475 | return e.value(); | |
36476 | } | |
36477 | ||
36478 | expression_t expression; | |
36479 | varref_t v; | |
36480 | lvr_vec_t lv; | |
36481 | std::size_t local_var_stack_size; | |
36482 | std::size_t stack_depth; | |
36483 | std::deque<var_t> param_stack; | |
36484 | std::deque<var_t> local_stack; | |
36485 | }; | |
36486 | ||
36487 | typedef std::map<std::string,base_func*> funcparam_t; | |
36488 | ||
36489 | struct func_0param : public base_func | |
36490 | { | |
36491 | using exprtk::ifunction<T>::operator(); | |
36492 | ||
36493 | func_0param() : base_func(0) {} | |
36494 | ||
36495 | inline T operator() () | |
36496 | { | |
36497 | return this->value(base_func::expression); | |
36498 | } | |
36499 | }; | |
36500 | ||
36501 | typedef const T& type; | |
36502 | ||
36503 | template <typename BaseFuncType> | |
36504 | struct scoped_bft | |
36505 | { | |
36506 | scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); } | |
36507 | ~scoped_bft() { bft_.post(); } | |
36508 | ||
36509 | BaseFuncType& bft_; | |
36510 | ||
36511 | private: | |
36512 | ||
36513 | scoped_bft(scoped_bft&); | |
36514 | scoped_bft& operator=(scoped_bft&); | |
36515 | }; | |
36516 | ||
36517 | struct func_1param : public base_func | |
36518 | { | |
36519 | using exprtk::ifunction<T>::operator(); | |
36520 | ||
36521 | func_1param() : base_func(1) {} | |
36522 | ||
36523 | inline T operator() (type v0) | |
36524 | { | |
36525 | scoped_bft<func_1param> sb(*this); | |
36526 | base_func::update(v0); | |
36527 | return this->value(base_func::expression); | |
36528 | } | |
36529 | }; | |
36530 | ||
36531 | struct func_2param : public base_func | |
36532 | { | |
36533 | using exprtk::ifunction<T>::operator(); | |
36534 | ||
36535 | func_2param() : base_func(2) {} | |
36536 | ||
36537 | inline T operator() (type v0, type v1) | |
36538 | { | |
36539 | scoped_bft<func_2param> sb(*this); | |
36540 | base_func::update(v0, v1); | |
36541 | return this->value(base_func::expression); | |
36542 | } | |
36543 | }; | |
36544 | ||
36545 | struct func_3param : public base_func | |
36546 | { | |
36547 | using exprtk::ifunction<T>::operator(); | |
36548 | ||
36549 | func_3param() : base_func(3) {} | |
36550 | ||
36551 | inline T operator() (type v0, type v1, type v2) | |
36552 | { | |
36553 | scoped_bft<func_3param> sb(*this); | |
36554 | base_func::update(v0, v1, v2); | |
36555 | return this->value(base_func::expression); | |
36556 | } | |
36557 | }; | |
36558 | ||
36559 | struct func_4param : public base_func | |
36560 | { | |
36561 | using exprtk::ifunction<T>::operator(); | |
36562 | ||
36563 | func_4param() : base_func(4) {} | |
36564 | ||
36565 | inline T operator() (type v0, type v1, type v2, type v3) | |
36566 | { | |
36567 | scoped_bft<func_4param> sb(*this); | |
36568 | base_func::update(v0, v1, v2, v3); | |
36569 | return this->value(base_func::expression); | |
36570 | } | |
36571 | }; | |
36572 | ||
36573 | struct func_5param : public base_func | |
36574 | { | |
36575 | using exprtk::ifunction<T>::operator(); | |
36576 | ||
36577 | func_5param() : base_func(5) {} | |
36578 | ||
36579 | inline T operator() (type v0, type v1, type v2, type v3, type v4) | |
36580 | { | |
36581 | scoped_bft<func_5param> sb(*this); | |
36582 | base_func::update(v0, v1, v2, v3, v4); | |
36583 | return this->value(base_func::expression); | |
36584 | } | |
36585 | }; | |
36586 | ||
36587 | struct func_6param : public base_func | |
36588 | { | |
36589 | using exprtk::ifunction<T>::operator(); | |
36590 | ||
36591 | func_6param() : base_func(6) {} | |
36592 | ||
36593 | inline T operator() (type v0, type v1, type v2, type v3, type v4, type v5) | |
36594 | { | |
36595 | scoped_bft<func_6param> sb(*this); | |
36596 | base_func::update(v0, v1, v2, v3, v4, v5); | |
36597 | return this->value(base_func::expression); | |
36598 | } | |
36599 | }; | |
36600 | ||
36601 | static T return_value(expression_t& e) | |
36602 | { | |
36603 | typedef exprtk::results_context<T> results_context_t; | |
36604 | typedef typename results_context_t::type_store_t type_t; | |
36605 | typedef typename type_t::scalar_view scalar_t; | |
36606 | ||
36607 | T result = e.value(); | |
36608 | ||
36609 | if (e.return_invoked()) | |
36610 | { | |
36611 | // Due to the post compilation checks, it can be safely | |
36612 | // assumed that there will be at least one parameter | |
36613 | // and that the first parameter will always be scalar. | |
36614 | return scalar_t(e.results()[0])(); | |
36615 | } | |
36616 | ||
36617 | return result; | |
36618 | } | |
36619 | ||
36620 | #define def_fp_retval(N) \ | |
36621 | struct func_##N##param_retval : public func_##N##param \ | |
36622 | { \ | |
36623 | inline T value(expression_t& e) \ | |
36624 | { \ | |
36625 | return return_value(e); \ | |
36626 | } \ | |
36627 | }; \ | |
36628 | ||
36629 | def_fp_retval(0) | |
36630 | def_fp_retval(1) | |
36631 | def_fp_retval(2) | |
36632 | def_fp_retval(3) | |
36633 | def_fp_retval(4) | |
36634 | def_fp_retval(5) | |
36635 | def_fp_retval(6) | |
36636 | ||
36637 | template <typename Allocator, | |
36638 | template <typename, typename> class Sequence> | |
36639 | inline bool add(const std::string& name, | |
36640 | const std::string& expression, | |
36641 | const Sequence<std::string,Allocator>& var_list, | |
36642 | const bool override = false) | |
36643 | { | |
36644 | const typename std::map<std::string,expression_t>::iterator itr = expr_map_.find(name); | |
36645 | ||
36646 | if (expr_map_.end() != itr) | |
36647 | { | |
36648 | if (!override) | |
36649 | { | |
36650 | exprtk_debug(("Compositor error(add): function '%s' already defined\n", | |
36651 | name.c_str())); | |
36652 | ||
36653 | return false; | |
36654 | } | |
36655 | ||
36656 | remove(name, var_list.size()); | |
36657 | } | |
36658 | ||
36659 | if (compile_expression(name,expression,var_list)) | |
36660 | { | |
36661 | const std::size_t n = var_list.size(); | |
36662 | ||
36663 | fp_map_[n][name]->setup(expr_map_[name]); | |
36664 | ||
36665 | return true; | |
36666 | } | |
36667 | else | |
36668 | { | |
36669 | exprtk_debug(("Compositor error(add): Failed to compile function '%s'\n", | |
36670 | name.c_str())); | |
36671 | ||
36672 | return false; | |
36673 | } | |
36674 | } | |
36675 | ||
36676 | public: | |
36677 | ||
36678 | function_compositor() | |
36679 | : parser_(settings_t::compile_all_opts + | |
36680 | settings_t::e_disable_zero_return), | |
36681 | fp_map_(7) | |
36682 | {} | |
36683 | ||
36684 | function_compositor(const symbol_table_t& st) | |
36685 | : symbol_table_(st), | |
36686 | parser_(settings_t::compile_all_opts + | |
36687 | settings_t::e_disable_zero_return), | |
36688 | fp_map_(7) | |
36689 | {} | |
36690 | ||
36691 | ~function_compositor() | |
36692 | { | |
36693 | clear(); | |
36694 | } | |
36695 | ||
36696 | inline symbol_table_t& symbol_table() | |
36697 | { | |
36698 | return symbol_table_; | |
36699 | } | |
36700 | ||
36701 | inline void add_auxiliary_symtab(symbol_table_t& symtab) | |
36702 | { | |
36703 | auxiliary_symtab_list_.push_back(&symtab); | |
36704 | } | |
36705 | ||
36706 | void clear() | |
36707 | { | |
36708 | symbol_table_.clear(); | |
36709 | expr_map_ .clear(); | |
36710 | ||
36711 | for (std::size_t i = 0; i < fp_map_.size(); ++i) | |
36712 | { | |
36713 | typename funcparam_t::iterator itr = fp_map_[i].begin(); | |
36714 | typename funcparam_t::iterator end = fp_map_[i].end (); | |
36715 | ||
36716 | while (itr != end) | |
36717 | { | |
36718 | delete itr->second; | |
36719 | ++itr; | |
36720 | } | |
36721 | ||
36722 | fp_map_[i].clear(); | |
36723 | } | |
36724 | } | |
36725 | ||
36726 | inline bool add(const function& f, const bool override = false) | |
36727 | { | |
36728 | return add(f.name_, f.expression_, f.v_,override); | |
36729 | } | |
36730 | ||
36731 | private: | |
36732 | ||
36733 | template <typename Allocator, | |
36734 | template <typename, typename> class Sequence> | |
36735 | bool compile_expression(const std::string& name, | |
36736 | const std::string& expression, | |
36737 | const Sequence<std::string,Allocator>& input_var_list, | |
36738 | bool return_present = false) | |
36739 | { | |
36740 | expression_t compiled_expression; | |
36741 | symbol_table_t local_symbol_table; | |
36742 | ||
36743 | local_symbol_table.load_from(symbol_table_); | |
36744 | local_symbol_table.add_constants(); | |
36745 | ||
36746 | if (!valid(name,input_var_list.size())) | |
36747 | return false; | |
36748 | ||
36749 | if (!forward(name, | |
36750 | input_var_list.size(), | |
36751 | local_symbol_table, | |
36752 | return_present)) | |
36753 | return false; | |
36754 | ||
36755 | compiled_expression.register_symbol_table(local_symbol_table); | |
36756 | ||
36757 | for (std::size_t i = 0; i < auxiliary_symtab_list_.size(); ++i) | |
36758 | { | |
36759 | compiled_expression.register_symbol_table((*auxiliary_symtab_list_[i])); | |
36760 | } | |
36761 | ||
36762 | std::string mod_expression; | |
36763 | ||
36764 | for (std::size_t i = 0; i < input_var_list.size(); ++i) | |
36765 | { | |
36766 | mod_expression += " var " + input_var_list[i] + "{};\n"; | |
36767 | } | |
36768 | ||
36769 | if ( | |
36770 | ('{' == details::front(expression)) && | |
36771 | ('}' == details::back (expression)) | |
36772 | ) | |
36773 | mod_expression += "~" + expression + ";"; | |
36774 | else | |
36775 | mod_expression += "~{" + expression + "};"; | |
36776 | ||
36777 | if (!parser_.compile(mod_expression,compiled_expression)) | |
36778 | { | |
36779 | exprtk_debug(("Compositor Error: %s\n",parser_.error().c_str())); | |
36780 | exprtk_debug(("Compositor modified expression: \n%s\n",mod_expression.c_str())); | |
36781 | ||
36782 | remove(name,input_var_list.size()); | |
36783 | ||
36784 | return false; | |
36785 | } | |
36786 | ||
36787 | if (!return_present && parser_.dec().return_present()) | |
36788 | { | |
36789 | remove(name,input_var_list.size()); | |
36790 | ||
36791 | return compile_expression(name, expression, input_var_list, true); | |
36792 | } | |
36793 | ||
36794 | // Make sure every return point has a scalar as its first parameter | |
36795 | if (parser_.dec().return_present()) | |
36796 | { | |
36797 | typedef std::vector<std::string> str_list_t; | |
36798 | ||
36799 | str_list_t ret_param_list = parser_.dec().return_param_type_list(); | |
36800 | ||
36801 | for (std::size_t i = 0; i < ret_param_list.size(); ++i) | |
36802 | { | |
36803 | const std::string& params = ret_param_list[i]; | |
36804 | ||
36805 | if (params.empty() || ('T' != params[0])) | |
36806 | { | |
36807 | exprtk_debug(("Compositor Error: Return statement in function '%s' is invalid\n", | |
36808 | name.c_str())); | |
36809 | ||
36810 | remove(name,input_var_list.size()); | |
36811 | ||
36812 | return false; | |
36813 | } | |
36814 | } | |
36815 | } | |
36816 | ||
36817 | expr_map_[name] = compiled_expression; | |
36818 | ||
36819 | exprtk::ifunction<T>& ifunc = (*(fp_map_[input_var_list.size()])[name]); | |
36820 | ||
36821 | if (symbol_table_.add_function(name,ifunc)) | |
36822 | return true; | |
36823 | else | |
36824 | { | |
36825 | exprtk_debug(("Compositor Error: Failed to add function '%s' to symbol table\n", | |
36826 | name.c_str())); | |
36827 | return false; | |
36828 | } | |
36829 | } | |
36830 | ||
36831 | inline bool symbol_used(const std::string& symbol) const | |
36832 | { | |
36833 | return ( | |
36834 | symbol_table_.is_variable (symbol) || | |
36835 | symbol_table_.is_stringvar (symbol) || | |
36836 | symbol_table_.is_function (symbol) || | |
36837 | symbol_table_.is_vector (symbol) || | |
36838 | symbol_table_.is_vararg_function(symbol) | |
36839 | ); | |
36840 | } | |
36841 | ||
36842 | inline bool valid(const std::string& name, | |
36843 | const std::size_t& arg_count) const | |
36844 | { | |
36845 | if (arg_count > 6) | |
36846 | return false; | |
36847 | else if (symbol_used(name)) | |
36848 | return false; | |
36849 | else if (fp_map_[arg_count].end() != fp_map_[arg_count].find(name)) | |
36850 | return false; | |
36851 | else | |
36852 | return true; | |
36853 | } | |
36854 | ||
36855 | inline bool forward(const std::string& name, | |
36856 | const std::size_t& arg_count, | |
36857 | symbol_table_t& sym_table, | |
36858 | const bool ret_present = false) | |
36859 | { | |
36860 | switch (arg_count) | |
36861 | { | |
36862 | #define case_stmt(N) \ | |
36863 | case N : (fp_map_[arg_count])[name] = \ | |
36864 | (!ret_present) ? static_cast<base_func*> \ | |
36865 | (new func_##N##param) : \ | |
36866 | static_cast<base_func*> \ | |
36867 | (new func_##N##param_retval) ; \ | |
36868 | break; \ | |
36869 | ||
36870 | case_stmt(0) case_stmt(1) case_stmt(2) | |
36871 | case_stmt(3) case_stmt(4) case_stmt(5) | |
36872 | case_stmt(6) | |
36873 | #undef case_stmt | |
36874 | } | |
36875 | ||
36876 | exprtk::ifunction<T>& ifunc = (*(fp_map_[arg_count])[name]); | |
36877 | ||
36878 | return sym_table.add_function(name,ifunc); | |
36879 | } | |
36880 | ||
36881 | inline void remove(const std::string& name, const std::size_t& arg_count) | |
36882 | { | |
36883 | if (arg_count > 6) | |
36884 | return; | |
36885 | ||
36886 | const typename std::map<std::string,expression_t>::iterator em_itr = expr_map_.find(name); | |
36887 | ||
36888 | if (expr_map_.end() != em_itr) | |
36889 | { | |
36890 | expr_map_.erase(em_itr); | |
36891 | } | |
36892 | ||
36893 | const typename funcparam_t::iterator fp_itr = fp_map_[arg_count].find(name); | |
36894 | ||
36895 | if (fp_map_[arg_count].end() != fp_itr) | |
36896 | { | |
36897 | delete fp_itr->second; | |
36898 | fp_map_[arg_count].erase(fp_itr); | |
36899 | } | |
36900 | ||
36901 | symbol_table_.remove_function(name); | |
36902 | } | |
36903 | ||
36904 | private: | |
36905 | ||
36906 | symbol_table_t symbol_table_; | |
36907 | parser_t parser_; | |
36908 | std::map<std::string,expression_t> expr_map_; | |
36909 | std::vector<funcparam_t> fp_map_; | |
36910 | std::vector<symbol_table_t*> auxiliary_symtab_list_; | |
36911 | }; | |
36912 | ||
36913 | template <typename T> | |
36914 | inline bool pgo_primer() | |
36915 | { | |
36916 | static const std::string expression_list[] = | |
36917 | { | |
36918 | "(y + x)", | |
36919 | "2 * (y + x)", | |
36920 | "(2 * y + 2 * x)", | |
36921 | "(y + x / y) * (x - y / x)", | |
36922 | "x / ((x + y) * (x - y)) / y", | |
36923 | "1 - ((x * y) + (y / x)) - 3", | |
36924 | "sin(2 * x) + cos(pi / y)", | |
36925 | "1 - sin(2 * x) + cos(pi / y)", | |
36926 | "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", | |
36927 | "(x^2 / sin(2 * pi / y)) -x / 2", | |
36928 | "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", | |
36929 | "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", | |
36930 | "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", | |
36931 | "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", | |
36932 | "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", | |
36933 | "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", | |
36934 | "(yy + xx)", | |
36935 | "2 * (yy + xx)", | |
36936 | "(2 * yy + 2 * xx)", | |
36937 | "(yy + xx / yy) * (xx - yy / xx)", | |
36938 | "xx / ((xx + yy) * (xx - yy)) / yy", | |
36939 | "1 - ((xx * yy) + (yy / xx)) - 3", | |
36940 | "sin(2 * xx) + cos(pi / yy)", | |
36941 | "1 - sin(2 * xx) + cos(pi / yy)", | |
36942 | "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", | |
36943 | "(xx^2 / sin(2 * pi / yy)) -xx / 2", | |
36944 | "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", | |
36945 | "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", | |
36946 | "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", | |
36947 | "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", | |
36948 | "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", | |
36949 | "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", | |
36950 | "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", | |
36951 | "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", | |
36952 | "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", | |
36953 | "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", | |
36954 | "(x + 2) * 3", "x + (2 * 3)", | |
36955 | "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", | |
36956 | "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", | |
36957 | "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", | |
36958 | "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", | |
36959 | "2 + (x * (y / 3))", "x + (2 * (3 / y))", | |
36960 | "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", | |
36961 | "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", | |
36962 | "x + ((2 * 3) / y)", "(((x + y) * z) / w)", | |
36963 | "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", | |
36964 | "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", | |
36965 | "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", | |
36966 | "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", | |
36967 | "((x + (2 * 3)) / y)", | |
36968 | "(xx + yy) * zz", "xx + (yy * zz)", | |
36969 | "(xx + yy) * 7", "xx + (yy * 7)", | |
36970 | "(xx + 7) * yy", "xx + (7 * yy)", | |
36971 | "(7 + xx) * yy", "7 + (xx * yy)", | |
36972 | "(2 + x) * 3", "2 + (x * 3)", | |
36973 | "(2 + 3) * x", "2 + (3 * x)", | |
36974 | "(x + 2) * 3", "x + (2 * 3)", | |
36975 | "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", | |
36976 | "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", | |
36977 | "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", | |
36978 | "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", | |
36979 | "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", | |
36980 | "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", | |
36981 | "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", | |
36982 | "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", | |
36983 | "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", | |
36984 | "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", | |
36985 | "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", | |
36986 | "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", | |
36987 | "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", | |
36988 | "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", | |
36989 | "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", | |
36990 | "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", | |
36991 | "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", | |
36992 | "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", | |
36993 | "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", | |
36994 | "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", | |
36995 | "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", | |
36996 | "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", | |
36997 | "((xx + (2 * 3)) / yy)" | |
36998 | }; | |
36999 | ||
37000 | static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); | |
37001 | ||
37002 | T x = T(0); | |
37003 | T y = T(0); | |
37004 | T z = T(0); | |
37005 | T w = T(0); | |
37006 | T xx = T(0); | |
37007 | T yy = T(0); | |
37008 | T zz = T(0); | |
37009 | T ww = T(0); | |
37010 | ||
37011 | exprtk::symbol_table<T> symbol_table; | |
37012 | symbol_table.add_constants(); | |
37013 | symbol_table.add_variable( "x", x); | |
37014 | symbol_table.add_variable( "y", y); | |
37015 | symbol_table.add_variable( "z", z); | |
37016 | symbol_table.add_variable( "w", w); | |
37017 | symbol_table.add_variable("xx",xx); | |
37018 | symbol_table.add_variable("yy",yy); | |
37019 | symbol_table.add_variable("zz",zz); | |
37020 | symbol_table.add_variable("ww",ww); | |
37021 | ||
37022 | typedef typename std::deque<exprtk::expression<T> > expr_list_t; | |
37023 | expr_list_t expr_list; | |
37024 | ||
37025 | const std::size_t rounds = 50; | |
37026 | ||
37027 | { | |
37028 | for (std::size_t r = 0; r < rounds; ++r) | |
37029 | { | |
37030 | expr_list.clear(); | |
37031 | exprtk::parser<T> parser; | |
37032 | ||
37033 | for (std::size_t i = 0; i < expression_list_size; ++i) | |
37034 | { | |
37035 | exprtk::expression<T> expression; | |
37036 | expression.register_symbol_table(symbol_table); | |
37037 | ||
37038 | if (!parser.compile(expression_list[i],expression)) | |
37039 | { | |
37040 | return false; | |
37041 | } | |
37042 | ||
37043 | expr_list.push_back(expression); | |
37044 | } | |
37045 | } | |
37046 | } | |
37047 | ||
37048 | struct execute | |
37049 | { | |
37050 | static inline T process(T& x, T& y, expression<T>& expression) | |
37051 | { | |
37052 | static const T lower_bound = T(-20); | |
37053 | static const T upper_bound = T(+20); | |
37054 | static const T delta = T(0.1); | |
37055 | ||
37056 | T total = T(0); | |
37057 | ||
37058 | for (x = lower_bound; x <= upper_bound; x += delta) | |
37059 | { | |
37060 | for (y = lower_bound; y <= upper_bound; y += delta) | |
37061 | { | |
37062 | total += expression.value(); | |
37063 | } | |
37064 | } | |
37065 | ||
37066 | return total; | |
37067 | } | |
37068 | }; | |
37069 | ||
37070 | for (std::size_t i = 0; i < expr_list.size(); ++i) | |
37071 | { | |
37072 | execute::process( x, y, expr_list[i]); | |
37073 | execute::process(xx, yy, expr_list[i]); | |
37074 | } | |
37075 | ||
37076 | { | |
37077 | for (std::size_t i = 0; i < 10000; ++i) | |
37078 | { | |
37079 | const T v = T(123.456 + i); | |
37080 | ||
37081 | if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),details::numeric::pow(v,T( 1))))) | |
37082 | return false; | |
37083 | ||
37084 | #define else_stmt(N) \ | |
37085 | else if (details::is_true(details::numeric::nequal(details::numeric::fast_exp<T,N>::result(v),details::numeric::pow(v,T(N))))) \ | |
37086 | return false; \ | |
37087 | ||
37088 | else_stmt( 2) else_stmt( 3) else_stmt( 4) else_stmt( 5) | |
37089 | else_stmt( 6) else_stmt( 7) else_stmt( 8) else_stmt( 9) | |
37090 | else_stmt(10) else_stmt(11) else_stmt(12) else_stmt(13) | |
37091 | else_stmt(14) else_stmt(15) else_stmt(16) else_stmt(17) | |
37092 | else_stmt(18) else_stmt(19) else_stmt(20) else_stmt(21) | |
37093 | else_stmt(22) else_stmt(23) else_stmt(24) else_stmt(25) | |
37094 | else_stmt(26) else_stmt(27) else_stmt(28) else_stmt(29) | |
37095 | else_stmt(30) else_stmt(31) else_stmt(32) else_stmt(33) | |
37096 | else_stmt(34) else_stmt(35) else_stmt(36) else_stmt(37) | |
37097 | else_stmt(38) else_stmt(39) else_stmt(40) else_stmt(41) | |
37098 | else_stmt(42) else_stmt(43) else_stmt(44) else_stmt(45) | |
37099 | else_stmt(46) else_stmt(47) else_stmt(48) else_stmt(49) | |
37100 | else_stmt(50) else_stmt(51) else_stmt(52) else_stmt(53) | |
37101 | else_stmt(54) else_stmt(55) else_stmt(56) else_stmt(57) | |
37102 | else_stmt(58) else_stmt(59) else_stmt(60) else_stmt(61) | |
37103 | } | |
37104 | } | |
37105 | ||
37106 | return true; | |
37107 | } | |
37108 | } | |
37109 | ||
37110 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) | |
37111 | # ifndef NOMINMAX | |
37112 | # define NOMINMAX | |
37113 | # endif | |
37114 | # ifndef WIN32_LEAN_AND_MEAN | |
37115 | # define WIN32_LEAN_AND_MEAN | |
37116 | # endif | |
4788af1e UH |
37117 | # define NOGDI |
37118 | # define NORESOURCE | |
4640a84e SA |
37119 | # include <windows.h> |
37120 | # include <ctime> | |
37121 | #else | |
37122 | # include <ctime> | |
37123 | # include <sys/time.h> | |
37124 | # include <sys/types.h> | |
37125 | #endif | |
37126 | ||
37127 | namespace exprtk | |
37128 | { | |
37129 | class timer | |
37130 | { | |
37131 | public: | |
37132 | ||
37133 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) | |
37134 | timer() | |
37135 | : in_use_(false) | |
37136 | { | |
37137 | QueryPerformanceFrequency(&clock_frequency_); | |
37138 | } | |
37139 | ||
37140 | inline void start() | |
37141 | { | |
37142 | in_use_ = true; | |
37143 | QueryPerformanceCounter(&start_time_); | |
37144 | } | |
37145 | ||
37146 | inline void stop() | |
37147 | { | |
37148 | QueryPerformanceCounter(&stop_time_); | |
37149 | in_use_ = false; | |
37150 | } | |
37151 | ||
37152 | inline double time() const | |
37153 | { | |
37154 | return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart); | |
37155 | } | |
37156 | ||
37157 | #else | |
37158 | ||
37159 | timer() | |
37160 | : in_use_(false) | |
37161 | { | |
37162 | start_time_.tv_sec = 0; | |
37163 | start_time_.tv_usec = 0; | |
37164 | stop_time_.tv_sec = 0; | |
37165 | stop_time_.tv_usec = 0; | |
37166 | } | |
37167 | ||
37168 | inline void start() | |
37169 | { | |
37170 | in_use_ = true; | |
37171 | gettimeofday(&start_time_,0); | |
37172 | } | |
37173 | ||
37174 | inline void stop() | |
37175 | { | |
37176 | gettimeofday(&stop_time_, 0); | |
37177 | in_use_ = false; | |
37178 | } | |
37179 | ||
37180 | inline unsigned long long int usec_time() const | |
37181 | { | |
37182 | if (!in_use_) | |
37183 | { | |
37184 | if (stop_time_.tv_sec >= start_time_.tv_sec) | |
37185 | { | |
37186 | return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + | |
37187 | static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; | |
37188 | } | |
37189 | else | |
37190 | return std::numeric_limits<details::_uint64_t>::max(); | |
37191 | } | |
37192 | else | |
37193 | return std::numeric_limits<details::_uint64_t>::max(); | |
37194 | } | |
37195 | ||
37196 | inline double time() const | |
37197 | { | |
37198 | return usec_time() * 0.000001; | |
37199 | } | |
37200 | ||
37201 | #endif | |
37202 | ||
37203 | inline bool in_use() const | |
37204 | { | |
37205 | return in_use_; | |
37206 | } | |
37207 | ||
37208 | private: | |
37209 | ||
37210 | bool in_use_; | |
37211 | ||
37212 | #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) | |
37213 | LARGE_INTEGER start_time_; | |
37214 | LARGE_INTEGER stop_time_; | |
37215 | LARGE_INTEGER clock_frequency_; | |
37216 | #else | |
37217 | struct timeval start_time_; | |
37218 | struct timeval stop_time_; | |
37219 | #endif | |
37220 | }; | |
37221 | ||
37222 | } // namespace exprtk | |
37223 | ||
37224 | #ifndef exprtk_disable_rtl_io | |
37225 | namespace exprtk | |
37226 | { | |
37227 | namespace rtl { namespace io { namespace details | |
37228 | { | |
37229 | template <typename T> | |
37230 | inline void print_type(const std::string& fmt, | |
37231 | const T v, | |
37232 | exprtk::details::numeric::details::real_type_tag) | |
37233 | { | |
37234 | printf(fmt.c_str(),v); | |
37235 | } | |
37236 | ||
37237 | template <typename T> | |
37238 | struct print_impl | |
37239 | { | |
37240 | typedef typename igeneric_function<T>::generic_type generic_type; | |
37241 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; | |
37242 | typedef typename generic_type::scalar_view scalar_t; | |
37243 | typedef typename generic_type::vector_view vector_t; | |
37244 | typedef typename generic_type::string_view string_t; | |
37245 | typedef typename exprtk::details::numeric::details::number_type<T>::type num_type; | |
37246 | ||
37247 | static void process(const std::string& scalar_format, parameter_list_t parameters) | |
37248 | { | |
37249 | for (std::size_t i = 0; i < parameters.size(); ++i) | |
37250 | { | |
37251 | generic_type& gt = parameters[i]; | |
37252 | ||
37253 | switch (gt.type) | |
37254 | { | |
37255 | case generic_type::e_scalar : print(scalar_format,scalar_t(gt)); | |
37256 | break; | |
37257 | ||
37258 | case generic_type::e_vector : print(scalar_format,vector_t(gt)); | |
37259 | break; | |
37260 | ||
37261 | case generic_type::e_string : print(string_t(gt)); | |
37262 | break; | |
37263 | ||
37264 | default : continue; | |
37265 | } | |
37266 | } | |
37267 | } | |
37268 | ||
37269 | static inline void print(const std::string& scalar_format, const scalar_t& s) | |
37270 | { | |
37271 | print_type(scalar_format,s(),num_type()); | |
37272 | } | |
37273 | ||
37274 | static inline void print(const std::string& scalar_format, const vector_t& v) | |
37275 | { | |
37276 | for (std::size_t i = 0; i < v.size(); ++i) | |
37277 | { | |
37278 | print_type(scalar_format,v[i],num_type()); | |
37279 | ||
37280 | if ((i + 1) < v.size()) | |
37281 | printf(" "); | |
37282 | } | |
37283 | } | |
37284 | ||
37285 | static inline void print(const string_t& s) | |
37286 | { | |
37287 | printf("%s",to_str(s).c_str()); | |
37288 | } | |
37289 | }; | |
37290 | ||
37291 | } // namespace exprtk::rtl::io::details | |
37292 | ||
37293 | template <typename T> | |
37294 | struct print : public exprtk::igeneric_function<T> | |
37295 | { | |
37296 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; | |
37297 | ||
37298 | using exprtk::igeneric_function<T>::operator(); | |
37299 | ||
37300 | print(const std::string& scalar_format = "%10.5f") | |
37301 | : scalar_format_(scalar_format) | |
37302 | { | |
37303 | exprtk::enable_zero_parameters(*this); | |
37304 | } | |
37305 | ||
37306 | inline T operator() (parameter_list_t parameters) | |
37307 | { | |
37308 | details::print_impl<T>::process(scalar_format_,parameters); | |
37309 | return T(0); | |
37310 | } | |
37311 | ||
37312 | std::string scalar_format_; | |
37313 | }; | |
37314 | ||
37315 | template <typename T> | |
37316 | struct println : public exprtk::igeneric_function<T> | |
37317 | { | |
37318 | typedef typename igeneric_function<T>::parameter_list_t parameter_list_t; | |
37319 | ||
37320 | using exprtk::igeneric_function<T>::operator(); | |
37321 | ||
37322 | println(const std::string& scalar_format = "%10.5f") | |
37323 | : scalar_format_(scalar_format) | |
37324 | { | |
37325 | exprtk::enable_zero_parameters(*this); | |
37326 | } | |
37327 | ||
37328 | inline T operator() (parameter_list_t parameters) | |
37329 | { | |
37330 | details::print_impl<T>::process(scalar_format_,parameters); | |
37331 | printf("\n"); | |
37332 | return T(0); | |
37333 | } | |
37334 | ||
37335 | std::string scalar_format_; | |
37336 | }; | |
37337 | ||
37338 | template <typename T> | |
37339 | struct package | |
37340 | { | |
37341 | print <T> p; | |
37342 | println<T> pl; | |
37343 | ||
37344 | bool register_package(exprtk::symbol_table<T>& symtab) | |
37345 | { | |
37346 | #define exprtk_register_function(FunctionName,FunctionType) \ | |
37347 | if (!symtab.add_function(FunctionName,FunctionType)) \ | |
37348 | { \ | |
37349 | exprtk_debug(( \ | |
37350 | "exprtk::rtl::io::register_package - Failed to add function: %s\n", \ | |
37351 | FunctionName)); \ | |
37352 | return false; \ | |
37353 | } \ | |
37354 | ||
37355 | exprtk_register_function("print" , p) | |
37356 | exprtk_register_function("println", pl) | |
37357 | #undef exprtk_register_function | |
37358 | ||
37359 | return true; | |
37360 | } | |
37361 | }; | |
37362 | ||
37363 | } // namespace exprtk::rtl::io | |
37364 | } // namespace exprtk::rtl | |
37365 | } // namespace exprtk | |
37366 | #endif | |
37367 | ||
37368 | #ifndef exprtk_disable_rtl_io_file | |
37369 | #include <fstream> | |
37370 | namespace exprtk | |
37371 | { | |
37372 | namespace rtl { namespace io { namespace file { namespace details | |
37373 | { | |
37374 | enum file_mode | |
37375 | { | |
37376 | e_error = 0, | |
37377 | e_read = 1, | |
37378 | e_write = 2, | |
37379 | e_rdwrt = 4 | |
37380 | }; | |
37381 | ||
37382 | struct file_descriptor | |
37383 | { | |
37384 | file_descriptor(const std::string& fname, const std::string& access) | |
37385 | : stream_ptr(0), | |
37386 | mode(get_file_mode(access)), | |
37387 | file_name(fname) | |
37388 | {} | |
37389 | ||
37390 | void* stream_ptr; | |
37391 | file_mode mode; | |
37392 | std::string file_name; | |
37393 | ||
37394 | bool open() | |
37395 | { | |
37396 | if (e_read == mode) | |
37397 | { | |
37398 | std::ifstream* stream = new std::ifstream(file_name.c_str(),std::ios::binary); | |
37399 | ||
37400 | if (!(*stream)) | |
37401 | { | |
37402 | file_name.clear(); | |
37403 | delete stream; | |
37404 | ||
37405 | return false; | |
37406 | } | |
37407 | else | |
37408 | stream_ptr = stream; | |
37409 | ||
37410 | return true; | |
37411 | } | |
37412 | else if (e_write == mode) | |
37413 | { | |
37414 | std::ofstream* stream = new std::ofstream(file_name.c_str(),std::ios::binary); | |
37415 | ||
37416 | if (!(*stream)) | |
37417 | { | |
37418 | file_name.clear(); | |
37419 | delete stream; | |
37420 | ||
37421 | return false; | |
37422 | } | |
37423 | else | |
37424 | stream_ptr = stream; | |
37425 | ||
37426 | return true; | |
37427 | } | |
37428 | else if (e_rdwrt == mode) | |
37429 | { | |
37430 | std::fstream* stream = new std::fstream(file_name.c_str(),std::ios::binary); | |
37431 | ||
37432 | if (!(*stream)) | |
37433 | { | |
37434 | file_name.clear(); | |
37435 | delete stream; | |
37436 | ||
37437 | return false; | |
37438 | } | |
37439 | else | |
37440 | stream_ptr = stream; | |
37441 | ||
37442 | return true; | |
37443 | } | |
37444 | else | |
37445 | return false; | |
37446 | } | |
37447 | ||
37448 | template <typename Stream, typename Ptr> | |
37449 | void close(Ptr& p) | |
37450 | { | |
37451 | Stream* stream = reinterpret_cast<Stream*>(p); | |
37452 | stream->close(); | |
37453 | delete stream; | |
37454 | p = reinterpret_cast<Ptr>(0); | |
37455 | } | |
37456 | ||
37457 | bool close() | |
37458 | { | |
37459 | switch (mode) | |
37460 | { | |
37461 | case e_read : close<std::ifstream>(stream_ptr); | |
37462 | break; | |
37463 | ||
37464 | case e_write : close<std::ofstream>(stream_ptr); | |
37465 | break; | |
37466 | ||
37467 | case e_rdwrt : close<std::fstream> (stream_ptr); | |
37468 | break; | |
37469 | ||
37470 | default : return false; | |
37471 | } | |
37472 | ||
37473 | return true; | |
37474 | } | |
37475 | ||
37476 | template <typename View> | |
37477 | bool write(const View& view, const std::size_t amount, const std::size_t offset = 0) | |
37478 | { | |
37479 | switch (mode) | |
37480 | { | |
37481 | case e_write : reinterpret_cast<std::ofstream*>(stream_ptr)-> | |
37482 | write(reinterpret_cast<const char*>(view.begin() + offset), amount * sizeof(typename View::value_t)); | |
37483 | break; | |
37484 | ||
37485 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> | |
37486 | write(reinterpret_cast<const char*>(view.begin() + offset) , amount * sizeof(typename View::value_t)); | |
37487 | break; | |
37488 | ||
37489 | default : return false; | |
37490 | } | |
37491 | ||
37492 | return true; | |
37493 | } | |
37494 | ||
37495 | template <typename View> | |
37496 | bool read(View& view, const std::size_t amount, const std::size_t offset = 0) | |
37497 | { | |
37498 | switch (mode) | |
37499 | { | |
37500 | case e_read : reinterpret_cast<std::ifstream*>(stream_ptr)-> | |
37501 | read(reinterpret_cast<char*>(view.begin() + offset), amount * sizeof(typename View::value_t)); | |
37502 | break; | |
37503 | ||
37504 | case e_rdwrt : reinterpret_cast<std::fstream*>(stream_ptr)-> | |
37505 | read(reinterpret_cast<char*>(view.begin() + offset) , amount * sizeof(typename View::value_t)); | |
37506 | break; | |
37507 | ||
37508 | default : return false; | |
37509 | } | |
37510 | ||
37511 | return true; | |
37512 | } | |
37513 | ||
37514 | bool getline(std::string& s) | |
37515 | { | |
37516 | switch (mode) | |
37517 | { | |
37518 | case e_read : return (!!std::getline(*reinterpret_cast<std::ifstream*>(stream_ptr),s)); | |
37519 | case e_rdwrt : return (!!std::getline(*reinterpret_cast<std::fstream* >(stream_ptr),s)); | |
37520 | default : return false; | |
37521 | } | |
37522 | } | |
37523 | ||
37524 | bool eof() const | |
37525 | { | |
37526 | switch (mode) | |
37527 | { | |
37528 | case e_read : return reinterpret_cast<std::ifstream*>(stream_ptr)->eof(); | |
37529 | case e_write : return reinterpret_cast<std::ofstream*>(stream_ptr)->eof(); | |
37530 | case e_rdwrt : return reinterpret_cast<std::fstream* >(stream_ptr)->eof(); | |
37531 | default : return true; | |
37532 | } | |
37533 | } | |
37534 | ||
37535 | file_mode get_file_mode(const std::string& access) const | |
37536 | { | |
37537 | if (access.empty() || access.size() > 2) | |
37538 | return e_error; | |
37539 | ||
37540 | std::size_t w_cnt = 0; | |
37541 | std::size_t r_cnt = 0; | |
37542 | ||
37543 | for (std::size_t i = 0; i < access.size(); ++i) | |
37544 | { | |
37545 | switch (std::tolower(access[i])) | |
37546 | { | |
37547 | case 'r' : r_cnt++; break; | |
37548 | case 'w' : w_cnt++; break; | |
37549 | default : return e_error; | |
37550 | } | |
37551 | } | |
37552 | ||
37553 | if ((0 == r_cnt) && (0 == w_cnt)) | |
37554 | return e_error; | |
37555 | else if ((r_cnt > 1) || (w_cnt > 1)) | |
37556 | return e_error; | |
37557 | else if ((1 == r_cnt) && (1 == w_cnt)) | |
37558 | return e_rdwrt; | |
37559 | else if (1 == r_cnt) | |
37560 | return e_read; | |
37561 | else | |
37562 | return e_write; | |
37563 | } | |
37564 | }; | |
37565 | ||
37566 | template <typename T> | |
37567 | file_descriptor* make_handle(T v) | |
37568 | { | |
37569 | file_descriptor* fd = reinterpret_cast<file_descriptor*>(0); | |
37570 | ||
37571 | std::memcpy(reinterpret_cast<char*>(&fd), | |
37572 | reinterpret_cast<const char*>(&v), | |
37573 | sizeof(fd)); | |
37574 | return fd; | |
37575 | } | |
37576 | ||
37577 | template <typename T> | |
37578 | void perform_check() | |
37579 | { | |
37580 | #ifdef _MSC_VER | |
37581 | #pragma warning(push) | |
37582 | #pragma warning(disable: 4127) | |
37583 | #endif | |
37584 | if (sizeof(T) < sizeof(void*)) | |
37585 | { | |
37586 | throw std::runtime_error("exprtk::rtl::io::file - Error - pointer size larger than holder."); | |
37587 | } | |
37588 | #ifdef _MSC_VER | |
37589 | #pragma warning(pop) | |
37590 | #endif | |
37591 | } | |
37592 | ||
37593 | } // namespace exprtk::rtl::io::file::details | |
37594 | ||
37595 | template <typename T> | |
37596 | class open : public exprtk::igeneric_function<T> | |
37597 | { | |
37598 | public: | |
37599 | ||
37600 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37601 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37602 | typedef typename igfun_t::generic_type generic_type; | |
37603 | typedef typename generic_type::string_view string_t; | |
37604 | ||
37605 | using exprtk::igeneric_function<T>::operator(); | |
37606 | ||
37607 | open() | |
37608 | : exprtk::igeneric_function<T>("S|SS") | |
37609 | { details::perform_check<T>(); } | |
37610 | ||
37611 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
37612 | { | |
37613 | std::string file_name = to_str(string_t(parameters[0])); | |
37614 | std::string access; | |
37615 | ||
37616 | if (file_name.empty()) | |
37617 | return T(0); | |
37618 | ||
37619 | if (0 == ps_index) | |
37620 | access = "r"; | |
37621 | else if (0 == string_t(parameters[1]).size()) | |
37622 | return T(0); | |
37623 | else | |
37624 | access = to_str(string_t(parameters[1])); | |
37625 | ||
37626 | details::file_descriptor* fd = new details::file_descriptor(file_name,access); | |
37627 | ||
37628 | if (fd->open()) | |
37629 | { | |
37630 | T t = T(0); | |
37631 | ||
37632 | std::memcpy(reinterpret_cast<char*>(&t ), | |
37633 | reinterpret_cast<char*>(&fd), | |
37634 | sizeof(fd)); | |
37635 | return t; | |
37636 | } | |
37637 | else | |
37638 | { | |
37639 | delete fd; | |
37640 | return T(0); | |
37641 | } | |
37642 | } | |
37643 | }; | |
37644 | ||
37645 | template <typename T> | |
37646 | struct close : public exprtk::ifunction<T> | |
37647 | { | |
37648 | using exprtk::ifunction<T>::operator(); | |
37649 | ||
37650 | close() | |
37651 | : exprtk::ifunction<T>(1) | |
37652 | { details::perform_check<T>(); } | |
37653 | ||
37654 | inline T operator() (const T& v) | |
37655 | { | |
37656 | details::file_descriptor* fd = details::make_handle(v); | |
37657 | ||
37658 | if (!fd->close()) | |
37659 | return T(0); | |
37660 | ||
37661 | delete fd; | |
37662 | ||
37663 | return T(1); | |
37664 | } | |
37665 | }; | |
37666 | ||
37667 | template <typename T> | |
37668 | class write : public exprtk::igeneric_function<T> | |
37669 | { | |
37670 | public: | |
37671 | ||
37672 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37673 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37674 | typedef typename igfun_t::generic_type generic_type; | |
37675 | typedef typename generic_type::string_view string_t; | |
37676 | typedef typename generic_type::scalar_view scalar_t; | |
37677 | typedef typename generic_type::vector_view vector_t; | |
37678 | ||
37679 | using exprtk::igeneric_function<T>::operator(); | |
37680 | ||
37681 | write() | |
37682 | : igfun_t("TS|TST|TV|TVT") | |
37683 | { details::perform_check<T>(); } | |
37684 | ||
37685 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
37686 | { | |
37687 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); | |
37688 | ||
37689 | std::size_t amount = 0; | |
37690 | ||
37691 | switch (ps_index) | |
37692 | { | |
37693 | case 0 : { | |
37694 | const string_t buffer(parameters[1]); | |
37695 | amount = buffer.size(); | |
37696 | return T(fd->write(buffer, amount) ? 1 : 0); | |
37697 | } | |
37698 | ||
37699 | case 1 : { | |
37700 | const string_t buffer(parameters[1]); | |
37701 | amount = std::min(buffer.size(), | |
37702 | static_cast<std::size_t>(scalar_t(parameters[2])())); | |
37703 | return T(fd->write(buffer, amount) ? 1 : 0); | |
37704 | } | |
37705 | ||
37706 | case 2 : { | |
37707 | const vector_t vec(parameters[1]); | |
37708 | amount = vec.size(); | |
37709 | return T(fd->write(vec, amount) ? 1 : 0); | |
37710 | } | |
37711 | ||
37712 | case 3 : { | |
37713 | const vector_t vec(parameters[1]); | |
37714 | amount = std::min(vec.size(), | |
37715 | static_cast<std::size_t>(scalar_t(parameters[2])())); | |
37716 | return T(fd->write(vec, amount) ? 1 : 0); | |
37717 | } | |
37718 | } | |
37719 | ||
37720 | return T(0); | |
37721 | } | |
37722 | }; | |
37723 | ||
37724 | template <typename T> | |
37725 | class read : public exprtk::igeneric_function<T> | |
37726 | { | |
37727 | public: | |
37728 | ||
37729 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37730 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37731 | typedef typename igfun_t::generic_type generic_type; | |
37732 | typedef typename generic_type::string_view string_t; | |
37733 | typedef typename generic_type::scalar_view scalar_t; | |
37734 | typedef typename generic_type::vector_view vector_t; | |
37735 | ||
37736 | using exprtk::igeneric_function<T>::operator(); | |
37737 | ||
37738 | read() | |
37739 | : igfun_t("TS|TST|TV|TVT") | |
37740 | { details::perform_check<T>(); } | |
37741 | ||
37742 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
37743 | { | |
37744 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); | |
37745 | ||
37746 | std::size_t amount = 0; | |
37747 | ||
37748 | switch (ps_index) | |
37749 | { | |
37750 | case 0 : { | |
37751 | string_t buffer(parameters[1]); | |
37752 | amount = buffer.size(); | |
37753 | return T(fd->read(buffer,amount) ? 1 : 0); | |
37754 | } | |
37755 | ||
37756 | case 1 : { | |
37757 | string_t buffer(parameters[1]); | |
37758 | amount = std::min(buffer.size(), | |
37759 | static_cast<std::size_t>(scalar_t(parameters[2])())); | |
37760 | return T(fd->read(buffer,amount) ? 1 : 0); | |
37761 | } | |
37762 | ||
37763 | case 2 : { | |
37764 | vector_t vec(parameters[1]); | |
37765 | amount = vec.size(); | |
37766 | return T(fd->read(vec,amount) ? 1 : 0); | |
37767 | } | |
37768 | ||
37769 | case 3 : { | |
37770 | vector_t vec(parameters[1]); | |
37771 | amount = std::min(vec.size(), | |
37772 | static_cast<std::size_t>(scalar_t(parameters[2])())); | |
37773 | return T(fd->read(vec,amount) ? 1 : 0); | |
37774 | } | |
37775 | } | |
37776 | ||
37777 | return T(0); | |
37778 | } | |
37779 | }; | |
37780 | ||
37781 | template <typename T> | |
37782 | class getline : public exprtk::igeneric_function<T> | |
37783 | { | |
37784 | public: | |
37785 | ||
37786 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37787 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37788 | typedef typename igfun_t::generic_type generic_type; | |
37789 | typedef typename generic_type::string_view string_t; | |
37790 | typedef typename generic_type::scalar_view scalar_t; | |
37791 | ||
37792 | using exprtk::igeneric_function<T>::operator(); | |
37793 | ||
37794 | getline() | |
37795 | : igfun_t("T",igfun_t::e_rtrn_string) | |
37796 | { details::perform_check<T>(); } | |
37797 | ||
37798 | inline T operator() (std::string& result, | |
37799 | parameter_list_t parameters) | |
37800 | { | |
37801 | details::file_descriptor* fd = details::make_handle(scalar_t(parameters[0])()); | |
37802 | return T(fd->getline(result) ? 1 : 0); | |
37803 | } | |
37804 | }; | |
37805 | ||
37806 | template <typename T> | |
37807 | struct eof : public exprtk::ifunction<T> | |
37808 | { | |
37809 | using exprtk::ifunction<T>::operator(); | |
37810 | ||
37811 | eof() | |
37812 | : exprtk::ifunction<T>(1) | |
37813 | { details::perform_check<T>(); } | |
37814 | ||
37815 | inline T operator() (const T& v) | |
37816 | { | |
37817 | details::file_descriptor* fd = details::make_handle(v); | |
37818 | ||
37819 | return (fd->eof() ? T(1) : T(0)); | |
37820 | } | |
37821 | }; | |
37822 | ||
37823 | template <typename T> | |
37824 | struct package | |
37825 | { | |
37826 | open <T> o; | |
37827 | close <T> c; | |
37828 | write <T> w; | |
37829 | read <T> r; | |
37830 | getline<T> g; | |
37831 | eof <T> e; | |
37832 | ||
37833 | bool register_package(exprtk::symbol_table<T>& symtab) | |
37834 | { | |
37835 | #define exprtk_register_function(FunctionName,FunctionType) \ | |
37836 | if (!symtab.add_function(FunctionName,FunctionType)) \ | |
37837 | { \ | |
37838 | exprtk_debug(( \ | |
37839 | "exprtk::rtl::io::file::register_package - Failed to add function: %s\n", \ | |
37840 | FunctionName)); \ | |
37841 | return false; \ | |
37842 | } \ | |
37843 | ||
37844 | exprtk_register_function("open" ,o) | |
37845 | exprtk_register_function("close" ,c) | |
37846 | exprtk_register_function("write" ,w) | |
37847 | exprtk_register_function("read" ,r) | |
37848 | exprtk_register_function("getline",g) | |
37849 | exprtk_register_function("eof" ,e) | |
37850 | #undef exprtk_register_function | |
37851 | ||
37852 | return true; | |
37853 | } | |
37854 | }; | |
37855 | ||
37856 | } // namespace exprtk::rtl::io::file | |
37857 | } // namespace exprtk::rtl::io | |
37858 | } // namespace exprtk::rtl | |
37859 | } // namespace exprtk | |
37860 | #endif | |
37861 | ||
37862 | #ifndef exprtk_disable_rtl_vecops | |
37863 | namespace exprtk | |
37864 | { | |
37865 | namespace rtl { namespace vecops { | |
37866 | ||
37867 | namespace helper | |
37868 | { | |
37869 | template <typename Vector> | |
37870 | inline bool invalid_range(const Vector& v, const std::size_t r0, const std::size_t r1) | |
37871 | { | |
37872 | if (r0 > (v.size() - 1)) | |
37873 | return true; | |
37874 | else if (r1 > (v.size() - 1)) | |
37875 | return true; | |
37876 | else if (r1 < r0) | |
37877 | return true; | |
37878 | else | |
37879 | return false; | |
37880 | } | |
37881 | ||
37882 | template <typename T> | |
37883 | struct load_vector_range | |
37884 | { | |
37885 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37886 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37887 | typedef typename igfun_t::generic_type generic_type; | |
37888 | typedef typename generic_type::scalar_view scalar_t; | |
37889 | typedef typename generic_type::vector_view vector_t; | |
37890 | ||
37891 | static inline bool process(parameter_list_t& parameters, | |
37892 | std::size_t& r0, std::size_t& r1, | |
37893 | const std::size_t& r0_prmidx, | |
37894 | const std::size_t& r1_prmidx, | |
37895 | const std::size_t vec_idx = 0) | |
37896 | { | |
37897 | if (r0_prmidx >= parameters.size()) | |
37898 | return false; | |
37899 | ||
37900 | if (r1_prmidx >= parameters.size()) | |
37901 | return false; | |
37902 | ||
37903 | if (!scalar_t(parameters[r0_prmidx]).to_uint(r0)) | |
37904 | return false; | |
37905 | ||
37906 | if (!scalar_t(parameters[r1_prmidx]).to_uint(r1)) | |
37907 | return false; | |
37908 | ||
37909 | return !invalid_range(vector_t(parameters[vec_idx]), r0, r1); | |
37910 | } | |
37911 | }; | |
37912 | } | |
37913 | ||
37914 | namespace details | |
37915 | { | |
37916 | template <typename T> | |
37917 | inline void kahan_sum(T& sum, T& error, const T v) | |
37918 | { | |
37919 | const T x = v - error; | |
37920 | const T y = sum + x; | |
37921 | error = (y - sum) - x; | |
37922 | sum = y; | |
37923 | } | |
37924 | ||
37925 | } // namespace exprtk::rtl::details | |
37926 | ||
37927 | template <typename T> | |
37928 | class all_true : public exprtk::igeneric_function<T> | |
37929 | { | |
37930 | public: | |
37931 | ||
37932 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37933 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37934 | typedef typename igfun_t::generic_type generic_type; | |
37935 | typedef typename generic_type::vector_view vector_t; | |
37936 | ||
37937 | using exprtk::igeneric_function<T>::operator(); | |
37938 | ||
37939 | all_true() | |
37940 | : exprtk::igeneric_function<T>("V|VTT") | |
37941 | /* | |
37942 | Overloads: | |
37943 | 0. V - vector | |
37944 | 1. VTT - vector, r0, r1 | |
37945 | */ | |
37946 | {} | |
37947 | ||
37948 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
37949 | { | |
37950 | const vector_t vec(parameters[0]); | |
37951 | ||
37952 | std::size_t r0 = 0; | |
37953 | std::size_t r1 = vec.size() - 1; | |
37954 | ||
37955 | if ( | |
37956 | (1 == ps_index) && | |
37957 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) | |
37958 | ) | |
37959 | return std::numeric_limits<T>::quiet_NaN(); | |
37960 | ||
37961 | for (std::size_t i = r0; i <= r1; ++i) | |
37962 | { | |
37963 | if (vec[i] == T(0)) | |
37964 | { | |
37965 | return T(0); | |
37966 | } | |
37967 | } | |
37968 | ||
37969 | return T(1); | |
37970 | } | |
37971 | }; | |
37972 | ||
37973 | template <typename T> | |
37974 | class all_false : public exprtk::igeneric_function<T> | |
37975 | { | |
37976 | public: | |
37977 | ||
37978 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
37979 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
37980 | typedef typename igfun_t::generic_type generic_type; | |
37981 | typedef typename generic_type::vector_view vector_t; | |
37982 | ||
37983 | using exprtk::igeneric_function<T>::operator(); | |
37984 | ||
37985 | all_false() | |
37986 | : exprtk::igeneric_function<T>("V|VTT") | |
37987 | /* | |
37988 | Overloads: | |
37989 | 0. V - vector | |
37990 | 1. VTT - vector, r0, r1 | |
37991 | */ | |
37992 | {} | |
37993 | ||
37994 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
37995 | { | |
37996 | const vector_t vec(parameters[0]); | |
37997 | ||
37998 | std::size_t r0 = 0; | |
37999 | std::size_t r1 = vec.size() - 1; | |
38000 | ||
38001 | if ( | |
38002 | (1 == ps_index) && | |
38003 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) | |
38004 | ) | |
38005 | return std::numeric_limits<T>::quiet_NaN(); | |
38006 | ||
38007 | for (std::size_t i = r0; i <= r1; ++i) | |
38008 | { | |
38009 | if (vec[i] != T(0)) | |
38010 | { | |
38011 | return T(0); | |
38012 | } | |
38013 | } | |
38014 | ||
38015 | return T(1); | |
38016 | } | |
38017 | }; | |
38018 | ||
38019 | template <typename T> | |
38020 | class any_true : public exprtk::igeneric_function<T> | |
38021 | { | |
38022 | public: | |
38023 | ||
38024 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38025 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38026 | typedef typename igfun_t::generic_type generic_type; | |
38027 | typedef typename generic_type::vector_view vector_t; | |
38028 | ||
38029 | using exprtk::igeneric_function<T>::operator(); | |
38030 | ||
38031 | any_true() | |
38032 | : exprtk::igeneric_function<T>("V|VTT") | |
38033 | /* | |
38034 | Overloads: | |
38035 | 0. V - vector | |
38036 | 1. VTT - vector, r0, r1 | |
38037 | */ | |
38038 | {} | |
38039 | ||
38040 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38041 | { | |
38042 | const vector_t vec(parameters[0]); | |
38043 | ||
38044 | std::size_t r0 = 0; | |
38045 | std::size_t r1 = vec.size() - 1; | |
38046 | ||
38047 | if ( | |
38048 | (1 == ps_index) && | |
38049 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) | |
38050 | ) | |
38051 | return std::numeric_limits<T>::quiet_NaN(); | |
38052 | ||
38053 | for (std::size_t i = r0; i <= r1; ++i) | |
38054 | { | |
38055 | if (vec[i] != T(0)) | |
38056 | { | |
38057 | return T(1); | |
38058 | } | |
38059 | } | |
38060 | ||
38061 | return T(0); | |
38062 | } | |
38063 | }; | |
38064 | ||
38065 | template <typename T> | |
38066 | class any_false : public exprtk::igeneric_function<T> | |
38067 | { | |
38068 | public: | |
38069 | ||
38070 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38071 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38072 | typedef typename igfun_t::generic_type generic_type; | |
38073 | typedef typename generic_type::vector_view vector_t; | |
38074 | ||
38075 | using exprtk::igeneric_function<T>::operator(); | |
38076 | ||
38077 | any_false() | |
38078 | : exprtk::igeneric_function<T>("V|VTT") | |
38079 | /* | |
38080 | Overloads: | |
38081 | 0. V - vector | |
38082 | 1. VTT - vector, r0, r1 | |
38083 | */ | |
38084 | {} | |
38085 | ||
38086 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38087 | { | |
38088 | const vector_t vec(parameters[0]); | |
38089 | ||
38090 | std::size_t r0 = 0; | |
38091 | std::size_t r1 = vec.size() - 1; | |
38092 | ||
38093 | if ( | |
38094 | (1 == ps_index) && | |
38095 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) | |
38096 | ) | |
38097 | return std::numeric_limits<T>::quiet_NaN(); | |
38098 | ||
38099 | for (std::size_t i = r0; i <= r1; ++i) | |
38100 | { | |
38101 | if (vec[i] == T(0)) | |
38102 | { | |
38103 | return T(1); | |
38104 | } | |
38105 | } | |
38106 | ||
38107 | return T(0); | |
38108 | } | |
38109 | }; | |
38110 | ||
38111 | template <typename T> | |
38112 | class count : public exprtk::igeneric_function<T> | |
38113 | { | |
38114 | public: | |
38115 | ||
38116 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38117 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38118 | typedef typename igfun_t::generic_type generic_type; | |
38119 | typedef typename generic_type::vector_view vector_t; | |
38120 | ||
38121 | using exprtk::igeneric_function<T>::operator(); | |
38122 | ||
38123 | count() | |
38124 | : exprtk::igeneric_function<T>("V|VTT") | |
38125 | /* | |
38126 | Overloads: | |
38127 | 0. V - vector | |
38128 | 1. VTT - vector, r0, r1 | |
38129 | */ | |
38130 | {} | |
38131 | ||
38132 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38133 | { | |
38134 | const vector_t vec(parameters[0]); | |
38135 | ||
38136 | std::size_t r0 = 0; | |
38137 | std::size_t r1 = vec.size() - 1; | |
38138 | ||
38139 | if ( | |
38140 | (1 == ps_index) && | |
38141 | !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0) | |
38142 | ) | |
38143 | return std::numeric_limits<T>::quiet_NaN(); | |
38144 | ||
38145 | std::size_t cnt = 0; | |
38146 | ||
38147 | for (std::size_t i = r0; i <= r1; ++i) | |
38148 | { | |
38149 | if (vec[i] != T(0)) ++cnt; | |
38150 | } | |
38151 | ||
38152 | return T(cnt); | |
38153 | } | |
38154 | }; | |
38155 | ||
38156 | template <typename T> | |
38157 | class copy : public exprtk::igeneric_function<T> | |
38158 | { | |
38159 | public: | |
38160 | ||
38161 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38162 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38163 | typedef typename igfun_t::generic_type generic_type; | |
38164 | typedef typename generic_type::scalar_view scalar_t; | |
38165 | typedef typename generic_type::vector_view vector_t; | |
38166 | ||
38167 | using exprtk::igeneric_function<T>::operator(); | |
38168 | ||
38169 | copy() | |
38170 | : exprtk::igeneric_function<T>("VV|VTTVTT") | |
38171 | /* | |
38172 | Overloads: | |
38173 | 0. VV - x(vector), y(vector) | |
38174 | 1. VTTVTT - x(vector), xr0, xr1, y(vector), yr0, yr1, | |
38175 | */ | |
38176 | {} | |
38177 | ||
38178 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38179 | { | |
38180 | const vector_t x(parameters[0]); | |
38181 | vector_t y(parameters[(0 == ps_index) ? 1 : 3]); | |
38182 | ||
38183 | std::size_t xr0 = 0; | |
38184 | std::size_t xr1 = x.size() - 1; | |
38185 | ||
38186 | std::size_t yr0 = 0; | |
38187 | std::size_t yr1 = y.size() - 1; | |
38188 | ||
38189 | if (1 == ps_index) | |
38190 | { | |
38191 | if ( | |
38192 | !helper::load_vector_range<T>::process(parameters, xr0, xr1, 1, 2, 0) || | |
38193 | !helper::load_vector_range<T>::process(parameters, yr0, yr1, 4, 5, 3) | |
38194 | ) | |
38195 | return T(0); | |
38196 | } | |
38197 | ||
38198 | const std::size_t n = std::min(xr1 - xr0 + 1, yr1 - yr0 + 1); | |
38199 | ||
38200 | std::copy(x.begin() + xr0, x.begin() + xr0 + n, y.begin() + yr0); | |
38201 | ||
38202 | return T(n); | |
38203 | } | |
38204 | }; | |
38205 | ||
38206 | template <typename T> | |
38207 | class rol : public exprtk::igeneric_function<T> | |
38208 | { | |
38209 | public: | |
38210 | ||
38211 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38212 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38213 | typedef typename igfun_t::generic_type generic_type; | |
38214 | typedef typename generic_type::scalar_view scalar_t; | |
38215 | typedef typename generic_type::vector_view vector_t; | |
38216 | ||
38217 | using exprtk::igeneric_function<T>::operator(); | |
38218 | ||
38219 | rol() | |
38220 | : exprtk::igeneric_function<T>("VT|VTTT") | |
38221 | /* | |
38222 | Overloads: | |
38223 | 0. VT - vector, N | |
38224 | 1. VTTT - vector, N, r0, r1 | |
38225 | */ | |
38226 | {} | |
38227 | ||
38228 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38229 | { | |
38230 | vector_t vec(parameters[0]); | |
38231 | ||
38232 | std::size_t n = 0; | |
38233 | std::size_t r0 = 0; | |
38234 | std::size_t r1 = vec.size() - 1; | |
38235 | ||
38236 | if (!scalar_t(parameters[1]).to_uint(n)) | |
38237 | return T(0); | |
38238 | ||
38239 | if ( | |
38240 | (1 == ps_index) && | |
38241 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) | |
38242 | ) | |
38243 | return T(0); | |
38244 | ||
38245 | std::size_t dist = r1 - r0 + 1; | |
38246 | std::size_t shift = n % dist; | |
38247 | ||
38248 | std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); | |
38249 | ||
38250 | return T(1); | |
38251 | } | |
38252 | }; | |
38253 | ||
38254 | template <typename T> | |
38255 | class ror : public exprtk::igeneric_function<T> | |
38256 | { | |
38257 | public: | |
38258 | ||
38259 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38260 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38261 | typedef typename igfun_t::generic_type generic_type; | |
38262 | typedef typename generic_type::scalar_view scalar_t; | |
38263 | typedef typename generic_type::vector_view vector_t; | |
38264 | ||
38265 | using exprtk::igeneric_function<T>::operator(); | |
38266 | ||
38267 | ror() | |
38268 | : exprtk::igeneric_function<T>("VT|VTTT") | |
38269 | /* | |
38270 | Overloads: | |
38271 | 0. VT - vector, N | |
38272 | 1. VTTT - vector, N, r0, r1 | |
38273 | */ | |
38274 | {} | |
38275 | ||
38276 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38277 | { | |
38278 | vector_t vec(parameters[0]); | |
38279 | ||
38280 | std::size_t n = 0; | |
38281 | std::size_t r0 = 0; | |
38282 | std::size_t r1 = vec.size() - 1; | |
38283 | ||
38284 | if (!scalar_t(parameters[1]).to_uint(n)) | |
38285 | return T(0); | |
38286 | ||
38287 | if ( | |
38288 | (1 == ps_index) && | |
38289 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) | |
38290 | ) | |
38291 | return T(0); | |
38292 | ||
38293 | std::size_t dist = r1 - r0 + 1; | |
38294 | std::size_t shift = (dist - (n % dist)) % dist; | |
38295 | ||
38296 | std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); | |
38297 | ||
38298 | return T(1); | |
38299 | } | |
38300 | }; | |
38301 | ||
38302 | template <typename T> | |
38303 | class shift_left : public exprtk::igeneric_function<T> | |
38304 | { | |
38305 | public: | |
38306 | ||
38307 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38308 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38309 | typedef typename igfun_t::generic_type generic_type; | |
38310 | typedef typename generic_type::scalar_view scalar_t; | |
38311 | typedef typename generic_type::vector_view vector_t; | |
38312 | ||
38313 | using exprtk::igeneric_function<T>::operator(); | |
38314 | ||
38315 | shift_left() | |
38316 | : exprtk::igeneric_function<T>("VT|VTTT") | |
38317 | /* | |
38318 | Overloads: | |
38319 | 0. VT - vector, N | |
38320 | 1. VTTT - vector, N, r0, r1 | |
38321 | */ | |
38322 | {} | |
38323 | ||
38324 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38325 | { | |
38326 | vector_t vec(parameters[0]); | |
38327 | ||
38328 | std::size_t n = 0; | |
38329 | std::size_t r0 = 0; | |
38330 | std::size_t r1 = vec.size() - 1; | |
38331 | ||
38332 | if (!scalar_t(parameters[1]).to_uint(n)) | |
38333 | return T(0); | |
38334 | ||
38335 | if ( | |
38336 | (1 == ps_index) && | |
38337 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) | |
38338 | ) | |
38339 | return T(0); | |
38340 | ||
38341 | std::size_t dist = r1 - r0 + 1; | |
38342 | ||
38343 | if (n > dist) | |
38344 | return T(0); | |
38345 | ||
38346 | std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1); | |
38347 | ||
38348 | for (std::size_t i = r1 - n + 1; i <= r1; ++i) | |
38349 | { | |
38350 | vec[i] = T(0); | |
38351 | } | |
38352 | ||
38353 | return T(1); | |
38354 | } | |
38355 | }; | |
38356 | ||
38357 | template <typename T> | |
38358 | class shift_right : public exprtk::igeneric_function<T> | |
38359 | { | |
38360 | public: | |
38361 | ||
38362 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38363 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38364 | typedef typename igfun_t::generic_type generic_type; | |
38365 | typedef typename generic_type::scalar_view scalar_t; | |
38366 | typedef typename generic_type::vector_view vector_t; | |
38367 | ||
38368 | using exprtk::igeneric_function<T>::operator(); | |
38369 | ||
38370 | shift_right() | |
38371 | : exprtk::igeneric_function<T>("VT|VTTT") | |
38372 | /* | |
38373 | Overloads: | |
38374 | 0. VT - vector, N | |
38375 | 1. VTTT - vector, N, r0, r1 | |
38376 | */ | |
38377 | {} | |
38378 | ||
38379 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38380 | { | |
38381 | vector_t vec(parameters[0]); | |
38382 | ||
38383 | std::size_t n = 0; | |
38384 | std::size_t r0 = 0; | |
38385 | std::size_t r1 = vec.size() - 1; | |
38386 | ||
38387 | if (!scalar_t(parameters[1]).to_uint(n)) | |
38388 | return T(0); | |
38389 | ||
38390 | if ( | |
38391 | (1 == ps_index) && | |
38392 | !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0) | |
38393 | ) | |
38394 | return T(0); | |
38395 | ||
38396 | std::size_t dist = r1 - r0 + 1; | |
38397 | ||
38398 | if (n > dist) | |
38399 | return T(0); | |
38400 | ||
38401 | std::size_t shift = (dist - (n % dist)) % dist; | |
38402 | ||
38403 | std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); | |
38404 | ||
38405 | for (std::size_t i = r0; i < r0 + n; ++i) | |
38406 | { | |
38407 | vec[i] = T(0); | |
38408 | } | |
38409 | ||
38410 | return T(1); | |
38411 | } | |
38412 | }; | |
38413 | ||
38414 | template <typename T> | |
38415 | class sort : public exprtk::igeneric_function<T> | |
38416 | { | |
38417 | public: | |
38418 | ||
38419 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38420 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38421 | typedef typename igfun_t::generic_type generic_type; | |
38422 | typedef typename generic_type::string_view string_t; | |
38423 | typedef typename generic_type::vector_view vector_t; | |
38424 | ||
38425 | using exprtk::igeneric_function<T>::operator(); | |
38426 | ||
38427 | sort() | |
38428 | : exprtk::igeneric_function<T>("V|VTT|VS|VSTT") | |
38429 | /* | |
38430 | Overloads: | |
38431 | 0. V - vector | |
38432 | 1. VTT - vector, r0, r1 | |
38433 | 2. VS - vector, string | |
38434 | 3. VSTT - vector, string, r0, r1 | |
38435 | */ | |
38436 | {} | |
38437 | ||
38438 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38439 | { | |
38440 | vector_t vec(parameters[0]); | |
38441 | ||
38442 | std::size_t r0 = 0; | |
38443 | std::size_t r1 = vec.size() - 1; | |
38444 | ||
38445 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) | |
38446 | return T(0); | |
38447 | if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) | |
38448 | return T(0); | |
38449 | ||
38450 | bool ascending = true; | |
38451 | ||
38452 | if ((2 == ps_index) || (3 == ps_index)) | |
38453 | { | |
38454 | if (exprtk::details::imatch(to_str(string_t(parameters[1])),"ascending")) | |
38455 | ascending = true; | |
38456 | else if (exprtk::details::imatch(to_str(string_t(parameters[1])),"descending")) | |
38457 | ascending = false; | |
38458 | else | |
38459 | return T(0); | |
38460 | } | |
38461 | ||
38462 | if (ascending) | |
38463 | std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::less<T> ()); | |
38464 | else | |
38465 | std::sort(vec.begin() + r0, vec.begin() + r1 + 1, std::greater<T>()); | |
38466 | ||
38467 | return T(1); | |
38468 | } | |
38469 | }; | |
38470 | ||
38471 | template <typename T> | |
38472 | class nthelement : public exprtk::igeneric_function<T> | |
38473 | { | |
38474 | public: | |
38475 | ||
38476 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38477 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38478 | typedef typename igfun_t::generic_type generic_type; | |
38479 | typedef typename generic_type::scalar_view scalar_t; | |
38480 | typedef typename generic_type::vector_view vector_t; | |
38481 | ||
38482 | using exprtk::igeneric_function<T>::operator(); | |
38483 | ||
38484 | nthelement() | |
38485 | : exprtk::igeneric_function<T>("VT|VTTT") | |
38486 | /* | |
38487 | Overloads: | |
38488 | 0. VT - vector, nth-element | |
38489 | 1. VTTT - vector, nth-element, r0, r1 | |
38490 | */ | |
38491 | {} | |
38492 | ||
38493 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38494 | { | |
38495 | vector_t vec(parameters[0]); | |
38496 | ||
38497 | std::size_t n = 0; | |
38498 | std::size_t r0 = 0; | |
38499 | std::size_t r1 = vec.size() - 1; | |
38500 | ||
38501 | if (!scalar_t(parameters[1]).to_uint(n)) | |
38502 | return T(0); | |
38503 | ||
38504 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) | |
38505 | return std::numeric_limits<T>::quiet_NaN(); | |
38506 | ||
38507 | std::nth_element(vec.begin() + r0, vec.begin() + r0 + n , vec.begin() + r1 + 1); | |
38508 | ||
38509 | return T(1); | |
38510 | } | |
38511 | }; | |
38512 | ||
38513 | template <typename T> | |
38514 | class iota : public exprtk::igeneric_function<T> | |
38515 | { | |
38516 | public: | |
38517 | ||
38518 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38519 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38520 | typedef typename igfun_t::generic_type generic_type; | |
38521 | typedef typename generic_type::scalar_view scalar_t; | |
38522 | typedef typename generic_type::vector_view vector_t; | |
38523 | ||
38524 | using exprtk::igeneric_function<T>::operator(); | |
38525 | ||
38526 | iota() | |
38527 | : exprtk::igeneric_function<T>("VT|VTT|VTTT|VTTTT") | |
38528 | /* | |
38529 | Overloads: | |
38530 | 0. VT - vector, increment | |
38531 | 1. VTT - vector, increment, base | |
38532 | 2. VTTTT - vector, increment, r0, r1 | |
38533 | 3. VTTTT - vector, increment, base, r0, r1 | |
38534 | */ | |
38535 | {} | |
38536 | ||
38537 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38538 | { | |
38539 | vector_t vec(parameters[0]); | |
38540 | ||
38541 | T increment = scalar_t(parameters[1])(); | |
38542 | T base = ((1 == ps_index) || (3 == ps_index)) ? scalar_t(parameters[2])() : T(0); | |
38543 | ||
38544 | std::size_t r0 = 0; | |
38545 | std::size_t r1 = vec.size() - 1; | |
38546 | ||
38547 | if ((2 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) | |
38548 | return std::numeric_limits<T>::quiet_NaN(); | |
38549 | else if ((3 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 0)) | |
38550 | return std::numeric_limits<T>::quiet_NaN(); | |
38551 | else | |
38552 | { | |
38553 | long long j = 0; | |
38554 | ||
38555 | for (std::size_t i = r0; i <= r1; ++i, ++j) | |
38556 | { | |
38557 | vec[i] = base + (increment * j); | |
38558 | } | |
38559 | } | |
38560 | ||
38561 | return T(1); | |
38562 | } | |
38563 | }; | |
38564 | ||
38565 | template <typename T> | |
38566 | class sumk : public exprtk::igeneric_function<T> | |
38567 | { | |
38568 | public: | |
38569 | ||
38570 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38571 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38572 | typedef typename igfun_t::generic_type generic_type; | |
38573 | typedef typename generic_type::vector_view vector_t; | |
38574 | ||
38575 | using exprtk::igeneric_function<T>::operator(); | |
38576 | ||
38577 | sumk() | |
38578 | : exprtk::igeneric_function<T>("V|VTT") | |
38579 | /* | |
38580 | Overloads: | |
38581 | 0. V - vector | |
38582 | 1. VTT - vector, r0, r1 | |
38583 | */ | |
38584 | {} | |
38585 | ||
38586 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38587 | { | |
38588 | const vector_t vec(parameters[0]); | |
38589 | ||
38590 | std::size_t r0 = 0; | |
38591 | std::size_t r1 = vec.size() - 1; | |
38592 | ||
38593 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 1, 2, 0)) | |
38594 | return std::numeric_limits<T>::quiet_NaN(); | |
38595 | ||
38596 | T result = T(0); | |
38597 | T error = T(0); | |
38598 | ||
38599 | for (std::size_t i = r0; i <= r1; ++i) | |
38600 | { | |
38601 | details::kahan_sum(result, error, vec[i]); | |
38602 | } | |
38603 | ||
38604 | return result; | |
38605 | } | |
38606 | }; | |
38607 | ||
38608 | template <typename T> | |
38609 | class axpy : public exprtk::igeneric_function<T> | |
38610 | { | |
38611 | public: | |
38612 | ||
38613 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38614 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38615 | typedef typename igfun_t::generic_type generic_type; | |
38616 | typedef typename generic_type::scalar_view scalar_t; | |
38617 | typedef typename generic_type::vector_view vector_t; | |
38618 | ||
38619 | using exprtk::igeneric_function<T>::operator(); | |
38620 | ||
38621 | axpy() | |
38622 | : exprtk::igeneric_function<T>("TVV|TVVTT") | |
38623 | /* | |
38624 | y <- ax + y | |
38625 | Overloads: | |
38626 | 0. TVV - a, x(vector), y(vector) | |
38627 | 1. TVVTT - a, x(vector), y(vector), r0, r1 | |
38628 | */ | |
38629 | {} | |
38630 | ||
38631 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38632 | { | |
38633 | const vector_t x(parameters[1]); | |
38634 | vector_t y(parameters[2]); | |
38635 | ||
38636 | std::size_t r0 = 0; | |
38637 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38638 | ||
38639 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) | |
38640 | return std::numeric_limits<T>::quiet_NaN(); | |
38641 | else if (helper::invalid_range(y, r0, r1)) | |
38642 | return std::numeric_limits<T>::quiet_NaN(); | |
38643 | ||
38644 | const T a = scalar_t(parameters[0])(); | |
38645 | ||
38646 | for (std::size_t i = r0; i <= r1; ++i) | |
38647 | { | |
38648 | y[i] = (a * x[i]) + y[i]; | |
38649 | } | |
38650 | ||
38651 | return T(1); | |
38652 | } | |
38653 | }; | |
38654 | ||
38655 | template <typename T> | |
38656 | class axpby : public exprtk::igeneric_function<T> | |
38657 | { | |
38658 | public: | |
38659 | ||
38660 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38661 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38662 | typedef typename igfun_t::generic_type generic_type; | |
38663 | typedef typename generic_type::scalar_view scalar_t; | |
38664 | typedef typename generic_type::vector_view vector_t; | |
38665 | ||
38666 | using exprtk::igeneric_function<T>::operator(); | |
38667 | ||
38668 | axpby() | |
38669 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") | |
38670 | /* | |
38671 | y <- ax + by | |
38672 | Overloads: | |
38673 | 0. TVTV - a, x(vector), b, y(vector) | |
38674 | 1. TVTVTT - a, x(vector), b, y(vector), r0, r1 | |
38675 | */ | |
38676 | {} | |
38677 | ||
38678 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38679 | { | |
38680 | const vector_t x(parameters[1]); | |
38681 | vector_t y(parameters[3]); | |
38682 | ||
38683 | std::size_t r0 = 0; | |
38684 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38685 | ||
38686 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) | |
38687 | return std::numeric_limits<T>::quiet_NaN(); | |
38688 | else if (helper::invalid_range(y, r0, r1)) | |
38689 | return std::numeric_limits<T>::quiet_NaN(); | |
38690 | ||
38691 | const T a = scalar_t(parameters[0])(); | |
38692 | const T b = scalar_t(parameters[2])(); | |
38693 | ||
38694 | for (std::size_t i = r0; i <= r1; ++i) | |
38695 | { | |
38696 | y[i] = (a * x[i]) + (b * y[i]); | |
38697 | } | |
38698 | ||
38699 | return T(1); | |
38700 | } | |
38701 | }; | |
38702 | ||
38703 | template <typename T> | |
38704 | class axpyz : public exprtk::igeneric_function<T> | |
38705 | { | |
38706 | public: | |
38707 | ||
38708 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38709 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38710 | typedef typename igfun_t::generic_type generic_type; | |
38711 | typedef typename generic_type::scalar_view scalar_t; | |
38712 | typedef typename generic_type::vector_view vector_t; | |
38713 | ||
38714 | using exprtk::igeneric_function<T>::operator(); | |
38715 | ||
38716 | axpyz() | |
38717 | : exprtk::igeneric_function<T>("TVVV|TVVVTT") | |
38718 | /* | |
38719 | z <- ax + y | |
38720 | Overloads: | |
38721 | 0. TVVV - a, x(vector), y(vector), z(vector) | |
38722 | 1. TVVVTT - a, x(vector), y(vector), z(vector), r0, r1 | |
38723 | */ | |
38724 | {} | |
38725 | ||
38726 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38727 | { | |
38728 | const vector_t x(parameters[1]); | |
38729 | const vector_t y(parameters[2]); | |
38730 | vector_t z(parameters[3]); | |
38731 | ||
38732 | std::size_t r0 = 0; | |
38733 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38734 | ||
38735 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 3, 4, 1)) | |
38736 | return std::numeric_limits<T>::quiet_NaN(); | |
38737 | else if (helper::invalid_range(y, r0, r1)) | |
38738 | return std::numeric_limits<T>::quiet_NaN(); | |
38739 | else if (helper::invalid_range(z, r0, r1)) | |
38740 | return std::numeric_limits<T>::quiet_NaN(); | |
38741 | ||
38742 | const T a = scalar_t(parameters[0])(); | |
38743 | ||
38744 | for (std::size_t i = r0; i <= r1; ++i) | |
38745 | { | |
38746 | z[i] = (a * x[i]) + y[i]; | |
38747 | } | |
38748 | ||
38749 | return T(1); | |
38750 | } | |
38751 | }; | |
38752 | ||
38753 | template <typename T> | |
38754 | class axpbyz : public exprtk::igeneric_function<T> | |
38755 | { | |
38756 | public: | |
38757 | ||
38758 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38759 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38760 | typedef typename igfun_t::generic_type generic_type; | |
38761 | typedef typename generic_type::scalar_view scalar_t; | |
38762 | typedef typename generic_type::vector_view vector_t; | |
38763 | ||
38764 | using exprtk::igeneric_function<T>::operator(); | |
38765 | ||
38766 | axpbyz() | |
38767 | : exprtk::igeneric_function<T>("TVTVV|TVTVVTT") | |
38768 | /* | |
38769 | z <- ax + by | |
38770 | Overloads: | |
38771 | 0. TVTVV - a, x(vector), b, y(vector), z(vector) | |
38772 | 1. TVTVVTT - a, x(vector), b, y(vector), z(vector), r0, r1 | |
38773 | */ | |
38774 | {} | |
38775 | ||
38776 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38777 | { | |
38778 | const vector_t x(parameters[1]); | |
38779 | const vector_t y(parameters[3]); | |
38780 | vector_t z(parameters[4]); | |
38781 | ||
38782 | std::size_t r0 = 0; | |
38783 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38784 | ||
38785 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) | |
38786 | return std::numeric_limits<T>::quiet_NaN(); | |
38787 | else if (helper::invalid_range(y, r0, r1)) | |
38788 | return std::numeric_limits<T>::quiet_NaN(); | |
38789 | else if (helper::invalid_range(z, r0, r1)) | |
38790 | return std::numeric_limits<T>::quiet_NaN(); | |
38791 | ||
38792 | const T a = scalar_t(parameters[0])(); | |
38793 | const T b = scalar_t(parameters[2])(); | |
38794 | ||
38795 | for (std::size_t i = r0; i <= r1; ++i) | |
38796 | { | |
38797 | z[i] = (a * x[i]) + (b * y[i]); | |
38798 | } | |
38799 | ||
38800 | return T(1); | |
38801 | } | |
38802 | }; | |
38803 | ||
38804 | template <typename T> | |
38805 | class axpbz : public exprtk::igeneric_function<T> | |
38806 | { | |
38807 | public: | |
38808 | ||
38809 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38810 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38811 | typedef typename igfun_t::generic_type generic_type; | |
38812 | typedef typename generic_type::scalar_view scalar_t; | |
38813 | typedef typename generic_type::vector_view vector_t; | |
38814 | ||
38815 | using exprtk::igeneric_function<T>::operator(); | |
38816 | ||
38817 | axpbz() | |
38818 | : exprtk::igeneric_function<T>("TVTV|TVTVTT") | |
38819 | /* | |
38820 | z <- ax + b | |
38821 | Overloads: | |
38822 | 0. TVTV - a, x(vector), b, z(vector) | |
38823 | 1. TVTVTT - a, x(vector), b, z(vector), r0, r1 | |
38824 | */ | |
38825 | {} | |
38826 | ||
38827 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38828 | { | |
38829 | const vector_t x(parameters[1]); | |
38830 | vector_t z(parameters[3]); | |
38831 | ||
38832 | std::size_t r0 = 0; | |
38833 | std::size_t r1 = x.size() - 1; | |
38834 | ||
38835 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 4, 5, 1)) | |
38836 | return std::numeric_limits<T>::quiet_NaN(); | |
38837 | else if (helper::invalid_range(z, r0, r1)) | |
38838 | return std::numeric_limits<T>::quiet_NaN(); | |
38839 | ||
38840 | const T a = scalar_t(parameters[0])(); | |
38841 | const T b = scalar_t(parameters[2])(); | |
38842 | ||
38843 | for (std::size_t i = r0; i <= r1; ++i) | |
38844 | { | |
38845 | z[i] = (a * x[i]) + b; | |
38846 | } | |
38847 | ||
38848 | return T(1); | |
38849 | } | |
38850 | }; | |
38851 | ||
38852 | template <typename T> | |
38853 | class dot : public exprtk::igeneric_function<T> | |
38854 | { | |
38855 | public: | |
38856 | ||
38857 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38858 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38859 | typedef typename igfun_t::generic_type generic_type; | |
38860 | typedef typename generic_type::scalar_view scalar_t; | |
38861 | typedef typename generic_type::vector_view vector_t; | |
38862 | ||
38863 | using exprtk::igeneric_function<T>::operator(); | |
38864 | ||
38865 | dot() | |
38866 | : exprtk::igeneric_function<T>("VV|VVTT") | |
38867 | /* | |
38868 | Overloads: | |
38869 | 0. VV - x(vector), y(vector) | |
38870 | 1. VVTT - x(vector), y(vector), r0, r1 | |
38871 | */ | |
38872 | {} | |
38873 | ||
38874 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38875 | { | |
38876 | const vector_t x(parameters[0]); | |
38877 | const vector_t y(parameters[1]); | |
38878 | ||
38879 | std::size_t r0 = 0; | |
38880 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38881 | ||
38882 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) | |
38883 | return std::numeric_limits<T>::quiet_NaN(); | |
38884 | else if (helper::invalid_range(y, r0, r1)) | |
38885 | return std::numeric_limits<T>::quiet_NaN(); | |
38886 | ||
38887 | T result = T(0); | |
38888 | ||
38889 | for (std::size_t i = r0; i <= r1; ++i) | |
38890 | { | |
38891 | result += (x[i] * y[i]); | |
38892 | } | |
38893 | ||
38894 | return result; | |
38895 | } | |
38896 | }; | |
38897 | ||
38898 | template <typename T> | |
38899 | class dotk : public exprtk::igeneric_function<T> | |
38900 | { | |
38901 | public: | |
38902 | ||
38903 | typedef typename exprtk::igeneric_function<T> igfun_t; | |
38904 | typedef typename igfun_t::parameter_list_t parameter_list_t; | |
38905 | typedef typename igfun_t::generic_type generic_type; | |
38906 | typedef typename generic_type::scalar_view scalar_t; | |
38907 | typedef typename generic_type::vector_view vector_t; | |
38908 | ||
38909 | using exprtk::igeneric_function<T>::operator(); | |
38910 | ||
38911 | dotk() | |
38912 | : exprtk::igeneric_function<T>("VV|VVTT") | |
38913 | /* | |
38914 | Overloads: | |
38915 | 0. VV - x(vector), y(vector) | |
38916 | 1. VVTT - x(vector), y(vector), r0, r1 | |
38917 | */ | |
38918 | {} | |
38919 | ||
38920 | inline T operator() (const std::size_t& ps_index, parameter_list_t parameters) | |
38921 | { | |
38922 | const vector_t x(parameters[0]); | |
38923 | const vector_t y(parameters[1]); | |
38924 | ||
38925 | std::size_t r0 = 0; | |
38926 | std::size_t r1 = std::min(x.size(),y.size()) - 1; | |
38927 | ||
38928 | if ((1 == ps_index) && !helper::load_vector_range<T>::process(parameters, r0, r1, 2, 3, 0)) | |
38929 | return std::numeric_limits<T>::quiet_NaN(); | |
38930 | else if (helper::invalid_range(y, r0, r1)) | |
38931 | return std::numeric_limits<T>::quiet_NaN(); | |
38932 | ||
38933 | T result = T(0); | |
38934 | T error = T(0); | |
38935 | ||
38936 | for (std::size_t i = r0; i <= r1; ++i) | |
38937 | { | |
38938 | details::kahan_sum(result, error, (x[i] * y[i])); | |
38939 | } | |
38940 | ||
38941 | return result; | |
38942 | } | |
38943 | }; | |
38944 | ||
38945 | template <typename T> | |
38946 | struct package | |
38947 | { | |
38948 | all_true <T> at; | |
38949 | all_false <T> af; | |
38950 | any_true <T> nt; | |
38951 | any_false <T> nf; | |
38952 | count <T> c; | |
38953 | copy <T> cp; | |
38954 | rol <T> rl; | |
38955 | ror <T> rr; | |
38956 | shift_left <T> sl; | |
38957 | shift_right<T> sr; | |
38958 | sort <T> st; | |
38959 | nthelement <T> ne; | |
38960 | iota <T> ia; | |
38961 | sumk <T> sk; | |
38962 | axpy <T> b1_axpy; | |
38963 | axpby <T> b1_axpby; | |
38964 | axpyz <T> b1_axpyz; | |
38965 | axpbyz <T> b1_axpbyz; | |
38966 | axpbz <T> b1_axpbz; | |
38967 | dot <T> dt; | |
38968 | dotk <T> dtk; | |
38969 | ||
38970 | bool register_package(exprtk::symbol_table<T>& symtab) | |
38971 | { | |
38972 | #define exprtk_register_function(FunctionName,FunctionType) \ | |
38973 | if (!symtab.add_function(FunctionName,FunctionType)) \ | |
38974 | { \ | |
38975 | exprtk_debug(( \ | |
38976 | "exprtk::rtl::vecops::register_package - Failed to add function: %s\n", \ | |
38977 | FunctionName)); \ | |
38978 | return false; \ | |
38979 | } \ | |
38980 | ||
38981 | exprtk_register_function("all_true" ,at) | |
38982 | exprtk_register_function("all_false" ,af) | |
38983 | exprtk_register_function("any_true" ,nt) | |
38984 | exprtk_register_function("any_false" ,nf) | |
38985 | exprtk_register_function("count" , c) | |
38986 | exprtk_register_function("copy" ,cp) | |
38987 | exprtk_register_function("rotate_left" ,rl) | |
38988 | exprtk_register_function("rol" ,rl) | |
38989 | exprtk_register_function("rotate_right" ,rr) | |
38990 | exprtk_register_function("ror" ,rr) | |
38991 | exprtk_register_function("shftl" ,sl) | |
38992 | exprtk_register_function("shftr" ,sr) | |
38993 | exprtk_register_function("sort" ,st) | |
38994 | exprtk_register_function("nth_element" ,ne) | |
38995 | exprtk_register_function("iota" ,ia) | |
38996 | exprtk_register_function("sumk" ,sk) | |
38997 | exprtk_register_function("axpy" ,b1_axpy) | |
38998 | exprtk_register_function("axpby" ,b1_axpby) | |
38999 | exprtk_register_function("axpyz" ,b1_axpyz) | |
39000 | exprtk_register_function("axpbyz",b1_axpbyz) | |
39001 | exprtk_register_function("axpbz" ,b1_axpbz) | |
39002 | exprtk_register_function("dot" ,dt) | |
39003 | exprtk_register_function("dotk" ,dtk) | |
39004 | #undef exprtk_register_function | |
39005 | ||
39006 | return true; | |
39007 | } | |
39008 | }; | |
39009 | ||
39010 | } // namespace exprtk::rtl::vecops | |
39011 | } // namespace exprtk::rtl | |
39012 | } // namespace exprtk | |
39013 | #endif | |
39014 | ||
39015 | namespace exprtk | |
39016 | { | |
39017 | namespace information | |
39018 | { | |
39019 | static const char* library = "Mathematical Expression Toolkit"; | |
39020 | static const char* version = "2.7182818284590452353602874713526624977572470936999595749" | |
39021 | "669676277240766303535475945713821785251664274274663919320"; | |
39022 | static const char* date = "20200101"; | |
39023 | ||
39024 | static inline std::string data() | |
39025 | { | |
39026 | static const std::string info_str = std::string(library) + | |
39027 | std::string(" v") + std::string(version) + | |
39028 | std::string(" (") + date + std::string(")"); | |
39029 | return info_str; | |
39030 | } | |
39031 | ||
39032 | } // namespace information | |
39033 | ||
39034 | #ifdef exprtk_debug | |
39035 | #undef exprtk_debug | |
39036 | #endif | |
39037 | ||
39038 | #ifdef exprtk_error_location | |
39039 | #undef exprtk_error_location | |
39040 | #endif | |
39041 | ||
39042 | #ifdef exprtk_disable_fallthrough_begin | |
39043 | #undef exprtk_disable_fallthrough_begin | |
39044 | #endif | |
39045 | ||
39046 | #ifdef exprtk_disable_fallthrough_end | |
39047 | #undef exprtk_disable_fallthrough_end | |
39048 | #endif | |
39049 | ||
39050 | } // namespace exprtk | |
39051 | ||
39052 | #endif |