PageRenderTime 139ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 2ms

/exprtk.hpp

http://fastmathparser.codeplex.com
C++ Header | 8207 lines | 7224 code | 873 blank | 110 comment | 1334 complexity | c5a4ad74bc8e61645a0da25ec83d8579 MD5 | raw file
  1. /*
  2. ****************************************************************
  3. * C++ Mathematical Expression Toolkit Library *
  4. * *
  5. * Author: Arash Partow (1999-2012) *
  6. * URL: http://www.partow.net/programming/exprtk/index.html *
  7. * *
  8. * Copyright notice: *
  9. * Free use of the C++ Mathematical Expression Toolkit Library *
  10. * is permitted under the guidelines and in accordance with the *
  11. * most current version of the Common Public License. *
  12. * http://www.opensource.org/licenses/cpl1.0.php *
  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) if(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) (12.34sin(x)cos(2y)7+1)==(12.34*sin(x)*cos(2*y)*7+1) *
  27. * (12) (x ilike 's*ri?g') and [y<(3z^7+w)] *
  28. * *
  29. ****************************************************************
  30. */
  31. #ifndef INCLUDE_EXPRTK_HPP
  32. #define INCLUDE_EXPRTK_HPP
  33. #include <cctype>
  34. #include <iostream>
  35. #include <string>
  36. #include <algorithm>
  37. #include <cmath>
  38. #include <limits>
  39. #include <deque>
  40. #include <list>
  41. #include <map>
  42. #include <set>
  43. #include <stack>
  44. #define exprtk_lean_and_mean
  45. #ifdef exprtk_lean_and_mean_numeric_only
  46. #ifndef exprtk_lean_and_mean
  47. #define exprtk_lean_and_mean
  48. #endif
  49. #ifndef exprtk_disable_string_capabilities
  50. #define exprtk_disable_string_capabilities
  51. #endif
  52. #endif
  53. #ifdef exprtk_lean_and_mean
  54. #ifndef exprtk_disable_extended_operator_optimizations
  55. #define exprtk_disable_extended_operator_optimizations
  56. #endif
  57. #ifndef exprtk_disable_extended_optimisations
  58. #define exprtk_disable_extended_optimisations
  59. #endif
  60. #endif
  61. namespace exprtk
  62. {
  63. namespace details
  64. {
  65. inline bool is_whitespace(const char& c)
  66. {
  67. return (' ' == c) ||
  68. ('\n' == c) ||
  69. ('\r' == c) ||
  70. ('\t' == c) ||
  71. ('\b' == c);
  72. }
  73. inline bool is_operator_char(const char& c)
  74. {
  75. return ('+' == c) || ('-' == c) ||
  76. ('*' == c) || ('/' == c) ||
  77. ('^' == c) || ('<' == c) ||
  78. ('>' == c) || ('=' == c) ||
  79. (',' == c) || ('!' == c) ||
  80. ('(' == c) || (')' == c) ||
  81. ('[' == c) || (']' == c) ||
  82. ('{' == c) || ('}' == c) ||
  83. ('%' == c) || (':' == c) ||
  84. ('?' == c);
  85. }
  86. inline bool is_letter(const char c)
  87. {
  88. return (('a' <= c) && (c <= 'z')) || (('A' <= c) && (c <= 'Z'));
  89. }
  90. inline bool is_digit(const char c)
  91. {
  92. return ('0' <= c) && (c <= '9');
  93. }
  94. inline bool is_left_bracket(const char c)
  95. {
  96. return ('(' == c) || ('[' == c) || ('{' == c);
  97. }
  98. inline bool is_right_bracket(const char c)
  99. {
  100. return (')' == c) || (']' == c) || ('}' == c);
  101. }
  102. inline bool is_sign(const char c)
  103. {
  104. return ('+' == c) || ('-' == c);
  105. }
  106. inline bool is_invalid(const char& c)
  107. {
  108. return !is_whitespace(c) &&
  109. !is_operator_char(c) &&
  110. !is_letter(c) &&
  111. !is_digit(c) &&
  112. ('.' != c) &&
  113. ('_' != c) &&
  114. ('$' != c) &&
  115. ('\'' != c);
  116. }
  117. inline bool imatch(const char& c1, const char& c2)
  118. {
  119. return std::tolower(c1) == std::tolower(c2);
  120. }
  121. inline bool imatch(const std::string& s1, const std::string& s2)
  122. {
  123. if (s1.size() == s2.size())
  124. {
  125. for (std::size_t i = 0; i < s1.size(); ++i)
  126. {
  127. if (std::tolower(s1[i]) != std::tolower(s2[i]))
  128. {
  129. return false;
  130. }
  131. }
  132. return true;
  133. }
  134. return false;
  135. }
  136. static const std::string reserved_words[] =
  137. {
  138. "and", "false", "for", "if", "ilike", "in", "like", "nand", "nor", "not",
  139. "or", "true", "while", "xor"
  140. };
  141. static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
  142. static const std::string reserved_symbols[] =
  143. {
  144. "abs", "acos", "and", "asin", "atan", "atan2", "avg", "ceil", "clamp",
  145. "cos", "cosh", "cot", "csc", "deg2grad", "deg2rad", "equal", "erf", "erfc",
  146. "exp", "false", "floor", "for", "grad2deg", "hyp", "if", "ilike", "in",
  147. "inrange", "like", "log", "log10", "logn", "max", "min", "mod", "mul",
  148. "nand", "nor", "not", "not_equal", "or", "rad2deg", "root", "round",
  149. "roundn", "sec", "sgn", "shl", "shr", "sin", "sinh", "sqrt", "sum",
  150. "tan", "tanh", "true", "while", "xor"
  151. };
  152. static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
  153. inline bool is_reserved_word(const std::string& symbol)
  154. {
  155. for (std::size_t i = 0; i < reserved_words_size; ++i)
  156. {
  157. if (imatch(symbol,reserved_words[i]))
  158. {
  159. return true;
  160. }
  161. }
  162. return false;
  163. }
  164. inline bool is_reserved_symbol(const std::string& symbol)
  165. {
  166. for (std::size_t i = 0; i < reserved_symbols_size; ++i)
  167. {
  168. if (imatch(symbol,reserved_symbols[i]))
  169. {
  170. return true;
  171. }
  172. }
  173. return false;
  174. }
  175. struct cs_match { static inline bool cmp(const char c0, const char c1) { return c0 == c1; } };
  176. struct cis_match { static inline bool cmp(const char c0, const char c1) { return std::tolower(c0) == std::tolower(c1); } };
  177. template <typename Iterator, typename Compare>
  178. inline bool match_impl(const Iterator pattern_begin,
  179. const Iterator pattern_end,
  180. const Iterator data_begin,
  181. const Iterator data_end,
  182. const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
  183. const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
  184. {
  185. if (0 == std::distance(data_begin,data_end)) return false;
  186. Iterator d_itr = data_begin;
  187. Iterator p_itr = pattern_begin;
  188. Iterator c_itr = data_begin;
  189. Iterator m_itr = data_begin;
  190. while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
  191. {
  192. if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
  193. {
  194. return false;
  195. }
  196. ++p_itr;
  197. ++d_itr;
  198. }
  199. while (data_end != d_itr)
  200. {
  201. if (zero_or_more == (*p_itr))
  202. {
  203. if (pattern_end == (++p_itr))
  204. {
  205. return true;
  206. }
  207. m_itr = p_itr;
  208. c_itr = d_itr;
  209. ++c_itr;
  210. }
  211. else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
  212. {
  213. ++p_itr;
  214. ++d_itr;
  215. }
  216. else
  217. {
  218. p_itr = m_itr;
  219. d_itr = c_itr++;
  220. }
  221. }
  222. while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) ++p_itr;
  223. return (p_itr == pattern_end);
  224. }
  225. inline bool wc_match(const std::string& wild_card,
  226. const std::string& str)
  227. {
  228. return match_impl<const char*,cs_match>(wild_card.data(),
  229. wild_card.data() + wild_card.size(),
  230. str.data(),
  231. str.data() + str.size(),
  232. '*',
  233. '?');
  234. }
  235. inline bool wc_imatch(const std::string& wild_card,
  236. const std::string& str)
  237. {
  238. return match_impl<const char*,cis_match>(wild_card.data(),
  239. wild_card.data() + wild_card.size(),
  240. str.data(),
  241. str.data() + str.size(),
  242. '*',
  243. '?');
  244. }
  245. static const double pow10[] = {
  246. 1.0,
  247. 10.0,
  248. 100.0,
  249. 1000.0,
  250. 10000.0,
  251. 100000.0,
  252. 1000000.0,
  253. 10000000.0,
  254. 100000000.0,
  255. 1000000000.0,
  256. 10000000000.0,
  257. 100000000000.0,
  258. 1000000000000.0,
  259. 10000000000000.0,
  260. 100000000000000.0,
  261. 1000000000000000.0,
  262. 10000000000000000.0,
  263. };
  264. namespace numeric
  265. {
  266. namespace constant
  267. {
  268. static const double e = 2.718281828459045235360;
  269. static const double pi = 3.141592653589793238462;
  270. static const double pi_2 = 1.570796326794896619231;
  271. static const double pi_4 = 0.785398163397448309616;
  272. static const double pi_180 = 0.017453292519943295769;
  273. static const double _1_pi = 0.318309886183790671538;
  274. static const double _2_pi = 0.636619772367581343076;
  275. static const double _180_pi = 57.295779513082320876798;
  276. }
  277. namespace details
  278. {
  279. struct unknown_type_tag {};
  280. struct real_type_tag {};
  281. struct int_type_tag {};
  282. template <typename T>
  283. struct number_type { typedef unknown_type_tag type; };
  284. #define exprtk_register_real_type_tag(T)\
  285. template<> struct number_type<T> { typedef real_type_tag type; };
  286. #define exprtk_register_int_type_tag(T)\
  287. template<> struct number_type<T> { typedef int_type_tag type; };
  288. exprtk_register_real_type_tag(double)
  289. exprtk_register_real_type_tag(long double)
  290. exprtk_register_real_type_tag(float)
  291. exprtk_register_int_type_tag(short)
  292. exprtk_register_int_type_tag(int)
  293. exprtk_register_int_type_tag(long long int)
  294. exprtk_register_int_type_tag(unsigned short)
  295. exprtk_register_int_type_tag(unsigned int)
  296. exprtk_register_int_type_tag(unsigned long long int)
  297. #undef exprtk_register_real_type_tag
  298. #undef exprtk_register_int_type_tag
  299. template <typename T>
  300. inline T equal_impl(const T& v0, const T& v1, real_type_tag)
  301. {
  302. static const T epsilon = T(0.0000000001);
  303. return (std::abs(v0 - v1) <= (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0);
  304. }
  305. template <typename T>
  306. inline T equal_impl(const T& v0, const T& v1, int_type_tag)
  307. {
  308. return (v0 == v1) ? 1 : 0;
  309. }
  310. template <typename T>
  311. inline T nequal_impl(const T& v0, const T& v1, real_type_tag)
  312. {
  313. static const T epsilon = T(0.0000000001);
  314. return (std::abs(v0 - v1) > (std::max(T(1),std::max(std::abs(v0),std::abs(v1))) * epsilon)) ? T(1) : T(0);
  315. }
  316. template <typename T>
  317. inline T nequal_impl(const T& v0, const T& v1, int_type_tag)
  318. {
  319. return (v0 != v1) ? 1 : 0;
  320. }
  321. template <typename T>
  322. inline T modulus_impl(const T& v0, const T& v1, real_type_tag)
  323. {
  324. return std::fmod(v0,v1);
  325. }
  326. template <typename T>
  327. inline T modulus_impl(const T& v0, const T& v1, int_type_tag)
  328. {
  329. return v0 % v1;
  330. }
  331. template <typename T>
  332. inline T pow_impl(const T& v0, const T& v1, real_type_tag)
  333. {
  334. return std::pow(v0,v1);
  335. }
  336. template <typename T>
  337. inline T pow_impl(const T& v0, const T& v1, int_type_tag)
  338. {
  339. return std::pow(static_cast<double>(v0),static_cast<double>(v1));
  340. }
  341. template <typename T>
  342. inline T logn_impl(const T& v0, const T& v1, real_type_tag)
  343. {
  344. return std::log(v0) / std::log(v1);
  345. }
  346. template <typename T>
  347. inline T logn_impl(const T& v0, const T& v1, int_type_tag)
  348. {
  349. return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
  350. }
  351. template <typename T>
  352. inline T root_impl(const T& v0, const T& v1, real_type_tag)
  353. {
  354. return std::pow(v0,T(1)/v1);
  355. }
  356. template <typename T>
  357. inline T root_impl(const T& v0, const T& v1, int_type_tag)
  358. {
  359. return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
  360. }
  361. template <typename T>
  362. inline T roundn_impl(const T& v0, const T& v1, real_type_tag)
  363. {
  364. return T(std::floor((v0 * pow10[(int)std::floor(v1)]) + T(0.5)) / T(pow10[(int)std::floor(v1)]));
  365. }
  366. template <typename T>
  367. inline T roundn_impl(const T& v0, const T&, int_type_tag)
  368. {
  369. return v0;
  370. }
  371. template <typename T>
  372. inline T hyp_impl(const T& v0, const T& v1, real_type_tag)
  373. {
  374. return std::sqrt((v0 * v0) + (v1 * v1));
  375. }
  376. template <typename T>
  377. inline T hyp_impl(const T& v0, const T& v1, int_type_tag)
  378. {
  379. return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
  380. }
  381. template <typename T>
  382. inline T atan2_impl(const T& v0, const T& v1, real_type_tag)
  383. {
  384. return std::atan2(v0,v1);
  385. }
  386. template <typename T>
  387. inline T atan2_impl(const T&, const T&, int_type_tag)
  388. {
  389. return 0;
  390. }
  391. template <typename T>
  392. inline T shr_impl(const T& v0, const T& v1, real_type_tag)
  393. {
  394. return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
  395. }
  396. template <typename T>
  397. inline T shr_impl(const T& v0, const T& v1, int_type_tag)
  398. {
  399. return v0 >> v1;
  400. }
  401. template <typename T>
  402. inline T shl_impl(const T& v0, const T& v1, real_type_tag)
  403. {
  404. return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
  405. }
  406. template <typename T>
  407. inline T shl_impl(const T& v0, const T& v1, int_type_tag)
  408. {
  409. return v0 << v1;
  410. }
  411. template <typename T>
  412. inline T sgn_impl(const T& v, real_type_tag)
  413. {
  414. if (v > T(0.0)) return T(+1.0);
  415. else if (v < T(0.0)) return T(-1.0);
  416. else return T( 0.0);
  417. }
  418. template <typename T>
  419. inline T sgn_impl(const T& v, int_type_tag)
  420. {
  421. if (v > T(0)) return T(+1);
  422. else if (v < T(0)) return T(-1);
  423. else return T( 0);
  424. }
  425. template <typename T>
  426. inline T xor_impl(const T& v0, const T& v1, real_type_tag)
  427. {
  428. return v0 != v1;
  429. }
  430. template <typename T>
  431. inline T xor_impl(const T& v0, const T& v1, int_type_tag)
  432. {
  433. return v0 ^ v1;
  434. }
  435. template <typename T>
  436. inline T erf_impl(T v, real_type_tag)
  437. {
  438. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  439. //Note: This should not be required for mscv 11.+
  440. T a1 = T(+0.254829592);
  441. T a2 = T(-0.284496736);
  442. T a3 = T(+1.421413741);
  443. T a4 = T(-1.453152027);
  444. T a5 = T(+1.061405429);
  445. T p = T( 0.327591100);
  446. T sign = T(1.0);
  447. if (v < 0)
  448. {
  449. sign = -1;
  450. v = abs(v);
  451. }
  452. T t = T(1.0) / (T(1.0) + p * v);
  453. T y = T(1.0) - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * std::exp(-v * v);
  454. return sign * y;
  455. #else
  456. return ::erf(v);
  457. #endif
  458. }
  459. template <typename T>
  460. inline T erf_impl(T v, int_type_tag)
  461. {
  462. return erf_impl(static_cast<double>(v),real_type_tag());
  463. }
  464. template <typename T>
  465. inline T erfc_impl(T v, real_type_tag)
  466. {
  467. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  468. return T(1.0) - erf_impl(v,real_type_tag());
  469. #else
  470. return ::erfc(v);
  471. #endif
  472. }
  473. template <typename T>
  474. inline T erfc_impl(T v, int_type_tag)
  475. {
  476. return erfc_impl(static_cast<double>(v),real_type_tag());
  477. }
  478. template <typename T> inline T abs_impl(const T& v, real_type_tag) { return std::abs (v); }
  479. template <typename T> inline T acos_impl(const T& v, real_type_tag) { return std::acos (v); }
  480. template <typename T> inline T asin_impl(const T& v, real_type_tag) { return std::asin (v); }
  481. template <typename T> inline T atan_impl(const T& v, real_type_tag) { return std::atan (v); }
  482. template <typename T> inline T ceil_impl(const T& v, real_type_tag) { return std::ceil (v); }
  483. template <typename T> inline T cos_impl(const T& v, real_type_tag) { return std::cos (v); }
  484. template <typename T> inline T cosh_impl(const T& v, real_type_tag) { return std::cosh (v); }
  485. template <typename T> inline T exp_impl(const T& v, real_type_tag) { return std::exp (v); }
  486. template <typename T> inline T floor_impl(const T& v, real_type_tag) { return std::floor(v); }
  487. template <typename T> inline T log_impl(const T& v, real_type_tag) { return std::log (v); }
  488. template <typename T> inline T log10_impl(const T& v, real_type_tag) { return std::log10(v); }
  489. template <typename T> inline T neg_impl(const T& v, real_type_tag) { return -v; }
  490. template <typename T> inline T pos_impl(const T& v, real_type_tag) { return +v; }
  491. template <typename T> inline T round_impl(const T& v, real_type_tag) { return std::floor(v + T(0.5)); }
  492. template <typename T> inline T sin_impl(const T& v, real_type_tag) { return std::sin (v); }
  493. template <typename T> inline T sinh_impl(const T& v, real_type_tag) { return std::sinh (v); }
  494. template <typename T> inline T sqrt_impl(const T& v, real_type_tag) { return std::sqrt (v); }
  495. template <typename T> inline T tan_impl(const T& v, real_type_tag) { return std::tan (v); }
  496. template <typename T> inline T tanh_impl(const T& v, real_type_tag) { return std::tanh (v); }
  497. template <typename T> inline T cot_impl(const T& v, real_type_tag) { return T(1) / std::tan(v); }
  498. template <typename T> inline T sec_impl(const T& v, real_type_tag) { return T(1) / std::cos(v); }
  499. template <typename T> inline T csc_impl(const T& v, real_type_tag) { return T(1) / std::sin(v); }
  500. template <typename T> inline T r2d_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
  501. template <typename T> inline T d2r_impl(const T& v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
  502. template <typename T> inline T d2g_impl(const T& v, real_type_tag) { return (v * T(20.0/9.0)); }
  503. template <typename T> inline T g2d_impl(const T& v, real_type_tag) { return (v * T(9.0/20.0)); }
  504. template <typename T> inline T notl_impl(const T& v, real_type_tag) { return (v != T(0) ? T(0) : T(1)); }
  505. template <typename T> inline T abs_impl(const T& v, int_type_tag) { return std::abs (v); }
  506. template <typename T> inline T exp_impl(const T& v, int_type_tag) { return std::exp (v); }
  507. template <typename T> inline T log_impl(const T& v, int_type_tag) { return std::log (v); }
  508. template <typename T> inline T log10_impl(const T& v, int_type_tag) { return std::log10(v); }
  509. template <typename T> inline T neg_impl(const T& v, int_type_tag) { return -v; }
  510. template <typename T> inline T pos_impl(const T& v, int_type_tag) { return +v; }
  511. template <typename T> inline T ceil_impl(const T& v, int_type_tag) { return v; }
  512. template <typename T> inline T floor_impl(const T& v, int_type_tag) { return v; }
  513. template <typename T> inline T round_impl(const T& v, int_type_tag) { return v; }
  514. template <typename T> inline T notl_impl(const T& v, int_type_tag) { return !v; }
  515. template <typename T> inline T sqrt_impl(const T& v, int_type_tag) { return std::sqrt (v); }
  516. template <typename T> inline T acos_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  517. template <typename T> inline T asin_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  518. template <typename T> inline T atan_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  519. template <typename T> inline T cos_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  520. template <typename T> inline T cosh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  521. template <typename T> inline T sin_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  522. template <typename T> inline T sinh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  523. template <typename T> inline T tan_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  524. template <typename T> inline T tanh_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  525. template <typename T> inline T cot_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  526. template <typename T> inline T sec_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  527. template <typename T> inline T csc_impl(const T& , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  528. template <typename T>
  529. inline bool is_integer_impl(const T& v, real_type_tag)
  530. {
  531. return (T(0.0) == std::fmod(v,T(1.0)));
  532. }
  533. template <typename T>
  534. inline bool is_integer_impl(const T&, int_type_tag)
  535. {
  536. return true;
  537. }
  538. }
  539. template <typename Type>
  540. struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
  541. template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
  542. template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
  543. template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
  544. template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
  545. template <typename T>
  546. inline T equal(const T& v0, const T& v1)
  547. {
  548. typename details::number_type<T>::type num_type;
  549. return details::equal_impl(v0,v1,num_type);
  550. }
  551. template <typename T>
  552. inline T nequal(const T& v0, const T& v1)
  553. {
  554. typename details::number_type<T>::type num_type;
  555. return details::nequal_impl(v0,v1,num_type);
  556. }
  557. template <typename T>
  558. inline T modulus(const T& v0, const T& v1)
  559. {
  560. typename details::number_type<T>::type num_type;
  561. return details::modulus_impl(v0,v1,num_type);
  562. }
  563. template <typename T>
  564. inline T pow(const T& v0, const T& v1)
  565. {
  566. typename details::number_type<T>::type num_type;
  567. return details::pow_impl(v0,v1,num_type);
  568. }
  569. template <typename T>
  570. inline T logn(const T& v0, const T& v1)
  571. {
  572. typename details::number_type<T>::type num_type;
  573. return details::logn_impl(v0,v1,num_type);
  574. }
  575. template <typename T>
  576. inline T root(const T& v0, const T& v1)
  577. {
  578. typename details::number_type<T>::type num_type;
  579. return details::root_impl(v0,v1,num_type);
  580. }
  581. template <typename T>
  582. inline T roundn(const T& v0, const T& v1)
  583. {
  584. typename details::number_type<T>::type num_type;
  585. return details::roundn_impl(v0,v1,num_type);
  586. }
  587. template <typename T>
  588. inline T hyp(const T& v0, const T& v1)
  589. {
  590. typename details::number_type<T>::type num_type;
  591. return details::hyp_impl(v0,v1,num_type);
  592. }
  593. template <typename T>
  594. inline T atan2(const T& v0, const T& v1)
  595. {
  596. typename details::number_type<T>::type num_type;
  597. return details::atan2_impl(v0,v1,num_type);
  598. }
  599. template <typename T>
  600. inline T shr(const T& v0, const T& v1)
  601. {
  602. typename details::number_type<T>::type num_type;
  603. return details::shr_impl(v0,v1,num_type);
  604. }
  605. template <typename T>
  606. inline T shl(const T& v0, const T& v1)
  607. {
  608. typename details::number_type<T>::type num_type;
  609. return details::shl_impl(v0,v1,num_type);
  610. }
  611. template <typename T>
  612. inline T xor_opr(const T& v0, const T& v1)
  613. {
  614. typename details::number_type<T>::type num_type;
  615. return details::xor_impl(v0,v1,num_type);
  616. }
  617. template <typename T>
  618. inline bool is_integer(const T& v)
  619. {
  620. typename details::number_type<T>::type num_type;
  621. return details::is_integer_impl(v,num_type);
  622. }
  623. template <typename T, unsigned int N>
  624. struct fast_exp
  625. {
  626. static inline T result(T v)
  627. {
  628. unsigned int k = N;
  629. T l = T(1);
  630. while (k)
  631. {
  632. if (k & 1)
  633. {
  634. l *= v;
  635. --k;
  636. }
  637. v *= v;
  638. k >>= 1;
  639. }
  640. return l;
  641. }
  642. };
  643. 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; } };
  644. template <typename T> struct fast_exp<T, 9> { static inline T result(T v) { return fast_exp<T,8>::result(v) * v; } };
  645. 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; } };
  646. template <typename T> struct fast_exp<T, 7> { static inline T result(T v) { return fast_exp<T,6>::result(v) * v; } };
  647. 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; } };
  648. template <typename T> struct fast_exp<T, 5> { static inline T result(T v) { return fast_exp<T,4>::result(v) * v; } };
  649. template <typename T> struct fast_exp<T, 4> { static inline T result(T v) { T v_2 = v * v; return v_2 * v_2; } };
  650. template <typename T> struct fast_exp<T, 3> { static inline T result(T v) { return v * v * v; } };
  651. template <typename T> struct fast_exp<T, 2> { static inline T result(T v) { return v * v; } };
  652. template <typename T> struct fast_exp<T, 1> { static inline T result(T v) { return v; } };
  653. template <typename T> struct fast_exp<T, 0> { static inline T result(T ) { return T(1); } };
  654. #define exprtk_define_unary_function(FunctionName) \
  655. template <typename T> \
  656. inline T FunctionName (const T& v) \
  657. { \
  658. typename details::number_type<T>::type num_type; \
  659. return details:: FunctionName##_impl(v,num_type); \
  660. }
  661. exprtk_define_unary_function(abs )
  662. exprtk_define_unary_function(acos )
  663. exprtk_define_unary_function(asin )
  664. exprtk_define_unary_function(atan )
  665. exprtk_define_unary_function(ceil )
  666. exprtk_define_unary_function(cos )
  667. exprtk_define_unary_function(cosh )
  668. exprtk_define_unary_function(exp )
  669. exprtk_define_unary_function(floor)
  670. exprtk_define_unary_function(log )
  671. exprtk_define_unary_function(log10)
  672. exprtk_define_unary_function(neg )
  673. exprtk_define_unary_function(pos )
  674. exprtk_define_unary_function(round)
  675. exprtk_define_unary_function(sin )
  676. exprtk_define_unary_function(sinh )
  677. exprtk_define_unary_function(sqrt )
  678. exprtk_define_unary_function(tan )
  679. exprtk_define_unary_function(tanh )
  680. exprtk_define_unary_function(cot )
  681. exprtk_define_unary_function(sec )
  682. exprtk_define_unary_function(csc )
  683. exprtk_define_unary_function(r2d )
  684. exprtk_define_unary_function(d2r )
  685. exprtk_define_unary_function(d2g )
  686. exprtk_define_unary_function(g2d )
  687. exprtk_define_unary_function(notl )
  688. exprtk_define_unary_function(sgn )
  689. exprtk_define_unary_function(erf )
  690. exprtk_define_unary_function(erfc )
  691. #undef exprtk_define_unary_function
  692. }
  693. template <typename T>
  694. struct token
  695. {
  696. enum token_type
  697. {
  698. none = 0,
  699. error = 1,
  700. eof = 2,
  701. number = 3,
  702. symbol = 4,
  703. string = 5,
  704. assign = 6,
  705. shr = 7,
  706. shl = 8,
  707. lte = 9,
  708. ne = 10,
  709. gte = 11,
  710. lt = '<',
  711. gt = '>',
  712. eq = '=',
  713. rbracket = ')',
  714. lbracket = '(',
  715. rsqrbracket = ']',
  716. lsqrbracket = '[',
  717. rcrlbracket = '}',
  718. lcrlbracket = '{',
  719. comma = ',',
  720. add = '+',
  721. sub = '-',
  722. div = '/',
  723. mul = '*',
  724. mod = '%',
  725. pow = '^'
  726. };
  727. token() {}
  728. explicit token(token_type ttype)
  729. : type(ttype)
  730. {}
  731. token(token_type ttype,
  732. const char* begin, const char* end)
  733. : type(ttype),
  734. value(std::string(begin,end)),
  735. numeric_value(T(0))
  736. {}
  737. token(token_type ttype, const std::string& v)
  738. : type(ttype),
  739. value(v),
  740. numeric_value(T(0))
  741. {}
  742. token(token_type ttype, const T& num_val)
  743. : type(ttype),
  744. numeric_value(num_val)
  745. {}
  746. token_type type;
  747. std::string value;
  748. T numeric_value;
  749. };
  750. template <typename T>
  751. class lexer
  752. {
  753. public:
  754. typedef token<T> token_t;
  755. inline bool process(const std::string& str)
  756. {
  757. error_description_ = "";
  758. s_itr = str.data();
  759. s_end = str.data() + str.size();
  760. eof_token_ = token_t(token_t::eof,s_end,s_end);
  761. token_list_.clear();
  762. while (s_end != s_itr)
  763. {
  764. scan_token();
  765. if (!error_description_.empty())
  766. {
  767. return false;
  768. }
  769. }
  770. process_commutative_symbols();
  771. token_itr_ = token_list_.begin();
  772. store_token_itr_ = token_list_.begin();
  773. return true;
  774. }
  775. inline void store()
  776. {
  777. store_token_itr_ = token_itr_;
  778. }
  779. inline void restore()
  780. {
  781. token_itr_ = store_token_itr_;
  782. }
  783. inline token_t& next_token()
  784. {
  785. if (token_list_.end() != token_itr_)
  786. {
  787. return *token_itr_++;
  788. }
  789. else
  790. return eof_token_;
  791. }
  792. inline std::string error() const
  793. {
  794. return error_description_;
  795. }
  796. private:
  797. inline void skip_whitespace()
  798. {
  799. while ((s_end != s_itr) && is_whitespace(*s_itr))
  800. {
  801. ++s_itr;
  802. }
  803. }
  804. inline void scan_token()
  805. {
  806. skip_whitespace();
  807. if (s_end == s_itr)
  808. {
  809. return;
  810. }
  811. else if (is_operator_char(*s_itr))
  812. {
  813. scan_operator();
  814. return;
  815. }
  816. else if (is_letter(*s_itr))
  817. {
  818. scan_symbol();
  819. return;
  820. }
  821. else if (is_digit((*s_itr)) || ('.' == (*s_itr)))
  822. {
  823. scan_number();
  824. return;
  825. }
  826. else if ('$' == (*s_itr))
  827. {
  828. scan_special_function();
  829. return;
  830. }
  831. #ifndef exprtk_disable_string_capabilities
  832. else if ('\'' == (*s_itr))
  833. {
  834. scan_string();
  835. return;
  836. }
  837. #endif
  838. else
  839. {
  840. set_error(std::string("scan_token() - error invalid token: ") + std::string(s_itr,s_itr + 2));
  841. token_list_.push_back(error(s_itr,s_itr + 1));
  842. ++s_itr;
  843. }
  844. }
  845. inline void scan_operator()
  846. {
  847. if ((s_itr + 1) != s_end)
  848. {
  849. typename token_t::token_type ttype = token_t::none;
  850. char c0 = s_itr[0];
  851. char c1 = s_itr[1];
  852. if ((c0 == '<') && (c1 == '=')) ttype = token_t::lte;
  853. else if ((c0 == '>') && (c1 == '=')) ttype = token_t::gte;
  854. else if ((c0 == '<') && (c1 == '>')) ttype = token_t::ne;
  855. else if ((c0 == '!') && (c1 == '=')) ttype = token_t::ne;
  856. else if ((c0 == '=') && (c1 == '=')) ttype = token_t::eq;
  857. else if ((c0 == ':') && (c1 == '=')) ttype = token_t::assign;
  858. else if ((c0 == '<') && (c1 == '<')) ttype = token_t::shl;
  859. else if ((c0 == '>') && (c1 == '>')) ttype = token_t::shr;
  860. if (token_t::none != ttype)
  861. {
  862. token_list_.push_back(token_t(ttype));
  863. s_itr += 2;
  864. return;
  865. }
  866. }
  867. if ('<' == *s_itr) token_list_.push_back(token_t(token_t::lt));
  868. else if ('>' == *s_itr) token_list_.push_back(token_t(token_t::gt));
  869. else
  870. token_list_.push_back(token_t(typename token_t::token_type((*s_itr))));
  871. ++s_itr;
  872. }
  873. inline void scan_symbol()
  874. {
  875. const char* begin = s_itr;
  876. while ((s_end != s_itr) &&
  877. (is_letter((*s_itr)) || is_digit ((*s_itr)) || ((*s_itr) == '_')))
  878. {
  879. ++s_itr;
  880. }
  881. static const std::string true_string = "true";
  882. static const std::string false_string = "false";
  883. if (details::imatch(std::string(begin,s_itr),true_string))
  884. token_list_.push_back(token_t(token_t::number,T(1)));
  885. else if (details::imatch(std::string(begin,s_itr),false_string))
  886. token_list_.push_back(token_t(token_t::number,T(0)));
  887. else
  888. token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
  889. }
  890. inline void scan_number()
  891. {
  892. /*
  893. Attempt to match a valid numeric value in one of the following formats:
  894. 1. 123456
  895. 2. 123.456
  896. 3. 123.456e3
  897. 4. 123.456E3
  898. 5. 123.456e+3
  899. 6. 123.456E+3
  900. 7. 123.456e-3
  901. 8. 123.456E-3
  902. */
  903. const char* begin = s_itr;
  904. bool dot_found = false;
  905. bool e_found = false;
  906. bool post_e_sign_found = false;
  907. while (s_end != s_itr)
  908. {
  909. if ('.' == (*s_itr))
  910. {
  911. if (dot_found)
  912. {
  913. set_error(std::string("scan_number() - error invalid numeric token[1]: ") + std::string(begin,s_itr));
  914. token_list_.push_back(error(begin,s_itr));
  915. return;
  916. }
  917. dot_found = true;
  918. ++s_itr;
  919. continue;
  920. }
  921. else if (imatch('e',(*s_itr)))
  922. {
  923. const char& c = *(s_itr + 1);
  924. if (s_end == (s_itr + 1))
  925. {
  926. set_error(std::string("scan_number() - error invalid numeric token[2]: ") + std::string(begin,s_itr));
  927. token_list_.push_back(error(begin,s_itr));
  928. return;
  929. }
  930. else if (('+' != c) && ('-' != c) && !is_digit(c))
  931. {
  932. set_error(std::string("scan_number() - error invalid numeric token[3]: ") + std::string(begin,s_itr));
  933. token_list_.push_back(error(begin,s_itr));
  934. return;
  935. }
  936. e_found = true;
  937. ++s_itr;
  938. continue;
  939. }
  940. else if (e_found && is_sign(*s_itr))
  941. {
  942. if (post_e_sign_found)
  943. {
  944. set_error(std::string("scan_number() - error invalid numeric token[4]: ") + std::string(begin,s_itr));
  945. token_list_.push_back(error(begin,s_itr));
  946. return;
  947. }
  948. post_e_sign_found = true;
  949. ++s_itr;
  950. continue;
  951. }
  952. else if (('.' != (*s_itr)) && !is_digit(*s_itr))
  953. break;
  954. else
  955. ++s_itr;
  956. }
  957. T value = T(0.0);
  958. if (string_to_real(begin,s_itr,value))
  959. token_list_.push_back(token_t(token_t::number,value));
  960. else
  961. {
  962. set_error(std::string("scan_number() - error failed to parse token to real type. ") + std::string(begin,s_itr));
  963. token_list_.push_back(error(begin,s_itr));
  964. }
  965. return;
  966. }
  967. inline void scan_special_function()
  968. {
  969. const char* begin = s_itr;
  970. //$fdd(x,x,x) = 11 chars
  971. if (std::distance(s_itr,s_end) < 11)
  972. {
  973. set_error(std::string("scan_special_function() - error invalid special function [1]: ") + std::string(begin,s_itr));
  974. token_list_.push_back(error(begin,s_itr));
  975. return;
  976. }
  977. if (!(('$' == *s_itr) &&
  978. (imatch('f',*(s_itr + 1))) &&
  979. ('(' == *(s_itr + 4)) &&
  980. (is_digit(*(s_itr + 2))) &&
  981. (is_digit(*(s_itr + 3)))))
  982. {
  983. set_error(std::string("scan_special_function() - error invalid special function [2]: ") + std::string(begin,s_itr));
  984. token_list_.push_back(error(begin,s_itr));
  985. return;
  986. }
  987. s_itr += 4;
  988. token_list_.push_back(token_t(token_t::symbol,begin,s_itr));
  989. return;
  990. }
  991. #ifndef exprtk_disable_string_capabilities
  992. inline void scan_string()
  993. {
  994. const char* begin = s_itr + 1;
  995. if (std::distance(s_itr,s_end) < 2)
  996. {
  997. set_error(std::string("scan_string() - error invalid string [1]: ") + std::string(begin,s_itr));
  998. token_list_.push_back(error(begin,s_itr));
  999. return;
  1000. }
  1001. ++s_itr;
  1002. bool escaped = false;
  1003. std::string result_string;
  1004. while (s_end != s_itr)
  1005. {
  1006. if ('\\' == *s_itr)
  1007. {
  1008. escaped = true;
  1009. ++s_itr;
  1010. continue;
  1011. }
  1012. else if (!escaped)
  1013. {
  1014. if ('\'' == *s_itr)
  1015. break;
  1016. }
  1017. else if (escaped)
  1018. escaped = false;
  1019. result_string += *s_itr;
  1020. ++s_itr;
  1021. }
  1022. if (s_end == s_itr)
  1023. {
  1024. set_error(std::string("scan_string() - error string has not been terminated: ") + std::string(begin,s_itr));
  1025. token_list_.push_back(error(begin,s_itr));
  1026. return;
  1027. }
  1028. token_list_.push_back(token_t(token_t::string,result_string));
  1029. ++s_itr;
  1030. return;
  1031. }
  1032. #endif
  1033. inline void process_commutative_symbols()
  1034. {
  1035. if (token_list_.size() < 2)
  1036. return;
  1037. typename std::deque<token_t>::iterator itr = token_list_.begin() + 1;
  1038. typename std::deque<token_t>::iterator prev_itr = token_list_.begin();
  1039. while (token_list_.end() != itr)
  1040. {
  1041. token_t& curr_token = *itr;
  1042. token_t& prev_token = *prev_itr;
  1043. bool curr_token_not_reserved = !is_reserved_word(curr_token.value);
  1044. if (
  1045. //3x -> 3*x
  1046. ((token_t::symbol == curr_token.type) && (token_t::number == prev_token.type) && curr_token_not_reserved) ||
  1047. //3(x+1) -> 3*(x+1)
  1048. (is_left_bracket (static_cast<char>(curr_token.type)) && (token_t::number == prev_token.type)) ||
  1049. //(x+1)3 -> (x+1)*3
  1050. (is_right_bracket(static_cast<char>(prev_token.type)) && (token_t::number == curr_token.type)) ||
  1051. //(x+1)y -> (x+1)*y
  1052. (is_right_bracket(static_cast<char>(prev_token.type)) && (token_t::symbol == curr_token.type) && curr_token_not_reserved)
  1053. )
  1054. {
  1055. prev_itr = itr = token_list_.insert(itr,token_t(token_t::mul));
  1056. ++itr;
  1057. continue;
  1058. }
  1059. ++itr;
  1060. ++prev_itr;
  1061. }
  1062. }
  1063. inline void set_error(const std::string& s)
  1064. {
  1065. if (error_description_.empty())
  1066. {
  1067. error_description_ = s;
  1068. }
  1069. }
  1070. inline token_t error(const char* begin, const char* end) const
  1071. {
  1072. return token_t(token_t::error,begin,end);
  1073. }
  1074. private:
  1075. template <typename Iterator, typename Type>
  1076. static inline bool string_to_type_converter_impl_ref(Iterator& itr, const Iterator end, Type& result)
  1077. {
  1078. if (end == itr) return false;
  1079. Type t = 0;
  1080. bool negative = false;
  1081. if ('+' == (*itr))
  1082. ++itr;
  1083. else if ('-' == (*itr))
  1084. {
  1085. ++itr;
  1086. negative = true;
  1087. }
  1088. if (end == itr)
  1089. return false;
  1090. unsigned int digit_count = 0;
  1091. while ((end != itr) && ('0' == (*itr))) ++itr;
  1092. bool return_result = true;
  1093. while (end != itr)
  1094. {
  1095. const unsigned char digit = (*itr - '0');
  1096. if (digit > 9)
  1097. {
  1098. return_result = false;
  1099. break;
  1100. }
  1101. if ((++digit_count) <= numeric::numeric_info<Type>::bound_length)
  1102. {
  1103. t *= 10;
  1104. t += digit;
  1105. }
  1106. else
  1107. {
  1108. typedef unsigned long long int base_type;
  1109. static const base_type max_limit = +std::numeric_limits<Type>::max();
  1110. static const base_type min_limit = -std::numeric_limits<Type>::min();
  1111. base_type tmp = static_cast<base_type>(t) * 10 + digit;
  1112. if (negative && static_cast<base_type>(tmp) > min_limit)
  1113. return_result = false;
  1114. else if (static_cast<base_type>(tmp) > max_limit)
  1115. return_result = false;
  1116. t = static_cast<Type>(tmp);
  1117. }
  1118. ++itr;
  1119. }
  1120. result = static_cast<Type>((negative) ? -t : t);
  1121. return return_result;
  1122. }
  1123. template <typename Iterator>
  1124. static inline bool parse_nan(Iterator& itr, const Iterator end, T& t)
  1125. {
  1126. typedef typename std::iterator_traits<Iterator>::value_type type;
  1127. static const std::size_t nan_length = 3;
  1128. if (std::distance(itr,end) != static_cast<int>(nan_length))
  1129. return false;
  1130. if (static_cast<type>('n') == (*itr))
  1131. {
  1132. if ((static_cast<type>('a') != *(itr + 1)) || (static_cast<type>('n') != *(itr + 2)))
  1133. {
  1134. return false;
  1135. }
  1136. }
  1137. else if ((static_cast<type>('A') != *(itr + 1)) || (static_cast<type>('N') != *(itr + 2)))
  1138. {
  1139. return false;
  1140. }
  1141. t = std::numeric_limits<T>::quiet_NaN();
  1142. return true;
  1143. }
  1144. template <typename Iterator>
  1145. static inline bool parse_inf(Iterator& itr, const Iterator end, T& t, bool negative)
  1146. {
  1147. static const char inf_uc[] = "INFINITY";
  1148. static const char inf_lc[] = "infinity";
  1149. static const std::size_t inf_length = 8;
  1150. const std::size_t length = std::distance(itr,end);
  1151. if ((3 != length) && (inf_length != length))
  1152. return false;
  1153. const char* inf_itr = ('i' == (*itr)) ? inf_lc : inf_uc;
  1154. while (end != itr)
  1155. {
  1156. if (*inf_itr == static_cast<char>(*itr))
  1157. {
  1158. ++itr;
  1159. ++inf_itr;
  1160. continue;
  1161. }
  1162. else
  1163. return false;
  1164. }
  1165. if (negative)
  1166. t = -std::numeric_limits<T>::infinity();
  1167. else
  1168. t = std::numeric_limits<T>::infinity();
  1169. return true;
  1170. }
  1171. template <typename Iterator>
  1172. inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t)
  1173. {
  1174. if (end == itr_external) return false;
  1175. Iterator itr = itr_external;
  1176. double d = 0.0;
  1177. bool negative = false;
  1178. if ('+' == (*itr))
  1179. ++itr;
  1180. else if ('-' == (*itr))
  1181. {
  1182. ++itr;
  1183. negative = true;
  1184. }
  1185. if (end == itr)
  1186. return false;
  1187. if (('I' <= (*itr)) && ((*itr) <= 'n'))
  1188. {
  1189. if (('i' == (*itr)) || ('I' == (*itr)))
  1190. {
  1191. return parse_inf(itr,end,t,negative);
  1192. }
  1193. else if (('n' == (*itr)) || ('N' == (*itr)))
  1194. {
  1195. return parse_nan(itr,end,t);
  1196. }
  1197. else
  1198. return false;
  1199. }
  1200. bool instate = false;
  1201. int pre_decimal = 0;
  1202. if ('.' != (*itr))
  1203. {
  1204. const Iterator curr = itr;
  1205. while ((end != itr) && ('0' == (*itr))) ++itr;
  1206. const Iterator post_zero_cull_itr = itr;
  1207. unsigned char digit = 0;
  1208. #define parse_digit_1 \
  1209. if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
  1210. #define parse_digit_2 \
  1211. if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
  1212. while (end != itr)
  1213. {
  1214. parse_digit_1
  1215. parse_digit_1
  1216. parse_digit_1
  1217. parse_digit_1
  1218. parse_digit_1
  1219. parse_digit_1
  1220. parse_digit_1
  1221. parse_digit_2
  1222. }
  1223. #undef parse_digit_1
  1224. #undef parse_digit_2
  1225. if (curr != itr) instate = true;
  1226. pre_decimal = static_cast<int>(std::distance(post_zero_cull_itr,itr));
  1227. }
  1228. int exponent = 0;
  1229. if (end != itr)
  1230. {
  1231. if ('.' == (*itr))
  1232. {
  1233. ++itr;
  1234. const Iterator curr = itr;
  1235. unsigned char digit = 0;
  1236. #define parse_digit_1 \
  1237. if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; if (end == ++itr) break; \
  1238. #define parse_digit_2 \
  1239. if ((digit = static_cast<unsigned char>((*itr) - '0')) < 10) { d *= 10.0; d += digit; } else break; ++itr;\
  1240. while (end != itr)
  1241. {
  1242. parse_digit_1
  1243. parse_digit_1
  1244. parse_digit_1
  1245. parse_digit_1
  1246. parse_digit_1
  1247. parse_digit_1
  1248. parse_digit_1
  1249. parse_digit_2
  1250. }
  1251. #undef parse_digit_1
  1252. #undef parse_digit_2
  1253. if (curr != itr) instate = true;
  1254. exponent -= static_cast<int>(std::distance(curr,itr));
  1255. }
  1256. if (end != itr)
  1257. {
  1258. typename std::iterator_traits<Iterator>::value_type c = (*itr);
  1259. if (('e' == c) || ('E' == c))
  1260. {
  1261. ++itr;
  1262. int exp = 0;
  1263. if (!string_to_type_converter_impl_ref(itr,end,exp))
  1264. {
  1265. if (end == itr)
  1266. return false;
  1267. else
  1268. c = (*itr);
  1269. }
  1270. if (
  1271. (exp < numeric::numeric_info<T>::min_exp) ||
  1272. (numeric::numeric_info<T>::max_exp < exp)
  1273. )
  1274. return false;
  1275. exponent += exp;
  1276. }
  1277. if (('f' == c) || ('F' == c) || ('l' == c) || ('L' == c))
  1278. ++itr;
  1279. else if ('#' == c)
  1280. {
  1281. ++itr;
  1282. if (end == itr)
  1283. return false;
  1284. if ((10.0 != d) || (exponent != -1))
  1285. return false;
  1286. if (('I' <= (*itr)) && ((*itr) <= 'n'))
  1287. {
  1288. if (('i' == (*itr)) || ('I' == (*itr)))
  1289. {
  1290. return parse_inf(itr,end,t,negative);
  1291. }
  1292. else if (('n' == (*itr)) || ('N' == (*itr)))
  1293. {
  1294. return parse_nan(itr,end,t);
  1295. }
  1296. else
  1297. return false;
  1298. }
  1299. return false;
  1300. }
  1301. }
  1302. }
  1303. if ((end != itr) || (!instate))
  1304. return false;
  1305. if (0 != exponent)
  1306. {
  1307. if (
  1308. (std::numeric_limits<T>::max_exponent10 < (exponent + pre_decimal)) ||
  1309. (std::numeric_limits<T>::min_exponent10 > (exponent + pre_decimal))
  1310. )
  1311. {
  1312. return false;
  1313. }
  1314. const int e = std::abs(exponent);
  1315. static const double fract10[] =
  1316. {
  1317. 0.0,
  1318. 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,
  1319. 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,
  1320. 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,
  1321. 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,
  1322. 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,
  1323. 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,
  1324. 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,
  1325. 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,
  1326. 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,
  1327. 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,
  1328. 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,
  1329. 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,
  1330. 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,
  1331. 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,
  1332. 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,
  1333. 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,
  1334. 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,
  1335. 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,
  1336. 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,
  1337. 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,
  1338. 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,
  1339. 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,
  1340. 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,
  1341. 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,
  1342. 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,
  1343. 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,
  1344. 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,
  1345. 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,
  1346. 1.0E+301, 1.0E+302, 1.0E+303, 1.0E+304, 1.0E+305, 1.0E+306, 1.0E+307, 1.0E+308
  1347. };
  1348. static const std::size_t fract10_size = sizeof(fract10) / sizeof(double);
  1349. if (d != 0.0)
  1350. {
  1351. if (static_cast<std::size_t>(e) < fract10_size)
  1352. {
  1353. if (exponent > 0)
  1354. d *= fract10[e];
  1355. else
  1356. d /= fract10[e];
  1357. }
  1358. else
  1359. d *= std::pow(10.0, 1.0 * exponent);
  1360. }
  1361. }
  1362. t = static_cast<T>((negative) ? -d : d);
  1363. return true;
  1364. }
  1365. std::string error_description_;
  1366. std::deque<token_t> token_list_;
  1367. typename std::deque<token_t>::iterator token_itr_;
  1368. typename std::deque<token_t>::iterator store_token_itr_;
  1369. token_t eof_token_;
  1370. const char* s_itr;
  1371. const char* s_end;
  1372. };
  1373. enum operator_type
  1374. {
  1375. e_default,
  1376. e_add ,
  1377. e_sub ,
  1378. e_mul ,
  1379. e_div ,
  1380. e_mod ,
  1381. e_pow ,
  1382. e_atan2 ,
  1383. e_min ,
  1384. e_max ,
  1385. e_avg ,
  1386. e_sum ,
  1387. e_prod ,
  1388. e_lt ,
  1389. e_lte ,
  1390. e_eq ,
  1391. e_equal ,
  1392. e_ne ,
  1393. e_nequal ,
  1394. e_gte ,
  1395. e_gt ,
  1396. e_and ,
  1397. e_nand ,
  1398. e_or ,
  1399. e_nor ,
  1400. e_xor ,
  1401. e_shr ,
  1402. e_shl ,
  1403. e_abs ,
  1404. e_acos ,
  1405. e_asin ,
  1406. e_atan ,
  1407. e_ceil ,
  1408. e_cos ,
  1409. e_cosh ,
  1410. e_exp ,
  1411. e_floor ,
  1412. e_log ,
  1413. e_log10 ,
  1414. e_logn ,
  1415. e_neg ,
  1416. e_pos ,
  1417. e_round ,
  1418. e_roundn ,
  1419. e_root ,
  1420. e_sqrt ,
  1421. e_sin ,
  1422. e_sinh ,
  1423. e_sec ,
  1424. e_csc ,
  1425. e_tan ,
  1426. e_tanh ,
  1427. e_cot ,
  1428. e_clamp ,
  1429. e_inrange,
  1430. e_sgn ,
  1431. e_r2d ,
  1432. e_d2r ,
  1433. e_d2g ,
  1434. e_g2d ,
  1435. e_hyp ,
  1436. e_notl ,
  1437. e_erf ,
  1438. e_erfc ,
  1439. e_assign ,
  1440. e_in ,
  1441. e_like ,
  1442. e_ilike ,
  1443. // Do not add new functions/operators after this point.
  1444. e_sf00 = 1000,
  1445. e_sf01 = 1001,
  1446. e_sf02 = 1002,
  1447. e_sf03 = 1003,
  1448. e_sf04 = 1004,
  1449. e_sf05 = 1005,
  1450. e_sf06 = 1006,
  1451. e_sf07 = 1007,
  1452. e_sf08 = 1008,
  1453. e_sf09 = 1009,
  1454. e_sf10 = 1010,
  1455. e_sf11 = 1011,
  1456. e_sf12 = 1012,
  1457. e_sf13 = 1013,
  1458. e_sf14 = 1014,
  1459. e_sf15 = 1015,
  1460. e_sf16 = 1016,
  1461. e_sf17 = 1017,
  1462. e_sf18 = 1018,
  1463. e_sf19 = 1019,
  1464. e_sf20 = 1020,
  1465. e_sf21 = 1021,
  1466. e_sf22 = 1022,
  1467. e_sf23 = 1023,
  1468. e_sf24 = 1024,
  1469. e_sf25 = 1025,
  1470. e_sf26 = 1026,
  1471. e_sf27 = 1027,
  1472. e_sf28 = 1028,
  1473. e_sf29 = 1029,
  1474. e_sf30 = 1030,
  1475. e_sf31 = 1031,
  1476. e_sf32 = 1032,
  1477. e_sf33 = 1033,
  1478. e_sf34 = 1034,
  1479. e_sf35 = 1035,
  1480. e_sf36 = 1036,
  1481. e_sf37 = 1037,
  1482. e_sf38 = 1038,
  1483. e_sf39 = 1039,
  1484. e_sf40 = 1040,
  1485. e_sf41 = 1041,
  1486. e_sf42 = 1042,
  1487. e_sf43 = 1043,
  1488. e_sf44 = 1044,
  1489. e_sf45 = 1045,
  1490. e_sf46 = 1046,
  1491. e_sf47 = 1047,
  1492. e_sf48 = 1048,
  1493. e_sf49 = 1049,
  1494. e_sf50 = 1050,
  1495. e_sf51 = 1051,
  1496. e_sf52 = 1052,
  1497. e_sf53 = 1053,
  1498. e_sf54 = 1054,
  1499. e_sf55 = 1055,
  1500. e_sf56 = 1056,
  1501. e_sf57 = 1057,
  1502. e_sf58 = 1058
  1503. };
  1504. namespace numeric
  1505. {
  1506. namespace details
  1507. {
  1508. template <typename T>
  1509. inline T process_impl(const operator_type operation, const T& arg, real_type_tag)
  1510. {
  1511. switch (operation)
  1512. {
  1513. case e_abs : return numeric::abs (arg);
  1514. case e_acos : return numeric::acos (arg);
  1515. case e_asin : return numeric::asin (arg);
  1516. case e_atan : return numeric::atan (arg);
  1517. case e_ceil : return numeric::ceil (arg);
  1518. case e_cos : return numeric::cos (arg);
  1519. case e_cosh : return numeric::cosh (arg);
  1520. case e_exp : return numeric::exp (arg);
  1521. case e_floor : return numeric::floor(arg);
  1522. case e_log : return numeric::log (arg);
  1523. case e_log10 : return numeric::log10(arg);
  1524. case e_neg : return numeric::neg (arg);
  1525. case e_pos : return numeric::pos (arg);
  1526. case e_round : return numeric::round(arg);
  1527. case e_sin : return numeric::sin (arg);
  1528. case e_sinh : return numeric::sinh (arg);
  1529. case e_sqrt : return numeric::sqrt (arg);
  1530. case e_tan : return numeric::tan (arg);
  1531. case e_tanh : return numeric::tanh (arg);
  1532. case e_cot : return numeric::cot (arg);
  1533. case e_sec : return numeric::sec (arg);
  1534. case e_csc : return numeric::csc (arg);
  1535. case e_r2d : return numeric::r2d (arg);
  1536. case e_d2r : return numeric::d2r (arg);
  1537. case e_d2g : return numeric::d2g (arg);
  1538. case e_g2d : return numeric::g2d (arg);
  1539. case e_notl : return numeric::notl (arg);
  1540. case e_sgn : return numeric::sgn (arg);
  1541. case e_erf : return numeric::erf (arg);
  1542. case e_erfc : return numeric::erfc (arg);
  1543. default : return std::numeric_limits<T>::quiet_NaN();
  1544. }
  1545. }
  1546. template <typename T>
  1547. inline T process_impl(const operator_type operation, const T& arg, int_type_tag)
  1548. {
  1549. switch (operation)
  1550. {
  1551. case e_abs : return numeric::abs (arg);
  1552. case e_exp : return numeric::exp (arg);
  1553. case e_log : return numeric::log (arg);
  1554. case e_log10 : return numeric::log10(arg);
  1555. case e_neg : return numeric::neg (arg);
  1556. case e_pos : return numeric::pos (arg);
  1557. case e_sqrt : return numeric::sqrt (arg);
  1558. case e_notl : return numeric::notl (arg);
  1559. case e_sgn : return numeric::sgn (arg);
  1560. default : return std::numeric_limits<T>::quiet_NaN();
  1561. }
  1562. }
  1563. template <typename T>
  1564. inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, real_type_tag)
  1565. {
  1566. switch (operation)
  1567. {
  1568. case e_add : return (arg0 + arg1);
  1569. case e_sub : return (arg0 - arg1);
  1570. case e_mul : return (arg0 * arg1);
  1571. case e_div : return (arg0 / arg1);
  1572. case e_mod : return modulus<T>(arg0,arg1);
  1573. case e_pow : return pow<T>(arg0,arg1);
  1574. case e_atan2 : return atan2<T>(arg0,arg1);
  1575. case e_min : return std::min<T>(arg0,arg1);
  1576. case e_max : return std::max<T>(arg0,arg1);
  1577. case e_logn : return logn<T>(arg0,arg1);
  1578. case e_lt : return (arg0 < arg1) ? T(1) : T(0);
  1579. case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
  1580. case e_eq : return (arg0 == arg1) ? T(1) : T(0);
  1581. case e_ne : return (arg0 != arg1) ? T(1) : T(0);
  1582. case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
  1583. case e_gt : return (arg0 > arg1) ? T(1) : T(0);
  1584. case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
  1585. case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
  1586. case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
  1587. case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
  1588. case e_xor : return (arg0 != arg1) ? T(1) : T(0);
  1589. case e_root : return root<T>(arg0,arg1);
  1590. case e_roundn : return roundn<T>(arg0,arg1);
  1591. case e_equal : return equal<T>(arg0,arg1);
  1592. case e_nequal : return nequal<T>(arg0,arg1);
  1593. case e_hyp : return hyp<T>(arg0,arg1);
  1594. case e_avg : return (arg0 + arg1)/T(2);
  1595. case e_sum : return (arg0 + arg1);
  1596. case e_prod : return (arg0 * arg1);
  1597. case e_shr : return shr<T>(arg0,arg1);
  1598. case e_shl : return shl<T>(arg0,arg1);
  1599. default : return std::numeric_limits<T>::quiet_NaN();
  1600. }
  1601. }
  1602. template <typename T>
  1603. inline T process_impl(const operator_type operation, const T& arg0, const T& arg1, int_type_tag)
  1604. {
  1605. switch (operation)
  1606. {
  1607. case e_add : return (arg0 + arg1);
  1608. case e_sub : return (arg0 - arg1);
  1609. case e_mul : return (arg0 * arg1);
  1610. case e_div : return (arg0 / arg1);
  1611. case e_mod : return arg0 % arg1;
  1612. case e_pow : return pow<T>(arg0,arg1);
  1613. case e_min : return std::min<T>(arg0,arg1);
  1614. case e_max : return std::max<T>(arg0,arg1);
  1615. case e_logn : return logn<T>(arg0,arg1);
  1616. case e_lt : return (arg0 < arg1) ? T(1) : T(0);
  1617. case e_lte : return (arg0 <= arg1) ? T(1) : T(0);
  1618. case e_eq : return (arg0 == arg1) ? T(1) : T(0);
  1619. case e_ne : return (arg0 != arg1) ? T(1) : T(0);
  1620. case e_gte : return (arg0 >= arg1) ? T(1) : T(0);
  1621. case e_gt : return (arg0 > arg1) ? T(1) : T(0);
  1622. case e_and : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(1) : T(0);
  1623. case e_nand : return ((arg0 != T(0)) && (arg1 != T(0))) ? T(0) : T(1);
  1624. case e_or : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(1) : T(0);
  1625. case e_nor : return ((arg0 != T(0)) || (arg1 != T(0))) ? T(0) : T(1);
  1626. case e_xor : return arg0 ^ arg1;
  1627. case e_root : return root<T>(arg0,arg1);
  1628. case e_equal : return arg0 == arg1;
  1629. case e_nequal : return arg0 != arg1;
  1630. case e_hyp : return hyp<T>(arg0,arg1);
  1631. case e_avg : return (arg0 + arg1) >> 1;
  1632. case e_sum : return (arg0 + arg1);
  1633. case e_prod : return (arg0 * arg1);
  1634. case e_shr : return arg0 >> arg1;
  1635. case e_shl : return arg0 << arg1;
  1636. default : return std::numeric_limits<T>::quiet_NaN();
  1637. }
  1638. }
  1639. }
  1640. template <typename T>
  1641. inline T process(const operator_type operation, const T& arg)
  1642. {
  1643. typename details::number_type<T>::type num_type;
  1644. return details::process_impl<T>(operation,arg,num_type);
  1645. }
  1646. template <typename T>
  1647. inline T process(const operator_type operation, const T& arg0, const T& arg1)
  1648. {
  1649. typename details::number_type<T>::type num_type;
  1650. return details::process_impl<T>(operation,arg0,arg1,num_type);
  1651. }
  1652. }
  1653. template <typename T>
  1654. class expression_node
  1655. {
  1656. public:
  1657. enum node_type
  1658. {
  1659. e_none ,
  1660. e_constant ,
  1661. e_unary ,
  1662. e_binary ,
  1663. e_trinary ,
  1664. e_quaternary ,
  1665. e_quinary ,
  1666. e_senary ,
  1667. e_conditional ,
  1668. e_while ,
  1669. e_variable ,
  1670. e_stringvar ,
  1671. e_stringconst ,
  1672. e_function ,
  1673. e_add ,
  1674. e_sub ,
  1675. e_mul ,
  1676. e_div ,
  1677. e_mod ,
  1678. e_pow ,
  1679. e_lt ,
  1680. e_lte ,
  1681. e_gt ,
  1682. e_gte ,
  1683. e_eq ,
  1684. e_ne ,
  1685. e_and ,
  1686. e_nand ,
  1687. e_or ,
  1688. e_nor ,
  1689. e_xor ,
  1690. e_in ,
  1691. e_like ,
  1692. e_ilike ,
  1693. e_inranges ,
  1694. e_ipow ,
  1695. e_vov ,
  1696. e_abs ,
  1697. e_acos ,
  1698. e_asin ,
  1699. e_atan ,
  1700. e_ceil ,
  1701. e_cos ,
  1702. e_cosh ,
  1703. e_exp ,
  1704. e_floor ,
  1705. e_log ,
  1706. e_log10 ,
  1707. e_neg ,
  1708. e_pos ,
  1709. e_round ,
  1710. e_sin ,
  1711. e_sinh ,
  1712. e_sqrt ,
  1713. e_tan ,
  1714. e_tanh ,
  1715. e_cot ,
  1716. e_sec ,
  1717. e_csc ,
  1718. e_r2d ,
  1719. e_d2r ,
  1720. e_d2g ,
  1721. e_g2d ,
  1722. e_notl ,
  1723. e_sgn ,
  1724. e_erf ,
  1725. e_erfc
  1726. };
  1727. typedef T value_type;
  1728. typedef expression_node<T>* expression_ptr;
  1729. virtual ~expression_node()
  1730. {}
  1731. virtual inline T value() const
  1732. {
  1733. return std::numeric_limits<T>::quiet_NaN();
  1734. }
  1735. virtual inline bool result() const
  1736. {
  1737. return (T(1.0) == value());
  1738. }
  1739. virtual inline expression_node<T>* branch(const std::size_t& index = 0) const
  1740. {
  1741. return reinterpret_cast<expression_ptr>(index * 0);
  1742. }
  1743. virtual inline node_type type() const
  1744. {
  1745. return e_none;
  1746. }
  1747. };
  1748. template <typename T>
  1749. inline bool is_unary_node(const expression_node<T>* node)
  1750. {
  1751. return (details::expression_node<T>::e_unary == node->type());
  1752. }
  1753. template <typename T>
  1754. inline bool is_binary_node(const expression_node<T>* node)
  1755. {
  1756. return (details::expression_node<T>::e_binary == node->type());
  1757. }
  1758. template <typename T>
  1759. inline bool is_variable_node(const expression_node<T>* node)
  1760. {
  1761. return (details::expression_node<T>::e_variable == node->type());
  1762. }
  1763. template <typename T>
  1764. inline bool is_constant_node(const expression_node<T>* node)
  1765. {
  1766. return (details::expression_node<T>::e_constant == node->type());
  1767. }
  1768. template <typename T>
  1769. inline bool is_function(const expression_node<T>* node)
  1770. {
  1771. return (details::expression_node<T>::e_function == node->type());
  1772. }
  1773. template <typename T>
  1774. inline bool branch_deletable(expression_node<T>* node)
  1775. {
  1776. return !is_variable_node(node);
  1777. }
  1778. template <typename T>
  1779. class literal_node : public expression_node<T>
  1780. {
  1781. public:
  1782. explicit literal_node(const T& value)
  1783. : value_(value)
  1784. {}
  1785. inline T value() const
  1786. {
  1787. return value_;
  1788. }
  1789. inline typename expression_node<T>::node_type type() const
  1790. {
  1791. return expression_node<T>::e_constant;
  1792. }
  1793. inline expression_node<T>* branch(const std::size_t& index = 0) const
  1794. {
  1795. return reinterpret_cast<expression_node<T>*>(index * 0);
  1796. }
  1797. private:
  1798. T value_;
  1799. };
  1800. template <typename T>
  1801. class string_literal_node : public expression_node<T>
  1802. {
  1803. public:
  1804. explicit string_literal_node(const std::string& value)
  1805. : value_(value)
  1806. {}
  1807. inline T value() const
  1808. {
  1809. return std::numeric_limits<T>::quiet_NaN();
  1810. }
  1811. inline typename expression_node<T>::node_type type() const
  1812. {
  1813. return expression_node<T>::e_stringconst;
  1814. }
  1815. inline expression_node<T>* branch(const std::size_t& index = 0) const
  1816. {
  1817. return reinterpret_cast<expression_node<T>*>(index * 0);
  1818. }
  1819. inline std::string str()
  1820. {
  1821. return value_;
  1822. }
  1823. private:
  1824. string_literal_node(const string_literal_node<T>&);
  1825. string_literal_node<T>& operator=(const string_literal_node<T>&);
  1826. const std::string value_;
  1827. };
  1828. template <typename T>
  1829. class unary_node : public expression_node<T>
  1830. {
  1831. public:
  1832. typedef expression_node<T>* expression_ptr;
  1833. unary_node(const operator_type& operation,
  1834. expression_ptr branch)
  1835. : operation_(operation),
  1836. branch_(branch),
  1837. branch_deletable_(branch_deletable(branch_))
  1838. {}
  1839. ~unary_node()
  1840. {
  1841. if (branch_ && branch_deletable_)
  1842. {
  1843. delete branch_;
  1844. branch_ = 0;
  1845. }
  1846. }
  1847. inline T value() const
  1848. {
  1849. const T arg = branch_->value();
  1850. return numeric::process<T>(operation_,arg);
  1851. }
  1852. inline typename expression_node<T>::node_type type() const
  1853. {
  1854. return expression_node<T>::e_unary;
  1855. }
  1856. inline operator_type operation() const
  1857. {
  1858. return operation_;
  1859. }
  1860. inline expression_node<T>* branch(const std::size_t& index = 0) const
  1861. {
  1862. if (0 == index)
  1863. return branch_;
  1864. else
  1865. return reinterpret_cast<expression_ptr>(0);
  1866. }
  1867. private:
  1868. operator_type operation_;
  1869. expression_ptr branch_;
  1870. bool branch_deletable_;
  1871. };
  1872. template<typename T, std::size_t D, bool B>
  1873. struct construct_branch_pair
  1874. {
  1875. template <std::size_t N>
  1876. static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*)
  1877. {}
  1878. };
  1879. template<typename T, std::size_t D>
  1880. struct construct_branch_pair<T,D,true>
  1881. {
  1882. template <std::size_t N>
  1883. static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b)
  1884. { if (b) branch[D] = std::make_pair(b,branch_deletable(b)); }
  1885. };
  1886. template <std::size_t N, typename T>
  1887. inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N],
  1888. expression_node<T>* b0,
  1889. expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0),
  1890. expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0),
  1891. expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0),
  1892. expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0),
  1893. expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0),
  1894. expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0),
  1895. expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0),
  1896. expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0),
  1897. expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0))
  1898. {
  1899. construct_branch_pair<T,0,(N > 0)>::process(branch,b0);
  1900. construct_branch_pair<T,1,(N > 1)>::process(branch,b1);
  1901. construct_branch_pair<T,2,(N > 2)>::process(branch,b2);
  1902. construct_branch_pair<T,3,(N > 3)>::process(branch,b3);
  1903. construct_branch_pair<T,4,(N > 4)>::process(branch,b4);
  1904. construct_branch_pair<T,5,(N > 5)>::process(branch,b5);
  1905. construct_branch_pair<T,6,(N > 6)>::process(branch,b6);
  1906. construct_branch_pair<T,7,(N > 7)>::process(branch,b7);
  1907. construct_branch_pair<T,8,(N > 8)>::process(branch,b8);
  1908. construct_branch_pair<T,9,(N > 9)>::process(branch,b9);
  1909. }
  1910. template <typename T, std::size_t N>
  1911. struct cleanup_branches
  1912. {
  1913. static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N])
  1914. {
  1915. for (std::size_t i = 0; i < N; ++i)
  1916. {
  1917. if (branch[i].first && branch[i].second)
  1918. {
  1919. delete branch[i].first;
  1920. branch[i].first = 0;
  1921. }
  1922. }
  1923. }
  1924. };
  1925. template <typename T>
  1926. class binary_node : public expression_node<T>
  1927. {
  1928. public:
  1929. typedef expression_node<T>* expression_ptr;
  1930. typedef std::pair<expression_ptr,bool> branch_t;
  1931. binary_node(const operator_type& operation,
  1932. expression_ptr branch0,
  1933. expression_ptr branch1)
  1934. : operation_(operation)
  1935. {
  1936. init_branches<2>(branch_,branch0,branch1);
  1937. }
  1938. ~binary_node()
  1939. {
  1940. cleanup_branches<T,2>::execute(branch_);
  1941. }
  1942. inline T value() const
  1943. {
  1944. const T arg0 = branch_[0].first->value();
  1945. const T arg1 = branch_[1].first->value();
  1946. return numeric::process<T>(operation_,arg0,arg1);
  1947. }
  1948. inline typename expression_node<T>::node_type type() const
  1949. {
  1950. return expression_node<T>::e_binary;
  1951. }
  1952. inline operator_type operation() const
  1953. {
  1954. return operation_;
  1955. }
  1956. inline expression_node<T>* branch(const std::size_t& index = 0) const
  1957. {
  1958. if (0 == index)
  1959. return branch_[0].first;
  1960. else if (1 == index)
  1961. return branch_[1].first;
  1962. else
  1963. return reinterpret_cast<expression_ptr>(0);
  1964. }
  1965. protected:
  1966. operator_type operation_;
  1967. branch_t branch_[2];
  1968. };
  1969. template <typename T>
  1970. class trinary_node : public expression_node<T>
  1971. {
  1972. public:
  1973. typedef expression_node<T>* expression_ptr;
  1974. typedef std::pair<expression_ptr,bool> branch_t;
  1975. trinary_node(const operator_type& operation,
  1976. expression_ptr branch0,
  1977. expression_ptr branch1,
  1978. expression_ptr branch2)
  1979. : operation_(operation)
  1980. {
  1981. init_branches<3>(branch_,branch0,branch1,branch2);
  1982. }
  1983. ~trinary_node()
  1984. {
  1985. cleanup_branches<T,3>::execute(branch_);
  1986. }
  1987. inline T value() const
  1988. {
  1989. const T arg0 = branch_[0].first->value();
  1990. const T arg1 = branch_[1].first->value();
  1991. const T arg2 = branch_[2].first->value();
  1992. switch (operation_)
  1993. {
  1994. case e_clamp : return (arg1 < arg0) ? arg0 : (arg1 > arg2 ? arg2 : arg1);
  1995. case e_inrange : return (arg1 < arg0) ? T(0) : ((arg1 > arg2) ? T(0) : T(1));
  1996. case e_min : return std::min<T>(std::min<T>(arg0,arg1),arg2);
  1997. case e_max : return std::max<T>(std::max<T>(arg0,arg1),arg2);
  1998. case e_avg : return (arg0 + arg1 + arg2) / T(3.0);
  1999. case e_sum : return (arg0 + arg1 + arg2);
  2000. case e_prod : return (arg0 * arg1 * arg2);
  2001. default : return std::numeric_limits<T>::quiet_NaN();
  2002. }
  2003. }
  2004. inline typename expression_node<T>::node_type type() const
  2005. {
  2006. return expression_node<T>::e_trinary;
  2007. }
  2008. protected:
  2009. operator_type operation_;
  2010. branch_t branch_[3];
  2011. };
  2012. template <typename T>
  2013. class quaternary_node : public expression_node<T>
  2014. {
  2015. public:
  2016. typedef expression_node<T>* expression_ptr;
  2017. typedef std::pair<expression_ptr,bool> branch_t;
  2018. quaternary_node(const operator_type& operation,
  2019. expression_ptr branch0,
  2020. expression_ptr branch1,
  2021. expression_ptr branch2,
  2022. expression_ptr branch3)
  2023. : operation_(operation)
  2024. {
  2025. init_branches<4>(branch_,branch0,branch1,branch2,branch3);
  2026. }
  2027. ~quaternary_node()
  2028. {
  2029. cleanup_branches<T,4>::execute(branch_);
  2030. }
  2031. inline T value() const
  2032. {
  2033. const T arg0 = branch_[0].first->value();
  2034. const T arg1 = branch_[1].first->value();
  2035. const T arg2 = branch_[2].first->value();
  2036. const T arg3 = branch_[3].first->value();
  2037. switch (operation_)
  2038. {
  2039. case e_min : return std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3));
  2040. case e_max : return std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3));
  2041. case e_avg : return (arg0 + arg1 + arg2 + arg3) / T(4.0);
  2042. case e_sum : return (arg0 + arg1 + arg2 + arg3);
  2043. case e_prod : return (arg0 * arg1 * arg2 * arg3);
  2044. default : return std::numeric_limits<T>::quiet_NaN();
  2045. }
  2046. }
  2047. inline typename expression_node<T>::node_type type() const
  2048. {
  2049. return expression_node<T>::e_quaternary;
  2050. }
  2051. protected:
  2052. operator_type operation_;
  2053. branch_t branch_[4];
  2054. };
  2055. template <typename T>
  2056. class quinary_node : public expression_node<T>
  2057. {
  2058. public:
  2059. typedef expression_node<T>* expression_ptr;
  2060. typedef std::pair<expression_ptr,bool> branch_t;
  2061. quinary_node(const operator_type& operation,
  2062. expression_ptr branch0,
  2063. expression_ptr branch1,
  2064. expression_ptr branch2,
  2065. expression_ptr branch3,
  2066. expression_ptr branch4)
  2067. : operation_(operation)
  2068. {
  2069. init_branches<5>(branch_,branch0,branch1,branch2,branch3,branch4);
  2070. }
  2071. ~quinary_node()
  2072. {
  2073. cleanup_branches<T,5>::execute(branch_);
  2074. }
  2075. inline T value() const
  2076. {
  2077. const T arg0 = branch_[0].first->value();
  2078. const T arg1 = branch_[1].first->value();
  2079. const T arg2 = branch_[2].first->value();
  2080. const T arg3 = branch_[3].first->value();
  2081. const T arg4 = branch_[4].first->value();
  2082. switch (operation_)
  2083. {
  2084. case e_min : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),arg4);
  2085. case e_max : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),arg4);
  2086. case e_avg : return (arg0 + arg1 + arg2 + arg3 + arg4) / T(5.0);
  2087. case e_sum : return (arg0 + arg1 + arg2 + arg3 + arg4);
  2088. case e_prod : return (arg0 * arg1 * arg2 * arg3 * arg4);
  2089. default : return std::numeric_limits<T>::quiet_NaN();
  2090. }
  2091. }
  2092. inline typename expression_node<T>::node_type type() const
  2093. {
  2094. return expression_node<T>::e_quinary;
  2095. }
  2096. private:
  2097. operator_type operation_;
  2098. branch_t branch_[5];
  2099. };
  2100. template <typename T>
  2101. class senary_node : public expression_node<T>
  2102. {
  2103. public:
  2104. typedef expression_node<T>* expression_ptr;
  2105. typedef std::pair<expression_ptr,bool> branch_t;
  2106. senary_node(const operator_type& operation,
  2107. expression_ptr branch0,
  2108. expression_ptr branch1,
  2109. expression_ptr branch2,
  2110. expression_ptr branch3,
  2111. expression_ptr branch4,
  2112. expression_ptr branch5)
  2113. : operation_(operation)
  2114. {
  2115. init_branches<6>(branch_,branch0,branch1,branch2,branch3,branch4,branch5);
  2116. }
  2117. ~senary_node()
  2118. {
  2119. cleanup_branches<T,6>::execute(branch_);
  2120. }
  2121. inline T value() const
  2122. {
  2123. const T arg0 = branch_[0].first->value();
  2124. const T arg1 = branch_[1].first->value();
  2125. const T arg2 = branch_[2].first->value();
  2126. const T arg3 = branch_[3].first->value();
  2127. const T arg4 = branch_[4].first->value();
  2128. const T arg5 = branch_[5].first->value();
  2129. switch (operation_)
  2130. {
  2131. case e_min : return std::min<T>(std::min<T>(std::min<T>(arg0,arg1),std::min<T>(arg2,arg3)),std::min<T>(arg4,arg5));
  2132. case e_max : return std::max<T>(std::max<T>(std::max<T>(arg0,arg1),std::max<T>(arg2,arg3)),std::max<T>(arg4,arg5));
  2133. case e_avg : return (arg0 + arg1 + arg2 + arg3 + arg4 + arg5) / T(6.0);
  2134. case e_sum : return (arg0 + arg1 + arg2 + arg3 + arg4 + arg5);
  2135. case e_prod : return (arg0 * arg1 * arg2 * arg3 * arg4 * arg5);
  2136. case e_default :
  2137. default : return std::numeric_limits<T>::quiet_NaN();
  2138. }
  2139. }
  2140. inline typename expression_node<T>::node_type type() const
  2141. {
  2142. return expression_node<T>::e_senary;
  2143. }
  2144. private:
  2145. operator_type operation_;
  2146. branch_t branch_[6];
  2147. };
  2148. template <typename T>
  2149. class conditional_node : public expression_node<T>
  2150. {
  2151. public:
  2152. typedef expression_node<T>* expression_ptr;
  2153. conditional_node(expression_ptr test,
  2154. expression_ptr consequent,
  2155. expression_ptr alternative)
  2156. : test_(test),
  2157. consequent_(consequent),
  2158. alternative_(alternative),
  2159. test_deletable_(!is_variable_node(test_)),
  2160. consequent_deletable_(!is_variable_node(consequent_)),
  2161. alternative_deletable_(!is_variable_node(alternative_))
  2162. {}
  2163. ~conditional_node()
  2164. {
  2165. if (test_ && test_deletable_) delete test_;
  2166. if (consequent_ && consequent_deletable_) delete consequent_;
  2167. if (alternative_ && alternative_deletable_) delete alternative_;
  2168. }
  2169. inline T value() const
  2170. {
  2171. if (test_->value() != 0)
  2172. return consequent_->value();
  2173. else
  2174. return alternative_->value();
  2175. }
  2176. inline typename expression_node<T>::node_type type() const
  2177. {
  2178. return expression_node<T>::e_conditional;
  2179. }
  2180. private:
  2181. expression_ptr test_;
  2182. expression_ptr consequent_;
  2183. expression_ptr alternative_;
  2184. bool test_deletable_;
  2185. bool consequent_deletable_;
  2186. bool alternative_deletable_;
  2187. };
  2188. template <typename T>
  2189. class while_loop_node : public expression_node<T>
  2190. {
  2191. public:
  2192. typedef expression_node<T>* expression_ptr;
  2193. while_loop_node(expression_ptr test,
  2194. expression_ptr branch)
  2195. : test_(test),
  2196. branch_(branch),
  2197. test_deletable_(!is_variable_node(test_)),
  2198. branch_deletable_(!is_variable_node(branch_))
  2199. {}
  2200. ~while_loop_node()
  2201. {
  2202. if (test_ && test_deletable_) delete test_;
  2203. if (branch_ && branch_deletable_) delete branch_;
  2204. }
  2205. inline T value() const
  2206. {
  2207. T result = T(0);
  2208. while (test_->value() != T(0))
  2209. {
  2210. result = branch_->value();
  2211. }
  2212. return result;
  2213. }
  2214. inline typename expression_node<T>::node_type type() const
  2215. {
  2216. return expression_node<T>::e_while;
  2217. }
  2218. private:
  2219. expression_ptr test_;
  2220. expression_ptr branch_;
  2221. bool test_deletable_;
  2222. bool branch_deletable_;
  2223. };
  2224. template <typename T>
  2225. class variable_node : public expression_node<T>
  2226. {
  2227. public:
  2228. static T null_value;
  2229. explicit variable_node()
  2230. : value_(&null_value)
  2231. {}
  2232. explicit variable_node(T& value)
  2233. : value_(&value)
  2234. {}
  2235. inline bool operator <(const variable_node<T>& v) const
  2236. {
  2237. return this < (&v);
  2238. }
  2239. inline T value() const
  2240. {
  2241. return (*value_);
  2242. }
  2243. inline T& ref()
  2244. {
  2245. return (*value_);
  2246. }
  2247. inline const T& ref() const
  2248. {
  2249. return (*value_);
  2250. }
  2251. inline typename expression_node<T>::node_type type() const
  2252. {
  2253. return expression_node<T>::e_variable;
  2254. }
  2255. private:
  2256. T* value_;
  2257. };
  2258. template <typename T>
  2259. T variable_node<T>::null_value = T(std::numeric_limits<T>::quiet_NaN());
  2260. #ifndef exprtk_disable_string_capabilities
  2261. template <typename T>
  2262. class stringvar_node : public expression_node<T>
  2263. {
  2264. public:
  2265. static std::string null_value;
  2266. explicit stringvar_node()
  2267. : value_(&null_value)
  2268. {}
  2269. explicit stringvar_node(std::string& value)
  2270. : value_(&value)
  2271. {}
  2272. inline bool operator <(const stringvar_node<T>& v) const
  2273. {
  2274. return this < (&v);
  2275. }
  2276. inline T value() const
  2277. {
  2278. return std::numeric_limits<T>::quiet_NaN();
  2279. }
  2280. inline std::string str() const
  2281. {
  2282. return (*value_);
  2283. }
  2284. inline virtual std::string& ref()
  2285. {
  2286. return (*value_);
  2287. }
  2288. inline virtual const std::string& ref() const
  2289. {
  2290. return (*value_);
  2291. }
  2292. inline typename expression_node<T>::node_type type() const
  2293. {
  2294. return expression_node<T>::e_stringvar;
  2295. }
  2296. private:
  2297. std::string* value_;
  2298. };
  2299. template <typename T>
  2300. std::string stringvar_node<T>::null_value = std::string("");
  2301. #endif
  2302. template <typename T, std::size_t N> inline T axn(T a, T x) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x); } // a*x^n
  2303. template <typename T, std::size_t N> inline T axnb(T a, T x, T b) { return a * exprtk::details::numeric::fast_exp<T,N>::result(x) + b; } // a*x^n+b
  2304. template <typename T> struct sf00_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) / z; } };
  2305. template <typename T> struct sf01_op { static inline T process(const T& x, const T& y, const T& z) { return (x + y) * z; } };
  2306. template <typename T> struct sf02_op { static inline T process(const T& x, const T& y, const T& z) { return (x - y) / z; } };
  2307. template <typename T> struct sf03_op { static inline T process(const T& x, const T& y, const T& z) { return (x - y) * z; } };
  2308. template <typename T> struct sf04_op { static inline T process(const T& x, const T& y, const T& z) { return (x * y) + z; } };
  2309. template <typename T> struct sf05_op { static inline T process(const T& x, const T& y, const T& z) { return (x * y) - z; } };
  2310. template <typename T> struct sf06_op { static inline T process(const T& x, const T& y, const T& z) { return (x * y) / z; } };
  2311. template <typename T> struct sf07_op { static inline T process(const T& x, const T& y, const T& z) { return (x * y) * z; } };
  2312. template <typename T> struct sf08_op { static inline T process(const T& x, const T& y, const T& z) { return (x / y) + z; } };
  2313. template <typename T> struct sf09_op { static inline T process(const T& x, const T& y, const T& z) { return (x / y) - z; } };
  2314. template <typename T> struct sf10_op { static inline T process(const T& x, const T& y, const T& z) { return (x / y) / z; } };
  2315. template <typename T> struct sf11_op { static inline T process(const T& x, const T& y, const T& z) { return (x / y) * z; } };
  2316. template <typename T> struct sf12_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x + y); } };
  2317. template <typename T> struct sf13_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x - y); } };
  2318. template <typename T> struct sf14_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x * y); } };
  2319. template <typename T> struct sf15_op { static inline T process(const T& x, const T& y, const T& z) { return z / (x / y); } };
  2320. template <typename T> struct sf16_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } };
  2321. template <typename T> struct sf17_op { static inline T process(const T& x, const T& y, const T& z) { return z - (x / y); } };
  2322. template <typename T> struct sf18_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,2>(x,y,z); } }; //x * y^2 + z
  2323. template <typename T> struct sf19_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,3>(x,y,z); } }; //x * y^3 + z
  2324. template <typename T> struct sf20_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,4>(x,y,z); } }; //x * y^4 + z
  2325. template <typename T> struct sf21_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,5>(x,y,z); } }; //x * y^5 + z
  2326. template <typename T> struct sf22_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,6>(x,y,z); } }; //x * y^6 + z
  2327. template <typename T> struct sf23_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,7>(x,y,z); } }; //x * y^7 + z
  2328. template <typename T> struct sf24_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,8>(x,y,z); } }; //x * y^8 + z
  2329. template <typename T> struct sf25_op { static inline T process(const T& x, const T& y, const T& z) { return axnb<T,9>(x,y,z); } }; //x * y^9 + z
  2330. template <typename T> struct sf26_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) / z); } };
  2331. template <typename T> struct sf27_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x + y) * z); } };
  2332. template <typename T> struct sf28_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) / z); } };
  2333. template <typename T> struct sf29_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x - y) * z); } };
  2334. template <typename T> struct sf30_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) / z); } };
  2335. template <typename T> struct sf31_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x * y) * z); } };
  2336. template <typename T> struct sf32_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) + z); } };
  2337. template <typename T> struct sf33_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) / z); } };
  2338. template <typename T> struct sf34_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w + ((x / y) * z); } };
  2339. template <typename T> struct sf35_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) / z); } };
  2340. template <typename T> struct sf36_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x + y) * z); } };
  2341. template <typename T> struct sf37_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) / z); } };
  2342. template <typename T> struct sf38_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x - y) * z); } };
  2343. template <typename T> struct sf39_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) / z); } };
  2344. template <typename T> struct sf40_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x * y) * z); } };
  2345. template <typename T> struct sf41_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) / z); } };
  2346. template <typename T> struct sf42_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return w - ((x / y) * z); } };
  2347. template <typename T> struct sf43_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) * z) - w; } };
  2348. template <typename T> struct sf44_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) * z) - w; } };
  2349. template <typename T> struct sf45_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) * z) - w; } };
  2350. template <typename T> struct sf46_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) * z) - w; } };
  2351. template <typename T> struct sf47_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x + y) / z) - w; } };
  2352. template <typename T> struct sf48_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x - y) / z) - w; } };
  2353. template <typename T> struct sf49_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x * y) / z) - w; } };
  2354. template <typename T> struct sf50_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return ((x / y) / z) - w; } };
  2355. template <typename T> struct sf51_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,2>(x,y) + axn<T,2>(z,w); } }; //x*y^2+z*w^2
  2356. template <typename T> struct sf52_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,3>(x,y) + axn<T,3>(z,w); } }; //x*y^3+z*w^3
  2357. template <typename T> struct sf53_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,4>(x,y) + axn<T,4>(z,w); } }; //x*y^4+z*w^4
  2358. template <typename T> struct sf54_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,5>(x,y) + axn<T,5>(z,w); } }; //x*y^5+z*w^5
  2359. template <typename T> struct sf55_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,6>(x,y) + axn<T,6>(z,w); } }; //x*y^6+z*w^6
  2360. template <typename T> struct sf56_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,7>(x,y) + axn<T,7>(z,w); } }; //x*y^7+z*w^7
  2361. template <typename T> struct sf57_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,8>(x,y) + axn<T,8>(z,w); } }; //x*y^8+z*w^8
  2362. template <typename T> struct sf58_op { static inline T process(const T& x, const T& y, const T& z, const T& w) { return axn<T,9>(x,y) + axn<T,9>(z,w); } }; //x*y^9+z*w^9
  2363. template <typename T, typename SpecialFunction>
  2364. class sf3_node : public trinary_node<T>
  2365. {
  2366. public:
  2367. typedef expression_node<T>* expression_ptr;
  2368. sf3_node(const operator_type& operation,
  2369. expression_ptr branch0,
  2370. expression_ptr branch1,
  2371. expression_ptr branch2)
  2372. : trinary_node<T>(operation,branch0,branch1,branch2)
  2373. {}
  2374. inline T value() const
  2375. {
  2376. const T x = trinary_node<T>::branch_[0].first->value();
  2377. const T y = trinary_node<T>::branch_[1].first->value();
  2378. const T z = trinary_node<T>::branch_[2].first->value();
  2379. return SpecialFunction::process(x,y,z);
  2380. }
  2381. };
  2382. template <typename T, typename SpecialFunction>
  2383. class sf4_node : public quaternary_node<T>
  2384. {
  2385. public:
  2386. typedef expression_node<T>* expression_ptr;
  2387. sf4_node(const operator_type& operation,
  2388. expression_ptr branch0,
  2389. expression_ptr branch1,
  2390. expression_ptr branch2,
  2391. expression_ptr branch3)
  2392. : quaternary_node<T>(operation,branch0,branch1,branch2,branch3)
  2393. {}
  2394. inline T value() const
  2395. {
  2396. const T x = quaternary_node<T>::branch_[0].first->value();
  2397. const T y = quaternary_node<T>::branch_[1].first->value();
  2398. const T z = quaternary_node<T>::branch_[2].first->value();
  2399. const T w = quaternary_node<T>::branch_[3].first->value();
  2400. return SpecialFunction::process(x,y,z,w);
  2401. }
  2402. };
  2403. template <typename T>
  2404. class assignment_node : public binary_node<T>
  2405. {
  2406. public:
  2407. typedef expression_node<T>* expression_ptr;
  2408. assignment_node(const operator_type& operation,
  2409. expression_ptr branch0,
  2410. expression_ptr branch1)
  2411. : binary_node<T>(operation,branch0,branch1)
  2412. {}
  2413. inline T value() const
  2414. {
  2415. if (is_variable_node(binary_node<T>::branch_[0].first))
  2416. {
  2417. variable_node<T>* var_node_ptr = dynamic_cast<variable_node<T>*>(binary_node<T>::branch_[0].first);
  2418. if (var_node_ptr)
  2419. {
  2420. T& result = var_node_ptr->ref();
  2421. result = binary_node<T>::branch_[1].first->value();
  2422. return result;
  2423. }
  2424. }
  2425. return std::numeric_limits<T>::quiet_NaN();
  2426. }
  2427. };
  2428. template <typename T, typename IFunction, std::size_t N>
  2429. class function_N_node : public expression_node<T>
  2430. {
  2431. public:
  2432. //function of N paramters.
  2433. typedef expression_node<T>* expression_ptr;
  2434. typedef std::pair<expression_ptr,bool> branch_t;
  2435. typedef IFunction ifunction;
  2436. function_N_node(ifunction* func)
  2437. : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)),
  2438. parameter_count_(func->param_count)
  2439. {}
  2440. ~function_N_node()
  2441. {
  2442. cleanup_branches<T,N>::execute(branch_);
  2443. }
  2444. template <std::size_t NumBranches>
  2445. bool init_branches(expression_ptr (&b)[NumBranches])
  2446. {
  2447. //Needed for incompetent and broken msvc compiler versions
  2448. #ifdef _MSC_VER
  2449. #pragma warning(push)
  2450. #pragma warning(disable: 4127)
  2451. #endif
  2452. if (N != NumBranches)
  2453. return false;
  2454. else
  2455. {
  2456. for (std::size_t i = 0; i < NumBranches; ++i)
  2457. {
  2458. if (b[i])
  2459. branch_[i] = std::make_pair(b[i],branch_deletable(b[i]));
  2460. else
  2461. return false;
  2462. }
  2463. return true;
  2464. }
  2465. #ifdef _MSC_VER
  2466. #pragma warning(pop)
  2467. #endif
  2468. }
  2469. inline bool operator <(const function_N_node<T,IFunction,N>& fn) const
  2470. {
  2471. return this < (&fn);
  2472. }
  2473. inline T value() const
  2474. {
  2475. //Needed for incompetent and broken msvc compiler versions
  2476. #ifdef _MSC_VER
  2477. #pragma warning(push)
  2478. #pragma warning(disable: 4127)
  2479. #endif
  2480. if ((0 == function_) || (0 == N))
  2481. return std::numeric_limits<T>::quiet_NaN();
  2482. else
  2483. {
  2484. T v[N];
  2485. evaluate_branches<T,N>::execute(v,branch_);
  2486. return invoke<T,N>::execute(*function_,v);
  2487. }
  2488. #ifdef _MSC_VER
  2489. #pragma warning(pop)
  2490. #endif
  2491. }
  2492. template <typename T_, std::size_t BranchCount>
  2493. struct evaluate_branches
  2494. {
  2495. static inline void execute(T_ (&v)[BranchCount], const branch_t (&b)[BranchCount])
  2496. {
  2497. for (std::size_t i = 0; i < BranchCount; ++i)
  2498. {
  2499. v[i] = b[i].first->value();
  2500. }
  2501. }
  2502. };
  2503. template <typename T_>
  2504. struct evaluate_branches <T_,5>
  2505. {
  2506. static inline void execute(T_ (&v)[5], const branch_t (&b)[5])
  2507. {
  2508. v[0] = b[0].first->value();
  2509. v[1] = b[1].first->value();
  2510. v[2] = b[2].first->value();
  2511. v[3] = b[3].first->value();
  2512. v[4] = b[4].first->value();
  2513. }
  2514. };
  2515. template <typename T_>
  2516. struct evaluate_branches <T_,4>
  2517. {
  2518. static inline void execute(T_ (&v)[4], const branch_t (&b)[4])
  2519. {
  2520. v[0] = b[0].first->value();
  2521. v[1] = b[1].first->value();
  2522. v[2] = b[2].first->value();
  2523. v[3] = b[3].first->value();
  2524. }
  2525. };
  2526. template <typename T_>
  2527. struct evaluate_branches <T_,3>
  2528. {
  2529. static inline void execute(T_ (&v)[3], const branch_t (&b)[3])
  2530. {
  2531. v[0] = b[0].first->value();
  2532. v[1] = b[1].first->value();
  2533. v[2] = b[2].first->value();
  2534. }
  2535. };
  2536. template <typename T_>
  2537. struct evaluate_branches <T_,2>
  2538. {
  2539. static inline void execute(T_ (&v)[2], const branch_t (&b)[2])
  2540. {
  2541. v[0] = b[0].first->value();
  2542. v[1] = b[1].first->value();
  2543. }
  2544. };
  2545. template <typename T_>
  2546. struct evaluate_branches <T_,1>
  2547. {
  2548. static inline void execute(T_ (&v)[1], const branch_t (&b)[1])
  2549. {
  2550. v[0] = b[0].first->value();
  2551. }
  2552. };
  2553. template <typename T_, std::size_t ParamCount>
  2554. struct invoke { static inline T execute(ifunction*, branch_t (&)[ParamCount]) { return std::numeric_limits<T_>::quiet_NaN(); } };
  2555. template <typename T_> struct invoke<T_,10> { static inline T_ execute(ifunction& f, T_ (&v)[10]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9]); } };
  2556. template <typename T_> struct invoke<T_, 9> { static inline T_ execute(ifunction& f, T_ (&v)[ 9]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8]); } };
  2557. template <typename T_> struct invoke<T_, 8> { static inline T_ execute(ifunction& f, T_ (&v)[ 8]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]); } };
  2558. template <typename T_> struct invoke<T_, 7> { static inline T_ execute(ifunction& f, T_ (&v)[ 7]) { return f(v[0],v[1],v[2],v[3],v[4],v[5],v[6]); } };
  2559. template <typename T_> struct invoke<T_, 6> { static inline T_ execute(ifunction& f, T_ (&v)[ 6]) { return f(v[0],v[1],v[2],v[3],v[4],v[5]); } };
  2560. template <typename T_> struct invoke<T_, 5> { static inline T_ execute(ifunction& f, T_ (&v)[ 5]) { return f(v[0],v[1],v[2],v[3],v[4]); } };
  2561. template <typename T_> struct invoke<T_, 4> { static inline T_ execute(ifunction& f, T_ (&v)[ 4]) { return f(v[0],v[1],v[2],v[3]); } };
  2562. template <typename T_> struct invoke<T_, 3> { static inline T_ execute(ifunction& f, T_ (&v)[ 3]) { return f(v[0],v[1],v[2]); } };
  2563. template <typename T_> struct invoke<T_, 2> { static inline T_ execute(ifunction& f, T_ (&v)[ 2]) { return f(v[0],v[1]); } };
  2564. template <typename T_> struct invoke<T_, 1> { static inline T_ execute(ifunction& f, T_ (&v)[ 1]) { return f(v[0]); } };
  2565. inline typename expression_node<T>::node_type type() const
  2566. {
  2567. return expression_node<T>::e_function;
  2568. }
  2569. private:
  2570. ifunction* function_;
  2571. std::size_t parameter_count_;
  2572. branch_t branch_[N];
  2573. };
  2574. template <typename T, typename IFunction>
  2575. class function_N_node<T,IFunction,0> : public expression_node<T>
  2576. {
  2577. public:
  2578. typedef expression_node<T>* expression_ptr;
  2579. typedef IFunction ifunction;
  2580. function_N_node(ifunction* func)
  2581. : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0))
  2582. {}
  2583. inline bool operator <(const function_N_node<T,IFunction,0>& fn) const
  2584. {
  2585. return this < (&fn);
  2586. }
  2587. inline T value() const
  2588. {
  2589. if (0 == function_)
  2590. return std::numeric_limits<T>::quiet_NaN();
  2591. else
  2592. return (*function_)();
  2593. }
  2594. inline typename expression_node<T>::node_type type() const
  2595. {
  2596. return expression_node<T>::e_function;
  2597. }
  2598. private:
  2599. ifunction* function_;
  2600. std::size_t parameter_count_;
  2601. };
  2602. #define exprtk_def_unary_op(OpName) \
  2603. template <typename T> \
  2604. struct OpName##_op \
  2605. { \
  2606. static inline T process(const T& v) { return numeric:: OpName (v); } \
  2607. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_##OpName; } \
  2608. static inline details::operator_type operation() { return details::e_##OpName; } \
  2609. };
  2610. exprtk_def_unary_op(abs )
  2611. exprtk_def_unary_op(acos )
  2612. exprtk_def_unary_op(asin )
  2613. exprtk_def_unary_op(atan )
  2614. exprtk_def_unary_op(ceil )
  2615. exprtk_def_unary_op(cos )
  2616. exprtk_def_unary_op(cosh )
  2617. exprtk_def_unary_op(exp )
  2618. exprtk_def_unary_op(floor)
  2619. exprtk_def_unary_op(log )
  2620. exprtk_def_unary_op(log10)
  2621. exprtk_def_unary_op(neg )
  2622. exprtk_def_unary_op(pos )
  2623. exprtk_def_unary_op(round)
  2624. exprtk_def_unary_op(sin )
  2625. exprtk_def_unary_op(sinh )
  2626. exprtk_def_unary_op(sqrt )
  2627. exprtk_def_unary_op(tan )
  2628. exprtk_def_unary_op(tanh )
  2629. exprtk_def_unary_op(cot )
  2630. exprtk_def_unary_op(sec )
  2631. exprtk_def_unary_op(csc )
  2632. exprtk_def_unary_op(r2d )
  2633. exprtk_def_unary_op(d2r )
  2634. exprtk_def_unary_op(d2g )
  2635. exprtk_def_unary_op(g2d )
  2636. exprtk_def_unary_op(notl )
  2637. exprtk_def_unary_op(sgn )
  2638. exprtk_def_unary_op(erf )
  2639. exprtk_def_unary_op(erfc )
  2640. #undef exprtk_def_unary_op
  2641. template <typename T>
  2642. struct add_op
  2643. {
  2644. static inline T process(const T& t1, const T& t2) { return t1 + t2; }
  2645. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_add; }
  2646. static inline details::operator_type operation() { return details::e_add; }
  2647. };
  2648. template <typename T>
  2649. struct mul_op
  2650. {
  2651. static inline T process(const T& t1, const T& t2) { return t1 * t2; }
  2652. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mul; }
  2653. static inline details::operator_type operation() { return details::e_mul; }
  2654. };
  2655. template <typename T>
  2656. struct sub_op
  2657. {
  2658. static inline T process(const T& t1, const T& t2) { return t1 - t2; }
  2659. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_sub; }
  2660. static inline details::operator_type operation() { return details::e_sub; }
  2661. };
  2662. template <typename T>
  2663. struct div_op
  2664. {
  2665. static inline T process(const T& t1, const T& t2) { return t1 / t2; }
  2666. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_div; }
  2667. static inline details::operator_type operation() { return details::e_div; }
  2668. };
  2669. template <typename T>
  2670. struct mod_op
  2671. {
  2672. static inline T process(const T& t1, const T& t2) { return numeric::modulus<T>(t1,t2); }
  2673. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_mod; }
  2674. static inline details::operator_type operation() { return details::e_mod; }
  2675. };
  2676. template <typename T>
  2677. struct pow_op
  2678. {
  2679. static inline T process(const T& t1, const T& t2) { return numeric::pow<T>(t1,t2); }
  2680. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_pow; }
  2681. static inline details::operator_type operation() { return details::e_pow; }
  2682. };
  2683. template <typename T>
  2684. struct lt_op
  2685. {
  2686. static inline T process(const T& t1, const T& t2) { return ((t1 < t2) ? T(1) : T(0)); }
  2687. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 < t2) ? T(1) : T(0)); }
  2688. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lt; }
  2689. static inline details::operator_type operation() { return details::e_lt; }
  2690. };
  2691. template <typename T>
  2692. struct lte_op
  2693. {
  2694. static inline T process(const T& t1, const T& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
  2695. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 <= t2) ? T(1) : T(0)); }
  2696. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_lte; }
  2697. static inline details::operator_type operation() { return details::e_lte; }
  2698. };
  2699. template <typename T>
  2700. struct gt_op
  2701. {
  2702. static inline T process(const T& t1, const T& t2) { return ((t1 > t2) ? T(1) : T(0)); }
  2703. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 > t2) ? T(1) : T(0)); }
  2704. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gt; }
  2705. static inline details::operator_type operation() { return details::e_gt; }
  2706. };
  2707. template <typename T>
  2708. struct gte_op
  2709. {
  2710. static inline T process(const T& t1, const T& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
  2711. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 >= t2) ? T(1) : T(0)); }
  2712. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_gte; }
  2713. static inline details::operator_type operation() { return details::e_gte; }
  2714. };
  2715. template <typename T>
  2716. struct eq_op
  2717. {
  2718. static inline T process(const T& t1, const T& t2) { return ((t1 == t2) ? T(1) : T(0)); }
  2719. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 == t2) ? T(1) : T(0)); }
  2720. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_eq; }
  2721. static inline details::operator_type operation() { return details::e_eq; }
  2722. };
  2723. template <typename T>
  2724. struct ne_op
  2725. {
  2726. static inline T process(const T& t1, const T& t2) { return ((t1 != t2) ? T(1) : T(0)); }
  2727. static inline T process(const std::string& t1, const std::string& t2) { return ((t1 != t2) ? T(1) : T(0)); }
  2728. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ne; }
  2729. static inline details::operator_type operation() { return details::e_ne; }
  2730. };
  2731. template <typename T>
  2732. struct and_op
  2733. {
  2734. static inline T process(const T& t1, const T& t2) { return ((t1 != T(0)) && (t2 != T(0))) ? T(1) : T(0); }
  2735. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_and; }
  2736. static inline details::operator_type operation() { return details::e_and; }
  2737. };
  2738. template <typename T>
  2739. struct nand_op
  2740. {
  2741. static inline T process(const T& t1, const T& t2) { return ((t1 != T(0)) && (t2 != T(0))) ? T(0) : T(1); }
  2742. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nand; }
  2743. static inline details::operator_type operation() { return details::e_nand; }
  2744. };
  2745. template <typename T>
  2746. struct or_op
  2747. {
  2748. static inline T process(const T& t1, const T& t2) { return ((t1 != T(0)) || (t2 != T(0))) ? T(1) : T(0); }
  2749. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_or; }
  2750. static inline details::operator_type operation() { return details::e_or; }
  2751. };
  2752. template <typename T>
  2753. struct nor_op
  2754. {
  2755. static inline T process(const T& t1, const T& t2) { return ((t1 != T(0)) || (t2 != T(0))) ? T(0) : T(1); }
  2756. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
  2757. static inline details::operator_type operation() { return details::e_nor; }
  2758. };
  2759. template <typename T>
  2760. struct xor_op
  2761. {
  2762. static inline T process(const T& t1, const T& t2) { return numeric::xor_opr<T>(t1,t2); }
  2763. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_nor; }
  2764. static inline details::operator_type operation() { return details::e_xor; }
  2765. };
  2766. template <typename T>
  2767. struct in_op
  2768. {
  2769. static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
  2770. static inline T process(const std::string& t1, const std::string& t2) { return ((std::string::npos != t2.find(t1)) ? T(1) : T(0)); }
  2771. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_in; }
  2772. static inline details::operator_type operation() { return details::e_in; }
  2773. };
  2774. template <typename T>
  2775. struct like_op
  2776. {
  2777. static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
  2778. static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_match(t2,t1) ? T(1) : T(0)); }
  2779. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_like; }
  2780. static inline details::operator_type operation() { return details::e_like; }
  2781. };
  2782. template <typename T>
  2783. struct ilike_op
  2784. {
  2785. static inline T process(const T&, const T&) { return std::numeric_limits<T>::quiet_NaN(); }
  2786. static inline T process(const std::string& t1, const std::string& t2) { return (details::wc_imatch(t2,t1) ? T(1) : T(0)); }
  2787. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_ilike; }
  2788. static inline details::operator_type operation() { return details::e_ilike; }
  2789. };
  2790. template <typename T>
  2791. struct inrange_op
  2792. {
  2793. static inline T process(const T& t0, const T& t1, const T& t2) { return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0); }
  2794. static inline T process(const std::string& t0, const std::string& t1, const std::string& t2)
  2795. {
  2796. return ((t0 <= t1) && (t1 <= t2)) ? T(1) : T(0);
  2797. }
  2798. static inline typename expression_node<T>::node_type type() { return expression_node<T>::e_inranges; }
  2799. static inline details::operator_type operation() { return details::e_ilike; }
  2800. };
  2801. template <typename T, typename Operation>
  2802. class unary_variable_node : public expression_node<T>
  2803. {
  2804. public:
  2805. typedef expression_node<T>* expression_ptr;
  2806. typedef Operation operation_t;
  2807. explicit unary_variable_node(T& v)
  2808. : v_(v)
  2809. {}
  2810. inline T value() const
  2811. {
  2812. return Operation::process(v_);
  2813. }
  2814. inline typename expression_node<T>::node_type type() const
  2815. {
  2816. return Operation::type();
  2817. }
  2818. inline operator_type operation() const
  2819. {
  2820. return Operation::operation();
  2821. }
  2822. inline T& v()
  2823. {
  2824. return v_;
  2825. }
  2826. private:
  2827. unary_variable_node(unary_variable_node<T,Operation>&);
  2828. unary_variable_node<T,Operation>& operator=(unary_variable_node<T,Operation>&);
  2829. T& v_;
  2830. };
  2831. template <typename T, typename Operation>
  2832. class unary_branch_node : public expression_node<T>
  2833. {
  2834. public:
  2835. typedef expression_node<T>* expression_ptr;
  2836. typedef Operation operation_t;
  2837. explicit unary_branch_node(expression_ptr branch)
  2838. : branch_(branch),
  2839. branch_deletable_(branch_deletable(branch_))
  2840. {}
  2841. ~unary_branch_node()
  2842. {
  2843. if (branch_ && branch_deletable_)
  2844. {
  2845. delete branch_;
  2846. branch_ = 0;
  2847. }
  2848. }
  2849. inline T value() const
  2850. {
  2851. T v = branch_->value();
  2852. return Operation::process(v);
  2853. }
  2854. inline typename expression_node<T>::node_type type() const
  2855. {
  2856. return Operation::type();
  2857. }
  2858. inline operator_type operation() const
  2859. {
  2860. return Operation::operation();
  2861. }
  2862. private:
  2863. unary_branch_node(unary_branch_node<T,Operation>&);
  2864. unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&);
  2865. expression_ptr branch_;
  2866. bool branch_deletable_;
  2867. };
  2868. template <typename T>
  2869. class vov_base_node : public expression_node<T>
  2870. {
  2871. public:
  2872. inline virtual operator_type operation() const
  2873. {
  2874. return details::e_default;
  2875. }
  2876. };
  2877. template <typename T>
  2878. class cov_base_node : public expression_node<T>
  2879. {
  2880. public:
  2881. inline virtual operator_type operation() const
  2882. {
  2883. return details::e_default;
  2884. }
  2885. };
  2886. template <typename T>
  2887. class sos_base_node : public expression_node<T>
  2888. {
  2889. public:
  2890. inline virtual operator_type operation() const
  2891. {
  2892. return details::e_default;
  2893. }
  2894. };
  2895. template <typename T>
  2896. class sosos_base_node : public expression_node<T>
  2897. {
  2898. public:
  2899. inline virtual operator_type operation() const
  2900. {
  2901. return details::e_default;
  2902. }
  2903. };
  2904. template <typename T, typename Operation>
  2905. class vov_node : public vov_base_node<T>
  2906. {
  2907. public:
  2908. typedef expression_node<T>* expression_ptr;
  2909. typedef Operation operation_t;
  2910. //variable op variable node
  2911. explicit vov_node(T& v0, T& v1)
  2912. : v0_(v0),
  2913. v1_(v1)
  2914. {}
  2915. inline T value() const
  2916. {
  2917. return Operation::process(v0_,v1_);
  2918. }
  2919. inline typename expression_node<T>::node_type type() const
  2920. {
  2921. return Operation::type();
  2922. }
  2923. inline operator_type operation() const
  2924. {
  2925. return Operation::operation();
  2926. }
  2927. inline T& v0()
  2928. {
  2929. return v0_;
  2930. }
  2931. inline T& v1()
  2932. {
  2933. return v1_;
  2934. }
  2935. protected:
  2936. T& v0_;
  2937. T& v1_;
  2938. private:
  2939. vov_node(vov_node<T,Operation>&);
  2940. vov_node<T,Operation>& operator=(vov_node<T,Operation>&);
  2941. };
  2942. template <typename T, typename Type0, typename Type1, typename Operation>
  2943. class vov_nodex : public vov_base_node<T>
  2944. {
  2945. public:
  2946. typedef expression_node<T>* expression_ptr;
  2947. typedef Operation operation_t;
  2948. //variable op variable node
  2949. explicit vov_nodex(Type0 v0, Type1 v1)
  2950. : v0_(v0),
  2951. v1_(v1)
  2952. {}
  2953. inline T value() const
  2954. {
  2955. return Operation::process(v0_,v1_);
  2956. }
  2957. inline typename expression_node<T>::node_type type() const
  2958. {
  2959. return Operation::type();
  2960. }
  2961. inline operator_type operation() const
  2962. {
  2963. return Operation::operation();
  2964. }
  2965. inline Type0 v0()
  2966. {
  2967. return v0_;
  2968. }
  2969. inline Type1 v1()
  2970. {
  2971. return v1_;
  2972. }
  2973. protected:
  2974. Type0 v0_;
  2975. Type1 v1_;
  2976. };
  2977. template <typename T, typename Operation>
  2978. class cov_node : public cov_base_node<T>
  2979. {
  2980. public:
  2981. typedef expression_node<T>* expression_ptr;
  2982. typedef Operation operation_t;
  2983. //constant op variable node
  2984. explicit cov_node(const T& c, T& v)
  2985. : c_(c),
  2986. v_(v)
  2987. {}
  2988. inline T value() const
  2989. {
  2990. return Operation::process(c_,v_);
  2991. }
  2992. inline typename expression_node<T>::node_type type() const
  2993. {
  2994. return Operation::type();
  2995. }
  2996. inline operator_type operation() const
  2997. {
  2998. return Operation::operation();
  2999. }
  3000. inline T c()
  3001. {
  3002. return c_;
  3003. }
  3004. inline T& v()
  3005. {
  3006. return v_;
  3007. }
  3008. protected:
  3009. T c_;
  3010. T& v_;
  3011. private:
  3012. cov_node(const cov_node<T,Operation>&);
  3013. cov_node<T,Operation>& operator=(const cov_node<T,Operation>&);
  3014. };
  3015. template <typename T, typename Operation>
  3016. class voc_node : public expression_node<T>
  3017. {
  3018. public:
  3019. typedef expression_node<T>* expression_ptr;
  3020. typedef Operation operation_t;
  3021. //variable op constant node
  3022. explicit voc_node(T& v, const T& c)
  3023. : v_(v),
  3024. c_(c)
  3025. {}
  3026. inline T value() const
  3027. {
  3028. return Operation::process(v_,c_);
  3029. }
  3030. inline typename expression_node<T>::node_type type() const
  3031. {
  3032. return Operation::type();
  3033. }
  3034. protected:
  3035. T& v_;
  3036. T c_;
  3037. private:
  3038. voc_node(const voc_node<T,Operation>&);
  3039. voc_node<T,Operation>& operator=(const voc_node<T,Operation>&);
  3040. };
  3041. template <typename T, typename Operation1, typename Operation2>
  3042. class vovov1_node : public expression_node<T>
  3043. {
  3044. public:
  3045. typedef expression_node<T>* expression_ptr;
  3046. typedef std::pair<expression_ptr,bool> branch_t;
  3047. //variable0 op1 (variable1 op2 variable2) node
  3048. explicit vovov1_node(T& v0, vov_node<T,Operation2>& vn)
  3049. : v0_(v0),
  3050. v1_(vn.v0()),
  3051. v2_(vn.v1())
  3052. {}
  3053. inline T value() const
  3054. {
  3055. return Operation1::process(v0_,Operation2::process(v1_,v2_));
  3056. }
  3057. inline typename expression_node<T>::node_type type() const
  3058. {
  3059. return expression_node<T>::e_none;
  3060. }
  3061. inline typename expression_node<T>::node_type type1() const
  3062. {
  3063. return Operation1::type();
  3064. }
  3065. inline typename expression_node<T>::node_type type2() const
  3066. {
  3067. return Operation2::type();
  3068. }
  3069. protected:
  3070. T& v0_;
  3071. T& v1_;
  3072. T& v2_;
  3073. private:
  3074. vovov1_node(const vovov1_node<T,Operation1,Operation2>&);
  3075. vovov1_node<T,Operation1,Operation2>& operator=(const vovov1_node<T,Operation1,Operation2>&);
  3076. };
  3077. template <typename T, typename Operation1, typename Operation2>
  3078. class vovov2_node : public expression_node<T>
  3079. {
  3080. public:
  3081. typedef expression_node<T>* expression_ptr;
  3082. typedef std::pair<expression_ptr,bool> branch_t;
  3083. //(variable0 op1 variable1) op2 variable2 node
  3084. explicit vovov2_node(vov_node<T,Operation1>& vn, T& v2)
  3085. : v0_(vn.v0()),
  3086. v1_(vn.v1()),
  3087. v2_(v2)
  3088. {}
  3089. inline T value() const
  3090. {
  3091. return Operation2::process(Operation1::process(v0_,v1_),v2_);
  3092. }
  3093. inline typename expression_node<T>::node_type type() const
  3094. {
  3095. return expression_node<T>::e_none;
  3096. }
  3097. inline typename expression_node<T>::node_type type1() const
  3098. {
  3099. return Operation1::type();
  3100. }
  3101. inline typename expression_node<T>::node_type type2() const
  3102. {
  3103. return Operation2::type();
  3104. }
  3105. protected:
  3106. T& v0_;
  3107. T& v1_;
  3108. T& v2_;
  3109. private:
  3110. vovov2_node(const vovov2_node<T,Operation1,Operation2>&);
  3111. vovov2_node<T,Operation1,Operation2>& operator=(const vovov2_node<T,Operation1,Operation2>&);
  3112. };
  3113. template <typename T, typename Operation1, typename Operation2>
  3114. class covov1_node : public expression_node<T>
  3115. {
  3116. public:
  3117. typedef expression_node<T>* expression_ptr;
  3118. typedef std::pair<expression_ptr,bool> branch_t;
  3119. //constant op1 (variable0 op2 variable1) node
  3120. explicit covov1_node(const T& c, vov_node<T,Operation2>& vn)
  3121. : c_(c),
  3122. v0_(vn.v0()),
  3123. v1_(vn.v1())
  3124. {}
  3125. inline T value() const
  3126. {
  3127. return Operation1::process(c_,Operation2::process(v0_,v1_));
  3128. }
  3129. inline typename expression_node<T>::node_type type() const
  3130. {
  3131. return expression_node<T>::e_none;
  3132. }
  3133. inline typename expression_node<T>::node_type type1() const
  3134. {
  3135. return Operation1::type();
  3136. }
  3137. inline typename expression_node<T>::node_type type2() const
  3138. {
  3139. return Operation2::type();
  3140. }
  3141. protected:
  3142. T c_;
  3143. T& v0_;
  3144. T& v1_;
  3145. private:
  3146. covov1_node(const covov1_node<T,Operation1,Operation2>&);
  3147. covov1_node<T,Operation1,Operation2>& operator=(const covov1_node<T,Operation1,Operation2>&);
  3148. };
  3149. template <typename T, typename Operation1, typename Operation2>
  3150. class covov2_node : public expression_node<T>
  3151. {
  3152. public:
  3153. typedef expression_node<T>* expression_ptr;
  3154. typedef std::pair<expression_ptr,bool> branch_t;
  3155. //(constant op1 variable0) op2 variable1 node
  3156. explicit covov2_node(cov_node<T,Operation1>& cvn, T& v1)
  3157. : c_(cvn.c()),
  3158. v0_(cvn.v()),
  3159. v1_(v1)
  3160. {}
  3161. inline T value() const
  3162. {
  3163. return Operation2::process(Operation1::process(c_,v0_),v1_);
  3164. }
  3165. inline typename expression_node<T>::node_type type() const
  3166. {
  3167. return expression_node<T>::e_none;
  3168. }
  3169. inline typename expression_node<T>::node_type type1() const
  3170. {
  3171. return Operation1::type();
  3172. }
  3173. inline typename expression_node<T>::node_type type2() const
  3174. {
  3175. return Operation2::type();
  3176. }
  3177. protected:
  3178. T c_;
  3179. T& v0_;
  3180. T& v1_;
  3181. private:
  3182. covov2_node(covov2_node<T,Operation1,Operation2>&);
  3183. covov2_node<T,Operation1,Operation2>& operator=(covov2_node<T,Operation1,Operation2>&);
  3184. };
  3185. template <typename T, typename Operation1, typename Operation2, typename Operation3>
  3186. class vovovov_node : public expression_node<T>
  3187. {
  3188. public:
  3189. typedef expression_node<T>* expression_ptr;
  3190. typedef std::pair<expression_ptr,bool> branch_t;
  3191. //(variable0 op1 variable1) op2 (variable2 op3 variable3) node
  3192. explicit vovovov_node(vov_node<T,Operation1>& vn0, vov_node<T,Operation3>& vn1)
  3193. : v0_(vn0.v0()),
  3194. v1_(vn0.v1()),
  3195. v2_(vn1.v0()),
  3196. v3_(vn1.v1())
  3197. {}
  3198. inline T value() const
  3199. {
  3200. return Operation2::process(Operation1::process(v0_,v1_),Operation3::process(v2_,v3_));
  3201. }
  3202. inline typename expression_node<T>::node_type type() const
  3203. {
  3204. return expression_node<T>::e_none;
  3205. }
  3206. inline typename expression_node<T>::node_type type1() const
  3207. {
  3208. return Operation1::type();
  3209. }
  3210. inline typename expression_node<T>::node_type type2() const
  3211. {
  3212. return Operation2::type();
  3213. }
  3214. protected:
  3215. T& v0_;
  3216. T& v1_;
  3217. T& v2_;
  3218. T& v3_;
  3219. private:
  3220. vovovov_node(vovovov_node<T,Operation1,Operation2,Operation3>&);
  3221. vovovov_node<T,Operation1,Operation2,Operation3>& operator=(const vovovov_node<T,Operation1,Operation2,Operation3>&);
  3222. };
  3223. #ifndef exprtk_disable_string_capabilities
  3224. template <typename T, typename SType0, typename SType1, typename Operation>
  3225. class sos_node : public sos_base_node<T>
  3226. {
  3227. public:
  3228. typedef expression_node<T>* expression_ptr;
  3229. typedef Operation operation_t;
  3230. //variable op variable node
  3231. explicit sos_node(SType0 s0, SType1 s1)
  3232. : s0_(s0),
  3233. s1_(s1)
  3234. {}
  3235. inline T value() const
  3236. {
  3237. return Operation::process(s0_,s1_);
  3238. }
  3239. inline typename expression_node<T>::node_type type() const
  3240. {
  3241. return Operation::type();
  3242. }
  3243. inline operator_type operation() const
  3244. {
  3245. return Operation::operation();
  3246. }
  3247. inline std::string& s0()
  3248. {
  3249. return s0_;
  3250. }
  3251. inline std::string& s1()
  3252. {
  3253. return s1_;
  3254. }
  3255. protected:
  3256. SType0 s0_;
  3257. SType1 s1_;
  3258. private:
  3259. sos_node(sos_node<T,SType0,SType1,Operation>&);
  3260. sos_node<T,SType0,SType1,Operation>& operator=(sos_node<T,SType0,SType1,Operation>&);
  3261. };
  3262. template <typename T, typename SType0, typename SType1, typename SType2, typename Operation>
  3263. class sosos_node : public sosos_base_node<T>
  3264. {
  3265. public:
  3266. typedef expression_node<T>* expression_ptr;
  3267. typedef Operation operation_t;
  3268. //variable op variable node
  3269. explicit sosos_node(SType0 s0, SType1 s1, SType2 s2)
  3270. : s0_(s0),
  3271. s1_(s1),
  3272. s2_(s2)
  3273. {}
  3274. inline T value() const
  3275. {
  3276. return Operation::process(s0_,s1_,s2_);
  3277. }
  3278. inline typename expression_node<T>::node_type type() const
  3279. {
  3280. return Operation::type();
  3281. }
  3282. inline operator_type operation() const
  3283. {
  3284. return Operation::operation();
  3285. }
  3286. inline std::string& s0()
  3287. {
  3288. return s0_;
  3289. }
  3290. inline std::string& s1()
  3291. {
  3292. return s1_;
  3293. }
  3294. inline std::string& s2()
  3295. {
  3296. return s2_;
  3297. }
  3298. protected:
  3299. SType0 s0_;
  3300. SType1 s1_;
  3301. SType2 s2_;
  3302. private:
  3303. sosos_node(sosos_node<T,SType0,SType1,SType2,Operation>&);
  3304. sosos_node<T,SType0,SType1,SType2,Operation>& operator=(sosos_node<T,SType0,SType1,SType2,Operation>&);
  3305. };
  3306. #endif
  3307. template <typename T, typename PowOp>
  3308. class ipow_node : public expression_node<T>
  3309. {
  3310. public:
  3311. typedef expression_node<T>* expression_ptr;
  3312. typedef PowOp operation_t;
  3313. //variable op constant node
  3314. explicit ipow_node(T& v, const bool not_recipricol = true)
  3315. : v_(v),
  3316. not_recipricol_(not_recipricol)
  3317. {}
  3318. inline T value() const
  3319. {
  3320. if (not_recipricol_)
  3321. return PowOp::result(v_);
  3322. else
  3323. return (T(1.0) / PowOp::result(v_));
  3324. }
  3325. inline typename expression_node<T>::node_type type() const
  3326. {
  3327. return expression_node<T>::e_ipow;
  3328. }
  3329. private:
  3330. ipow_node(const ipow_node<T,PowOp>&);
  3331. ipow_node<T,PowOp>& operator=(const ipow_node<T,PowOp>&);
  3332. T& v_;
  3333. const bool not_recipricol_;
  3334. };
  3335. template <typename T>
  3336. inline bool is_vov_node(const expression_node<T>* node)
  3337. {
  3338. return (0 != dynamic_cast<const vov_base_node<T>*>(node));
  3339. }
  3340. template <typename T>
  3341. inline bool is_cov_node(const expression_node<T>* node)
  3342. {
  3343. return (0 != dynamic_cast<const cov_base_node<T>*>(node));
  3344. }
  3345. template <typename T>
  3346. inline bool is_string_node(const expression_node<T>* node)
  3347. {
  3348. return (expression_node<T>::e_stringvar == node->type());
  3349. }
  3350. template <typename T>
  3351. inline bool is_const_string_node(const expression_node<T>* node)
  3352. {
  3353. return (expression_node<T>::e_stringconst == node->type());
  3354. }
  3355. class node_allocator
  3356. {
  3357. public:
  3358. template <typename ResultNode, typename OpType, typename ExprNode>
  3359. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1])
  3360. {
  3361. return allocate<ResultNode>(operation,branch[0]);
  3362. }
  3363. template <typename ResultNode, typename OpType, typename ExprNode>
  3364. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2])
  3365. {
  3366. return allocate<ResultNode>(operation,branch[0],branch[1]);
  3367. }
  3368. template <typename ResultNode, typename OpType, typename ExprNode>
  3369. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3])
  3370. {
  3371. return allocate<ResultNode>(operation,branch[0],branch[1],branch[2]);
  3372. }
  3373. template <typename ResultNode, typename OpType, typename ExprNode>
  3374. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4])
  3375. {
  3376. return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3]);
  3377. }
  3378. template <typename ResultNode, typename OpType, typename ExprNode>
  3379. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5])
  3380. {
  3381. return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4]);
  3382. }
  3383. template <typename ResultNode, typename OpType, typename ExprNode>
  3384. inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6])
  3385. {
  3386. return allocate<ResultNode>(operation,branch[0],branch[1],branch[2],branch[3],branch[4],branch[5]);
  3387. }
  3388. template <typename node_type, typename T1>
  3389. inline expression_node<typename node_type::value_type>* allocate(T1& t1) const
  3390. {
  3391. return new node_type(t1);
  3392. }
  3393. template <typename node_type, typename T1>
  3394. inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const
  3395. {
  3396. return new node_type(t1);
  3397. }
  3398. template <typename node_type,
  3399. typename T1, typename T2>
  3400. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const
  3401. {
  3402. return new node_type(t1,t2);
  3403. }
  3404. template <typename node_type,
  3405. typename T1, typename T2>
  3406. inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const
  3407. {
  3408. return new node_type(t1,t2);
  3409. }
  3410. template <typename node_type,
  3411. typename T1, typename T2>
  3412. inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const
  3413. {
  3414. return new node_type(t1,t2);
  3415. }
  3416. template <typename node_type,
  3417. typename T1, typename T2>
  3418. inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const
  3419. {
  3420. return new node_type(t1,t2);
  3421. }
  3422. template <typename node_type,
  3423. typename T1, typename T2>
  3424. inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const
  3425. {
  3426. return new node_type(t1,t2);
  3427. }
  3428. template <typename node_type,
  3429. typename T1, typename T2, typename T3>
  3430. inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const
  3431. {
  3432. return new node_type(t1,t2,t3);
  3433. }
  3434. template <typename node_type,
  3435. typename T1, typename T2, typename T3>
  3436. inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const
  3437. {
  3438. return new node_type(t1,t2,t3);
  3439. }
  3440. template <typename node_type,
  3441. typename T1, typename T2,
  3442. typename T3>
  3443. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3444. const T3& t3) const
  3445. {
  3446. return new node_type(t1,t2,t3);
  3447. }
  3448. template <typename node_type,
  3449. typename T1, typename T2,
  3450. typename T3, typename T4>
  3451. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3452. const T3& t3, const T4& t4) const
  3453. {
  3454. return new node_type(t1,t2,t3,t4);
  3455. }
  3456. template <typename node_type,
  3457. typename T1, typename T2,
  3458. typename T3, typename T4, typename T5>
  3459. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3460. const T3& t3, const T4& t4,
  3461. const T5& t5) const
  3462. {
  3463. return new node_type(t1,t2,t3,t4,t5);
  3464. }
  3465. template <typename node_type,
  3466. typename T1, typename T2,
  3467. typename T3, typename T4, typename T5, typename T6>
  3468. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3469. const T3& t3, const T4& t4,
  3470. const T5& t5, const T6& t6) const
  3471. {
  3472. return new node_type(t1,t2,t3,t4,t5,t6);
  3473. }
  3474. template <typename node_type,
  3475. typename T1, typename T2,
  3476. typename T3, typename T4,
  3477. typename T5, typename T6, typename T7>
  3478. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3479. const T3& t3, const T4& t4,
  3480. const T5& t5, const T6& t6,
  3481. const T7& t7) const
  3482. {
  3483. return new node_type(t1,t2,t3,t4,t5,t6,t7);
  3484. }
  3485. template <typename node_type,
  3486. typename T1, typename T2,
  3487. typename T3, typename T4,
  3488. typename T5, typename T6,
  3489. typename T7, typename T8>
  3490. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3491. const T3& t3, const T4& t4,
  3492. const T5& t5, const T6& t6,
  3493. const T7& t7, const T8& t8) const
  3494. {
  3495. return new node_type(t1,t2,t3,t4,t5,t6,t7,t8);
  3496. }
  3497. template <typename node_type,
  3498. typename T1, typename T2,
  3499. typename T3, typename T4,
  3500. typename T5, typename T6,
  3501. typename T7, typename T8, typename T9>
  3502. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3503. const T3& t3, const T4& t4,
  3504. const T5& t5, const T6& t6,
  3505. const T7& t7, const T8& t8,
  3506. const T9& t9) const
  3507. {
  3508. return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9);
  3509. }
  3510. template <typename node_type,
  3511. typename T1, typename T2,
  3512. typename T3, typename T4,
  3513. typename T5, typename T6,
  3514. typename T7, typename T8,
  3515. typename T9, typename T10>
  3516. inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2,
  3517. const T3& t3, const T4& t4,
  3518. const T5& t5, const T6& t6,
  3519. const T7& t7, const T8& t8,
  3520. const T9& t9, const T10& t10) const
  3521. {
  3522. return new node_type(t1,t2,t3,t4,t5,t6,t7,t8,t9,t10);
  3523. }
  3524. template <typename T>
  3525. void inline free(expression_node<T>*& e) const
  3526. {
  3527. delete e;
  3528. e = 0;
  3529. }
  3530. };
  3531. struct operation_t
  3532. {
  3533. operation_t(const std::string& n, const operator_type t, const unsigned int& np)
  3534. : name(n),
  3535. type(t),
  3536. num_params(np)
  3537. {}
  3538. std::string name;
  3539. operator_type type;
  3540. unsigned int num_params;
  3541. };
  3542. static const operation_t operation_list[] =
  3543. {
  3544. operation_t( "abs" , e_abs , 1),
  3545. operation_t( "acos" , e_acos , 1),
  3546. operation_t( "asin" , e_asin , 1),
  3547. operation_t( "atan" , e_atan , 1),
  3548. operation_t( "ceil" , e_ceil , 1),
  3549. operation_t( "cos" , e_cos , 1),
  3550. operation_t( "cosh" , e_cosh , 1),
  3551. operation_t( "exp" , e_exp , 1),
  3552. operation_t( "floor" , e_floor , 1),
  3553. operation_t( "log" , e_log , 1),
  3554. operation_t( "log10" , e_log10 , 1),
  3555. operation_t( "round" , e_round , 1),
  3556. operation_t( "sin" , e_sin , 1),
  3557. operation_t( "sinh" , e_sinh , 1),
  3558. operation_t( "sec" , e_sec , 1),
  3559. operation_t( "csc" , e_csc , 1),
  3560. operation_t( "sqrt" , e_sqrt , 1),
  3561. operation_t( "tan" , e_tan , 1),
  3562. operation_t( "tanh" , e_tanh , 1),
  3563. operation_t( "cot" , e_cot , 1),
  3564. operation_t( "rad2deg" , e_r2d , 1),
  3565. operation_t( "deg2rad" , e_d2r , 1),
  3566. operation_t( "deg2grad" , e_d2g , 1),
  3567. operation_t( "grad2deg" , e_g2d , 1),
  3568. operation_t( "sgn" , e_sgn , 1),
  3569. operation_t( "not" , e_notl , 1),
  3570. operation_t( "erf" , e_erf , 1),
  3571. operation_t( "erfc" , e_erfc , 1),
  3572. operation_t( "atan2", e_atan2 , 2),
  3573. operation_t( "min", e_min , 2),
  3574. operation_t( "max", e_max , 2),
  3575. operation_t( "avg", e_avg , 2),
  3576. operation_t( "sum", e_sum , 2),
  3577. operation_t( "mul", e_prod , 2),
  3578. operation_t( "mod", e_mod , 2),
  3579. operation_t( "logn", e_logn , 2),
  3580. operation_t( "root", e_root , 2),
  3581. operation_t( "roundn", e_roundn , 2),
  3582. operation_t( "equal", e_equal , 2),
  3583. operation_t("not_equal", e_nequal , 2),
  3584. operation_t( "hyp", e_hyp , 2),
  3585. operation_t( "shr", e_shr , 2),
  3586. operation_t( "shl", e_shl , 2),
  3587. operation_t( "clamp", e_clamp , 3),
  3588. operation_t( "inrange", e_inrange , 3),
  3589. operation_t( "min", e_min , 3),
  3590. operation_t( "max", e_max , 3),
  3591. operation_t( "avg", e_avg , 3),
  3592. operation_t( "sum", e_sum , 3),
  3593. operation_t( "mul", e_prod , 3),
  3594. operation_t( "min", e_min , 4),
  3595. operation_t( "max", e_max , 4),
  3596. operation_t( "avg", e_avg , 4),
  3597. operation_t( "sum", e_sum , 4),
  3598. operation_t( "mul", e_prod , 4),
  3599. operation_t( "min", e_min , 5),
  3600. operation_t( "max", e_max , 5),
  3601. operation_t( "avg", e_avg , 5),
  3602. operation_t( "sum", e_sum , 5),
  3603. operation_t( "mul", e_prod , 5),
  3604. operation_t( "min", e_min , 6),
  3605. operation_t( "max", e_max , 6),
  3606. operation_t( "avg", e_avg , 6),
  3607. operation_t( "sum", e_sum , 6),
  3608. operation_t( "mul", e_prod , 6),
  3609. };
  3610. static const std::size_t operation_list_size = sizeof(operation_list) / sizeof(operation_t);
  3611. } // namespace details
  3612. template <typename T>
  3613. class ifunction
  3614. {
  3615. public:
  3616. explicit ifunction(const std::size_t& pc)
  3617. : param_count(pc)
  3618. {}
  3619. virtual ~ifunction()
  3620. {}
  3621. std::size_t param_count;
  3622. inline virtual T operator()()
  3623. {
  3624. return std::numeric_limits<T>::quiet_NaN();
  3625. }
  3626. inline virtual T operator()(const T&)
  3627. {
  3628. return std::numeric_limits<T>::quiet_NaN();
  3629. }
  3630. inline virtual T operator()(const T&,const T&)
  3631. {
  3632. return std::numeric_limits<T>::quiet_NaN();
  3633. }
  3634. inline virtual T operator()(const T&, const T&, const T&)
  3635. {
  3636. return std::numeric_limits<T>::quiet_NaN();
  3637. }
  3638. inline virtual T operator()(const T&, const T&, const T&, const T&)
  3639. {
  3640. return std::numeric_limits<T>::quiet_NaN();
  3641. }
  3642. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&)
  3643. {
  3644. return std::numeric_limits<T>::quiet_NaN();
  3645. }
  3646. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&)
  3647. {
  3648. return std::numeric_limits<T>::quiet_NaN();
  3649. }
  3650. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&)
  3651. {
  3652. return std::numeric_limits<T>::quiet_NaN();
  3653. }
  3654. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
  3655. {
  3656. return std::numeric_limits<T>::quiet_NaN();
  3657. }
  3658. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
  3659. {
  3660. return std::numeric_limits<T>::quiet_NaN();
  3661. }
  3662. inline virtual T operator()(const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&)
  3663. {
  3664. return std::numeric_limits<T>::quiet_NaN();
  3665. }
  3666. };
  3667. template <typename T>
  3668. class symbol_table
  3669. {
  3670. private:
  3671. struct ilesscompare
  3672. {
  3673. inline bool operator()(const std::string& s1, const std::string& s2) const
  3674. {
  3675. const std::size_t length = std::min(s1.size(),s2.size());
  3676. for (std::size_t i = 0; i < length; ++i)
  3677. {
  3678. if (std::tolower(s1[i]) > std::tolower(s2[i]))
  3679. return false;
  3680. else if (std::tolower(s1[i]) < std::tolower(s2[i]))
  3681. return true;
  3682. }
  3683. return s1.size() < s2.size();
  3684. }
  3685. };
  3686. template <typename Type, typename RawType>
  3687. struct type_store
  3688. {
  3689. typedef typename details::variable_node<T> variable_node_t;
  3690. typedef ifunction<T> ifunction_t;
  3691. #ifndef exprtk_disable_string_capabilities
  3692. typedef typename details::stringvar_node<T> stringvar_node_t;
  3693. #endif
  3694. typedef Type type_t;
  3695. typedef type_t* type_ptr;
  3696. typedef std::pair<bool,type_ptr> type_pair_t;
  3697. typedef std::map<std::string,type_pair_t,ilesscompare> type_map_t;
  3698. typedef typename type_map_t::iterator tm_itr_t;
  3699. typedef typename type_map_t::const_iterator tm_const_itr_t;
  3700. enum { lut_size = 256 };
  3701. type_pair_t short_type_lut[lut_size];
  3702. type_map_t map;
  3703. std::size_t size;
  3704. type_store()
  3705. : size(0)
  3706. {}
  3707. inline bool symbol_exists(const std::string& symbol_name) const
  3708. {
  3709. if ((1 == symbol_name.size()) && short_type_lut[static_cast<std::size_t>(symbol_name[0])].second)
  3710. return true;
  3711. else if (map.end() != map.find(symbol_name))
  3712. return true;
  3713. else
  3714. return false;
  3715. }
  3716. inline bool is_constant(const std::string& symbol_name) const
  3717. {
  3718. if (1 == symbol_name.size() && short_type_lut[static_cast<std::size_t>(symbol_name[0])].first)
  3719. return true;
  3720. else
  3721. {
  3722. tm_const_itr_t itr = map.find(symbol_name);
  3723. if (map.end() == itr)
  3724. return false;
  3725. else
  3726. return (*itr).second.first;
  3727. }
  3728. }
  3729. inline bool add(const std::string& symbol_name, RawType& t, const bool is_constant = false)
  3730. {
  3731. struct tie
  3732. {
  3733. static inline std::pair<bool,variable_node_t*> make(T& t,const bool is_constant = false)
  3734. {
  3735. return std::make_pair(is_constant,new variable_node_t(t));
  3736. }
  3737. #ifndef exprtk_disable_string_capabilities
  3738. static inline std::pair<bool,stringvar_node_t*> make(std::string& t,const bool is_constant = false)
  3739. {
  3740. return std::make_pair(is_constant,new stringvar_node_t(t));
  3741. }
  3742. #endif
  3743. static inline std::pair<bool,function_t*> make(function_t& t, const bool is_constant = false)
  3744. {
  3745. return std::make_pair(is_constant,&t);
  3746. }
  3747. };
  3748. if (1 == symbol_name.size())
  3749. {
  3750. short_type_lut[static_cast<std::size_t>(symbol_name[0])] = tie::make(t,is_constant);
  3751. ++size;
  3752. }
  3753. else
  3754. {
  3755. for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
  3756. {
  3757. if (details::imatch(symbol_name,details::reserved_symbols[i]))
  3758. {
  3759. return false;
  3760. }
  3761. }
  3762. tm_itr_t itr = map.find(symbol_name);
  3763. if (map.end() == itr)
  3764. {
  3765. map[symbol_name] = tie::make(t,is_constant);
  3766. ++size;
  3767. }
  3768. }
  3769. return true;
  3770. }
  3771. inline type_ptr get(const std::string& symbol_name)
  3772. {
  3773. if (1 == symbol_name.size())
  3774. {
  3775. type_pair_t& tp = short_type_lut[static_cast<std::size_t>(symbol_name[0])];
  3776. if (tp.second)
  3777. return tp.second;
  3778. else
  3779. return reinterpret_cast<type_ptr>(0);
  3780. }
  3781. else
  3782. {
  3783. tm_const_itr_t itr = map.find(symbol_name);
  3784. if (map.end() == itr)
  3785. return reinterpret_cast<type_ptr>(0);
  3786. else
  3787. return itr->second.second;
  3788. }
  3789. }
  3790. inline bool remove(const std::string& symbol_name)
  3791. {
  3792. if (1 == symbol_name.size())
  3793. {
  3794. type_pair_t& tp = short_type_lut[static_cast<std::size_t>(symbol_name[0])];
  3795. if (0 == tp.second)
  3796. return false;
  3797. struct deleter
  3798. {
  3799. static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
  3800. #ifndef exprtk_disable_string_capabilities
  3801. static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
  3802. #endif
  3803. static inline void process(std::pair<bool,function_t*>&) { }
  3804. };
  3805. deleter::process(tp);
  3806. tp.first = false;
  3807. tp.second = 0;
  3808. --size;
  3809. return true;
  3810. }
  3811. else
  3812. {
  3813. tm_itr_t itr = map.find(symbol_name);
  3814. if (map.end() != itr)
  3815. {
  3816. struct deleter
  3817. {
  3818. static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
  3819. #ifndef exprtk_disable_string_capabilities
  3820. static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
  3821. #endif
  3822. static inline void process(std::pair<bool,function_t*>&) { }
  3823. };
  3824. deleter::process((*itr).second);
  3825. map.erase(itr);
  3826. --size;
  3827. return true;
  3828. }
  3829. else
  3830. return false;
  3831. }
  3832. }
  3833. inline RawType& type_ref(const std::string& symbol_name)
  3834. {
  3835. struct init_type
  3836. {
  3837. static inline double set(long double) { return (0.0); }
  3838. static inline float set(float) { return (0.0f); }
  3839. static inline std::string set(std::string) { return std::string(""); }
  3840. };
  3841. static RawType null_type = init_type::set(RawType());
  3842. if (1 == symbol_name.size())
  3843. {
  3844. type_pair_t& tp = short_type_lut[static_cast<std::size_t>(symbol_name[0])];
  3845. if (tp.second)
  3846. return tp->second.ref();
  3847. else
  3848. return null_type;
  3849. }
  3850. else
  3851. {
  3852. tm_const_itr_t itr = map.find(symbol_name);
  3853. if (map.end() == itr)
  3854. return null_type;
  3855. else
  3856. return itr->second.second->ref();
  3857. }
  3858. }
  3859. inline void clear()
  3860. {
  3861. for (std::size_t i = 0; i < lut_size; ++i)
  3862. {
  3863. if (short_type_lut[i].second)
  3864. {
  3865. delete (short_type_lut[i]).second;
  3866. short_type_lut[i].first = false;
  3867. short_type_lut[i].second = reinterpret_cast<type_ptr>(0);
  3868. }
  3869. }
  3870. if (!map.empty())
  3871. {
  3872. tm_itr_t itr = map.begin();
  3873. tm_itr_t end = map.end();
  3874. while (end != itr)
  3875. {
  3876. struct deleter
  3877. {
  3878. static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; }
  3879. static inline void process(std::pair<bool,function_t*>&) { }
  3880. #ifndef exprtk_disable_string_capabilities
  3881. static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; }
  3882. #endif
  3883. };
  3884. deleter::process((*itr).second);
  3885. ++itr;
  3886. }
  3887. map.clear();
  3888. }
  3889. }
  3890. template <typename Allocator,
  3891. template <typename, typename> class Sequence>
  3892. inline std::size_t get_list(Sequence<std::pair<std::string,RawType>,Allocator>& list) const
  3893. {
  3894. std::size_t count = 0;
  3895. for (std::size_t i = 0; i < lut_size; ++i)
  3896. {
  3897. const type_pair_t& tp = short_type_lut[static_cast<std::size_t>(i)];
  3898. if (0 != tp.second)
  3899. {
  3900. list.push_back(std::make_pair(std::string("") + static_cast<char>(i),tp.second->ref()));
  3901. ++count;
  3902. }
  3903. }
  3904. if (!map.empty())
  3905. {
  3906. tm_const_itr_t itr = map.begin();
  3907. tm_const_itr_t end = map.end();
  3908. while (end != itr)
  3909. {
  3910. list.push_back(std::make_pair((*itr).first,itr->second.second->ref()));
  3911. ++itr;
  3912. ++count;
  3913. }
  3914. }
  3915. return count;
  3916. }
  3917. template <typename Allocator,
  3918. template <typename, typename> class Sequence>
  3919. inline std::size_t get_list(Sequence<std::string,Allocator>& vlist) const
  3920. {
  3921. std::size_t count = 0;
  3922. for (std::size_t i = 0; i < lut_size; ++i)
  3923. {
  3924. const type_pair_t& tp = short_type_lut[static_cast<std::size_t>(i)];
  3925. if (0 != tp.second)
  3926. {
  3927. vlist.push_back(std::string("") + static_cast<char>(i));
  3928. ++count;
  3929. }
  3930. }
  3931. if (!map.empty())
  3932. {
  3933. tm_const_itr_t itr = map.begin();
  3934. tm_const_itr_t end = map.end();
  3935. while (end != itr)
  3936. {
  3937. vlist.push_back((*itr).first);
  3938. ++itr;
  3939. ++count;
  3940. }
  3941. }
  3942. return count;
  3943. }
  3944. };
  3945. typedef typename details::variable_node<T> variable_t;
  3946. typedef variable_t* variable_ptr;
  3947. #ifndef exprtk_disable_string_capabilities
  3948. typedef typename details::stringvar_node<T> stringvar_t;
  3949. typedef stringvar_t* stringvar_ptr;
  3950. #endif
  3951. typedef ifunction<T> function_t;
  3952. typedef function_t* function_ptr;
  3953. static const std::size_t lut_size = 256;
  3954. struct st_holder
  3955. {
  3956. struct st_data
  3957. {
  3958. type_store<typename details::variable_node<T>,T> variable_store;
  3959. #ifndef exprtk_disable_string_capabilities
  3960. type_store<typename details::stringvar_node<T>,std::string> stringvar_store;
  3961. #endif
  3962. type_store<ifunction<T>,ifunction<T> > function_store;
  3963. st_data()
  3964. {
  3965. for (std::size_t i = 0; i < details::reserved_words_size; ++i)
  3966. {
  3967. reserved_symbol_table_.insert(details::reserved_words[i]);
  3968. }
  3969. for (std::size_t i = 0; i < details::reserved_symbols_size; ++i)
  3970. {
  3971. reserved_symbol_table_.insert(details::reserved_symbols[i]);
  3972. }
  3973. }
  3974. inline bool is_reserved_symbol(const std::string& symbol) const
  3975. {
  3976. return (reserved_symbol_table_.end() != reserved_symbol_table_.find(symbol));
  3977. }
  3978. std::list<T> local_symbol_list_;
  3979. std::list<std::string> local_stringvar_list_;
  3980. std::set<std::string> reserved_symbol_table_;
  3981. };
  3982. st_holder()
  3983. : ref_count(1),
  3984. data_(new st_data)
  3985. {}
  3986. st_holder(st_data* data)
  3987. : ref_count(1),
  3988. data_(data)
  3989. {}
  3990. ~st_holder()
  3991. {
  3992. if (data_ && (0 == ref_count))
  3993. {
  3994. delete data_;
  3995. data_ = 0;
  3996. }
  3997. }
  3998. std::size_t ref_count;
  3999. st_data* data_;
  4000. };
  4001. public:
  4002. symbol_table()
  4003. : holder_(new st_holder)
  4004. {
  4005. clear();
  4006. }
  4007. ~symbol_table()
  4008. {
  4009. if (holder_)
  4010. {
  4011. if (0 == --holder_->ref_count)
  4012. {
  4013. clear();
  4014. delete holder_;
  4015. }
  4016. }
  4017. }
  4018. symbol_table(const symbol_table<T>& st)
  4019. {
  4020. holder_ = st.holder_;
  4021. holder_->ref_count++;
  4022. }
  4023. symbol_table<T>& operator=(const symbol_table<T>& st)
  4024. {
  4025. if (holder_)
  4026. {
  4027. if (0 == --holder_->ref_count)
  4028. {
  4029. delete holder_;
  4030. }
  4031. holder_ = 0;
  4032. }
  4033. holder_ = st.holder_;
  4034. holder_->ref_count++;
  4035. return *this;
  4036. }
  4037. inline void clear()
  4038. {
  4039. if (!valid()) return;
  4040. local_data().variable_store.clear();
  4041. local_data().function_store.clear();
  4042. #ifndef exprtk_disable_string_capabilities
  4043. local_data().stringvar_store.clear();
  4044. #endif
  4045. }
  4046. inline std::size_t variable_count() const
  4047. {
  4048. if (valid())
  4049. return local_data().variable_store().size;
  4050. else
  4051. return 0;
  4052. }
  4053. #ifndef exprtk_disable_string_capabilities
  4054. inline std::size_t stringvar_count() const
  4055. {
  4056. if (valid())
  4057. return local_data().stringvar_store().size;
  4058. else
  4059. return 0;
  4060. }
  4061. #endif
  4062. inline std::size_t function_count() const
  4063. {
  4064. if (valid())
  4065. return local_data().function_store().size;
  4066. else
  4067. return 0;
  4068. }
  4069. inline variable_ptr get_variable(const std::string& variable_name)
  4070. {
  4071. if (!valid())
  4072. return reinterpret_cast<variable_ptr>(0);
  4073. else if (!valid_symbol(variable_name))
  4074. return reinterpret_cast<variable_ptr>(0);
  4075. else
  4076. return local_data().variable_store.get(variable_name);
  4077. }
  4078. #ifndef exprtk_disable_string_capabilities
  4079. inline stringvar_ptr get_stringvar(const std::string& string_name)
  4080. {
  4081. if (!valid())
  4082. return reinterpret_cast<stringvar_ptr>(0);
  4083. else if (!valid_symbol(string_name))
  4084. return reinterpret_cast<stringvar_ptr>(0);
  4085. else
  4086. return local_data().stringvar_store.get(string_name);
  4087. }
  4088. #endif
  4089. inline function_ptr get_function(const std::string& function_name)
  4090. {
  4091. if (!valid())
  4092. return reinterpret_cast<function_ptr>(0);
  4093. else if (!valid_symbol(function_name))
  4094. return reinterpret_cast<function_ptr>(0);
  4095. else
  4096. return local_data().function_store.get(function_name);
  4097. }
  4098. inline T& variable_ref(const std::string& symbol_name)
  4099. {
  4100. static T null_var = T(0);
  4101. if (!valid())
  4102. return null_var;
  4103. else if (!valid_symbol(symbol_name))
  4104. return null_var;
  4105. else
  4106. return local_data().variable_store.type_ref(symbol_name);
  4107. }
  4108. #ifndef exprtk_disable_string_capabilities
  4109. inline std::string& stringvar_ref(const std::string& symbol_name)
  4110. {
  4111. static std::string null_stringvar;
  4112. if (!valid())
  4113. return null_stringvar;
  4114. else if (!valid_symbol(symbol_name))
  4115. return null_stringvar;
  4116. else
  4117. return local_data().stringvar_store.type_ref(symbol_name);
  4118. }
  4119. #endif
  4120. inline bool is_constant_node(const std::string& symbol_name) const
  4121. {
  4122. if (!valid())
  4123. return false;
  4124. else if (!valid_symbol(symbol_name))
  4125. return false;
  4126. else if (!local_data().variable_store.symbol_exists(symbol_name))
  4127. return false;
  4128. else
  4129. return local_data().variable_store.is_constant(symbol_name);
  4130. }
  4131. #ifndef exprtk_disable_string_capabilities
  4132. inline bool is_constant_string(const std::string& symbol_name) const
  4133. {
  4134. if (!valid())
  4135. return false;
  4136. else if (!valid_symbol(symbol_name))
  4137. return false;
  4138. else if (!local_data().stringvar_store.symbol_exists(symbol_name))
  4139. return false;
  4140. else
  4141. return local_data().stringvar_store.is_constant(symbol_name);
  4142. }
  4143. #endif
  4144. inline bool create_variable(const std::string& variable_name, const T& value = T(0))
  4145. {
  4146. if (!valid())
  4147. return false;
  4148. else if (!valid_symbol(variable_name))
  4149. return false;
  4150. else if (symbol_exists(variable_name))
  4151. return false;
  4152. local_data().local_symbol_list_.push_back(value);
  4153. T& t = local_data().local_symbol_list_.back();
  4154. return add_variable(variable_name,t);
  4155. }
  4156. #ifndef exprtk_disable_string_capabilities
  4157. inline bool create_stringvar(const std::string& stringvar_name, const std::string& value = std::string(""))
  4158. {
  4159. if (!valid())
  4160. return false;
  4161. else if (!valid_symbol(stringvar_name))
  4162. return false;
  4163. else if (symbol_exists(stringvar_name))
  4164. return false;
  4165. local_data().local_stringvar_list_.push_back(value);
  4166. std::string& s = local_data().local_stringvar_list_.back();
  4167. return add_stringvar(stringvar_name,s);
  4168. }
  4169. #endif
  4170. inline bool add_variable(const std::string& variable_name, T& t, const bool is_constant = false)
  4171. {
  4172. if (!valid())
  4173. return false;
  4174. else if (!valid_symbol(variable_name))
  4175. return false;
  4176. else if (symbol_exists(variable_name))
  4177. return false;
  4178. else
  4179. return local_data().variable_store.add(variable_name,t,is_constant);
  4180. }
  4181. #ifndef exprtk_disable_string_capabilities
  4182. inline bool add_stringvar(const std::string& stringvar_name, std::string& s, const bool is_constant = false)
  4183. {
  4184. if (!valid())
  4185. return false;
  4186. else if (!valid_symbol(stringvar_name))
  4187. return false;
  4188. else if (symbol_exists(stringvar_name))
  4189. return false;
  4190. else
  4191. return local_data().stringvar_store.add(stringvar_name,s,is_constant);
  4192. }
  4193. #endif
  4194. inline bool add_function(const std::string& function_name, function_t& function)
  4195. {
  4196. if (!valid())
  4197. return false;
  4198. else if (!valid_symbol(function_name))
  4199. return false;
  4200. else if (symbol_exists(function_name))
  4201. return false;
  4202. else
  4203. return local_data().function_store.add(function_name,function);
  4204. }
  4205. inline bool remove_variable(const std::string& variable_name)
  4206. {
  4207. if (!valid())
  4208. return false;
  4209. else
  4210. return local_data().variable_store.remove(variable_name);
  4211. }
  4212. #ifndef exprtk_disable_string_capabilities
  4213. inline bool remove_stringvar(const std::string& string_name)
  4214. {
  4215. if (!valid())
  4216. return false;
  4217. else
  4218. return local_data().stringvar_store.remove(string_name);
  4219. }
  4220. #endif
  4221. inline bool remove_function(const std::string& function_name)
  4222. {
  4223. if (!valid())
  4224. return false;
  4225. else
  4226. return local_data().function_store.remove(function_name);
  4227. }
  4228. inline bool add_constants()
  4229. {
  4230. return add_pi() &&
  4231. add_epsilon() &&
  4232. add_infinity();
  4233. }
  4234. inline bool add_pi()
  4235. {
  4236. static T pi = T(details::numeric::constant::pi);
  4237. return add_variable("pi",pi,true);
  4238. }
  4239. inline bool add_epsilon()
  4240. {
  4241. static T epsilon = std::numeric_limits<T>::epsilon();
  4242. return add_variable("epsilon",epsilon,true);
  4243. }
  4244. inline bool add_infinity()
  4245. {
  4246. static T infinity = std::numeric_limits<T>::infinity();
  4247. return add_variable("inf",infinity,true);
  4248. }
  4249. template <typename Allocator,
  4250. template <typename, typename> class Sequence>
  4251. inline std::size_t get_variable_list(Sequence<std::pair<std::string,T>,Allocator>& vlist) const
  4252. {
  4253. if (!valid())
  4254. return 0;
  4255. else
  4256. return local_data().variable_store.get_list(vlist);
  4257. }
  4258. template <typename Allocator,
  4259. template <typename, typename> class Sequence>
  4260. inline std::size_t get_variable_list(Sequence<std::string,Allocator>& vlist) const
  4261. {
  4262. if (!valid())
  4263. return 0;
  4264. else
  4265. return local_data().variable_store.get_list(vlist);
  4266. }
  4267. #ifndef exprtk_disable_string_capabilities
  4268. template <typename Allocator,
  4269. template <typename, typename> class Sequence>
  4270. inline std::size_t get_stringvar_list(Sequence<std::pair<std::string,std::string>,Allocator>& svlist) const
  4271. {
  4272. if (!valid())
  4273. return 0;
  4274. else
  4275. return local_data().stringvar_store.get_list(svlist);
  4276. }
  4277. template <typename Allocator,
  4278. template <typename, typename> class Sequence>
  4279. inline std::size_t get_stringvar_list(Sequence<std::string,Allocator>& svlist) const
  4280. {
  4281. if (!valid())
  4282. return 0;
  4283. else
  4284. return local_data().stringvar_store.get_list(svlist);
  4285. }
  4286. #endif
  4287. inline bool symbol_exists(const std::string& symbol_name) const
  4288. {
  4289. /*
  4290. Will return true if symbol_name exists as either a reserved symbol,
  4291. variable, stringvar or function name in any of the type stores.
  4292. */
  4293. if (!valid())
  4294. return false;
  4295. else if (local_data().variable_store.symbol_exists(symbol_name))
  4296. return true;
  4297. #ifndef exprtk_disable_string_capabilities
  4298. else if (local_data().stringvar_store.symbol_exists(symbol_name))
  4299. return true;
  4300. #endif
  4301. else if (local_data().function_store.symbol_exists(symbol_name))
  4302. return true;
  4303. else if (local_data().is_reserved_symbol(symbol_name))
  4304. return true;
  4305. else
  4306. return false;
  4307. }
  4308. inline bool is_variable(const std::string& variable_name) const
  4309. {
  4310. if (!valid())
  4311. return false;
  4312. else
  4313. return local_data().variable_store.symbol_exists(variable_name);
  4314. }
  4315. #ifndef exprtk_disable_string_capabilities
  4316. inline bool is_stringvar(const std::string& stringvar_name) const
  4317. {
  4318. if (!valid())
  4319. return false;
  4320. else
  4321. return local_data().stringvar_store.symbol_exists(stringvar_name);
  4322. }
  4323. #endif
  4324. inline bool is_function(const std::string& function_name) const
  4325. {
  4326. if (!valid())
  4327. return false;
  4328. else
  4329. return local_data().function_store.symbol_exists(function_name);
  4330. }
  4331. inline bool valid() const
  4332. {
  4333. //symbol table sanity check.
  4334. return holder_ && holder_->data_;
  4335. }
  4336. private:
  4337. inline bool valid_symbol(const std::string& symbol) const
  4338. {
  4339. if (symbol.empty())
  4340. return false;
  4341. if (!details::is_letter(symbol[0]))
  4342. return false;
  4343. else if (symbol.size() > 1)
  4344. {
  4345. for (std::size_t i = 1; i < symbol.size(); ++i)
  4346. {
  4347. if (
  4348. (!details::is_letter(symbol[i])) &&
  4349. (!details:: is_digit(symbol[i])) &&
  4350. ('_' != symbol[i])
  4351. )
  4352. return false;
  4353. }
  4354. }
  4355. return (!local_data().is_reserved_symbol(symbol));
  4356. }
  4357. inline typename st_holder::st_data& local_data()
  4358. {
  4359. return *(holder_->data_);
  4360. }
  4361. inline const typename st_holder::st_data& local_data() const
  4362. {
  4363. return *(holder_->data_);
  4364. }
  4365. st_holder* holder_;
  4366. };
  4367. template <typename T> class parser;
  4368. template <typename T> class expression_helper;
  4369. template <typename T>
  4370. class expression
  4371. {
  4372. private:
  4373. typedef details::expression_node<T>* expression_ptr;
  4374. struct expression_holder
  4375. {
  4376. expression_holder()
  4377. : ref_count(0),
  4378. expr(0)
  4379. {}
  4380. expression_holder(expression_ptr e)
  4381. : ref_count(1),
  4382. expr(e)
  4383. {}
  4384. ~expression_holder()
  4385. {
  4386. if (expr && !is_variable_node(expr))
  4387. {
  4388. delete expr;
  4389. }
  4390. }
  4391. std::size_t ref_count;
  4392. expression_ptr expr;
  4393. };
  4394. public:
  4395. expression()
  4396. : expression_holder_(0)
  4397. {}
  4398. expression(const expression& e)
  4399. {
  4400. expression_holder_ = e.expression_holder_;
  4401. expression_holder_->ref_count++;
  4402. symbol_table_ = e.symbol_table_;
  4403. }
  4404. expression& operator=(const expression& e)
  4405. {
  4406. if (expression_holder_)
  4407. {
  4408. if (0 == --expression_holder_->ref_count)
  4409. {
  4410. delete expression_holder_;
  4411. }
  4412. expression_holder_ = 0;
  4413. }
  4414. expression_holder_ = e.expression_holder_;
  4415. expression_holder_->ref_count++;
  4416. symbol_table_ = e.symbol_table_;
  4417. return *this;
  4418. }
  4419. inline bool operator!() const
  4420. {
  4421. return ((0 == expression_holder_) || (0 == expression_holder_->expr));
  4422. }
  4423. inline expression& release()
  4424. {
  4425. if (expression_holder_)
  4426. {
  4427. if (0 == --expression_holder_->ref_count)
  4428. {
  4429. delete expression_holder_;
  4430. }
  4431. expression_holder_ = 0;
  4432. }
  4433. return *this;
  4434. }
  4435. ~expression()
  4436. {
  4437. if (expression_holder_)
  4438. {
  4439. if (0 == --expression_holder_->ref_count)
  4440. {
  4441. if (!is_variable_node(expression_holder_->expr))
  4442. {
  4443. delete expression_holder_;
  4444. }
  4445. }
  4446. }
  4447. }
  4448. inline T value() const
  4449. {
  4450. if (expression_holder_ && expression_holder_->expr)
  4451. return expression_holder_->expr->value();
  4452. else
  4453. return std::numeric_limits<T>::quiet_NaN();
  4454. }
  4455. inline T operator()() const
  4456. {
  4457. return value();
  4458. }
  4459. inline operator T() const
  4460. {
  4461. return value();
  4462. }
  4463. inline operator bool() const
  4464. {
  4465. return (T(0) != value());
  4466. }
  4467. inline void register_symbol_table(symbol_table<T>& st)
  4468. {
  4469. symbol_table_ = st;
  4470. }
  4471. inline const symbol_table<T>& get_symbol_table() const
  4472. {
  4473. return symbol_table_;
  4474. }
  4475. inline symbol_table<T>& get_symbol_table()
  4476. {
  4477. return symbol_table_;
  4478. }
  4479. private:
  4480. inline void set_expression(const expression_ptr expr)
  4481. {
  4482. if (expr)
  4483. {
  4484. if (expression_holder_)
  4485. {
  4486. if (0 == --expression_holder_->ref_count)
  4487. {
  4488. delete expression_holder_;
  4489. }
  4490. }
  4491. expression_holder_ = new expression_holder(expr);
  4492. }
  4493. }
  4494. expression_holder* expression_holder_;
  4495. symbol_table<T> symbol_table_;
  4496. friend class parser<T>;
  4497. friend class expression_helper<T>;
  4498. };
  4499. template <typename T>
  4500. class expression_helper
  4501. {
  4502. public:
  4503. static inline bool is_head_constant(const expression<T>& expr)
  4504. {
  4505. return details::is_constant_node(expr.expression_holder_->expr);
  4506. }
  4507. static inline bool is_head_variable(const expression<T>& expr)
  4508. {
  4509. return details::is_variable_node(expr.expression_holder_->expr);
  4510. }
  4511. static inline bool is_head_unary(const expression<T>& expr)
  4512. {
  4513. return details::is_unary_node(expr.expression_holder_->expr);
  4514. }
  4515. static inline bool is_head_binary(const expression<T>& expr)
  4516. {
  4517. return details::is_binary_node(expr.expression_holder_->expr);
  4518. }
  4519. static inline bool is_head_function(const expression<T>& expr)
  4520. {
  4521. return details::is_function(expr.expression_holder_->expr);
  4522. }
  4523. };
  4524. template <typename T>
  4525. class parser
  4526. {
  4527. private:
  4528. enum precedence_level
  4529. {
  4530. e_level00,
  4531. e_level01,
  4532. e_level02,
  4533. e_level03,
  4534. e_level04,
  4535. e_level05,
  4536. e_level06,
  4537. e_level07,
  4538. e_level08,
  4539. e_level09,
  4540. e_level10,
  4541. e_level11,
  4542. e_level12,
  4543. e_level13
  4544. };
  4545. typedef ifunction <T> F;
  4546. typedef ifunction <T> ifunction_t;
  4547. typedef details::expression_node <T> expression_node_t;
  4548. typedef details::literal_node <T> literal_node_t;
  4549. typedef details::string_literal_node<T> string_literal_node_t;
  4550. typedef details::unary_node <T> unary_node_t;
  4551. typedef details::binary_node <T> binary_node_t;
  4552. typedef details::trinary_node <T> trinary_node_t;
  4553. typedef details::quaternary_node <T> quaternary_node_t;
  4554. typedef details::quinary_node <T> quinary_node_t;
  4555. typedef details::senary_node <T> senary_node_t;
  4556. typedef details::conditional_node<T> conditional_node_t;
  4557. typedef details::while_loop_node <T> while_loop_node_t;
  4558. typedef details::variable_node <T> variable_node_t;
  4559. #ifndef exprtk_disable_string_capabilities
  4560. typedef details::stringvar_node <T> stringvar_node_t;
  4561. #endif
  4562. typedef details::assignment_node <T> assignment_node_t;
  4563. typedef details::token <T> token_t;
  4564. typedef expression_node_t* expression_node_ptr;
  4565. public:
  4566. enum optimization_level
  4567. {
  4568. e_none = 0,
  4569. e_level1 = 1,
  4570. e_level2 = 2,
  4571. e_level3 = 4,
  4572. e_all = 7
  4573. };
  4574. parser()
  4575. : symbol_name_caching_(false)
  4576. {}
  4577. inline bool compile(const std::string& expression_string, expression<T>& expr, const optimization_level& opt_level = e_all)
  4578. {
  4579. if (!validate_expression(expression_string))
  4580. {
  4581. return false;
  4582. }
  4583. error_description_ = "";
  4584. expression_generator_.set_optimization_level(opt_level);
  4585. expression_generator_.set_allocator(node_allocator_);
  4586. if (!lexer_.process(expression_string))
  4587. {
  4588. set_error(lexer_.error());
  4589. return false;
  4590. }
  4591. symbol_table_ = expr.get_symbol_table();
  4592. symbol_name_cache_.clear();
  4593. next_token();
  4594. expression_node_ptr e = parse_expression();
  4595. if ((0 != e) && (token_t::eof == current_token_.type))
  4596. {
  4597. expr.set_expression(e);
  4598. return !(!expr);
  4599. }
  4600. else
  4601. {
  4602. set_error("parser::compile() - Incomplete expression!");
  4603. symbol_name_cache_.clear();
  4604. if (0 != e) delete e;
  4605. return false;
  4606. }
  4607. }
  4608. inline std::string error() const
  4609. {
  4610. return error_description_;
  4611. }
  4612. inline bool& cache_symbols()
  4613. {
  4614. return symbol_name_caching_;
  4615. }
  4616. template <typename Allocator,
  4617. template <typename,typename> class Sequence>
  4618. inline std::size_t expression_symbols(Sequence<std::string,Allocator>& symbols_list)
  4619. {
  4620. if (!symbol_name_caching_)
  4621. return 0;
  4622. if (symbol_name_cache_.empty())
  4623. return 0;
  4624. std::copy(symbol_name_cache_.begin(),
  4625. symbol_name_cache_.end(),
  4626. std::back_inserter(symbols_list));
  4627. return symbol_name_cache_.size();
  4628. }
  4629. private:
  4630. inline void store_token()
  4631. {
  4632. lexer_.store();
  4633. store_current_token_ = current_token_;
  4634. }
  4635. inline void restore_token()
  4636. {
  4637. lexer_.restore();
  4638. current_token_ = store_current_token_;
  4639. }
  4640. inline void next_token()
  4641. {
  4642. current_token_ = lexer_.next_token();
  4643. }
  4644. static const precedence_level default_precedence = e_level00;
  4645. struct state_t
  4646. {
  4647. inline void set(const precedence_level& l,
  4648. const precedence_level& r,
  4649. const details::operator_type& o)
  4650. {
  4651. left = l;
  4652. right = r;
  4653. operation = o;
  4654. }
  4655. inline void reset()
  4656. {
  4657. left = e_level00;
  4658. right = e_level00;
  4659. }
  4660. precedence_level left;
  4661. precedence_level right;
  4662. details::operator_type operation;
  4663. };
  4664. inline expression_node_ptr parse_expression(precedence_level precedence = e_level00)
  4665. {
  4666. expression_node_ptr expr = parse_branch();
  4667. if (0 == expr)
  4668. {
  4669. return expr;
  4670. }
  4671. bool break_loop = false;
  4672. state_t current_state;
  4673. for ( ; ; )
  4674. {
  4675. current_state.reset();
  4676. switch (current_token_.type)
  4677. {
  4678. case token_t::assign : current_state.set(e_level00,e_level00,details::e_assign); break;
  4679. case token_t::lt : current_state.set(e_level05,e_level06,details:: e_lt); break;
  4680. case token_t::lte : current_state.set(e_level05,e_level06,details:: e_lte); break;
  4681. case token_t::eq : current_state.set(e_level05,e_level06,details:: e_eq); break;
  4682. case token_t::ne : current_state.set(e_level05,e_level06,details:: e_ne); break;
  4683. case token_t::gte : current_state.set(e_level05,e_level06,details:: e_gte); break;
  4684. case token_t::gt : current_state.set(e_level05,e_level06,details:: e_gt); break;
  4685. case token_t::add : current_state.set(e_level07,e_level08,details:: e_add); break;
  4686. case token_t::sub : current_state.set(e_level07,e_level08,details:: e_sub); break;
  4687. case token_t::div : current_state.set(e_level10,e_level11,details:: e_div); break;
  4688. case token_t::mul : current_state.set(e_level10,e_level11,details:: e_mul); break;
  4689. case token_t::mod : current_state.set(e_level10,e_level11,details:: e_mod); break;
  4690. case token_t::pow : current_state.set(e_level12,e_level12,details:: e_pow); break;
  4691. default : if (token_t::symbol == current_token_.type)
  4692. {
  4693. static const std::string s_and = "and";
  4694. static const std::string s_nand = "nand";
  4695. static const std::string s_or = "or";
  4696. static const std::string s_nor = "nor";
  4697. static const std::string s_xor = "xor";
  4698. static const std::string s_in = "in";
  4699. static const std::string s_like = "like";
  4700. static const std::string s_ilike = "ilike";
  4701. if (details::imatch(current_token_.value,s_and))
  4702. {
  4703. current_state.set(e_level01,e_level02,details::e_and);
  4704. break;
  4705. }
  4706. else if (details::imatch(current_token_.value,s_nand))
  4707. {
  4708. current_state.set(e_level01,e_level02,details::e_nand);
  4709. break;
  4710. }
  4711. else if (details::imatch(current_token_.value,s_or))
  4712. {
  4713. current_state.set(e_level03,e_level04,details::e_or);
  4714. break;
  4715. }
  4716. else if (details::imatch(current_token_.value,s_nor))
  4717. {
  4718. current_state.set(e_level03,e_level04,details::e_nor);
  4719. break;
  4720. }
  4721. else if (details::imatch(current_token_.value,s_xor))
  4722. {
  4723. current_state.set(e_level03,e_level04,details::e_xor);
  4724. break;
  4725. }
  4726. else if (details::imatch(current_token_.value,s_in))
  4727. {
  4728. current_state.set(e_level03,e_level04,details::e_in);
  4729. break;
  4730. }
  4731. else if (details::imatch(current_token_.value,s_like))
  4732. {
  4733. current_state.set(e_level03,e_level04,details::e_like);
  4734. break;
  4735. }
  4736. else if (details::imatch(current_token_.value,s_ilike))
  4737. {
  4738. current_state.set(e_level03,e_level04,details::e_ilike);
  4739. break;
  4740. }
  4741. }
  4742. break_loop = true;
  4743. }
  4744. if (break_loop)
  4745. break;
  4746. else if (current_state.left < precedence)
  4747. break;
  4748. next_token();
  4749. expr = expression_generator_(current_state.operation,expr,parse_expression(current_state.right));
  4750. if (0 == expr)
  4751. {
  4752. return expr;
  4753. }
  4754. }
  4755. return expr;
  4756. }
  4757. static inline expression_node_ptr error_node()
  4758. {
  4759. return reinterpret_cast<expression_node_ptr>(0);
  4760. }
  4761. template <typename Type, std::size_t N>
  4762. struct scoped_delete
  4763. {
  4764. typedef Type* ptr_t;
  4765. scoped_delete(parser<T>& pr, ptr_t& p)
  4766. : delete_ptr(true),
  4767. parser_(pr),
  4768. p_(&p)
  4769. {}
  4770. scoped_delete(parser<T>& pr, ptr_t (&p)[N])
  4771. : delete_ptr(true),
  4772. parser_(pr),
  4773. p_(&p[0])
  4774. {}
  4775. ~scoped_delete()
  4776. {
  4777. if (delete_ptr)
  4778. {
  4779. for (std::size_t i = 0; i < N; ++i)
  4780. {
  4781. if (p_[i] && !is_variable_node(p_[i]))
  4782. {
  4783. parser_.node_allocator_.free(p_[i]);
  4784. }
  4785. }
  4786. }
  4787. }
  4788. bool delete_ptr;
  4789. parser<T>& parser_;
  4790. ptr_t* p_;
  4791. private:
  4792. scoped_delete<Type,N>& operator=(const scoped_delete<Type,N>&);
  4793. };
  4794. template <std::size_t NumberofParameters>
  4795. inline expression_node_ptr parse_function_call(const details::operator_type& opt_type)
  4796. {
  4797. expression_node_ptr branch[NumberofParameters];
  4798. expression_node_ptr result = 0;
  4799. std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
  4800. scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
  4801. store_token();
  4802. next_token();
  4803. if (!token_is(token_t::lbracket))
  4804. {
  4805. return error_node();
  4806. }
  4807. for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
  4808. {
  4809. branch[i] = parse_expression();
  4810. if (i < static_cast<int>(NumberofParameters - 1))
  4811. {
  4812. if (!token_is(token_t::comma))
  4813. {
  4814. return error_node();
  4815. }
  4816. }
  4817. }
  4818. if (!token_is(token_t::rbracket))
  4819. {
  4820. return error_node();
  4821. }
  4822. else
  4823. result = expression_generator_(opt_type,branch);
  4824. sd.delete_ptr = false;
  4825. return result;
  4826. }
  4827. template <std::size_t NumberofParameters>
  4828. inline expression_node_ptr parse_function_call(ifunction<T>* function)
  4829. {
  4830. expression_node_ptr branch[NumberofParameters];
  4831. expression_node_ptr result = 0;
  4832. std::fill_n(branch,NumberofParameters,reinterpret_cast<expression_node_ptr>(0));
  4833. scoped_delete<expression_node_t,NumberofParameters> sd(*this,branch);
  4834. next_token();
  4835. if (!token_is(token_t::lbracket))
  4836. {
  4837. return error_node();
  4838. }
  4839. for (int i = 0; i < static_cast<int>(NumberofParameters); ++i)
  4840. {
  4841. branch[i] = parse_expression();
  4842. if (i < static_cast<int>(NumberofParameters - 1))
  4843. {
  4844. if (!token_is(token_t::comma))
  4845. {
  4846. return error_node();
  4847. }
  4848. }
  4849. }
  4850. if (!token_is(token_t::rbracket))
  4851. {
  4852. return error_node();
  4853. }
  4854. else
  4855. result = expression_generator_.function(function,branch);
  4856. sd.delete_ptr = false;
  4857. return result;
  4858. }
  4859. inline expression_node_ptr parse_conditional_statement()
  4860. {
  4861. //Parse: [if][(][condition][,][consequent][,][alternative][)]
  4862. expression_node_ptr condition = 0;
  4863. expression_node_ptr consequent = 0;
  4864. expression_node_ptr alternative = 0;
  4865. next_token();
  4866. if (token_is(token_t::lbracket))
  4867. condition = parse_expression();
  4868. else
  4869. return error_node();
  4870. if (token_is(token_t::comma))
  4871. consequent = parse_expression();
  4872. else
  4873. return error_node();
  4874. if (token_is(token_t::comma))
  4875. alternative = parse_expression();
  4876. else
  4877. return error_node();
  4878. if (token_is(token_t::rbracket))
  4879. return expression_generator_.conditional(condition,consequent,alternative);
  4880. else
  4881. return error_node();
  4882. }
  4883. inline expression_node_ptr parse_while_loop()
  4884. {
  4885. //Parse: [while][(][test expr][)][{][expression][}]
  4886. expression_node_ptr condition = 0;
  4887. expression_node_ptr branch = 0;
  4888. next_token();
  4889. if (token_is(token_t::lbracket))
  4890. condition = parse_expression();
  4891. else
  4892. return error_node();
  4893. if (!token_is(token_t::rbracket))
  4894. return error_node();
  4895. if (token_is(token_t::lcrlbracket))
  4896. branch = parse_expression();
  4897. else
  4898. return error_node();
  4899. if (token_is(token_t::rcrlbracket))
  4900. return expression_generator_.while_loop(condition,branch);
  4901. else
  4902. return error_node();
  4903. }
  4904. inline expression_node_ptr parse_special_function(const unsigned int id)
  4905. {
  4906. //Expect: $fDD(expr0,expr1,expr2) or $fDD(expr0,expr1,expr2,expr3)
  4907. const details::operator_type opt_type = details::operator_type(id + 1000);
  4908. const std::size_t NumberOfParameters = (id < (details::e_sf26 - 1000)) ? 3 : 4;
  4909. expression_node_ptr branch3[3];
  4910. expression_node_ptr branch4[4];
  4911. expression_node_ptr* branch = (id < (details::e_sf26 - 1000)) ? &branch3[0] : &branch4[0];
  4912. expression_node_ptr result = 0;
  4913. std::fill_n(branch3,3,reinterpret_cast<expression_node_ptr>(0));
  4914. std::fill_n(branch4,4,reinterpret_cast<expression_node_ptr>(0));
  4915. scoped_delete<expression_node_t,3> sd3(*this,branch3);
  4916. scoped_delete<expression_node_t,4> sd4(*this,branch4);
  4917. next_token();
  4918. if (!token_is(token_t::lbracket))
  4919. {
  4920. return error_node();
  4921. }
  4922. for (std::size_t i = 0; i < NumberOfParameters; ++i)
  4923. {
  4924. branch[i] = parse_expression();
  4925. if (i < (NumberOfParameters - 1))
  4926. {
  4927. if (!token_is(token_t::comma))
  4928. {
  4929. return error_node();
  4930. }
  4931. }
  4932. }
  4933. if (!token_is(token_t::rbracket))
  4934. return error_node();
  4935. else
  4936. {
  4937. switch (NumberOfParameters)
  4938. {
  4939. case 3 : result = expression_generator_.special_function(opt_type,branch3); break;
  4940. case 4 : result = expression_generator_.special_function(opt_type,branch4); break;
  4941. default : return error_node();
  4942. }
  4943. }
  4944. sd3.delete_ptr = false;
  4945. sd4.delete_ptr = false;
  4946. return result;
  4947. }
  4948. inline expression_node_ptr parse_symbol()
  4949. {
  4950. std::pair<bool,std::string> match_found_error(false,"");
  4951. if (current_token_.value.size() > 1)
  4952. {
  4953. for (std::size_t i = 0; i < details::operation_list_size; ++i)
  4954. {
  4955. if (details::imatch(details::operation_list[i].name,current_token_.value))
  4956. {
  4957. store_token();
  4958. std::string token_value = current_token_.value;
  4959. expression_node_ptr branch = reinterpret_cast<expression_node_ptr>(0);
  4960. switch (details::operation_list[i].num_params)
  4961. {
  4962. case 1 : branch = parse_function_call<1>(details::operation_list[i].type); break;
  4963. case 2 : branch = parse_function_call<2>(details::operation_list[i].type); break;
  4964. case 3 : branch = parse_function_call<3>(details::operation_list[i].type); break;
  4965. case 4 : branch = parse_function_call<4>(details::operation_list[i].type); break;
  4966. case 5 : branch = parse_function_call<5>(details::operation_list[i].type); break;
  4967. case 6 : branch = parse_function_call<6>(details::operation_list[i].type); break;
  4968. }
  4969. if (branch)
  4970. {
  4971. return branch;
  4972. }
  4973. else if (!match_found_error.first)
  4974. {
  4975. match_found_error.first = true;
  4976. match_found_error.second = token_value;
  4977. set_error("");
  4978. }
  4979. restore_token();
  4980. }
  4981. }
  4982. if (match_found_error.first)
  4983. {
  4984. set_error("parser::parse_branch() - invalid argument count for function: " + match_found_error.second);
  4985. return error_node();
  4986. }
  4987. }
  4988. static const std::string symbol_if = "if";
  4989. static const std::string symbol_while = "while";
  4990. if (details::imatch(current_token_.value,symbol_if))
  4991. {
  4992. return parse_conditional_statement();
  4993. }
  4994. else if (details::imatch(current_token_.value,symbol_while))
  4995. {
  4996. return parse_while_loop();
  4997. }
  4998. else if ((current_token_.value.size() == 4) && '$' == current_token_.value[0] && details::imatch('f',current_token_.value[1]))
  4999. {
  5000. unsigned int id = (current_token_.value[2] - '0') * 10 + (current_token_.value[3] - '0');
  5001. if (id <= 99)
  5002. return parse_special_function(id);
  5003. else
  5004. {
  5005. set_error("parser::parse_branch() - invalid special function: " + current_token_.value);
  5006. return error_node();
  5007. }
  5008. }
  5009. else if (symbol_table_.valid())
  5010. {
  5011. const std::string& symbol = current_token_.value;
  5012. //Are we dealing with a variable or a special constant?
  5013. expression_node_ptr variable = symbol_table_.get_variable(symbol);
  5014. if (variable)
  5015. {
  5016. if (symbol_name_caching_)
  5017. {
  5018. symbol_name_cache_.push_back(symbol);
  5019. }
  5020. if (symbol_table_.is_constant_node(symbol))
  5021. {
  5022. variable = expression_generator_(variable->value());
  5023. }
  5024. next_token();
  5025. return variable;
  5026. }
  5027. #ifndef exprtk_disable_string_capabilities
  5028. //Are we dealing with a string variable?
  5029. variable = symbol_table_.get_stringvar(symbol);
  5030. if (variable)
  5031. {
  5032. if (symbol_name_caching_)
  5033. {
  5034. symbol_name_cache_.push_back(symbol);
  5035. }
  5036. if (symbol_table_.is_constant_node(symbol))
  5037. {
  5038. variable = expression_generator_(dynamic_cast<details::string_literal_node<T>*>(variable)->str());
  5039. }
  5040. next_token();
  5041. return variable;
  5042. }
  5043. #endif
  5044. //Are we dealing with a function?
  5045. ifunction<T>* function = symbol_table_.get_function(symbol);
  5046. if (function)
  5047. {
  5048. expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0);
  5049. switch (function->param_count)
  5050. {
  5051. case 0 : func_node = expression_generator_.function(function); break;
  5052. case 1 : func_node = parse_function_call< 1>(function); break;
  5053. case 2 : func_node = parse_function_call< 2>(function); break;
  5054. case 3 : func_node = parse_function_call< 3>(function); break;
  5055. case 4 : func_node = parse_function_call< 4>(function); break;
  5056. case 5 : func_node = parse_function_call< 5>(function); break;
  5057. case 6 : func_node = parse_function_call< 6>(function); break;
  5058. case 7 : func_node = parse_function_call< 7>(function); break;
  5059. case 8 : func_node = parse_function_call< 8>(function); break;
  5060. case 9 : func_node = parse_function_call< 9>(function); break;
  5061. case 10 : func_node = parse_function_call<10>(function); break;
  5062. default : {
  5063. set_error("parser::parse_branch() - invalid number of parameters for function: " + symbol);
  5064. return expression_node_ptr(0);
  5065. }
  5066. }
  5067. if (func_node)
  5068. return func_node;
  5069. else
  5070. {
  5071. set_error("parser::parse_branch() - failed to generate node for function: " + symbol);
  5072. return error_node();
  5073. }
  5074. }
  5075. else
  5076. {
  5077. set_error("parser::parse_branch() - undefined variable or function: " + symbol);
  5078. return error_node();
  5079. }
  5080. }
  5081. else
  5082. {
  5083. set_error("parser::parse_branch() - variable or function detected, yet symbol-table is invalid" + current_token_.value);
  5084. return error_node();
  5085. }
  5086. }
  5087. inline expression_node_ptr parse_branch()
  5088. {
  5089. switch (current_token_.type)
  5090. {
  5091. case token_t::number :
  5092. {
  5093. expression_node_ptr literal_exp = expression_generator_(current_token_.numeric_value);
  5094. next_token();
  5095. return literal_exp;
  5096. }
  5097. case token_t::symbol : return parse_symbol();
  5098. #ifndef exprtk_disable_string_capabilities
  5099. case token_t::string :
  5100. {
  5101. expression_node_ptr literal_exp = expression_generator_(current_token_.value);
  5102. next_token();
  5103. return literal_exp;
  5104. }
  5105. #endif
  5106. case '(' :
  5107. {
  5108. next_token();
  5109. expression_node_ptr branch = parse_expression();
  5110. if (token_is(token_t::rbracket))
  5111. return branch;
  5112. else
  5113. return error_node();
  5114. }
  5115. case '[' :
  5116. {
  5117. next_token();
  5118. expression_node_ptr branch = parse_expression();
  5119. if (token_is(token_t::rsqrbracket))
  5120. return branch;
  5121. else
  5122. return error_node();
  5123. }
  5124. case '{' :
  5125. {
  5126. next_token();
  5127. expression_node_ptr branch = parse_expression();
  5128. if (token_is(token_t::rcrlbracket))
  5129. return branch;
  5130. else
  5131. return error_node();
  5132. }
  5133. case '-' :
  5134. {
  5135. next_token();
  5136. return expression_generator_(details::e_neg,parse_expression(e_level09));
  5137. }
  5138. case '+' :
  5139. {
  5140. next_token();
  5141. return expression_generator_(details::e_pos,parse_expression(e_level09));
  5142. }
  5143. case token_t::eof :
  5144. {
  5145. set_error("parser::parse_branch() - expected a valid branch [1]");
  5146. return error_node();
  5147. }
  5148. default :
  5149. {
  5150. set_error("parser::parse_branch() - expected a valid branch [2]");
  5151. return error_node();
  5152. }
  5153. }
  5154. }
  5155. inline bool token_is(const typename token_t::token_type& ttype)
  5156. {
  5157. if (current_token_.type != ttype)
  5158. {
  5159. if (!((']' == current_token_.type) && (token_t::rbracket == ttype)))
  5160. {
  5161. set_error(std::string("parser::token_is() - expected: ") + static_cast<char>(ttype));
  5162. return false;
  5163. }
  5164. }
  5165. next_token();
  5166. return true;
  5167. }
  5168. template <typename Type>
  5169. class expression_generator
  5170. {
  5171. public:
  5172. typedef details::expression_node<Type>* expression_node_ptr;
  5173. inline void set_optimization_level(const optimization_level& optimization_level)
  5174. {
  5175. optimization_level_ = optimization_level;
  5176. }
  5177. inline void set_allocator(details::node_allocator& na)
  5178. {
  5179. node_allocator_ = &na;
  5180. }
  5181. inline expression_node_ptr operator()(const Type& v) const
  5182. {
  5183. return node_allocator_->allocate<literal_node_t>(v);
  5184. }
  5185. inline expression_node_ptr operator()(const std::string& s) const
  5186. {
  5187. return node_allocator_->allocate<string_literal_node_t>(s);
  5188. }
  5189. inline bool unary_optimizable(const details::operator_type& operation) const
  5190. {
  5191. return (details::e_abs == operation) || (details::e_acos == operation) ||
  5192. (details::e_asin == operation) || (details::e_atan == operation) ||
  5193. (details::e_ceil == operation) || (details::e_cos == operation) ||
  5194. (details::e_cosh == operation) || (details::e_exp == operation) ||
  5195. (details::e_floor == operation) || (details::e_log == operation) ||
  5196. (details::e_log10 == operation) || (details::e_neg == operation) ||
  5197. (details::e_pos == operation) || (details::e_round == operation) ||
  5198. (details::e_sin == operation) || (details::e_sinh == operation) ||
  5199. (details::e_sqrt == operation) || (details::e_tan == operation) ||
  5200. (details::e_tanh == operation) || (details::e_cot == operation) ||
  5201. (details::e_sec == operation) || (details::e_csc == operation) ||
  5202. (details::e_r2d == operation) || (details::e_d2r == operation) ||
  5203. (details::e_d2g == operation) || (details::e_g2d == operation) ||
  5204. (details::e_notl == operation) || (details::e_sgn == operation) ||
  5205. (details::e_erf == operation) || (details::e_erfc == operation);
  5206. }
  5207. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[1])
  5208. {
  5209. if (0 == branch[0])
  5210. return error_node();
  5211. else if (details::is_constant_node(branch[0]))
  5212. return synthesize_expression<unary_node_t,1>(operation,branch);
  5213. else if (unary_optimizable(operation) && details::is_variable_node(branch[0]))
  5214. return synthesize_uv_expression(operation,branch);
  5215. else
  5216. return synthesize_unary_expression(operation,branch);
  5217. }
  5218. #ifndef exprtk_disable_string_capabilities
  5219. inline bool valid_string_operation(const details::operator_type& operation) const
  5220. {
  5221. return (details::e_add == operation) ||
  5222. (details::e_lt == operation) ||
  5223. (details::e_lte == operation) ||
  5224. (details::e_gt == operation) ||
  5225. (details::e_gte == operation) ||
  5226. (details::e_eq == operation) ||
  5227. (details::e_ne == operation) ||
  5228. (details::e_in == operation) ||
  5229. (details::e_like == operation) ||
  5230. (details::e_ilike == operation);
  5231. }
  5232. #else
  5233. inline bool valid_string_operation(const details::operator_type&) const
  5234. {
  5235. return false;
  5236. }
  5237. #endif
  5238. inline bool operation_optimizable(const details::operator_type& operation) const
  5239. {
  5240. return (details::e_add == operation) ||
  5241. (details::e_sub == operation) ||
  5242. (details::e_mul == operation) ||
  5243. (details::e_div == operation) ||
  5244. (details::e_mod == operation) ||
  5245. (details::e_pow == operation) ||
  5246. #ifndef exprtk_disable_extended_operator_optimizations
  5247. (details::e_lt == operation) ||
  5248. (details::e_lte == operation) ||
  5249. (details::e_gt == operation) ||
  5250. (details::e_gte == operation) ||
  5251. (details::e_eq == operation) ||
  5252. (details::e_ne == operation) ||
  5253. (details::e_and == operation) ||
  5254. (details::e_nand == operation) ||
  5255. (details::e_or == operation) ||
  5256. (details::e_nor == operation) ||
  5257. (details::e_xor == operation) ||
  5258. #endif
  5259. false;
  5260. }
  5261. inline bool is_level_optimizable(const std::size_t& level = 0) const
  5262. {
  5263. switch (level)
  5264. {
  5265. case 1 : return (e_level1 == (optimization_level_ & e_level1));
  5266. case 2 : return (e_level2 == (optimization_level_ & e_level2)) && is_level_optimizable(1);
  5267. case 3 : return (e_level3 == (optimization_level_ & e_level3)) && is_level_optimizable(2);
  5268. case 0 : return (e_all == (optimization_level_ & e_all));
  5269. default : return false;
  5270. }
  5271. }
  5272. inline bool cov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5273. {
  5274. if (!operation_optimizable(operation))
  5275. return false;
  5276. else if (!is_level_optimizable(1))
  5277. return false;
  5278. else
  5279. return (details::is_constant_node(branch[0]) && details::is_variable_node(branch[1]));
  5280. }
  5281. inline bool voc_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5282. {
  5283. if (!operation_optimizable(operation))
  5284. return false;
  5285. else if (!is_level_optimizable(1))
  5286. return false;
  5287. else
  5288. return (details::is_variable_node(branch[0]) && details::is_constant_node(branch[1]));
  5289. }
  5290. inline bool vov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5291. {
  5292. if (!operation_optimizable(operation))
  5293. return false;
  5294. else if (!is_level_optimizable(1))
  5295. return false;
  5296. else
  5297. return (details::is_variable_node(branch[0]) && details::is_variable_node(branch[1]));
  5298. }
  5299. inline bool vovov1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5300. {
  5301. if (!operation_optimizable(operation))
  5302. return false;
  5303. else if (!is_level_optimizable(2))
  5304. return false;
  5305. else
  5306. return (details::is_variable_node(branch[0]) && details::is_vov_node(branch[1]));
  5307. }
  5308. inline bool vovov2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5309. {
  5310. if (!operation_optimizable(operation))
  5311. return false;
  5312. else if (!is_level_optimizable(2))
  5313. return false;
  5314. else
  5315. return (details::is_vov_node(branch[0]) && details::is_variable_node(branch[1]));
  5316. }
  5317. inline bool covov1_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5318. {
  5319. if (!operation_optimizable(operation))
  5320. return false;
  5321. else if (!is_level_optimizable(2))
  5322. return false;
  5323. else
  5324. return (details::is_constant_node(branch[0]) && details::is_vov_node(branch[1]));
  5325. }
  5326. inline bool covov2_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5327. {
  5328. if (!operation_optimizable(operation))
  5329. return false;
  5330. else if (!is_level_optimizable(2))
  5331. return false;
  5332. else
  5333. return (details::is_cov_node(branch[0]) && details::is_variable_node(branch[1]));
  5334. }
  5335. inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5336. {
  5337. const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
  5338. const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
  5339. if ((b0_string || b1_string) && !(b0_string && b1_string))
  5340. return true;
  5341. if (!valid_string_operation(operation) && b0_string && b1_string)
  5342. return true;
  5343. else
  5344. return false;
  5345. }
  5346. inline bool is_invalid_string_op(const details::operator_type& operation, expression_node_ptr (&branch)[3])
  5347. {
  5348. bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
  5349. bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
  5350. bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]);
  5351. if ((b0_string || b1_string || b2_string) && !(b0_string && b1_string && b2_string))
  5352. return true;
  5353. if ((details::e_inrange != operation) && b0_string && b1_string && b2_string)
  5354. return true;
  5355. else
  5356. return false;
  5357. }
  5358. inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5359. {
  5360. const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
  5361. const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
  5362. return (b0_string && b1_string && valid_string_operation(operation));
  5363. }
  5364. inline bool is_string_operation(const details::operator_type& operation, expression_node_ptr (&branch)[3])
  5365. {
  5366. const bool b0_string = details::is_string_node(branch[0]) || details::is_const_string_node(branch[0]);
  5367. const bool b1_string = details::is_string_node(branch[1]) || details::is_const_string_node(branch[1]);
  5368. const bool b2_string = details::is_string_node(branch[2]) || details::is_const_string_node(branch[2]);
  5369. return (b0_string && b1_string && b2_string && (details::e_inrange == operation));
  5370. }
  5371. // Note: Extended Optimisations
  5372. // When using older C++ compilers due to the large number of type instantiations
  5373. // required by the extended optimisations the compiler may crash or not be able
  5374. // to compile this translation unit properly.
  5375. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  5376. #if (defined(_MSC_VER) && (_MSC_VER <= 1400))
  5377. #ifndef exprtk_disable_extended_optimisations
  5378. #define exprtk_disable_extended_optimisations
  5379. #endif
  5380. #endif
  5381. #endif
  5382. #ifndef exprtk_disable_extended_optimisations
  5383. inline bool vovovov_optimizable(const details::operator_type& operation, expression_node_ptr (&branch)[2]) const
  5384. {
  5385. if (!operation_optimizable(operation))
  5386. return false;
  5387. else if (!is_level_optimizable(3))
  5388. return false;
  5389. else
  5390. return (details::is_vov_node(branch[0]) && details::is_vov_node(branch[1]));
  5391. }
  5392. #else
  5393. inline bool vovovov_optimizable(const details::operator_type&, expression_node_ptr (&)[2]) const
  5394. {
  5395. return false;
  5396. }
  5397. #endif
  5398. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5399. {
  5400. if ((0 == branch[0]) || (0 == branch[1]))
  5401. return error_node();
  5402. else if (is_invalid_string_op(operation,branch))
  5403. return error_node();
  5404. else if (details::e_assign == operation)
  5405. return synthesize_assignment_expression(operation,branch);
  5406. else if (is_string_operation(operation,branch))
  5407. return synthesize_string_expression(operation,branch);
  5408. else if (cov_optimizable(operation,branch))
  5409. return synthesize_cov_expression(operation,branch);
  5410. else if (voc_optimizable(operation,branch))
  5411. return synthesize_voc_expression(operation,branch);
  5412. else if (vov_optimizable(operation,branch))
  5413. return synthesize_vov_expression(operation,branch);
  5414. else if (vovov1_optimizable(operation,branch))
  5415. return synthesize_vovov1_expression(operation,branch);
  5416. else if (vovov2_optimizable(operation,branch))
  5417. return synthesize_vovov2_expression(operation,branch);
  5418. else if (covov1_optimizable(operation,branch))
  5419. return synthesize_covov1_expression(operation,branch);
  5420. else if (covov2_optimizable(operation,branch))
  5421. return synthesize_covov2_expression(operation,branch);
  5422. else if (vovovov_optimizable(operation,branch))
  5423. return synthesize_vovovov_expression(operation,branch);
  5424. else
  5425. return synthesize_expression<binary_node_t,2>(operation,branch);
  5426. }
  5427. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[3])
  5428. {
  5429. if ((0 == branch[0]) || (0 == branch[1]) || (0 == branch[2]))
  5430. return error_node();
  5431. else if (is_invalid_string_op(operation,branch))
  5432. return error_node();
  5433. else if (is_string_operation(operation,branch))
  5434. return synthesize_string_expression(operation,branch);
  5435. else
  5436. return synthesize_expression<trinary_node_t,3>(operation,branch);
  5437. }
  5438. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[4])
  5439. {
  5440. return synthesize_expression<quaternary_node_t,4>(operation,branch);
  5441. }
  5442. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[5])
  5443. {
  5444. return synthesize_expression<quinary_node_t,5>(operation,branch);
  5445. }
  5446. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr (&branch)[6])
  5447. {
  5448. return synthesize_expression<senary_node_t,6>(operation,branch);
  5449. }
  5450. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0)
  5451. {
  5452. expression_node_ptr branch[1] = { b0 };
  5453. return synthesize_expression<unary_node_t,1>(operation,branch);
  5454. }
  5455. inline expression_node_ptr operator()(const details::operator_type& operation, expression_node_ptr b0, expression_node_ptr b1)
  5456. {
  5457. expression_node_ptr branch[2] = { b0, b1 };
  5458. if ((0 == b0) || (0 == b1))
  5459. return error_node();
  5460. else
  5461. return expression_generator<Type>::operator()(operation,branch);
  5462. }
  5463. inline expression_node_ptr conditional(expression_node_ptr condition,
  5464. expression_node_ptr consequent,
  5465. expression_node_ptr alternative) const
  5466. {
  5467. //Can the condition be immediately evaluated? if so optimize.
  5468. if ((0 == condition) || (0 == consequent) || (0 == alternative))
  5469. return error_node();
  5470. else if (details::is_constant_node(condition))
  5471. {
  5472. // True branch
  5473. if (Type(0) != condition->value())
  5474. {
  5475. node_allocator_->free(condition);
  5476. node_allocator_->free(alternative);
  5477. return consequent;
  5478. }
  5479. // False branch
  5480. else
  5481. {
  5482. node_allocator_->free(condition);
  5483. node_allocator_->free(consequent);
  5484. return alternative;
  5485. }
  5486. }
  5487. else
  5488. return node_allocator_->allocate<conditional_node_t>(condition,consequent,alternative);
  5489. }
  5490. inline expression_node_ptr while_loop(expression_node_ptr condition,
  5491. expression_node_ptr branch) const
  5492. {
  5493. return node_allocator_->allocate<while_loop_node_t>(condition,branch);
  5494. }
  5495. inline expression_node_ptr synthesize_uv_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
  5496. {
  5497. T& v = dynamic_cast<details::variable_node<T>*>(branch[0])->ref();
  5498. switch (operation)
  5499. {
  5500. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<typename details::unary_variable_node<Type,op1<Type> > >(v);
  5501. case_stmt(details:: e_abs,details:: abs_op)
  5502. case_stmt(details:: e_acos,details:: acos_op)
  5503. case_stmt(details:: e_asin,details:: asin_op)
  5504. case_stmt(details:: e_atan,details:: atan_op)
  5505. case_stmt(details:: e_ceil,details:: ceil_op)
  5506. case_stmt(details:: e_cos,details:: cos_op)
  5507. case_stmt(details:: e_cosh,details:: cosh_op)
  5508. case_stmt(details:: e_exp,details:: exp_op)
  5509. case_stmt(details::e_floor,details::floor_op)
  5510. case_stmt(details:: e_log,details:: log_op)
  5511. case_stmt(details::e_log10,details::log10_op)
  5512. case_stmt(details:: e_neg,details:: neg_op)
  5513. case_stmt(details:: e_pos,details:: pos_op)
  5514. case_stmt(details::e_round,details::round_op)
  5515. case_stmt(details:: e_sin,details:: sin_op)
  5516. case_stmt(details:: e_sinh,details:: sinh_op)
  5517. case_stmt(details:: e_sqrt,details:: sqrt_op)
  5518. case_stmt(details:: e_tan,details:: tan_op)
  5519. case_stmt(details:: e_tanh,details:: tanh_op)
  5520. case_stmt(details:: e_cot,details:: cot_op)
  5521. case_stmt(details:: e_sec,details:: sec_op)
  5522. case_stmt(details:: e_csc,details:: csc_op)
  5523. case_stmt(details:: e_r2d,details:: r2d_op)
  5524. case_stmt(details:: e_d2r,details:: d2r_op)
  5525. case_stmt(details:: e_d2g,details:: d2g_op)
  5526. case_stmt(details:: e_g2d,details:: g2d_op)
  5527. case_stmt(details:: e_notl,details:: notl_op)
  5528. case_stmt(details:: e_sgn,details:: sgn_op)
  5529. case_stmt(details:: e_erf,details:: erf_op)
  5530. case_stmt(details:: e_erfc,details:: erfc_op)
  5531. #undef case_stmt
  5532. default : return error_node();
  5533. }
  5534. }
  5535. inline expression_node_ptr synthesize_unary_expression(const details::operator_type& operation, expression_node_ptr (&branch)[1])
  5536. {
  5537. switch (operation)
  5538. {
  5539. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<typename details::unary_branch_node<Type,op1<Type> > >(branch[0]);
  5540. case_stmt(details:: e_abs,details:: abs_op)
  5541. case_stmt(details:: e_acos,details:: acos_op)
  5542. case_stmt(details:: e_asin,details:: asin_op)
  5543. case_stmt(details:: e_atan,details:: atan_op)
  5544. case_stmt(details:: e_ceil,details:: ceil_op)
  5545. case_stmt(details:: e_cos,details:: cos_op)
  5546. case_stmt(details:: e_cosh,details:: cosh_op)
  5547. case_stmt(details:: e_exp,details:: exp_op)
  5548. case_stmt(details::e_floor,details::floor_op)
  5549. case_stmt(details:: e_log,details:: log_op)
  5550. case_stmt(details::e_log10,details::log10_op)
  5551. case_stmt(details:: e_neg,details:: neg_op)
  5552. case_stmt(details:: e_pos,details:: pos_op)
  5553. case_stmt(details::e_round,details::round_op)
  5554. case_stmt(details:: e_sin,details:: sin_op)
  5555. case_stmt(details:: e_sinh,details:: sinh_op)
  5556. case_stmt(details:: e_sqrt,details:: sqrt_op)
  5557. case_stmt(details:: e_tan,details:: tan_op)
  5558. case_stmt(details:: e_tanh,details:: tanh_op)
  5559. case_stmt(details:: e_cot,details:: cot_op)
  5560. case_stmt(details:: e_sec,details:: sec_op)
  5561. case_stmt(details:: e_csc,details:: csc_op)
  5562. case_stmt(details:: e_r2d,details:: r2d_op)
  5563. case_stmt(details:: e_d2r,details:: d2r_op)
  5564. case_stmt(details:: e_d2g,details:: d2g_op)
  5565. case_stmt(details:: e_g2d,details:: g2d_op)
  5566. case_stmt(details:: e_notl,details:: notl_op)
  5567. case_stmt(details:: e_sgn,details:: sgn_op)
  5568. case_stmt(details:: e_erf,details:: erf_op)
  5569. case_stmt(details:: e_erfc,details:: erfc_op)
  5570. #undef case_stmt
  5571. default : return error_node();
  5572. }
  5573. }
  5574. inline expression_node_ptr const_optimize_sf3(const details::operator_type& operation, expression_node_ptr (&branch)[3])
  5575. {
  5576. expression_node_ptr temp_node = error_node();
  5577. switch (operation)
  5578. {
  5579. #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate<details::sf3_node<Type,op1<Type> > >(operation,branch); break;
  5580. case_stmt(details::e_sf00,details::sf00_op)
  5581. case_stmt(details::e_sf01,details::sf01_op)
  5582. case_stmt(details::e_sf02,details::sf02_op)
  5583. case_stmt(details::e_sf03,details::sf03_op)
  5584. case_stmt(details::e_sf04,details::sf04_op)
  5585. case_stmt(details::e_sf05,details::sf05_op)
  5586. case_stmt(details::e_sf06,details::sf06_op)
  5587. case_stmt(details::e_sf07,details::sf07_op)
  5588. case_stmt(details::e_sf08,details::sf08_op)
  5589. case_stmt(details::e_sf09,details::sf09_op)
  5590. case_stmt(details::e_sf10,details::sf10_op)
  5591. case_stmt(details::e_sf11,details::sf11_op)
  5592. case_stmt(details::e_sf12,details::sf12_op)
  5593. case_stmt(details::e_sf13,details::sf13_op)
  5594. case_stmt(details::e_sf14,details::sf14_op)
  5595. case_stmt(details::e_sf15,details::sf15_op)
  5596. case_stmt(details::e_sf16,details::sf16_op)
  5597. case_stmt(details::e_sf17,details::sf17_op)
  5598. case_stmt(details::e_sf18,details::sf18_op)
  5599. case_stmt(details::e_sf19,details::sf19_op)
  5600. case_stmt(details::e_sf20,details::sf20_op)
  5601. case_stmt(details::e_sf21,details::sf21_op)
  5602. case_stmt(details::e_sf22,details::sf22_op)
  5603. case_stmt(details::e_sf23,details::sf23_op)
  5604. case_stmt(details::e_sf24,details::sf24_op)
  5605. case_stmt(details::e_sf25,details::sf25_op)
  5606. #undef case_stmt
  5607. default : return error_node();
  5608. }
  5609. T v = temp_node->value();
  5610. node_allocator_->free(temp_node);
  5611. return node_allocator_->allocate<literal_node_t>(v);
  5612. }
  5613. inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[3])
  5614. {
  5615. if (!all_nodes_valid(branch))
  5616. return error_node();
  5617. else if (is_constant_foldable(branch))
  5618. return const_optimize_sf3(operation,branch);
  5619. switch (operation)
  5620. {
  5621. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf3_node<Type,op1<Type> > >(operation,branch);
  5622. case_stmt(details::e_sf00,details::sf00_op)
  5623. case_stmt(details::e_sf01,details::sf01_op)
  5624. case_stmt(details::e_sf02,details::sf02_op)
  5625. case_stmt(details::e_sf03,details::sf03_op)
  5626. case_stmt(details::e_sf04,details::sf04_op)
  5627. case_stmt(details::e_sf05,details::sf05_op)
  5628. case_stmt(details::e_sf06,details::sf06_op)
  5629. case_stmt(details::e_sf07,details::sf07_op)
  5630. case_stmt(details::e_sf08,details::sf08_op)
  5631. case_stmt(details::e_sf09,details::sf09_op)
  5632. case_stmt(details::e_sf10,details::sf10_op)
  5633. case_stmt(details::e_sf11,details::sf11_op)
  5634. case_stmt(details::e_sf12,details::sf12_op)
  5635. case_stmt(details::e_sf13,details::sf13_op)
  5636. case_stmt(details::e_sf14,details::sf14_op)
  5637. case_stmt(details::e_sf15,details::sf15_op)
  5638. case_stmt(details::e_sf16,details::sf16_op)
  5639. case_stmt(details::e_sf17,details::sf17_op)
  5640. case_stmt(details::e_sf18,details::sf18_op)
  5641. case_stmt(details::e_sf19,details::sf19_op)
  5642. case_stmt(details::e_sf20,details::sf20_op)
  5643. case_stmt(details::e_sf21,details::sf21_op)
  5644. case_stmt(details::e_sf22,details::sf22_op)
  5645. case_stmt(details::e_sf23,details::sf23_op)
  5646. case_stmt(details::e_sf24,details::sf24_op)
  5647. case_stmt(details::e_sf25,details::sf25_op)
  5648. #undef case_stmt
  5649. default : return error_node();
  5650. }
  5651. }
  5652. inline expression_node_ptr const_optimize_sf4(const details::operator_type& operation, expression_node_ptr (&branch)[4])
  5653. {
  5654. expression_node_ptr temp_node = error_node();
  5655. switch (operation)
  5656. {
  5657. #define case_stmt(op0,op1) case op0 : temp_node = node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch); break;
  5658. case_stmt(details::e_sf26,details::sf26_op)
  5659. case_stmt(details::e_sf27,details::sf27_op)
  5660. case_stmt(details::e_sf28,details::sf28_op)
  5661. case_stmt(details::e_sf29,details::sf29_op)
  5662. case_stmt(details::e_sf30,details::sf30_op)
  5663. case_stmt(details::e_sf31,details::sf31_op)
  5664. case_stmt(details::e_sf32,details::sf32_op)
  5665. case_stmt(details::e_sf33,details::sf33_op)
  5666. case_stmt(details::e_sf34,details::sf34_op)
  5667. case_stmt(details::e_sf35,details::sf35_op)
  5668. case_stmt(details::e_sf36,details::sf36_op)
  5669. case_stmt(details::e_sf37,details::sf37_op)
  5670. case_stmt(details::e_sf38,details::sf38_op)
  5671. case_stmt(details::e_sf39,details::sf39_op)
  5672. case_stmt(details::e_sf40,details::sf40_op)
  5673. case_stmt(details::e_sf41,details::sf41_op)
  5674. case_stmt(details::e_sf42,details::sf42_op)
  5675. case_stmt(details::e_sf43,details::sf43_op)
  5676. case_stmt(details::e_sf44,details::sf44_op)
  5677. case_stmt(details::e_sf45,details::sf45_op)
  5678. case_stmt(details::e_sf46,details::sf46_op)
  5679. case_stmt(details::e_sf47,details::sf47_op)
  5680. case_stmt(details::e_sf48,details::sf48_op)
  5681. case_stmt(details::e_sf49,details::sf49_op)
  5682. case_stmt(details::e_sf50,details::sf50_op)
  5683. case_stmt(details::e_sf51,details::sf51_op)
  5684. case_stmt(details::e_sf52,details::sf52_op)
  5685. case_stmt(details::e_sf53,details::sf53_op)
  5686. case_stmt(details::e_sf54,details::sf54_op)
  5687. case_stmt(details::e_sf55,details::sf55_op)
  5688. case_stmt(details::e_sf56,details::sf56_op)
  5689. case_stmt(details::e_sf57,details::sf57_op)
  5690. case_stmt(details::e_sf58,details::sf58_op)
  5691. #undef case_stmt
  5692. default : return error_node();
  5693. }
  5694. T v = temp_node->value();
  5695. node_allocator_->free(temp_node);
  5696. return node_allocator_->allocate<literal_node_t>(v);
  5697. }
  5698. inline expression_node_ptr special_function(const details::operator_type& operation, expression_node_ptr (&branch)[4])
  5699. {
  5700. if (!all_nodes_valid(branch))
  5701. return error_node();
  5702. else if (is_constant_foldable(branch))
  5703. return const_optimize_sf4(operation,branch);
  5704. switch (operation)
  5705. {
  5706. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate<details::sf4_node<Type,op1<Type> > >(operation,branch);
  5707. case_stmt(details::e_sf26,details::sf26_op)
  5708. case_stmt(details::e_sf27,details::sf27_op)
  5709. case_stmt(details::e_sf28,details::sf28_op)
  5710. case_stmt(details::e_sf29,details::sf29_op)
  5711. case_stmt(details::e_sf30,details::sf30_op)
  5712. case_stmt(details::e_sf31,details::sf31_op)
  5713. case_stmt(details::e_sf32,details::sf32_op)
  5714. case_stmt(details::e_sf33,details::sf33_op)
  5715. case_stmt(details::e_sf34,details::sf34_op)
  5716. case_stmt(details::e_sf35,details::sf35_op)
  5717. case_stmt(details::e_sf36,details::sf36_op)
  5718. case_stmt(details::e_sf37,details::sf37_op)
  5719. case_stmt(details::e_sf38,details::sf38_op)
  5720. case_stmt(details::e_sf39,details::sf39_op)
  5721. case_stmt(details::e_sf40,details::sf40_op)
  5722. case_stmt(details::e_sf41,details::sf41_op)
  5723. case_stmt(details::e_sf42,details::sf42_op)
  5724. case_stmt(details::e_sf43,details::sf43_op)
  5725. case_stmt(details::e_sf44,details::sf44_op)
  5726. case_stmt(details::e_sf45,details::sf45_op)
  5727. case_stmt(details::e_sf46,details::sf46_op)
  5728. case_stmt(details::e_sf47,details::sf47_op)
  5729. case_stmt(details::e_sf48,details::sf48_op)
  5730. case_stmt(details::e_sf49,details::sf49_op)
  5731. case_stmt(details::e_sf50,details::sf50_op)
  5732. case_stmt(details::e_sf51,details::sf51_op)
  5733. case_stmt(details::e_sf52,details::sf52_op)
  5734. case_stmt(details::e_sf53,details::sf53_op)
  5735. case_stmt(details::e_sf54,details::sf54_op)
  5736. case_stmt(details::e_sf55,details::sf55_op)
  5737. case_stmt(details::e_sf56,details::sf56_op)
  5738. case_stmt(details::e_sf57,details::sf57_op)
  5739. case_stmt(details::e_sf58,details::sf58_op)
  5740. #undef case_stmt
  5741. default : return error_node();
  5742. }
  5743. }
  5744. template <std::size_t N>
  5745. inline expression_node_ptr function(ifunction_t* f, expression_node_ptr (&b)[N])
  5746. {
  5747. typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
  5748. expression_node_ptr result = synthesize_expression<function_N_node_t,N>(f,b);
  5749. if (0 == result)
  5750. return error_node();
  5751. else
  5752. {
  5753. //has the function call been completely optimized?
  5754. if (details::is_constant_node(result))
  5755. return result;
  5756. else if (!all_nodes_valid(b))
  5757. return error_node();
  5758. else if (N != f->param_count)
  5759. return error_node();
  5760. function_N_node_t* func_node_ptr = dynamic_cast<function_N_node_t*>(result);
  5761. if (func_node_ptr)
  5762. {
  5763. if (func_node_ptr->init_branches(b))
  5764. return result;
  5765. else
  5766. return error_node();
  5767. }
  5768. else
  5769. return error_node();
  5770. }
  5771. }
  5772. inline expression_node_ptr function(ifunction_t* f)
  5773. {
  5774. typedef typename details::function_N_node<T,ifunction_t,0> function_N_node_t;
  5775. return node_allocator_->allocate<function_N_node_t>(f);
  5776. }
  5777. private:
  5778. template <std::size_t N, typename NodePtr>
  5779. inline bool is_constant_foldable(NodePtr (&b)[N]) const
  5780. {
  5781. for (std::size_t i = 0; i < N; ++i)
  5782. {
  5783. if (0 == b[i])
  5784. return false;
  5785. else if (!details::is_constant_node(b[i]))
  5786. return false;
  5787. }
  5788. return true;
  5789. }
  5790. template <std::size_t N>
  5791. inline bool all_nodes_valid(expression_node_ptr (&b)[N]) const
  5792. {
  5793. for (std::size_t i = 0; i < N; ++i)
  5794. {
  5795. if (0 == b[i]) return false;
  5796. }
  5797. return true;
  5798. }
  5799. inline expression_node_ptr synthesize_assignment_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5800. {
  5801. if (details::is_variable_node(branch[0]))
  5802. return synthesize_expression<assignment_node_t,2>(operation,branch);
  5803. else
  5804. return error_node();
  5805. }
  5806. inline expression_node_ptr synthesize_cov_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5807. {
  5808. T c = dynamic_cast<details::literal_node<T>* >(branch[0])->value();
  5809. T& v = dynamic_cast<details::variable_node<T>*>(branch[1])->ref();
  5810. node_allocator_->free(branch[0]);
  5811. switch (operation)
  5812. {
  5813. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_cr<typename details::cov_node<Type,op1<Type> > >(c,v);
  5814. case_stmt(details:: e_add,details:: add_op)
  5815. case_stmt(details:: e_sub,details:: sub_op)
  5816. case_stmt(details:: e_mul,details:: mul_op)
  5817. case_stmt(details:: e_div,details:: div_op)
  5818. case_stmt(details:: e_mod,details:: mod_op)
  5819. case_stmt(details:: e_pow,details:: pow_op)
  5820. #ifndef exprtk_disable_extended_operator_optimizations
  5821. case_stmt(details:: e_lt,details:: lt_op)
  5822. case_stmt(details:: e_lte,details:: lte_op)
  5823. case_stmt(details:: e_gt,details:: gt_op)
  5824. case_stmt(details:: e_gte,details:: gte_op)
  5825. case_stmt(details:: e_eq,details:: eq_op)
  5826. case_stmt(details:: e_ne,details:: ne_op)
  5827. case_stmt(details:: e_and,details:: and_op)
  5828. case_stmt(details::e_nand,details::nand_op)
  5829. case_stmt(details:: e_or,details:: or_op)
  5830. case_stmt(details:: e_nor,details:: nor_op)
  5831. case_stmt(details:: e_xor,details:: xor_op)
  5832. #endif
  5833. #undef case_stmt
  5834. default : return error_node();
  5835. }
  5836. }
  5837. #ifndef exprtk_disable_cardinal_pow_optimisation
  5838. inline expression_node_ptr cardinal_pow_optimization(T& v, const T& c)
  5839. {
  5840. const bool not_recipricol = (c >= T(0.0));
  5841. const unsigned int p = static_cast<unsigned int>(std::abs(c));
  5842. if (0 == p)
  5843. return node_allocator_->allocate_c<literal_node_t>(T(1.0));
  5844. else
  5845. {
  5846. switch(p)
  5847. {
  5848. #define case_stmt(cp) case cp : return node_allocator_->allocate_rc<typename details::ipow_node<T,details::numeric::fast_exp<T,cp> > >(v,not_recipricol);
  5849. case_stmt( 1) case_stmt( 2) case_stmt( 3) case_stmt( 4)
  5850. case_stmt( 5) case_stmt( 6) case_stmt( 7) case_stmt( 8)
  5851. case_stmt( 9) case_stmt(10) case_stmt(11) case_stmt(12)
  5852. case_stmt(13) case_stmt(14) case_stmt(15) case_stmt(16)
  5853. case_stmt(17) case_stmt(18) case_stmt(19) case_stmt(20)
  5854. case_stmt(21) case_stmt(22) case_stmt(23) case_stmt(24)
  5855. case_stmt(25) case_stmt(26) case_stmt(27) case_stmt(28)
  5856. case_stmt(29) case_stmt(30) case_stmt(31) case_stmt(32)
  5857. case_stmt(33) case_stmt(34) case_stmt(35) case_stmt(36)
  5858. case_stmt(37) case_stmt(38) case_stmt(39) case_stmt(40)
  5859. case_stmt(41) case_stmt(42) case_stmt(43) case_stmt(44)
  5860. case_stmt(45) case_stmt(46) case_stmt(47) case_stmt(48)
  5861. case_stmt(49) case_stmt(50) case_stmt(51) case_stmt(52)
  5862. case_stmt(53) case_stmt(54) case_stmt(55) case_stmt(56)
  5863. case_stmt(57) case_stmt(58) case_stmt(59) case_stmt(60)
  5864. #undef case_stmt
  5865. default : return error_node();
  5866. }
  5867. }
  5868. }
  5869. inline bool cardinal_pow_optimizable(const details::operator_type& operation, const T& c)
  5870. {
  5871. return (details::e_pow == operation) && (std::abs(c) <= T(60.0)) && details::numeric::is_integer(c);
  5872. }
  5873. #else
  5874. inline expression_node_ptr cardinal_pow_optimization(T&, const T&)
  5875. {
  5876. return error_node();
  5877. }
  5878. inline bool cardinal_pow_optimizable(const details::operator_type&, const T&)
  5879. {
  5880. return false;
  5881. }
  5882. #endif
  5883. inline expression_node_ptr synthesize_voc_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5884. {
  5885. T& v = dynamic_cast<details::variable_node<T>*>(branch[0])->ref();
  5886. T c = dynamic_cast<details::literal_node<T>* >(branch[1])->value();
  5887. node_allocator_->free(branch[1]);
  5888. if (cardinal_pow_optimizable(operation,c))
  5889. {
  5890. return cardinal_pow_optimization(v,c);
  5891. }
  5892. switch (operation)
  5893. {
  5894. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rc<typename details::voc_node<Type,op1<Type> > >(v,c);
  5895. case_stmt(details:: e_add,details:: add_op)
  5896. case_stmt(details:: e_sub,details:: sub_op)
  5897. case_stmt(details:: e_mul,details:: mul_op)
  5898. case_stmt(details:: e_div,details:: div_op)
  5899. case_stmt(details:: e_mod,details:: mod_op)
  5900. case_stmt(details:: e_pow,details:: pow_op)
  5901. #ifndef exprtk_disable_extended_operator_optimizations
  5902. case_stmt(details:: e_lt,details:: lt_op)
  5903. case_stmt(details:: e_lte,details:: lte_op)
  5904. case_stmt(details:: e_gt,details:: gt_op)
  5905. case_stmt(details:: e_gte,details:: gte_op)
  5906. case_stmt(details:: e_eq,details:: eq_op)
  5907. case_stmt(details:: e_ne,details:: ne_op)
  5908. case_stmt(details:: e_and,details:: and_op)
  5909. case_stmt(details::e_nand,details::nand_op)
  5910. case_stmt(details:: e_or,details:: or_op)
  5911. case_stmt(details:: e_nor,details:: nor_op)
  5912. case_stmt(details:: e_xor,details:: xor_op)
  5913. #endif
  5914. #undef case_stmt
  5915. default : return error_node();
  5916. }
  5917. }
  5918. inline expression_node_ptr synthesize_vov_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5919. {
  5920. Type& v1 = dynamic_cast<details::variable_node<Type>*>(branch[0])->ref();
  5921. Type& v2 = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
  5922. switch (operation)
  5923. {
  5924. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::vov_node<Type,op1<Type> > >(v1,v2);
  5925. case_stmt(details:: e_add,details:: add_op)
  5926. case_stmt(details:: e_sub,details:: sub_op)
  5927. case_stmt(details:: e_mul,details:: mul_op)
  5928. case_stmt(details:: e_div,details:: div_op)
  5929. case_stmt(details:: e_mod,details:: mod_op)
  5930. case_stmt(details:: e_pow,details:: pow_op)
  5931. #ifndef exprtk_disable_extended_operator_optimizations
  5932. case_stmt(details:: e_lt,details:: lt_op)
  5933. case_stmt(details:: e_lte,details:: lte_op)
  5934. case_stmt(details:: e_gt,details:: gt_op)
  5935. case_stmt(details:: e_gte,details:: gte_op)
  5936. case_stmt(details:: e_eq,details:: eq_op)
  5937. case_stmt(details:: e_ne,details:: ne_op)
  5938. case_stmt(details:: e_and,details:: and_op)
  5939. case_stmt(details::e_nand,details::nand_op)
  5940. case_stmt(details:: e_or,details:: or_op)
  5941. case_stmt(details:: e_nor,details:: nor_op)
  5942. case_stmt(details:: e_xor,details:: xor_op)
  5943. #endif
  5944. #undef case_stmt
  5945. default : return error_node();
  5946. }
  5947. }
  5948. template <typename Operation1>
  5949. inline expression_node_ptr synthesize_vovov1_expression_impl(Type& v0, expression_node_ptr node)
  5950. {
  5951. details::operator_type op = dynamic_cast<details::vov_base_node<Type>*>(node)->operation();
  5952. switch (op)
  5953. {
  5954. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::vovov1_node<Type,Operation1,op1<Type> > >(v0,(*dynamic_cast<details::vov_node<T,op1<Type> >*>(node)));
  5955. case_stmt(details:: e_add,details:: add_op)
  5956. case_stmt(details:: e_sub,details:: sub_op)
  5957. case_stmt(details:: e_mul,details:: mul_op)
  5958. case_stmt(details:: e_div,details:: div_op)
  5959. case_stmt(details:: e_mod,details:: mod_op)
  5960. case_stmt(details:: e_pow,details:: pow_op)
  5961. #ifndef exprtk_disable_extended_operator_optimizations
  5962. case_stmt(details:: e_lt,details:: lt_op)
  5963. case_stmt(details:: e_lte,details:: lte_op)
  5964. case_stmt(details:: e_gt,details:: gt_op)
  5965. case_stmt(details:: e_gte,details:: gte_op)
  5966. case_stmt(details:: e_eq,details:: eq_op)
  5967. case_stmt(details:: e_ne,details:: ne_op)
  5968. case_stmt(details:: e_and,details:: and_op)
  5969. case_stmt(details::e_nand,details::nand_op)
  5970. case_stmt(details:: e_or,details:: or_op)
  5971. case_stmt(details:: e_nor,details:: nor_op)
  5972. case_stmt(details:: e_xor,details:: xor_op)
  5973. #endif
  5974. #undef case_stmt
  5975. default : return error_node();
  5976. }
  5977. }
  5978. inline expression_node_ptr synthesize_vovov1_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  5979. {
  5980. T& v0 = dynamic_cast<details::variable_node<T>*>(branch[0])->ref();
  5981. expression_node_ptr result = error_node();
  5982. switch (operation)
  5983. {
  5984. #define case_stmt(op0,op1) case op0 : result = synthesize_vovov1_expression_impl<op1<Type> >(v0,branch[1]); break;
  5985. case_stmt(details:: e_add,details:: add_op)
  5986. case_stmt(details:: e_sub,details:: sub_op)
  5987. case_stmt(details:: e_mul,details:: mul_op)
  5988. case_stmt(details:: e_div,details:: div_op)
  5989. case_stmt(details:: e_mod,details:: mod_op)
  5990. case_stmt(details:: e_pow,details:: pow_op)
  5991. #ifndef exprtk_disable_extended_operator_optimizations
  5992. case_stmt(details:: e_lt,details:: lt_op)
  5993. case_stmt(details:: e_lte,details:: lte_op)
  5994. case_stmt(details:: e_gt,details:: gt_op)
  5995. case_stmt(details:: e_gte,details:: gte_op)
  5996. case_stmt(details:: e_eq,details:: eq_op)
  5997. case_stmt(details:: e_ne,details:: ne_op)
  5998. case_stmt(details:: e_and,details:: and_op)
  5999. case_stmt(details::e_nand,details::nand_op)
  6000. case_stmt(details:: e_or,details:: or_op)
  6001. case_stmt(details:: e_nor,details:: nor_op)
  6002. case_stmt(details:: e_xor,details:: xor_op)
  6003. #endif
  6004. #undef case_stmt
  6005. default : return error_node();
  6006. }
  6007. node_allocator_->free(branch[1]);
  6008. return result;
  6009. }
  6010. template <typename Operation1>
  6011. inline expression_node_ptr synthesize_vovov2_expression_impl(T& v0, expression_node_ptr node)
  6012. {
  6013. details::operator_type op = dynamic_cast<details::vov_base_node<T>*>(node)->operation();
  6014. switch (op)
  6015. {
  6016. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::vovov2_node<T,op1<T>,Operation1> >((*dynamic_cast<details::vov_node<T,op1<T> >*>(node)),v0);
  6017. case_stmt(details:: e_add,details:: add_op)
  6018. case_stmt(details:: e_sub,details:: sub_op)
  6019. case_stmt(details:: e_mul,details:: mul_op)
  6020. case_stmt(details:: e_div,details:: div_op)
  6021. case_stmt(details:: e_mod,details:: mod_op)
  6022. case_stmt(details:: e_pow,details:: pow_op)
  6023. #ifndef exprtk_disable_extended_operator_optimizations
  6024. case_stmt(details:: e_lt,details:: lt_op)
  6025. case_stmt(details:: e_lte,details:: lte_op)
  6026. case_stmt(details:: e_gt,details:: gt_op)
  6027. case_stmt(details:: e_gte,details:: gte_op)
  6028. case_stmt(details:: e_eq,details:: eq_op)
  6029. case_stmt(details:: e_ne,details:: ne_op)
  6030. case_stmt(details:: e_and,details:: and_op)
  6031. case_stmt(details::e_nand,details::nand_op)
  6032. case_stmt(details:: e_or,details:: or_op)
  6033. case_stmt(details:: e_nor,details:: nor_op)
  6034. case_stmt(details:: e_xor,details:: xor_op)
  6035. #endif
  6036. #undef case_stmt
  6037. default : return error_node();
  6038. }
  6039. }
  6040. inline expression_node_ptr synthesize_vovov2_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  6041. {
  6042. T& v0 = dynamic_cast<details::variable_node<T>*>(branch[1])->ref();
  6043. expression_node_ptr result = error_node();
  6044. switch (operation)
  6045. {
  6046. #define case_stmt(op0,op1) case op0 : result = synthesize_vovov2_expression_impl<op1<Type> >(v0,branch[0]); break;
  6047. case_stmt(details:: e_add,details:: add_op)
  6048. case_stmt(details:: e_sub,details:: sub_op)
  6049. case_stmt(details:: e_mul,details:: mul_op)
  6050. case_stmt(details:: e_div,details:: div_op)
  6051. case_stmt(details:: e_mod,details:: mod_op)
  6052. case_stmt(details:: e_pow,details:: pow_op)
  6053. #ifndef exprtk_disable_extended_operator_optimizations
  6054. case_stmt(details:: e_lt,details:: lt_op)
  6055. case_stmt(details:: e_lte,details:: lte_op)
  6056. case_stmt(details:: e_gt,details:: gt_op)
  6057. case_stmt(details:: e_gte,details:: gte_op)
  6058. case_stmt(details:: e_eq,details:: eq_op)
  6059. case_stmt(details:: e_ne,details:: ne_op)
  6060. case_stmt(details:: e_and,details:: and_op)
  6061. case_stmt(details::e_nand,details::nand_op)
  6062. case_stmt(details:: e_or,details:: or_op)
  6063. case_stmt(details:: e_nor,details:: nor_op)
  6064. case_stmt(details:: e_xor,details:: xor_op)
  6065. #endif
  6066. #undef case_stmt
  6067. default : return error_node();
  6068. }
  6069. node_allocator_->free(branch[0]);
  6070. return result;
  6071. }
  6072. template <typename Operation1>
  6073. inline expression_node_ptr synthesize_covov1_expression_impl(const T& c, expression_node_ptr node)
  6074. {
  6075. details::operator_type op = dynamic_cast<details::vov_base_node<T>*>(node)->operation();
  6076. switch (op)
  6077. {
  6078. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::covov1_node<Type,Operation1,op1<Type> > >(c,(*dynamic_cast<details::vov_node<T,op1<T> >*>(node)));
  6079. case_stmt(details:: e_add,details:: add_op)
  6080. case_stmt(details:: e_sub,details:: sub_op)
  6081. case_stmt(details:: e_mul,details:: mul_op)
  6082. case_stmt(details:: e_div,details:: div_op)
  6083. case_stmt(details:: e_mod,details:: mod_op)
  6084. case_stmt(details:: e_pow,details:: pow_op)
  6085. #ifndef exprtk_disable_extended_operator_optimizations
  6086. case_stmt(details:: e_lt,details:: lt_op)
  6087. case_stmt(details:: e_lte,details:: lte_op)
  6088. case_stmt(details:: e_gt,details:: gt_op)
  6089. case_stmt(details:: e_gte,details:: gte_op)
  6090. case_stmt(details:: e_eq,details:: eq_op)
  6091. case_stmt(details:: e_ne,details:: ne_op)
  6092. case_stmt(details:: e_and,details:: and_op)
  6093. case_stmt(details::e_nand,details::nand_op)
  6094. case_stmt(details:: e_or,details:: or_op)
  6095. case_stmt(details:: e_nor,details:: nor_op)
  6096. case_stmt(details:: e_xor,details:: xor_op)
  6097. #endif
  6098. #undef case_stmt
  6099. default : return error_node();
  6100. }
  6101. }
  6102. inline expression_node_ptr synthesize_covov1_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  6103. {
  6104. T c = dynamic_cast<details::literal_node<Type>*>(branch[0])->value();
  6105. expression_node_ptr result = error_node();
  6106. switch (operation)
  6107. {
  6108. #define case_stmt(op0,op1) case op0 : result = synthesize_covov1_expression_impl<op1<Type> >(c,branch[1]); break;
  6109. case_stmt(details:: e_add,details:: add_op)
  6110. case_stmt(details:: e_sub,details:: sub_op)
  6111. case_stmt(details:: e_mul,details:: mul_op)
  6112. case_stmt(details:: e_div,details:: div_op)
  6113. case_stmt(details:: e_mod,details:: mod_op)
  6114. case_stmt(details:: e_pow,details:: pow_op)
  6115. #ifndef exprtk_disable_extended_operator_optimizations
  6116. case_stmt(details:: e_lt,details:: lt_op)
  6117. case_stmt(details:: e_lte,details:: lte_op)
  6118. case_stmt(details:: e_gt,details:: gt_op)
  6119. case_stmt(details:: e_gte,details:: gte_op)
  6120. case_stmt(details:: e_eq,details:: eq_op)
  6121. case_stmt(details:: e_ne,details:: ne_op)
  6122. case_stmt(details:: e_and,details:: and_op)
  6123. case_stmt(details::e_nand,details::nand_op)
  6124. case_stmt(details:: e_or,details:: or_op)
  6125. case_stmt(details:: e_nor,details:: nor_op)
  6126. case_stmt(details:: e_xor,details:: xor_op)
  6127. #endif
  6128. #undef case_stmt
  6129. default : return error_node();
  6130. }
  6131. node_allocator_->free(branch[1]);
  6132. return result;
  6133. }
  6134. template <typename Operation2>
  6135. inline expression_node_ptr synthesize_covov2_expression_impl(expression_node_ptr node, T& v)
  6136. {
  6137. details::operator_type op = dynamic_cast<details::cov_base_node<T>*>(node)->operation();
  6138. switch (op)
  6139. {
  6140. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::covov2_node<Type,op1<T>,Operation2> >((*dynamic_cast<details::cov_node<T,op1<T> >*>(node)),v);
  6141. case_stmt(details:: e_add,details:: add_op)
  6142. case_stmt(details:: e_sub,details:: sub_op)
  6143. case_stmt(details:: e_mul,details:: mul_op)
  6144. case_stmt(details:: e_div,details:: div_op)
  6145. case_stmt(details:: e_mod,details:: mod_op)
  6146. case_stmt(details:: e_pow,details:: pow_op)
  6147. #ifndef exprtk_disable_extended_operator_optimizations
  6148. case_stmt(details:: e_lt,details:: lt_op)
  6149. case_stmt(details:: e_lte,details:: lte_op)
  6150. case_stmt(details:: e_gt,details:: gt_op)
  6151. case_stmt(details:: e_gte,details:: gte_op)
  6152. case_stmt(details:: e_eq,details:: eq_op)
  6153. case_stmt(details:: e_ne,details:: ne_op)
  6154. case_stmt(details:: e_and,details:: and_op)
  6155. case_stmt(details::e_nand,details::nand_op)
  6156. case_stmt(details:: e_or,details:: or_op)
  6157. case_stmt(details:: e_nor,details:: nor_op)
  6158. case_stmt(details:: e_xor,details:: xor_op)
  6159. #endif
  6160. #undef case_stmt
  6161. default : return error_node();
  6162. }
  6163. }
  6164. inline expression_node_ptr synthesize_covov2_expression(const details::operator_type& operation, expression_node_ptr (&branch)[2])
  6165. {
  6166. T& v = dynamic_cast<details::variable_node<Type>*>(branch[1])->ref();
  6167. expression_node_ptr result = error_node();
  6168. switch (operation)
  6169. {
  6170. #define case_stmt(op0,op1) case op0 : result = synthesize_covov2_expression_impl<op1<Type> >(branch[0],v); break;
  6171. case_stmt(details:: e_add,details:: add_op)
  6172. case_stmt(details:: e_sub,details:: sub_op)
  6173. case_stmt(details:: e_mul,details:: mul_op)
  6174. case_stmt(details:: e_div,details:: div_op)
  6175. case_stmt(details:: e_mod,details:: mod_op)
  6176. case_stmt(details:: e_pow,details:: pow_op)
  6177. #ifndef exprtk_disable_extended_operator_optimizations
  6178. case_stmt(details:: e_lt,details:: lt_op)
  6179. case_stmt(details:: e_lte,details:: lte_op)
  6180. case_stmt(details:: e_gt,details:: gt_op)
  6181. case_stmt(details:: e_gte,details:: gte_op)
  6182. case_stmt(details:: e_eq,details:: eq_op)
  6183. case_stmt(details:: e_ne,details:: ne_op)
  6184. case_stmt(details:: e_and,details:: and_op)
  6185. case_stmt(details::e_nand,details::nand_op)
  6186. case_stmt(details:: e_or,details:: or_op)
  6187. case_stmt(details:: e_nor,details:: nor_op)
  6188. case_stmt(details:: e_xor,details:: xor_op)
  6189. #endif
  6190. #undef case_stmt
  6191. default : return error_node();
  6192. }
  6193. node_allocator_->free(branch[0]);
  6194. return result;
  6195. }
  6196. #ifndef exprtk_disable_extended_optimisations
  6197. template <typename Op1, typename Op2>
  6198. inline expression_node_ptr synthesize_vovovov_expression_impl2(expression_node_ptr (&node)[2])
  6199. {
  6200. details::operator_type op = dynamic_cast<details::vov_base_node<T>*>(node[1])->operation();
  6201. switch (op)
  6202. {
  6203. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_rr<typename details::vovovov_node<Type,Op1,Op2,op1<T> > >((*dynamic_cast<details::vov_node<T,Op1>*>(node[0])),(*dynamic_cast<details::vov_node<T,op1<T> >*>(node[1])));
  6204. case_stmt(details:: e_add,details:: add_op)
  6205. case_stmt(details:: e_sub,details:: sub_op)
  6206. case_stmt(details:: e_mul,details:: mul_op)
  6207. case_stmt(details:: e_div,details:: div_op)
  6208. case_stmt(details:: e_mod,details:: mod_op)
  6209. case_stmt(details:: e_pow,details:: pow_op)
  6210. #ifndef exprtk_disable_extended_operator_optimizations
  6211. case_stmt(details:: e_lt,details:: lt_op)
  6212. case_stmt(details:: e_lte,details:: lte_op)
  6213. case_stmt(details:: e_gt,details:: gt_op)
  6214. case_stmt(details:: e_gte,details:: gte_op)
  6215. case_stmt(details:: e_eq,details:: eq_op)
  6216. case_stmt(details:: e_ne,details:: ne_op)
  6217. case_stmt(details:: e_and,details:: and_op)
  6218. case_stmt(details::e_nand,details::nand_op)
  6219. case_stmt(details:: e_or,details:: or_op)
  6220. case_stmt(details:: e_nor,details:: nor_op)
  6221. case_stmt(details:: e_xor,details:: xor_op)
  6222. #endif
  6223. #undef case_stmt
  6224. default : return error_node();
  6225. }
  6226. #else
  6227. template <typename Op1, typename Op2>
  6228. inline expression_node_ptr synthesize_vovovov_expression_impl2(expression_node_ptr (&)[2])
  6229. {
  6230. return error_node();
  6231. #endif
  6232. }
  6233. #ifndef exprtk_disable_extended_optimisations
  6234. template <typename Operation2>
  6235. inline expression_node_ptr synthesize_vovovov_expression_impl1(expression_node_ptr (&node)[2])
  6236. {
  6237. details::operator_type op = dynamic_cast<details::vov_base_node<T>*>(node[0])->operation();
  6238. switch (op)
  6239. {
  6240. #define case_stmt(op0,op1) case op0 : return synthesize_vovovov_expression_impl2<op1<T>,Operation2>(node); break;
  6241. case_stmt(details:: e_add,details:: add_op)
  6242. case_stmt(details:: e_sub,details:: sub_op)
  6243. case_stmt(details:: e_mul,details:: mul_op)
  6244. case_stmt(details:: e_div,details:: div_op)
  6245. case_stmt(details:: e_mod,details:: mod_op)
  6246. case_stmt(details:: e_pow,details:: pow_op)
  6247. #ifndef exprtk_disable_extended_operator_optimizations
  6248. case_stmt(details:: e_lt,details:: lt_op)
  6249. case_stmt(details:: e_lte,details:: lte_op)
  6250. case_stmt(details:: e_gt,details:: gt_op)
  6251. case_stmt(details:: e_gte,details:: gte_op)
  6252. case_stmt(details:: e_eq,details:: eq_op)
  6253. case_stmt(details:: e_ne,details:: ne_op)
  6254. case_stmt(details:: e_and,details:: and_op)
  6255. case_stmt(details::e_nand,details::nand_op)
  6256. case_stmt(details:: e_or,details:: or_op)
  6257. case_stmt(details:: e_nor,details:: nor_op)
  6258. case_stmt(details:: e_xor,details:: xor_op)
  6259. #endif
  6260. #undef case_stmt
  6261. default : return error_node();
  6262. }
  6263. }
  6264. #else
  6265. template <typename Operation2>
  6266. inline expression_node_ptr synthesize_vovovov_expression_impl1(expression_node_ptr (&)[2])
  6267. {
  6268. return error_node();
  6269. }
  6270. #endif
  6271. #ifndef exprtk_disable_extended_optimisations
  6272. inline expression_node_ptr synthesize_vovovov_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6273. {
  6274. expression_node_ptr result = error_node();
  6275. switch (opr)
  6276. {
  6277. #define case_stmt(op0,op1) case op0 : result = synthesize_vovovov_expression_impl1<op1<T> >(branch); break;
  6278. case_stmt(details:: e_add,details:: add_op)
  6279. case_stmt(details:: e_sub,details:: sub_op)
  6280. case_stmt(details:: e_mul,details:: mul_op)
  6281. case_stmt(details:: e_div,details:: div_op)
  6282. case_stmt(details:: e_mod,details:: mod_op)
  6283. case_stmt(details:: e_pow,details:: pow_op)
  6284. #ifndef exprtk_disable_extended_operator_optimizations
  6285. case_stmt(details:: e_lt,details:: lt_op)
  6286. case_stmt(details:: e_lte,details:: lte_op)
  6287. case_stmt(details:: e_gt,details:: gt_op)
  6288. case_stmt(details:: e_gte,details:: gte_op)
  6289. case_stmt(details:: e_eq,details:: eq_op)
  6290. case_stmt(details:: e_ne,details:: ne_op)
  6291. case_stmt(details:: e_and,details:: and_op)
  6292. case_stmt(details::e_nand,details::nand_op)
  6293. case_stmt(details:: e_or,details:: or_op)
  6294. case_stmt(details:: e_nor,details:: nor_op)
  6295. case_stmt(details:: e_xor,details:: xor_op)
  6296. #endif
  6297. #undef case_stmt
  6298. default : return error_node();
  6299. }
  6300. node_allocator_->free(branch[0]);
  6301. node_allocator_->free(branch[1]);
  6302. return result;
  6303. }
  6304. #else
  6305. inline expression_node_ptr synthesize_vovovov_expression(const details::operator_type&, expression_node_ptr (&)[2])
  6306. {
  6307. return error_node();
  6308. }
  6309. #endif
  6310. #ifndef exprtk_disable_string_capabilities
  6311. template <typename T0, typename T1>
  6312. inline expression_node_ptr synthesize_sos_expression_impl(const details::operator_type& opr, T0 s0, T1 s1)
  6313. {
  6314. switch (opr)
  6315. {
  6316. #define case_stmt(op0,op1) case op0 : return node_allocator_->allocate_tt<typename details::sos_node<Type,T0,T1,op1<Type> >,T0,T1>(s0,s1);
  6317. case_stmt(details::e_lt ,details:: lt_op)
  6318. case_stmt(details::e_lte ,details:: lte_op)
  6319. case_stmt(details::e_gt ,details:: gt_op)
  6320. case_stmt(details::e_gte ,details:: gte_op)
  6321. case_stmt(details::e_eq ,details:: eq_op)
  6322. case_stmt(details::e_ne ,details:: ne_op)
  6323. case_stmt(details::e_in ,details:: in_op)
  6324. case_stmt(details::e_like ,details:: like_op)
  6325. case_stmt(details::e_ilike,details::ilike_op)
  6326. #undef case_stmt
  6327. default : return error_node();
  6328. }
  6329. }
  6330. inline expression_node_ptr synthesize_sos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6331. {
  6332. std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
  6333. std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
  6334. return synthesize_sos_expression_impl<std::string&,std::string&>(opr,s0,s1);
  6335. }
  6336. inline expression_node_ptr synthesize_socs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6337. {
  6338. std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
  6339. std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
  6340. node_allocator_->free(branch[1]);
  6341. return synthesize_sos_expression_impl<std::string&,const std::string>(opr,s0,s1);
  6342. }
  6343. inline expression_node_ptr synthesize_csos_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6344. {
  6345. std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
  6346. std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
  6347. node_allocator_->free(branch[0]);
  6348. return synthesize_sos_expression_impl<const std::string,std::string&>(opr,s0,s1);
  6349. }
  6350. inline expression_node_ptr synthesize_csocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6351. {
  6352. const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
  6353. const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
  6354. expression_node_ptr result = error_node();
  6355. if (details::e_add == opr)
  6356. result = node_allocator_->allocate_c<details::string_literal_node<Type> >(s0 + s1);
  6357. else if (details::e_in == opr)
  6358. result = node_allocator_->allocate_c<details::literal_node<Type> >(details::in_op<Type>::process(s0,s1));
  6359. else if (details::e_like == opr)
  6360. result = node_allocator_->allocate_c<details::literal_node<Type> >(details::like_op<Type>::process(s0,s1));
  6361. else if (details::e_ilike == opr)
  6362. result = node_allocator_->allocate_c<details::literal_node<Type> >(details::ilike_op<Type>::process(s0,s1));
  6363. else
  6364. {
  6365. expression_node_ptr temp = synthesize_sos_expression_impl<const std::string,const std::string>(opr,s0,s1);
  6366. Type v = temp->value();
  6367. node_allocator_->free(temp);
  6368. result = node_allocator_->allocate<literal_node_t>(v);
  6369. }
  6370. node_allocator_->free(branch[0]);
  6371. node_allocator_->free(branch[1]);
  6372. return result;
  6373. }
  6374. #endif
  6375. #ifndef exprtk_disable_string_capabilities
  6376. inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2])
  6377. {
  6378. if (details::is_string_node(branch[0]))
  6379. {
  6380. if (details::is_string_node(branch[1])) return synthesize_sos_expression(opr,branch);
  6381. else if (details::is_const_string_node(branch[1])) return synthesize_socs_expression(opr,branch);
  6382. }
  6383. else if (details::is_const_string_node(branch[0]))
  6384. {
  6385. if (details::is_string_node(branch[1])) return synthesize_csos_expression(opr,branch);
  6386. else if (details::is_const_string_node(branch[1])) return synthesize_csocs_expression(opr,branch);
  6387. }
  6388. return error_node();
  6389. }
  6390. #else
  6391. inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[2])
  6392. {
  6393. return error_node();
  6394. }
  6395. #endif
  6396. #ifndef exprtk_disable_string_capabilities
  6397. inline expression_node_ptr synthesize_string_expression(const details::operator_type& opr, expression_node_ptr (&branch)[3])
  6398. {
  6399. if (details::e_inrange != opr)
  6400. return error_node();
  6401. else if (
  6402. details::is_const_string_node(branch[0]) &&
  6403. details::is_const_string_node(branch[1]) &&
  6404. details::is_const_string_node(branch[2])
  6405. )
  6406. {
  6407. const std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
  6408. const std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
  6409. const std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
  6410. Type v = (((s0 <= s1) && (s1 <= s2)) ? Type(1) : Type(0));
  6411. node_allocator_->free(branch[0]);
  6412. node_allocator_->free(branch[1]);
  6413. node_allocator_->free(branch[2]);
  6414. return node_allocator_->allocate_c<details::literal_node<Type> >(v);
  6415. }
  6416. else if (
  6417. details::is_string_node(branch[0]) &&
  6418. details::is_string_node(branch[1]) &&
  6419. details::is_string_node(branch[2])
  6420. )
  6421. {
  6422. std::string& s0 = dynamic_cast<details::stringvar_node<Type>*>(branch[0])->ref();
  6423. std::string& s1 = dynamic_cast<details::stringvar_node<Type>*>(branch[1])->ref();
  6424. std::string& s2 = dynamic_cast<details::stringvar_node<Type>*>(branch[2])->ref();
  6425. typedef typename details::sosos_node<Type,std::string&,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
  6426. return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string&>(s0,s1,s2);
  6427. }
  6428. else if (
  6429. details::is_const_string_node(branch[0]) &&
  6430. details::is_string_node(branch[1]) &&
  6431. details::is_const_string_node(branch[2])
  6432. )
  6433. {
  6434. std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
  6435. std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
  6436. std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
  6437. typedef typename details::sosos_node<Type,std::string,std::string&,std::string,details::inrange_op<Type> > inrange_t;
  6438. node_allocator_->free(branch[0]);
  6439. node_allocator_->free(branch[2]);
  6440. return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string>(s0,s1,s2);
  6441. }
  6442. else if (
  6443. details::is_string_node(branch[0]) &&
  6444. details::is_const_string_node(branch[1]) &&
  6445. details::is_string_node(branch[2])
  6446. )
  6447. {
  6448. std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
  6449. std::string s1 = dynamic_cast<details::string_literal_node<Type>*>(branch[1])->str();
  6450. std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
  6451. typedef typename details::sosos_node<Type,std::string&,std::string,std::string&,details::inrange_op<Type> > inrange_t;
  6452. node_allocator_->free(branch[1]);
  6453. return node_allocator_->allocate_type<inrange_t,std::string&,std::string,std::string&>(s0,s1,s2);
  6454. }
  6455. else if (
  6456. details::is_string_node(branch[0]) &&
  6457. details::is_string_node(branch[1]) &&
  6458. details::is_const_string_node(branch[2])
  6459. )
  6460. {
  6461. std::string& s0 = dynamic_cast< details::stringvar_node<Type>*>(branch[0])->ref();
  6462. std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
  6463. std::string s2 = dynamic_cast<details::string_literal_node<Type>*>(branch[2])->str();
  6464. typedef typename details::sosos_node<Type,std::string&,std::string&,std::string,details::inrange_op<Type> > inrange_t;
  6465. node_allocator_->free(branch[2]);
  6466. return node_allocator_->allocate_type<inrange_t,std::string&,std::string&,std::string>(s0,s1,s2);
  6467. }
  6468. else if (
  6469. details::is_const_string_node(branch[0]) &&
  6470. details:: is_string_node(branch[1]) &&
  6471. details:: is_string_node(branch[2])
  6472. )
  6473. {
  6474. std::string s0 = dynamic_cast<details::string_literal_node<Type>*>(branch[0])->str();
  6475. std::string& s1 = dynamic_cast< details::stringvar_node<Type>*>(branch[1])->ref();
  6476. std::string& s2 = dynamic_cast< details::stringvar_node<Type>*>(branch[2])->ref();
  6477. typedef typename details::sosos_node<Type,std::string,std::string&,std::string&,details::inrange_op<Type> > inrange_t;
  6478. node_allocator_->free(branch[0]);
  6479. return node_allocator_->allocate_type<inrange_t,std::string,std::string&,std::string&>(s0,s1,s2);
  6480. }
  6481. else
  6482. return error_node();
  6483. }
  6484. #else
  6485. inline expression_node_ptr synthesize_string_expression(const details::operator_type&, expression_node_ptr (&)[3])
  6486. {
  6487. return error_node();
  6488. }
  6489. #endif
  6490. template <typename NodeType, std::size_t N>
  6491. inline expression_node_ptr synthesize_expression(const details::operator_type& operation, expression_node_ptr (&branch)[N])
  6492. {
  6493. if ((details::e_in == operation) || (details::e_like == operation) || (details::e_ilike == operation))
  6494. return error_node();
  6495. else if ((details::e_default != operation) && all_nodes_valid<N>(branch))
  6496. {
  6497. //Attempt simple constant folding optimization.
  6498. expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(operation,branch);
  6499. if (is_constant_foldable<N>(branch))
  6500. {
  6501. Type v = expression_point->value();
  6502. node_allocator_->free(expression_point);
  6503. return node_allocator_->allocate<literal_node_t>(v);
  6504. }
  6505. else
  6506. return expression_point;
  6507. }
  6508. else
  6509. return error_node();
  6510. }
  6511. template <typename NodeType, std::size_t N>
  6512. inline expression_node_ptr synthesize_expression(F* f, expression_node_ptr (&branch)[N])
  6513. {
  6514. if (all_nodes_valid<N>(branch))
  6515. {
  6516. typedef typename details::function_N_node<T,ifunction_t,N> function_N_node_t;
  6517. //Attempt simple constant folding optimization.
  6518. expression_node_ptr expression_point = node_allocator_->allocate<NodeType>(f);
  6519. dynamic_cast<function_N_node_t*>(expression_point)->init_branches(branch);
  6520. if (is_constant_foldable<N>(branch))
  6521. {
  6522. Type v = expression_point->value();
  6523. node_allocator_->free(expression_point);
  6524. return node_allocator_->allocate<literal_node_t>(v);
  6525. }
  6526. else
  6527. return expression_point;
  6528. }
  6529. else
  6530. return error_node();
  6531. }
  6532. details::node_allocator* node_allocator_;
  6533. optimization_level optimization_level_;
  6534. };
  6535. template <typename Type>
  6536. class expression_optimizer
  6537. {
  6538. public:
  6539. typedef details::expression_node<Type>* expression_node_ptr;
  6540. inline void set_allocator(details::node_allocator& na)
  6541. {
  6542. node_allocator_ = &na;
  6543. }
  6544. inline void process(expression_node_ptr expr)
  6545. {
  6546. std::deque<expression_node_ptr> node_list;
  6547. node_list.push_back(expr);
  6548. expression_node_ptr node = reinterpret_cast<expression_node_ptr>(0);
  6549. while (!node_list.empty())
  6550. {
  6551. node = node_list.front();
  6552. node_list.pop_front();
  6553. if (details::is_constant_node(node) || details::is_variable_node(node))
  6554. continue;
  6555. else if (details::is_binary_node(node) && bn_type0_optimizable(node))
  6556. perform_bn_type0_optimization(node);
  6557. else
  6558. add_sub_branches(node,node_list);
  6559. }
  6560. }
  6561. private:
  6562. template <typename Allocator,
  6563. template <typename, typename> class Sequence>
  6564. void add_sub_branches(expression_node_ptr node, Sequence<expression_node_ptr,Allocator>& seq)
  6565. {
  6566. if (details::is_unary_node(node))
  6567. seq.push_back(node->branch(0));
  6568. else if (details::is_binary_node(node))
  6569. {
  6570. seq.push_back(node->branch(0));
  6571. seq.push_back(node->branch(1));
  6572. }
  6573. }
  6574. inline bool operation_optimizable(const details::operator_type& operation) const
  6575. {
  6576. return (details::e_add == operation) || (details::e_sub == operation) ||
  6577. (details::e_mul == operation) || (details::e_div == operation) ||
  6578. (details::e_mod == operation) || (details::e_pow == operation) ||
  6579. (details::e_lt == operation) || (details::e_lte == operation) ||
  6580. (details::e_gt == operation) || (details::e_gte == operation) ||
  6581. (details::e_eq == operation) || (details::e_ne == operation) ||
  6582. (details::e_and == operation) || (details::e_nand == operation) ||
  6583. (details::e_or == operation) || (details::e_nor == operation) ||
  6584. (details::e_xor == operation);
  6585. }
  6586. inline bool bn_type0_optimizable(const expression_node_ptr expr) const
  6587. {
  6588. const details::binary_node<Type>* node = dynamic_cast<const details::binary_node<Type>*>(expr);
  6589. if (0 == node)
  6590. return false;
  6591. else if (!operation_optimizable(node->operation()))
  6592. return false;
  6593. expression_node_ptr b0 = node->branch(0);
  6594. expression_node_ptr b1 = node->branch(1);
  6595. if (details::is_variable_node(b0) && (details::is_variable_node(b1) || details::is_constant_node(b1)))
  6596. return true;
  6597. else if (details::is_constant_node(b0) && (details::is_variable_node(b1) || details::is_constant_node(b1)))
  6598. return true;
  6599. else
  6600. return false;
  6601. }
  6602. inline void perform_bn_type0_optimization(const expression_node_ptr)
  6603. {
  6604. }
  6605. private:
  6606. details::node_allocator* node_allocator_;
  6607. };
  6608. inline bool check0(const char c0, const char c1,
  6609. const char v0, const char v1,
  6610. const char v2)
  6611. {
  6612. return ((c0 == v0) && ((c1 == v1) || (c1 == v2)));
  6613. }
  6614. inline bool check1(const char c0, const char c1,
  6615. const char v0, const char v1)
  6616. {
  6617. return ((c0 == v0) && (c1 == v1));
  6618. }
  6619. inline bool validate_expression(const std::string& expression_string)
  6620. {
  6621. if (expression_string.empty())
  6622. {
  6623. set_error("parser::validate_expression() - empty expression");
  6624. return false;
  6625. }
  6626. //Check for certain illegal sequences of characters.
  6627. std::stack<char> bracket_stack;
  6628. bool in_string = false;
  6629. for (std::size_t i = 0; i < (expression_string.size() - 1); ++i)
  6630. {
  6631. char c0 = expression_string[i];
  6632. char c1 = expression_string[i + 1];
  6633. if ('\'' == c0)
  6634. {
  6635. in_string = !in_string;
  6636. continue;
  6637. }
  6638. else if (in_string)
  6639. continue;
  6640. else if (details::is_invalid(c0))
  6641. {
  6642. set_error(std::string("parser::validate_expression() - invalid character: ") + c0);
  6643. return false;
  6644. }
  6645. else if (
  6646. check0(c0,c1,'*','*','/') || check0(c0,c1,'*','%','^') ||
  6647. check0(c0,c1,'/','*','/') || check0(c0,c1,'/','%','^') ||
  6648. check0(c0,c1,'+','*','/') || check0(c0,c1,'+','%','^') ||
  6649. check0(c0,c1,'-','*','/') || check0(c0,c1,'-','%','^') ||
  6650. check0(c0,c1,'^','*','/') || check0(c0,c1,'^','^','%') ||
  6651. check0(c0,c1,'%','*','/') || check0(c0,c1,'%','^','%') ||
  6652. check0(c0,c1,'.','%','^') || check0(c0,c1,'.','*','/') ||
  6653. check0(c0,c1,',','%','^') || check0(c0,c1,',','*','/') ||
  6654. check0(c0,c1,'(','*','/') || check0(c0,c1,'(','%','^') ||
  6655. check0(c0,c1,'[','*','/') || check0(c0,c1,'[','%','^') ||
  6656. check0(c0,c1,'{','*','/') || check0(c0,c1,'{','%','^') ||
  6657. check0(c0,c1,'+',')',']') || check0(c0,c1,'-',')',']') ||
  6658. check0(c0,c1,'*',')',']') || check0(c0,c1,'/',')',']') ||
  6659. check0(c0,c1,'^',')',']') || check0(c0,c1,'%',')',']') ||
  6660. check1(c0,c1,'+','}' ) || check1(c0,c1,'-','}' ) ||
  6661. check1(c0,c1,'*','}' ) || check1(c0,c1,'/','}' ) ||
  6662. check1(c0,c1,'^','}' ) || check1(c0,c1,'%','}' ) ||
  6663. check1(c0,c1,'.','.' ) || check1(c0,c1,'.','+' ) ||
  6664. check1(c0,c1,'.','-' ) || check1(c0,c1,'.','*' ) ||
  6665. check1(c0,c1,'.','/' ) || check1(c0,c1,',',',' )
  6666. )
  6667. {
  6668. set_error(std::string("parser::validate_expression() - invalid character combination: ") + expression_string.substr(i,2));
  6669. return false;
  6670. }
  6671. else if (c0 == '(')
  6672. bracket_stack.push(')');
  6673. else if (c0 == '[')
  6674. bracket_stack.push(']');
  6675. else if (c0 == '{')
  6676. bracket_stack.push('}');
  6677. else if (details::is_right_bracket(c0))
  6678. {
  6679. if (bracket_stack.empty())
  6680. {
  6681. set_error(std::string("parser::validate_expression() - invalid/mismatched bracket(s)[0]: ") + expression_string.substr(0,i));
  6682. return false;
  6683. }
  6684. else if (c0 != bracket_stack.top())
  6685. {
  6686. set_error(std::string("parser::validate_expression() - invalid/mismatched bracket(s)[1]: ") + expression_string.substr(0,i));
  6687. return false;
  6688. }
  6689. else
  6690. bracket_stack.pop();
  6691. }
  6692. }
  6693. if (!bracket_stack.empty())
  6694. {
  6695. if (1 == bracket_stack.size())
  6696. {
  6697. char c0 = expression_string[expression_string.size() - 1];
  6698. if (details::is_right_bracket(c0))
  6699. {
  6700. if (c0 == bracket_stack.top())
  6701. return true;
  6702. else
  6703. {
  6704. set_error(std::string("parser::validate_expression() - invalid/mismatched bracket(s)[2]: ") + expression_string);
  6705. return false;
  6706. }
  6707. }
  6708. }
  6709. set_error(std::string("parser::validate_expression() - invalid/mismatched bracket(s)[3]: ") + expression_string);
  6710. return false;
  6711. }
  6712. return true;
  6713. }
  6714. inline void set_error(const std::string& err_str)
  6715. {
  6716. //would it be better if this were a stack?
  6717. if (error_description_.empty())
  6718. {
  6719. error_description_ = err_str;
  6720. }
  6721. }
  6722. private:
  6723. details::lexer<T> lexer_;
  6724. details::token<T> current_token_;
  6725. details::token<T> store_current_token_;
  6726. expression_generator<T> expression_generator_;
  6727. expression_optimizer<T> expression_optimizer_;
  6728. details::node_allocator node_allocator_;
  6729. symbol_table<T> symbol_table_;
  6730. std::string error_description_;
  6731. bool symbol_name_caching_;
  6732. std::deque<std::string> symbol_name_cache_;
  6733. };
  6734. template <typename T>
  6735. inline T integrate(expression<T>& e,
  6736. T& x,
  6737. const T& r0, const T& r1,
  6738. const std::size_t number_of_intervals = 1000000)
  6739. {
  6740. if (r0 > r1) return T(0);
  6741. T h = (r1 - r0) / (T(2.0) * number_of_intervals);
  6742. T total_area = T(0);
  6743. for (std::size_t i = 0; i < number_of_intervals; ++i)
  6744. {
  6745. x = r0 + T(2.0) * i * h;
  6746. T y0 = e.value(); x += h;
  6747. T y1 = e.value(); x += h;
  6748. T y2 = e.value(); x += h;
  6749. total_area += h * (y0 + T(4.0) * y1 + y2) / T(3.0);
  6750. }
  6751. return total_area;
  6752. }
  6753. template <typename T>
  6754. inline T integrate(expression<T>& e,
  6755. const std::string& variable_name,
  6756. const T& r0, const T& r1,
  6757. const std::size_t number_of_intervals = 1000000)
  6758. {
  6759. symbol_table<T>& sym_table = e.get_symbol_table();
  6760. if (!sym_table.valid())
  6761. return std::numeric_limits<T>::quiet_NaN();
  6762. details::variable_node<T>* var = sym_table.get_variable(variable_name);
  6763. if (var)
  6764. {
  6765. T& x = var->ref();
  6766. T x_original = x;
  6767. T result = integrate(e,x,r0,r1,number_of_intervals);
  6768. x = x_original;
  6769. return result;
  6770. }
  6771. else
  6772. return std::numeric_limits<T>::quiet_NaN();
  6773. }
  6774. template <typename T>
  6775. inline T derivative(expression<T>& e,
  6776. T& x,
  6777. const double& h = 0.00001)
  6778. {
  6779. T x_init = x;
  6780. x = x_init + T(2.0) * h;
  6781. T y0 = e.value();
  6782. x = x_init + h;
  6783. T y1 = e.value();
  6784. x = x_init - h;
  6785. T y2 = e.value();
  6786. x = x_init - T(2.0) * h;
  6787. T y3 = e.value();
  6788. x = x_init;
  6789. return (-y0 + T(8.0) * (y1 - y2) + y3) / (T(12.0) * h);
  6790. }
  6791. template <typename T>
  6792. inline T derivative(expression<T>& e,
  6793. const std::string& variable_name,
  6794. const double& h = 0.00001)
  6795. {
  6796. symbol_table<T>& sym_table = e.get_symbol_table();
  6797. if (!sym_table.valid())
  6798. return std::numeric_limits<T>::quiet_NaN();
  6799. details::variable_node<T>* var = sym_table.get_variable(variable_name);
  6800. if (var)
  6801. {
  6802. T& x = var->ref();
  6803. T x_original = x;
  6804. T result = derivative(e,x,h);
  6805. x = x_original;
  6806. return result;
  6807. }
  6808. else
  6809. return std::numeric_limits<T>::quiet_NaN();
  6810. }
  6811. /*
  6812. Note: The following 'compute' routines are very simple helpers,
  6813. for quickly setting up the required pieces of code in order to
  6814. evaluate an expression. By virtue of how they the operate there
  6815. will be an overhead with regards to their setup and teardown and
  6816. hence should not be used in time critical sections of code.
  6817. Furthermore they only assume a small sub set of variables - no
  6818. string variables or user defined functions.
  6819. */
  6820. template <typename T>
  6821. inline bool compute(const std::string& expression_string, T& result)
  6822. {
  6823. //No variables
  6824. symbol_table<T> symbol_table;
  6825. symbol_table.add_constants();
  6826. expression<T> expression;
  6827. parser<T> parser;
  6828. if (parser.compile(expression_string,expression))
  6829. {
  6830. result = expression.value();
  6831. return true;
  6832. }
  6833. else
  6834. return false;
  6835. }
  6836. template <typename T>
  6837. inline bool compute(const std::string& expression_string,
  6838. const T& x,
  6839. T& result)
  6840. {
  6841. //Only 'x'
  6842. static const std::string x_var("x");
  6843. symbol_table<T> symbol_table;
  6844. symbol_table.add_constants();
  6845. symbol_table.add_variable("x",x);
  6846. expression<T> expression;
  6847. parser<T> parser;
  6848. if (parser.compile(expression_string,expression))
  6849. {
  6850. result = expression.value();
  6851. return true;
  6852. }
  6853. else
  6854. return false;
  6855. }
  6856. template <typename T>
  6857. inline bool compute(const std::string& expression_string,
  6858. const T&x, const T& y,
  6859. T& result)
  6860. {
  6861. //Only 'x' and 'y'
  6862. static const std::string x_var("x");
  6863. static const std::string y_var("y");
  6864. symbol_table<T> symbol_table;
  6865. symbol_table.add_constants();
  6866. symbol_table.add_variable("x",x);
  6867. symbol_table.add_variable("y",y);
  6868. expression<T> expression;
  6869. parser<T> parser;
  6870. if (parser.compile(expression_string,expression))
  6871. {
  6872. result = expression.value();
  6873. return true;
  6874. }
  6875. else
  6876. return false;
  6877. }
  6878. template <typename T>
  6879. inline bool compute(const std::string& expression_string,
  6880. const T& x, const T& y, const T& z,
  6881. T& result)
  6882. {
  6883. //Only 'x', 'y' or 'z'
  6884. static const std::string x_var("x");
  6885. static const std::string y_var("y");
  6886. static const std::string z_var("z");
  6887. symbol_table<T> symbol_table;
  6888. symbol_table.add_constants();
  6889. symbol_table.add_variable(x_var,x);
  6890. symbol_table.add_variable(y_var,y);
  6891. symbol_table.add_variable(z_var,z);
  6892. expression<T> expression;
  6893. parser<T> parser;
  6894. if (parser.compile(expression_string,expression))
  6895. {
  6896. result = expression.value();
  6897. return true;
  6898. }
  6899. else
  6900. return false;
  6901. }
  6902. template <typename T, std::size_t N>
  6903. class polynomial : public ifunction<T>
  6904. {
  6905. private:
  6906. template <typename Type, std::size_t NumberOfCoefficients>
  6907. struct poly_impl { };
  6908. template <typename Type>
  6909. struct poly_impl <Type,9>
  6910. {
  6911. static inline T evaluate(const Type x,
  6912. const Type c9, const Type c8, const Type c7, const Type c6, const Type c5,
  6913. const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
  6914. {
  6915. //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_0
  6916. return (((((((((c9 * x + c8) * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
  6917. }
  6918. };
  6919. template <typename Type>
  6920. struct poly_impl <Type,8>
  6921. {
  6922. static inline T evaluate(const Type x,
  6923. const Type c8, const Type c7, const Type c6, const Type c5, const Type c4,
  6924. const Type c3, const Type c2, const Type c1, const Type c0)
  6925. {
  6926. //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_0
  6927. return ((((((((c8 * x + c7) * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
  6928. }
  6929. };
  6930. template <typename Type>
  6931. struct poly_impl <Type,7>
  6932. {
  6933. static inline T evaluate(const Type x,
  6934. const Type c7, const Type c6, const Type c5, const Type c4, const Type c3,
  6935. const Type c2, const Type c1, const Type c0)
  6936. {
  6937. //p(x) = c_7x^7 + c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
  6938. return (((((((c7 * x + c6) * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
  6939. }
  6940. };
  6941. template <typename Type>
  6942. struct poly_impl <Type,6>
  6943. {
  6944. static inline T evaluate(const Type x,
  6945. const Type c6, const Type c5, const Type c4, const Type c3, const Type c2,
  6946. const Type c1, const Type c0)
  6947. {
  6948. //p(x) = c_6x^6 + c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
  6949. return ((((((c6 * x + c5) * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
  6950. }
  6951. };
  6952. template <typename Type>
  6953. struct poly_impl <Type,5>
  6954. {
  6955. static inline T evaluate(const Type x,
  6956. const Type c5, const Type c4, const Type c3, const Type c2,
  6957. const Type c1, const Type c0)
  6958. {
  6959. //p(x) = c_5x^5 + c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
  6960. return (((((c5 * x + c4) * x + c3) * x + c2) * x + c1) * x + c0);
  6961. }
  6962. };
  6963. template <typename Type>
  6964. struct poly_impl <Type,4>
  6965. {
  6966. static inline T evaluate(const Type x, const Type c4, const Type c3, const Type c2, const Type c1, const Type c0)
  6967. {
  6968. //p(x) = c_4x^4 + c_3x^3 + c_2x^2 + c_1x^1 + c_0
  6969. return ((((c4 * x + c3) * x + c2) * x + c1) * x + c0);
  6970. }
  6971. };
  6972. template <typename Type>
  6973. struct poly_impl <Type,3>
  6974. {
  6975. static inline T evaluate(const Type x, const Type c3, const Type c2, const Type c1, const Type c0)
  6976. {
  6977. //p(x) = c_3x^3 + c_2x^2 + c_1x^1 + c_0
  6978. return (((c3 * x + c2) * x + c1) * x + c0);
  6979. }
  6980. };
  6981. template <typename Type>
  6982. struct poly_impl <Type,2>
  6983. {
  6984. static inline T evaluate(const Type x, const Type c2, const Type c1, const Type c0)
  6985. {
  6986. //p(x) = c_2x^2 + c_1x^1 + c_0
  6987. return ((c2 * x + c1) * x + c0);
  6988. }
  6989. };
  6990. template <typename Type>
  6991. struct poly_impl <Type,1>
  6992. {
  6993. static inline T evaluate(const Type x, const Type c1, const Type c0)
  6994. {
  6995. //p(x) = c_1x^1 + c_0
  6996. return (c1 * x + c0);
  6997. }
  6998. };
  6999. public:
  7000. polynomial() : exprtk::ifunction<T>(N) {}
  7001. inline virtual T operator()(const T& x, const T& c1, const T& c0)
  7002. {
  7003. return ((1 == N) ? poly_impl<T,1>::evaluate(x,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7004. }
  7005. inline virtual T operator()(const T& x, const T& c2, const T& c1, const T& c0)
  7006. {
  7007. return ((2 == N) ? poly_impl<T,2>::evaluate(x,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7008. }
  7009. inline virtual T operator()(const T& x, const T& c3, const T& c2, const T& c1, const T& c0)
  7010. {
  7011. return ((3 == N) ? poly_impl<T,3>::evaluate(x,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7012. }
  7013. inline virtual T operator()(const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0)
  7014. {
  7015. return ((4 == N) ? poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7016. }
  7017. 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)
  7018. {
  7019. return ((5 == N) ? poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7020. }
  7021. 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)
  7022. {
  7023. return ((6 == N) ? poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7024. }
  7025. 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)
  7026. {
  7027. return ((7 == N) ? poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7028. }
  7029. 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)
  7030. {
  7031. return ((8 == N) ? poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0) : std::numeric_limits<T>::quiet_NaN());
  7032. }
  7033. inline virtual T operator()()
  7034. {
  7035. return std::numeric_limits<T>::quiet_NaN();
  7036. }
  7037. inline virtual T operator()(const T&)
  7038. {
  7039. return std::numeric_limits<T>::quiet_NaN();
  7040. }
  7041. inline virtual T operator()(const T&, const T&)
  7042. {
  7043. return std::numeric_limits<T>::quiet_NaN();
  7044. }
  7045. };
  7046. template <typename T>
  7047. inline bool pgo_primer()
  7048. {
  7049. static const std::string expression_list[]
  7050. = {
  7051. "(y + x)",
  7052. "2 * (y + x)",
  7053. "(2 * y + 2 * x)",
  7054. "(y + x / y) * (x - y / x)",
  7055. "x / ((x + y) * (x - y)) / y",
  7056. "1 - ((x * y) + (y / x)) - 3",
  7057. "sin(2 * x) + cos(pi / y)",
  7058. "1 - sin(2 * x) + cos(pi / y)",
  7059. "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)",
  7060. "(x^2 / sin(2 * pi / y)) -x / 2",
  7061. "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y",
  7062. "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)",
  7063. "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))",
  7064. "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x",
  7065. "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55",
  7066. "(yy + xx)",
  7067. "2 * (yy + xx)",
  7068. "(2 * yy + 2 * xx)",
  7069. "(yy + xx / yy) * (xx - yy / xx)",
  7070. "xx / ((xx + yy) * (xx - yy)) / yy",
  7071. "1 - ((xx * yy) + (yy / xx)) - 3",
  7072. "sin(2 * xx) + cos(pi / yy)",
  7073. "1 - sin(2 * xx) + cos(pi / yy)",
  7074. "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)",
  7075. "(xx^2 / sin(2 * pi / yy)) -xx / 2",
  7076. "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy",
  7077. "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)",
  7078. "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))",
  7079. "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx",
  7080. "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55"
  7081. };
  7082. static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string);
  7083. T x = T(0);
  7084. T y = T(0);
  7085. T xx = T(0);
  7086. T yy = T(0);
  7087. exprtk::symbol_table<T> symbol_table;
  7088. symbol_table.add_constants();
  7089. symbol_table.add_variable( "x", x);
  7090. symbol_table.add_variable( "y", y);
  7091. symbol_table.add_variable("xx",xx);
  7092. symbol_table.add_variable("yy",yy);
  7093. typedef typename std::deque<exprtk::expression<T> > expr_list_t;
  7094. expr_list_t optimized_expr_list;
  7095. expr_list_t unoptimized_expr_list;
  7096. const std::size_t rounds = 1000;
  7097. //Generate optimised expressions
  7098. {
  7099. for (std::size_t r = 0; r < rounds; ++r)
  7100. {
  7101. optimized_expr_list.clear();
  7102. exprtk::parser<T> parser;
  7103. for (std::size_t i = 0; i < expression_list_size; ++i)
  7104. {
  7105. exprtk::expression<T> expression;
  7106. expression.register_symbol_table(symbol_table);
  7107. if (!parser.compile(expression_list[i],expression,exprtk::parser<T>::e_all))
  7108. {
  7109. return false;
  7110. }
  7111. optimized_expr_list.push_back(expression);
  7112. }
  7113. }
  7114. }
  7115. //Generate unoptimised expressions
  7116. {
  7117. for (std::size_t r = 0; r < rounds; ++r)
  7118. {
  7119. unoptimized_expr_list.clear();
  7120. exprtk::parser<T> parser;
  7121. for (std::size_t i = 0; i < expression_list_size; ++i)
  7122. {
  7123. exprtk::expression<T> expression;
  7124. expression.register_symbol_table(symbol_table);
  7125. if (!parser.compile(expression_list[i],expression,exprtk::parser<T>::e_none))
  7126. {
  7127. return false;
  7128. }
  7129. unoptimized_expr_list.push_back(expression);
  7130. }
  7131. }
  7132. }
  7133. struct execute
  7134. {
  7135. static inline T process(T& x, T& y, expression<T>& expression)
  7136. {
  7137. static const T lower_bound = T(-20.0);
  7138. static const T upper_bound = T(+20.0);
  7139. T delta = T(0.1);
  7140. T total = T(0.0);
  7141. for (x = lower_bound; x <= upper_bound; x += delta)
  7142. {
  7143. for (y = lower_bound; y <= upper_bound; y += delta)
  7144. {
  7145. total += expression.value();
  7146. }
  7147. }
  7148. return total;
  7149. }
  7150. };
  7151. for (std::size_t i = 0; i < optimized_expr_list.size(); ++i)
  7152. {
  7153. execute::process( x, y, optimized_expr_list[i]);
  7154. execute::process(xx,yy, optimized_expr_list[i]);
  7155. execute::process( x, y,unoptimized_expr_list[i]);
  7156. execute::process(xx,yy,unoptimized_expr_list[i]);
  7157. }
  7158. {
  7159. for (std::size_t i = 0; i < 10000; ++i)
  7160. {
  7161. T v = T(123.456 + i);
  7162. if (details::numeric::nequal(details::numeric::fast_exp<T, 1>::result(v),std::pow(v,T( 1.0)))) return false;
  7163. else if (details::numeric::nequal(details::numeric::fast_exp<T, 2>::result(v),std::pow(v,T( 2.0)))) return false;
  7164. else if (details::numeric::nequal(details::numeric::fast_exp<T, 3>::result(v),std::pow(v,T( 3.0)))) return false;
  7165. else if (details::numeric::nequal(details::numeric::fast_exp<T, 4>::result(v),std::pow(v,T( 4.0)))) return false;
  7166. else if (details::numeric::nequal(details::numeric::fast_exp<T, 5>::result(v),std::pow(v,T( 5.0)))) return false;
  7167. else if (details::numeric::nequal(details::numeric::fast_exp<T, 6>::result(v),std::pow(v,T( 6.0)))) return false;
  7168. else if (details::numeric::nequal(details::numeric::fast_exp<T, 7>::result(v),std::pow(v,T( 7.0)))) return false;
  7169. else if (details::numeric::nequal(details::numeric::fast_exp<T, 8>::result(v),std::pow(v,T( 8.0)))) return false;
  7170. else if (details::numeric::nequal(details::numeric::fast_exp<T, 9>::result(v),std::pow(v,T( 9.0)))) return false;
  7171. else if (details::numeric::nequal(details::numeric::fast_exp<T,10>::result(v),std::pow(v,T(10.0)))) return false;
  7172. else if (details::numeric::nequal(details::numeric::fast_exp<T,11>::result(v),std::pow(v,T(11.0)))) return false;
  7173. else if (details::numeric::nequal(details::numeric::fast_exp<T,12>::result(v),std::pow(v,T(12.0)))) return false;
  7174. else if (details::numeric::nequal(details::numeric::fast_exp<T,13>::result(v),std::pow(v,T(13.0)))) return false;
  7175. else if (details::numeric::nequal(details::numeric::fast_exp<T,14>::result(v),std::pow(v,T(14.0)))) return false;
  7176. else if (details::numeric::nequal(details::numeric::fast_exp<T,15>::result(v),std::pow(v,T(15.0)))) return false;
  7177. else if (details::numeric::nequal(details::numeric::fast_exp<T,16>::result(v),std::pow(v,T(16.0)))) return false;
  7178. else if (details::numeric::nequal(details::numeric::fast_exp<T,17>::result(v),std::pow(v,T(17.0)))) return false;
  7179. else if (details::numeric::nequal(details::numeric::fast_exp<T,18>::result(v),std::pow(v,T(18.0)))) return false;
  7180. else if (details::numeric::nequal(details::numeric::fast_exp<T,19>::result(v),std::pow(v,T(19.0)))) return false;
  7181. else if (details::numeric::nequal(details::numeric::fast_exp<T,20>::result(v),std::pow(v,T(20.0)))) return false;
  7182. else if (details::numeric::nequal(details::numeric::fast_exp<T,21>::result(v),std::pow(v,T(21.0)))) return false;
  7183. else if (details::numeric::nequal(details::numeric::fast_exp<T,22>::result(v),std::pow(v,T(22.0)))) return false;
  7184. else if (details::numeric::nequal(details::numeric::fast_exp<T,23>::result(v),std::pow(v,T(23.0)))) return false;
  7185. else if (details::numeric::nequal(details::numeric::fast_exp<T,24>::result(v),std::pow(v,T(24.0)))) return false;
  7186. else if (details::numeric::nequal(details::numeric::fast_exp<T,25>::result(v),std::pow(v,T(25.0)))) return false;
  7187. else if (details::numeric::nequal(details::numeric::fast_exp<T,26>::result(v),std::pow(v,T(26.0)))) return false;
  7188. else if (details::numeric::nequal(details::numeric::fast_exp<T,27>::result(v),std::pow(v,T(27.0)))) return false;
  7189. else if (details::numeric::nequal(details::numeric::fast_exp<T,28>::result(v),std::pow(v,T(28.0)))) return false;
  7190. else if (details::numeric::nequal(details::numeric::fast_exp<T,29>::result(v),std::pow(v,T(29.0)))) return false;
  7191. else if (details::numeric::nequal(details::numeric::fast_exp<T,30>::result(v),std::pow(v,T(30.0)))) return false;
  7192. else if (details::numeric::nequal(details::numeric::fast_exp<T,31>::result(v),std::pow(v,T(31.0)))) return false;
  7193. else if (details::numeric::nequal(details::numeric::fast_exp<T,32>::result(v),std::pow(v,T(32.0)))) return false;
  7194. else if (details::numeric::nequal(details::numeric::fast_exp<T,33>::result(v),std::pow(v,T(33.0)))) return false;
  7195. else if (details::numeric::nequal(details::numeric::fast_exp<T,34>::result(v),std::pow(v,T(34.0)))) return false;
  7196. else if (details::numeric::nequal(details::numeric::fast_exp<T,35>::result(v),std::pow(v,T(35.0)))) return false;
  7197. else if (details::numeric::nequal(details::numeric::fast_exp<T,36>::result(v),std::pow(v,T(36.0)))) return false;
  7198. else if (details::numeric::nequal(details::numeric::fast_exp<T,37>::result(v),std::pow(v,T(37.0)))) return false;
  7199. else if (details::numeric::nequal(details::numeric::fast_exp<T,38>::result(v),std::pow(v,T(38.0)))) return false;
  7200. else if (details::numeric::nequal(details::numeric::fast_exp<T,39>::result(v),std::pow(v,T(39.0)))) return false;
  7201. else if (details::numeric::nequal(details::numeric::fast_exp<T,40>::result(v),std::pow(v,T(40.0)))) return false;
  7202. else if (details::numeric::nequal(details::numeric::fast_exp<T,41>::result(v),std::pow(v,T(41.0)))) return false;
  7203. else if (details::numeric::nequal(details::numeric::fast_exp<T,42>::result(v),std::pow(v,T(42.0)))) return false;
  7204. else if (details::numeric::nequal(details::numeric::fast_exp<T,43>::result(v),std::pow(v,T(43.0)))) return false;
  7205. else if (details::numeric::nequal(details::numeric::fast_exp<T,44>::result(v),std::pow(v,T(44.0)))) return false;
  7206. else if (details::numeric::nequal(details::numeric::fast_exp<T,45>::result(v),std::pow(v,T(45.0)))) return false;
  7207. else if (details::numeric::nequal(details::numeric::fast_exp<T,46>::result(v),std::pow(v,T(46.0)))) return false;
  7208. else if (details::numeric::nequal(details::numeric::fast_exp<T,47>::result(v),std::pow(v,T(47.0)))) return false;
  7209. else if (details::numeric::nequal(details::numeric::fast_exp<T,48>::result(v),std::pow(v,T(48.0)))) return false;
  7210. else if (details::numeric::nequal(details::numeric::fast_exp<T,49>::result(v),std::pow(v,T(49.0)))) return false;
  7211. else if (details::numeric::nequal(details::numeric::fast_exp<T,50>::result(v),std::pow(v,T(50.0)))) return false;
  7212. else if (details::numeric::nequal(details::numeric::fast_exp<T,51>::result(v),std::pow(v,T(51.0)))) return false;
  7213. else if (details::numeric::nequal(details::numeric::fast_exp<T,52>::result(v),std::pow(v,T(52.0)))) return false;
  7214. else if (details::numeric::nequal(details::numeric::fast_exp<T,53>::result(v),std::pow(v,T(53.0)))) return false;
  7215. else if (details::numeric::nequal(details::numeric::fast_exp<T,54>::result(v),std::pow(v,T(54.0)))) return false;
  7216. else if (details::numeric::nequal(details::numeric::fast_exp<T,55>::result(v),std::pow(v,T(55.0)))) return false;
  7217. else if (details::numeric::nequal(details::numeric::fast_exp<T,56>::result(v),std::pow(v,T(56.0)))) return false;
  7218. else if (details::numeric::nequal(details::numeric::fast_exp<T,57>::result(v),std::pow(v,T(57.0)))) return false;
  7219. else if (details::numeric::nequal(details::numeric::fast_exp<T,58>::result(v),std::pow(v,T(58.0)))) return false;
  7220. else if (details::numeric::nequal(details::numeric::fast_exp<T,59>::result(v),std::pow(v,T(59.0)))) return false;
  7221. else if (details::numeric::nequal(details::numeric::fast_exp<T,60>::result(v),std::pow(v,T(60.0)))) return false;
  7222. else
  7223. return true;
  7224. }
  7225. }
  7226. return true;
  7227. }
  7228. }
  7229. #ifdef WIN32
  7230. #ifndef NOMINMAX
  7231. #define NOMINMAX
  7232. #endif
  7233. #ifndef WIN32_LEAN_AND_MEAN
  7234. #define WIN32_LEAN_AND_MEAN
  7235. #endif
  7236. #include <windows.h>
  7237. #else
  7238. #include <sys/time.h>
  7239. #include <sys/types.h>
  7240. #endif
  7241. namespace exprtk
  7242. {
  7243. class timer
  7244. {
  7245. public:
  7246. #ifdef WIN32
  7247. timer()
  7248. : in_use_(false)
  7249. {
  7250. QueryPerformanceFrequency(&clock_frequency_);
  7251. }
  7252. inline void start()
  7253. {
  7254. in_use_ = true;
  7255. QueryPerformanceCounter(&start_time_);
  7256. }
  7257. inline void stop()
  7258. {
  7259. QueryPerformanceCounter(&stop_time_);
  7260. in_use_ = false;
  7261. }
  7262. inline double time() const
  7263. {
  7264. return (1.0 * (stop_time_.QuadPart - start_time_.QuadPart)) / (1.0 * clock_frequency_.QuadPart);
  7265. }
  7266. #else
  7267. timer()
  7268. : in_use_(false)
  7269. {
  7270. start_time_.tv_sec = 0;
  7271. start_time_.tv_usec = 0;
  7272. stop_time_.tv_sec = 0;
  7273. stop_time_.tv_usec = 0;
  7274. }
  7275. inline void start()
  7276. {
  7277. in_use_ = true;
  7278. gettimeofday(&start_time_,0);
  7279. }
  7280. inline void stop()
  7281. {
  7282. gettimeofday(&stop_time_, 0);
  7283. in_use_ = false;
  7284. }
  7285. inline unsigned long long int usec_time() const
  7286. {
  7287. if (!in_use_)
  7288. {
  7289. if (stop_time_.tv_sec >= start_time_.tv_sec)
  7290. {
  7291. return 1000000 * (stop_time_.tv_sec - start_time_.tv_sec ) +
  7292. (stop_time_.tv_usec - start_time_.tv_usec);
  7293. }
  7294. else
  7295. return std::numeric_limits<unsigned long long int>::max();
  7296. }
  7297. else
  7298. return std::numeric_limits<unsigned long long int>::max();
  7299. }
  7300. inline double time() const
  7301. {
  7302. return usec_time() * 0.000001;
  7303. }
  7304. #endif
  7305. inline bool in_use() const
  7306. {
  7307. return in_use_;
  7308. }
  7309. private:
  7310. bool in_use_;
  7311. #ifdef WIN32
  7312. LARGE_INTEGER start_time_;
  7313. LARGE_INTEGER stop_time_;
  7314. LARGE_INTEGER clock_frequency_;
  7315. #else
  7316. struct timeval start_time_;
  7317. struct timeval stop_time_;
  7318. #endif
  7319. };
  7320. namespace information
  7321. {
  7322. static const char* library = "Mathematical Expression Toolkit";
  7323. static const char* version = "2.71828182845904523536028";
  7324. static const char* date = "20120505";
  7325. static inline std::string data()
  7326. {
  7327. static const std::string info_str = std::string(library) +
  7328. std::string(" v") + std::string(version) +
  7329. std::string(" (") + date + std::string(")");
  7330. return info_str;
  7331. }
  7332. } // namespace information
  7333. } // namespace exprtk
  7334. #endif