PageRenderTime 73ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 3ms

/exprtk.hpp

http://nanocalc.codeplex.com
C++ Header | 15710 lines | 13003 code | 2594 blank | 113 comment | 1608 complexity | 304dd65fa1664a3781c0e72ef5a01b4d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. ******************************************************************
  3. * C++ Mathematical Expression Toolkit Library *
  4. * *
  5. * Author: Arash Partow (1999-2015) *
  6. * URL: http://www.partow.net/programming/exprtk/index.html *
  7. * *
  8. * Copyright notice: *
  9. * Free use of the C++ Mathematical Expression Toolkit Library is *
  10. * permitted under the guidelines and in accordance with the most *
  11. * current version of the 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) (avg(x,y) <= x + y ? x - y : x * y) + 2 * pi / x *
  22. * (07) z := x + sin(2 * pi / y) *
  23. * (08) u := 2 * (pi * z) / (w := x + cos(y / pi)) *
  24. * (09) clamp(-1,sin(2 * pi * x) + cos(y / 2 * pi),+1) *
  25. * (10) inrange(-2,m,+2) == if(({-2 <= m} and [m <= +2]),1,0) *
  26. * (11) (2sin(x)cos(2y)7 + 1) == (2 * sin(x) * cos(2*y) * 7 + 1) *
  27. * (12) (x ilike 's*ri?g') and [y < (3 z^7 + w)] *
  28. * *
  29. ******************************************************************
  30. */
  31. #ifndef INCLUDE_EXPRTK_HPP
  32. #define INCLUDE_EXPRTK_HPP
  33. #include <algorithm>
  34. #include <cctype>
  35. #include <cmath>
  36. #include <complex>
  37. #include <cstdio>
  38. #include <cstdlib>
  39. #include <deque>
  40. #include <exception>
  41. #include <functional>
  42. #include <iterator>
  43. #include <limits>
  44. #include <list>
  45. #include <map>
  46. #include <set>
  47. #include <stack>
  48. #include <stdexcept>
  49. #include <string>
  50. #include <utility>
  51. #include <vector>
  52. namespace exprtk
  53. {
  54. #if exprtk_enable_debugging
  55. #define exprtk_debug(params) printf params
  56. #else
  57. #define exprtk_debug(params) (void)0
  58. #endif
  59. namespace details
  60. {
  61. inline bool is_whitespace(const char c)
  62. {
  63. return (' ' == c) || ('\n' == c) ||
  64. ('\r' == c) || ('\t' == c) ||
  65. ('\b' == c) || ('\v' == c) ||
  66. ('\f' == c) ;
  67. }
  68. inline bool is_operator_char(const char c)
  69. {
  70. return ('+' == c) || ('-' == c) ||
  71. ('*' == c) || ('/' == c) ||
  72. ('^' == c) || ('<' == c) ||
  73. ('>' == c) || ('=' == c) ||
  74. (',' == c) || ('!' == c) ||
  75. ('(' == c) || (')' == c) ||
  76. ('[' == c) || (']' == c) ||
  77. ('{' == c) || ('}' == c) ||
  78. ('%' == c) || (':' == c) ||
  79. ('?' == c) || ('&' == c) ||
  80. ('|' == c) || (';' == c) ;
  81. }
  82. inline bool is_letter(const char c)
  83. {
  84. return (('a' <= c) && (c <= 'z')) ||
  85. (('A' <= c) && (c <= 'Z')) ;
  86. }
  87. inline bool is_digit(const char c)
  88. {
  89. return ('0' <= c) && (c <= '9');
  90. }
  91. inline bool is_letter_or_digit(const char c)
  92. {
  93. return is_letter(c) || is_digit(c);
  94. }
  95. inline bool is_left_bracket(const char c)
  96. {
  97. return ('(' == c) || ('[' == c) || ('{' == c);
  98. }
  99. inline bool is_right_bracket(const char c)
  100. {
  101. return (')' == c) || (']' == c) || ('}' == c);
  102. }
  103. inline bool is_bracket(const char c)
  104. {
  105. return is_left_bracket(c) || is_right_bracket(c);
  106. }
  107. inline bool is_sign(const char c)
  108. {
  109. return ('+' == c) || ('-' == c);
  110. }
  111. inline bool is_invalid(const char c)
  112. {
  113. return !is_whitespace (c) &&
  114. !is_operator_char(c) &&
  115. !is_letter (c) &&
  116. !is_digit (c) &&
  117. ('.' != c) &&
  118. ('_' != c) &&
  119. ('$' != c) &&
  120. ('~' != c) &&
  121. ('\'' != c);
  122. }
  123. inline bool imatch(const char c1, const char c2)
  124. {
  125. return std::tolower(c1) == std::tolower(c2);
  126. }
  127. inline bool imatch(const std::string& s1, const std::string& s2)
  128. {
  129. if (s1.size() == s2.size())
  130. {
  131. for (std::size_t i = 0; i < s1.size(); ++i)
  132. {
  133. if (std::tolower(s1[i]) != std::tolower(s2[i]))
  134. {
  135. return false;
  136. }
  137. }
  138. return true;
  139. }
  140. return false;
  141. }
  142. inline bool is_valid_sf_symbol(const std::string& symbol)
  143. {
  144. // Special function: $f12 or $F34
  145. return (4 == symbol.size()) &&
  146. ('$' == symbol[0]) &&
  147. imatch('f',symbol[1]) &&
  148. is_digit(symbol[2]) &&
  149. is_digit(symbol[3]);
  150. }
  151. inline const char& front(const std::string& s)
  152. {
  153. return s[0];
  154. }
  155. inline const char& back(const std::string& s)
  156. {
  157. return s[s.size() - 1];
  158. }
  159. inline std::string to_str(int i)
  160. {
  161. if (0 == i)
  162. return std::string("0");
  163. std::string result;
  164. if (i < 0)
  165. {
  166. for ( ; i; i /= 10)
  167. {
  168. result += '0' + char(-(i % 10));
  169. }
  170. result += '-';
  171. }
  172. else
  173. {
  174. for ( ; i; i /= 10)
  175. {
  176. result += '0' + char(i % 10);
  177. }
  178. }
  179. std::reverse(result.begin(), result.end());
  180. return result;
  181. }
  182. inline bool is_hex_digit(const std::string::value_type digit)
  183. {
  184. return (('0' <= digit) && (digit <= '9')) ||
  185. (('A' <= digit) && (digit <= 'F')) ||
  186. (('a' <= digit) && (digit <= 'f')) ;
  187. }
  188. inline unsigned char hex_to_bin(unsigned char h)
  189. {
  190. if (('0' <= h) && (h <= '9'))
  191. return (h - '0');
  192. else
  193. return (std::toupper(h) - 'A');
  194. }
  195. template <typename Iterator>
  196. inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result)
  197. {
  198. if (
  199. (end != (itr )) &&
  200. (end != (itr + 1)) &&
  201. (end != (itr + 2)) &&
  202. (end != (itr + 3)) &&
  203. ('0' == *(itr )) &&
  204. (
  205. ('x' == *(itr + 1)) ||
  206. ('X' == *(itr + 1))
  207. ) &&
  208. (is_hex_digit(*(itr + 2))) &&
  209. (is_hex_digit(*(itr + 3)))
  210. )
  211. {
  212. result = hex_to_bin(*(itr + 2)) << 4 | hex_to_bin(*(itr + 3));
  213. itr += 3;
  214. }
  215. else
  216. result = '\0';
  217. }
  218. inline void cleanup_escapes(std::string& s)
  219. {
  220. typedef std::string::iterator str_itr_t;
  221. str_itr_t itr1 = s.begin();
  222. str_itr_t itr2 = s.begin();
  223. str_itr_t end = s.end ();
  224. std::size_t removal_count = 0;
  225. while (end != itr1)
  226. {
  227. if ('\\' == (*itr1))
  228. {
  229. ++removal_count;
  230. if (end == ++itr1)
  231. break;
  232. else if ('\\' != (*itr1))
  233. {
  234. switch (*itr1)
  235. {
  236. case 'n' : (*itr1) = '\n'; break;
  237. case 'r' : (*itr1) = '\r'; break;
  238. case 't' : (*itr1) = '\t'; break;
  239. case '0' : parse_hex(itr1, end, (*itr1));
  240. removal_count += 3;
  241. break;
  242. }
  243. continue;
  244. }
  245. }
  246. if (itr1 != itr2)
  247. {
  248. (*itr2) = (*itr1);
  249. }
  250. ++itr1;
  251. ++itr2;
  252. }
  253. s.resize(s.size() - removal_count);
  254. }
  255. class build_string
  256. {
  257. public:
  258. build_string(const std::size_t& initial_size = 64)
  259. {
  260. data_.reserve(initial_size);
  261. }
  262. inline build_string& operator << (const std::string& s)
  263. {
  264. data_ += s;
  265. return (*this);
  266. }
  267. inline build_string& operator << (const char* s)
  268. {
  269. data_ += std::string(s);
  270. return (*this);
  271. }
  272. inline operator std::string () const
  273. {
  274. return data_;
  275. }
  276. inline std::string as_string() const
  277. {
  278. return data_;
  279. }
  280. private:
  281. std::string data_;
  282. };
  283. struct ilesscompare
  284. {
  285. inline bool operator()(const std::string& s1, const std::string& s2) const
  286. {
  287. const std::size_t length = std::min(s1.size(),s2.size());
  288. for (std::size_t i = 0; i < length; ++i)
  289. {
  290. const char c1 = static_cast<char>(std::tolower(s1[i]));
  291. const char c2 = static_cast<char>(std::tolower(s2[i]));
  292. if (c1 > c2)
  293. return false;
  294. else if (c1 < c2)
  295. return true;
  296. }
  297. return s1.size() < s2.size();
  298. }
  299. };
  300. static const std::string reserved_words[] =
  301. {
  302. "break", "case", "continue", "default", "false", "for",
  303. "if", "else", "ilike", "in", "like", "and", "nand", "nor",
  304. "not", "null", "or", "repeat", "return", "shl", "shr",
  305. "swap", "switch", "true", "until", "var", "while", "xnor",
  306. "xor", "&", "|"
  307. };
  308. static const std::size_t reserved_words_size = sizeof(reserved_words) / sizeof(std::string);
  309. static const std::string reserved_symbols[] =
  310. {
  311. "abs", "acos", "acosh", "and", "asin", "asinh", "atan",
  312. "atanh", "atan2", "avg", "break", "case", "ceil", "clamp",
  313. "continue", "cos", "cosh", "cot", "csc", "default",
  314. "deg2grad", "deg2rad", "equal", "erf", "erfc", "exp",
  315. "expm1", "false", "floor", "for", "frac", "grad2deg",
  316. "hypot", "iclamp", "if", "else", "ilike", "in", "inrange",
  317. "like", "log", "log10", "log2", "logn", "log1p", "mand",
  318. "max", "min", "mod", "mor", "mul", "ncdf", "nand", "nor",
  319. "not", "not_equal", "null", "or", "pow", "rad2deg",
  320. "repeat", "return", "root", "round", "roundn", "sec", "sgn",
  321. "shl", "shr", "sin", "sinc", "sinh", "sqrt", "sum", "swap",
  322. "switch", "tan", "tanh", "true", "trunc", "until", "var",
  323. "while", "xnor", "xor", "&", "|"
  324. };
  325. static const std::size_t reserved_symbols_size = sizeof(reserved_symbols) / sizeof(std::string);
  326. static const std::string base_function_list[] =
  327. {
  328. "abs", "acos", "acosh", "asin", "asinh", "atan", "atanh",
  329. "atan2", "avg", "ceil", "clamp", "cos", "cosh", "cot",
  330. "csc", "equal", "erf", "erfc", "exp", "expm1", "floor",
  331. "frac", "hypot", "iclamp", "like", "log", "log10", "log2",
  332. "logn", "log1p", "mand", "max", "min", "mod", "mor", "mul",
  333. "ncdf", "pow", "root", "round", "roundn", "sec", "sgn",
  334. "sin", "sinc", "sinh", "sqrt", "sum", "swap", "tan", "tanh",
  335. "trunc", "not_equal", "inrange", "deg2grad", "deg2rad",
  336. "rad2deg", "grad2deg"
  337. };
  338. static const std::size_t base_function_list_size = sizeof(base_function_list) / sizeof(std::string);
  339. static const std::string logic_ops_list[] =
  340. {
  341. "and", "nand", "nor", "not", "or", "xnor", "xor", "&", "|"
  342. };
  343. static const std::size_t logic_ops_list_size = sizeof(logic_ops_list) / sizeof(std::string);
  344. static const std::string cntrl_struct_list[] =
  345. {
  346. "for", "if", "repeat", "switch", "while"
  347. };
  348. static const std::size_t cntrl_struct_list_size = sizeof(cntrl_struct_list) / sizeof(std::string);
  349. inline bool is_reserved_word(const std::string& symbol)
  350. {
  351. for (std::size_t i = 0; i < reserved_words_size; ++i)
  352. {
  353. if (imatch(symbol,reserved_words[i]))
  354. {
  355. return true;
  356. }
  357. }
  358. return false;
  359. }
  360. inline bool is_reserved_symbol(const std::string& symbol)
  361. {
  362. for (std::size_t i = 0; i < reserved_symbols_size; ++i)
  363. {
  364. if (imatch(symbol,reserved_symbols[i]))
  365. {
  366. return true;
  367. }
  368. }
  369. return false;
  370. }
  371. inline bool is_base_function(const std::string& function_name)
  372. {
  373. for (std::size_t i = 0; i < base_function_list_size; ++i)
  374. {
  375. if (imatch(function_name,base_function_list[i]))
  376. {
  377. return true;
  378. }
  379. }
  380. return false;
  381. }
  382. inline bool is_control_struct(const std::string& cntrl_strct)
  383. {
  384. for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
  385. {
  386. if (imatch(cntrl_strct,cntrl_struct_list[i]))
  387. {
  388. return true;
  389. }
  390. }
  391. return false;
  392. }
  393. inline bool is_logic_opr(const std::string& lgc_opr)
  394. {
  395. for (std::size_t i = 0; i < cntrl_struct_list_size; ++i)
  396. {
  397. if (imatch(lgc_opr,logic_ops_list[i]))
  398. {
  399. return true;
  400. }
  401. }
  402. return false;
  403. }
  404. struct cs_match
  405. {
  406. static inline bool cmp(const char c0, const char c1)
  407. {
  408. return (c0 == c1);
  409. }
  410. };
  411. struct cis_match
  412. {
  413. static inline bool cmp(const char c0, const char c1)
  414. {
  415. return (std::tolower(c0) == std::tolower(c1));
  416. }
  417. };
  418. template <typename Iterator, typename Compare>
  419. inline bool match_impl(const Iterator pattern_begin,
  420. const Iterator pattern_end,
  421. const Iterator data_begin,
  422. const Iterator data_end,
  423. const typename std::iterator_traits<Iterator>::value_type& zero_or_more,
  424. const typename std::iterator_traits<Iterator>::value_type& zero_or_one)
  425. {
  426. if (0 == std::distance(data_begin,data_end))
  427. {
  428. return false;
  429. }
  430. Iterator d_itr = data_begin;
  431. Iterator p_itr = pattern_begin;
  432. Iterator c_itr = data_begin;
  433. Iterator m_itr = data_begin;
  434. while ((data_end != d_itr) && (zero_or_more != (*p_itr)))
  435. {
  436. if ((!Compare::cmp((*p_itr),(*d_itr))) && (zero_or_one != (*p_itr)))
  437. {
  438. return false;
  439. }
  440. ++p_itr;
  441. ++d_itr;
  442. }
  443. while (data_end != d_itr)
  444. {
  445. if (zero_or_more == (*p_itr))
  446. {
  447. if (pattern_end == (++p_itr))
  448. {
  449. return true;
  450. }
  451. m_itr = p_itr;
  452. c_itr = d_itr;
  453. ++c_itr;
  454. }
  455. else if ((Compare::cmp((*p_itr),(*d_itr))) || (zero_or_one == (*p_itr)))
  456. {
  457. ++p_itr;
  458. ++d_itr;
  459. }
  460. else
  461. {
  462. p_itr = m_itr;
  463. d_itr = c_itr++;
  464. }
  465. }
  466. while ((p_itr != pattern_end) && (zero_or_more == (*p_itr))) { ++p_itr; }
  467. return (p_itr == pattern_end);
  468. }
  469. inline bool wc_match(const std::string& wild_card,
  470. const std::string& str)
  471. {
  472. return match_impl<const char*,cs_match>(wild_card.data(),
  473. wild_card.data() + wild_card.size(),
  474. str.data(),
  475. str.data() + str.size(),
  476. '*',
  477. '?');
  478. }
  479. inline bool wc_imatch(const std::string& wild_card,
  480. const std::string& str)
  481. {
  482. return match_impl<const char*,cis_match>(wild_card.data(),
  483. wild_card.data() + wild_card.size(),
  484. str.data(),
  485. str.data() + str.size(),
  486. '*',
  487. '?');
  488. }
  489. inline bool sequence_match(const std::string& pattern,
  490. const std::string& str,
  491. std::size_t& diff_index,
  492. char& diff_value)
  493. {
  494. if (str.empty() || pattern.empty())
  495. return false;
  496. else if ('*' == pattern[0])
  497. return false;
  498. typedef std::string::const_iterator itr_t;
  499. itr_t p_itr = pattern.begin();
  500. itr_t s_itr = str .begin();
  501. itr_t p_end = pattern.end();
  502. itr_t s_end = str .end();
  503. while ((s_end != s_itr) && (p_end != p_itr))
  504. {
  505. if ('*' == (*p_itr))
  506. {
  507. const char target = std::toupper(*(p_itr - 1));
  508. if ('*' == target)
  509. {
  510. diff_index = std::distance(str.begin(),s_itr);
  511. diff_value = std::toupper(*p_itr);
  512. return false;
  513. }
  514. else
  515. ++p_itr;
  516. while (s_itr != s_end)
  517. {
  518. if (target != std::toupper(*s_itr))
  519. break;
  520. else
  521. ++s_itr;
  522. }
  523. continue;
  524. }
  525. else if (
  526. ('?' != *p_itr) &&
  527. std::toupper(*p_itr) != std::toupper(*s_itr)
  528. )
  529. {
  530. diff_index = std::distance(str.begin(),s_itr);
  531. diff_value = std::toupper(*p_itr);
  532. return false;
  533. }
  534. ++p_itr;
  535. ++s_itr;
  536. }
  537. return (
  538. (s_end == s_itr) &&
  539. (
  540. (p_end == p_itr) ||
  541. ('*' == *p_itr)
  542. )
  543. );
  544. }
  545. static const double pow10[] = {
  546. 1.0,
  547. 1.0E+001, 1.0E+002, 1.0E+003, 1.0E+004,
  548. 1.0E+005, 1.0E+006, 1.0E+007, 1.0E+008,
  549. 1.0E+009, 1.0E+010, 1.0E+011, 1.0E+012,
  550. 1.0E+013, 1.0E+014, 1.0E+015, 1.0E+016
  551. };
  552. static const std::size_t pow10_size = sizeof(pow10) / sizeof(double);
  553. namespace numeric
  554. {
  555. namespace constant
  556. {
  557. static const double e = 2.718281828459045235360;
  558. static const double pi = 3.141592653589793238462;
  559. static const double pi_2 = 1.570796326794896619231;
  560. static const double pi_4 = 0.785398163397448309616;
  561. static const double pi_180 = 0.017453292519943295769;
  562. static const double _1_pi = 0.318309886183790671538;
  563. static const double _2_pi = 0.636619772367581343076;
  564. static const double _180_pi = 57.295779513082320876798;
  565. static const double log2 = 0.693147180559945309417;
  566. static const double sqrt2 = 1.414213562373095048801;
  567. }
  568. namespace details
  569. {
  570. struct unknown_type_tag {};
  571. struct real_type_tag {};
  572. struct complex_type_tag {};
  573. struct int_type_tag {};
  574. template <typename T>
  575. struct number_type { typedef unknown_type_tag type; };
  576. #define exprtk_register_real_type_tag(T) \
  577. template<> struct number_type<T> { typedef real_type_tag type; }; \
  578. #define exprtk_register_complex_type_tag(T) \
  579. template<> struct number_type<std::complex<T> > \
  580. { typedef complex_type_tag type; }; \
  581. #define exprtk_register_int_type_tag(T) \
  582. template<> struct number_type<T> { typedef int_type_tag type; }; \
  583. exprtk_register_real_type_tag(double )
  584. exprtk_register_real_type_tag(long double)
  585. exprtk_register_real_type_tag(float )
  586. exprtk_register_complex_type_tag(double )
  587. exprtk_register_complex_type_tag(long double)
  588. exprtk_register_complex_type_tag(float )
  589. exprtk_register_int_type_tag(short )
  590. exprtk_register_int_type_tag(int )
  591. exprtk_register_int_type_tag(long long int )
  592. exprtk_register_int_type_tag(unsigned short )
  593. exprtk_register_int_type_tag(unsigned int )
  594. exprtk_register_int_type_tag(unsigned long long int)
  595. #undef exprtk_register_real_type_tag
  596. #undef exprtk_register_int_type_tag
  597. template <typename T>
  598. struct epsilon_type
  599. {
  600. static inline T value()
  601. {
  602. const T epsilon = T(0.0000000001);
  603. return epsilon;
  604. }
  605. };
  606. template <>
  607. struct epsilon_type <float>
  608. {
  609. static inline float value()
  610. {
  611. const float epsilon = float(0.000001f);
  612. return epsilon;
  613. }
  614. };
  615. template <>
  616. struct epsilon_type <long double>
  617. {
  618. static inline long double value()
  619. {
  620. const long double epsilon = (long double)(0.000000000001);
  621. return epsilon;
  622. }
  623. };
  624. template <typename T>
  625. inline bool is_nan_impl(const T v, real_type_tag)
  626. {
  627. return std::not_equal_to<T>()(v,v);
  628. }
  629. template <typename T>
  630. inline int to_int32_impl(const T v, real_type_tag)
  631. {
  632. return static_cast<int>(v);
  633. }
  634. template <typename T>
  635. inline long long int to_int64_impl(const T v, real_type_tag)
  636. {
  637. return static_cast<long long int>(v);
  638. }
  639. template <typename T>
  640. inline bool is_true_impl(const T v)
  641. {
  642. return std::not_equal_to<T>()(T(0),v);
  643. }
  644. template <typename T>
  645. inline bool is_false_impl(const T v)
  646. {
  647. return std::equal_to<T>()(T(0),v);
  648. }
  649. template <typename T>
  650. inline T abs_impl(const T v, real_type_tag)
  651. {
  652. return ((v >= T(0)) ? v : -v);
  653. }
  654. template <typename T>
  655. inline T min_impl(const T v0, const T v1, real_type_tag)
  656. {
  657. return std::min<T>(v0,v1);
  658. }
  659. template <typename T>
  660. inline T max_impl(const T v0, const T v1, real_type_tag)
  661. {
  662. return std::max<T>(v0,v1);
  663. }
  664. template <typename T>
  665. inline T equal_impl(const T v0, const T v1, real_type_tag)
  666. {
  667. const T epsilon = epsilon_type<T>::value();
  668. return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(T(1),std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? T(1) : T(0);
  669. }
  670. inline float equal_impl(const float v0, const float v1, real_type_tag)
  671. {
  672. const float epsilon = epsilon_type<float>::value();
  673. return (abs_impl(v0 - v1,real_type_tag()) <= (std::max(1.0f,std::max(abs_impl(v0,real_type_tag()),abs_impl(v1,real_type_tag()))) * epsilon)) ? 1.0f : 0.0f;
  674. }
  675. template <typename T>
  676. inline T equal_impl(const T v0, const T v1, int_type_tag)
  677. {
  678. return (v0 == v1) ? 1 : 0;
  679. }
  680. template <typename T>
  681. inline T expm1_impl(const T v, real_type_tag)
  682. {
  683. // return std::expm1<T>(v);
  684. if (abs_impl(v,real_type_tag()) < T(0.00001))
  685. return v + (T(0.5) * v * v);
  686. else
  687. return std::exp(v) - T(1);
  688. }
  689. template <typename T>
  690. inline T expm1_impl(const T v, int_type_tag)
  691. {
  692. return T(std::exp<double>(v)) - T(1);
  693. }
  694. template <typename T>
  695. inline T nequal_impl(const T v0, const T v1, real_type_tag)
  696. {
  697. typedef real_type_tag rtg;
  698. const T epsilon = epsilon_type<T>::value();
  699. return (abs_impl(v0 - v1,rtg()) > (std::max(T(1),std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? T(1) : T(0);
  700. }
  701. inline float nequal_impl(const float v0, const float v1, real_type_tag)
  702. {
  703. typedef real_type_tag rtg;
  704. const float epsilon = epsilon_type<float>::value();
  705. return (abs_impl(v0 - v1,rtg()) > (std::max(1.0f,std::max(abs_impl(v0,rtg()),abs_impl(v1,rtg()))) * epsilon)) ? 1.0f : 0.0f;
  706. }
  707. template <typename T>
  708. inline T nequal_impl(const T v0, const T v1, int_type_tag)
  709. {
  710. return (v0 != v1) ? 1 : 0;
  711. }
  712. template <typename T>
  713. inline T modulus_impl(const T v0, const T v1, real_type_tag)
  714. {
  715. return std::fmod(v0,v1);
  716. }
  717. template <typename T>
  718. inline T modulus_impl(const T v0, const T v1, int_type_tag)
  719. {
  720. return v0 % v1;
  721. }
  722. template <typename T>
  723. inline T pow_impl(const T v0, const T v1, real_type_tag)
  724. {
  725. return std::pow(v0,v1);
  726. }
  727. template <typename T>
  728. inline T pow_impl(const T v0, const T v1, int_type_tag)
  729. {
  730. return std::pow(static_cast<double>(v0),static_cast<double>(v1));
  731. }
  732. template <typename T>
  733. inline T logn_impl(const T v0, const T v1, real_type_tag)
  734. {
  735. return std::log(v0) / std::log(v1);
  736. }
  737. template <typename T>
  738. inline T logn_impl(const T v0, const T v1, int_type_tag)
  739. {
  740. return static_cast<T>(logn_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag()));
  741. }
  742. template <typename T>
  743. inline T log1p_impl(const T v, real_type_tag)
  744. {
  745. if (v > T(-1))
  746. {
  747. if (abs_impl(v,real_type_tag()) > T(0.0001))
  748. {
  749. return std::log(T(1) + v);
  750. }
  751. else
  752. return (T(-0.5) * v + T(1)) * v;
  753. }
  754. else
  755. return std::numeric_limits<T>::quiet_NaN();
  756. }
  757. template <typename T>
  758. inline T log1p_impl(const T v, int_type_tag)
  759. {
  760. if (v > T(-1))
  761. {
  762. return std::log(T(1) + v);
  763. }
  764. else
  765. return std::numeric_limits<T>::quiet_NaN();
  766. }
  767. template <typename T>
  768. inline T root_impl(const T v0, const T v1, real_type_tag)
  769. {
  770. return std::pow(v0,T(1) / v1);
  771. }
  772. template <typename T>
  773. inline T root_impl(const T v0, const T v1, int_type_tag)
  774. {
  775. return root_impl<double>(static_cast<double>(v0),static_cast<double>(v1),real_type_tag());
  776. }
  777. template <typename T>
  778. inline T round_impl(const T v, real_type_tag)
  779. {
  780. return ((v < T(0)) ? std::ceil(v - T(0.5)) : std::floor(v + T(0.5)));
  781. }
  782. template <typename T>
  783. inline T roundn_impl(const T v0, const T v1, real_type_tag)
  784. {
  785. const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1)));
  786. const T p10 = T(pow10[index]);
  787. if (v0 < T(0))
  788. return T(std::ceil ((v0 * p10) - T(0.5)) / p10);
  789. else
  790. return T(std::floor((v0 * p10) + T(0.5)) / p10);
  791. }
  792. template <typename T>
  793. inline T roundn_impl(const T v0, const T, int_type_tag)
  794. {
  795. return v0;
  796. }
  797. template <typename T>
  798. inline T hypot_impl(const T v0, const T v1, real_type_tag)
  799. {
  800. return std::sqrt((v0 * v0) + (v1 * v1));
  801. }
  802. template <typename T>
  803. inline T hypot_impl(const T v0, const T v1, int_type_tag)
  804. {
  805. return static_cast<T>(std::sqrt(static_cast<double>((v0 * v0) + (v1 * v1))));
  806. }
  807. template <typename T>
  808. inline T atan2_impl(const T v0, const T v1, real_type_tag)
  809. {
  810. return std::atan2(v0,v1);
  811. }
  812. template <typename T>
  813. inline T atan2_impl(const T, const T, int_type_tag)
  814. {
  815. return 0;
  816. }
  817. template <typename T>
  818. inline T shr_impl(const T v0, const T v1, real_type_tag)
  819. {
  820. return v0 * (T(1) / std::pow(T(2),static_cast<T>(static_cast<int>(v1))));
  821. }
  822. template <typename T>
  823. inline T shr_impl(const T v0, const T v1, int_type_tag)
  824. {
  825. return v0 >> v1;
  826. }
  827. template <typename T>
  828. inline T shl_impl(const T v0, const T v1, real_type_tag)
  829. {
  830. return v0 * std::pow(T(2),static_cast<T>(static_cast<int>(v1)));
  831. }
  832. template <typename T>
  833. inline T shl_impl(const T v0, const T v1, int_type_tag)
  834. {
  835. return v0 << v1;
  836. }
  837. template <typename T>
  838. inline T sgn_impl(const T v, real_type_tag)
  839. {
  840. if (v > T(0)) return T(+1);
  841. else if (v < T(0)) return T(-1);
  842. else return T( 0);
  843. }
  844. template <typename T>
  845. inline T sgn_impl(const T v, int_type_tag)
  846. {
  847. if (v > T(0)) return T(+1);
  848. else if (v < T(0)) return T(-1);
  849. else return T( 0);
  850. }
  851. template <typename T>
  852. inline T and_impl(const T v0, const T v1, real_type_tag)
  853. {
  854. return (is_true_impl(v0) && is_true_impl(v1)) ? T(1) : T(0);
  855. }
  856. template <typename T>
  857. inline T and_impl(const T v0, const T v1, int_type_tag)
  858. {
  859. return v0 && v1;
  860. }
  861. template <typename T>
  862. inline T nand_impl(const T v0, const T v1, real_type_tag)
  863. {
  864. return (is_false_impl(v0) || is_false_impl(v1)) ? T(1) : T(0);
  865. }
  866. template <typename T>
  867. inline T nand_impl(const T v0, const T v1, int_type_tag)
  868. {
  869. return !(v0 && v1);
  870. }
  871. template <typename T>
  872. inline T or_impl(const T v0, const T v1, real_type_tag)
  873. {
  874. return (is_true_impl(v0) || is_true_impl(v1)) ? T(1) : T(0);
  875. }
  876. template <typename T>
  877. inline T or_impl(const T v0, const T v1, int_type_tag)
  878. {
  879. return (v0 || v1);
  880. }
  881. template <typename T>
  882. inline T nor_impl(const T v0, const T v1, real_type_tag)
  883. {
  884. return (is_false_impl(v0) && is_false_impl(v1)) ? T(1) : T(0);
  885. }
  886. template <typename T>
  887. inline T nor_impl(const T v0, const T v1, int_type_tag)
  888. {
  889. return !(v0 || v1);
  890. }
  891. template <typename T>
  892. inline T xor_impl(const T v0, const T v1, real_type_tag)
  893. {
  894. return (is_false_impl(v0) != is_false_impl(v1)) ? T(1) : T(0);
  895. }
  896. template <typename T>
  897. inline T xor_impl(const T v0, const T v1, int_type_tag)
  898. {
  899. return v0 ^ v1;
  900. }
  901. template <typename T>
  902. inline T xnor_impl(const T v0, const T v1, real_type_tag)
  903. {
  904. const bool v0_true = is_true_impl(v0);
  905. const bool v1_true = is_true_impl(v1);
  906. if ((v0_true && v1_true) || (!v0_true && !v1_true))
  907. return T(1);
  908. else
  909. return T(0);
  910. }
  911. template <typename T>
  912. inline T xnor_impl(const T v0, const T v1, int_type_tag)
  913. {
  914. const bool v0_true = is_true_impl(v0);
  915. const bool v1_true = is_true_impl(v1);
  916. if ((v0_true && v1_true) || (!v0_true && !v1_true))
  917. return T(1);
  918. else
  919. return T(0);
  920. }
  921. template <typename T>
  922. inline T erf_impl(T v, real_type_tag)
  923. {
  924. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  925. // Credits: Abramowitz & Stegun Equations 7.1.25-28
  926. const T t = T(1) / (T(1) + T(0.5) * abs_impl(v,real_type_tag()));
  927. static const T c[] = {
  928. T( 1.26551223), T(1.00002368),
  929. T( 0.37409196), T(0.09678418),
  930. T(-0.18628806), T(0.27886807),
  931. T(-1.13520398), T(1.48851587),
  932. T(-0.82215223), T(0.17087277)
  933. };
  934. T result = T(1) - t * std::exp((-v * v) -
  935. c[0] + t * (c[1] + t *
  936. (c[2] + t * (c[3] + t *
  937. (c[4] + t * (c[5] + t *
  938. (c[6] + t * (c[7] + t *
  939. (c[8] + t * (c[9]))))))))));
  940. return (v >= T(0)) ? result : -result;
  941. #else
  942. return ::erf(v);
  943. #endif
  944. }
  945. template <typename T>
  946. inline T erf_impl(T v, int_type_tag)
  947. {
  948. return erf_impl(static_cast<double>(v),real_type_tag());
  949. }
  950. template <typename T>
  951. inline T erfc_impl(T v, real_type_tag)
  952. {
  953. #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
  954. return T(1) - erf_impl(v,real_type_tag());
  955. #else
  956. return ::erfc(v);
  957. #endif
  958. }
  959. template <typename T>
  960. inline T erfc_impl(T v, int_type_tag)
  961. {
  962. return erfc_impl(static_cast<double>(v),real_type_tag());
  963. }
  964. template <typename T>
  965. inline T ncdf_impl(T v, real_type_tag)
  966. {
  967. T cnd = T(0.5) * (T(1) + erf_impl(
  968. abs_impl(v,real_type_tag()) /
  969. T(numeric::constant::sqrt2),real_type_tag()));
  970. return (v < T(0)) ? (T(1) - cnd) : cnd;
  971. }
  972. template <typename T>
  973. inline T ncdf_impl(T v, int_type_tag)
  974. {
  975. return ncdf_impl(static_cast<double>(v),real_type_tag());
  976. }
  977. template <typename T>
  978. inline T sinc_impl(T v, real_type_tag)
  979. {
  980. if (std::abs(v) >= std::numeric_limits<T>::epsilon())
  981. return(std::sin(v) / v);
  982. else
  983. return T(1);
  984. }
  985. template <typename T>
  986. inline T sinc_impl(T v, int_type_tag)
  987. {
  988. return sinc_impl(static_cast<double>(v),real_type_tag());
  989. }
  990. template <typename T> inline T acos_impl(const T v, real_type_tag) { return std::acos (v); }
  991. template <typename T> inline T acosh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) - T(1))); }
  992. template <typename T> inline T asin_impl(const T v, real_type_tag) { return std::asin (v); }
  993. template <typename T> inline T asinh_impl(const T v, real_type_tag) { return std::log(v + std::sqrt((v * v) + T(1))); }
  994. template <typename T> inline T atan_impl(const T v, real_type_tag) { return std::atan (v); }
  995. template <typename T> inline T atanh_impl(const T v, real_type_tag) { return (std::log(T(1) + v) - log(T(1) - v)) / T(2); }
  996. template <typename T> inline T ceil_impl(const T v, real_type_tag) { return std::ceil (v); }
  997. template <typename T> inline T cos_impl(const T v, real_type_tag) { return std::cos (v); }
  998. template <typename T> inline T cosh_impl(const T v, real_type_tag) { return std::cosh (v); }
  999. template <typename T> inline T exp_impl(const T v, real_type_tag) { return std::exp (v); }
  1000. template <typename T> inline T floor_impl(const T v, real_type_tag) { return std::floor(v); }
  1001. template <typename T> inline T log_impl(const T v, real_type_tag) { return std::log (v); }
  1002. template <typename T> inline T log10_impl(const T v, real_type_tag) { return std::log10(v); }
  1003. template <typename T> inline T log2_impl(const T v, real_type_tag) { return std::log(v)/T(numeric::constant::log2); }
  1004. template <typename T> inline T neg_impl(const T v, real_type_tag) { return -v; }
  1005. template <typename T> inline T pos_impl(const T v, real_type_tag) { return +v; }
  1006. template <typename T> inline T sin_impl(const T v, real_type_tag) { return std::sin (v); }
  1007. template <typename T> inline T sinh_impl(const T v, real_type_tag) { return std::sinh (v); }
  1008. template <typename T> inline T sqrt_impl(const T v, real_type_tag) { return std::sqrt (v); }
  1009. template <typename T> inline T tan_impl(const T v, real_type_tag) { return std::tan (v); }
  1010. template <typename T> inline T tanh_impl(const T v, real_type_tag) { return std::tanh (v); }
  1011. template <typename T> inline T cot_impl(const T v, real_type_tag) { return T(1) / std::tan(v); }
  1012. template <typename T> inline T sec_impl(const T v, real_type_tag) { return T(1) / std::cos(v); }
  1013. template <typename T> inline T csc_impl(const T v, real_type_tag) { return T(1) / std::sin(v); }
  1014. template <typename T> inline T r2d_impl(const T v, real_type_tag) { return (v * T(numeric::constant::_180_pi)); }
  1015. template <typename T> inline T d2r_impl(const T v, real_type_tag) { return (v * T(numeric::constant::pi_180)); }
  1016. template <typename T> inline T d2g_impl(const T v, real_type_tag) { return (v * T(20.0/9.0)); }
  1017. template <typename T> inline T g2d_impl(const T v, real_type_tag) { return (v * T(9.0/20.0)); }
  1018. template <typename T> inline T notl_impl(const T v, real_type_tag) { return (std::not_equal_to<T>()(T(0),v) ? T(0) : T(1)); }
  1019. template <typename T> inline T frac_impl(const T v, real_type_tag) { return (v - static_cast<long long>(v)); }
  1020. template <typename T> inline T trunc_impl(const T v, real_type_tag) { return T(static_cast<long long>(v)); }
  1021. template <typename T> inline T abs_impl(const T v, int_type_tag) { return ((v >= T(0)) ? v : -v); }
  1022. template <typename T> inline T exp_impl(const T v, int_type_tag) { return std::exp (v); }
  1023. template <typename T> inline T log_impl(const T v, int_type_tag) { return std::log (v); }
  1024. template <typename T> inline T log10_impl(const T v, int_type_tag) { return std::log10(v); }
  1025. template <typename T> inline T log2_impl(const T v, int_type_tag) { return std::log(v)/T(numeric::constant::log2); }
  1026. template <typename T> inline T neg_impl(const T v, int_type_tag) { return -v; }
  1027. template <typename T> inline T pos_impl(const T v, int_type_tag) { return +v; }
  1028. template <typename T> inline T ceil_impl(const T v, int_type_tag) { return v; }
  1029. template <typename T> inline T floor_impl(const T v, int_type_tag) { return v; }
  1030. template <typename T> inline T round_impl(const T v, int_type_tag) { return v; }
  1031. template <typename T> inline T notl_impl(const T v, int_type_tag) { return !v; }
  1032. template <typename T> inline T sqrt_impl(const T v, int_type_tag) { return std::sqrt (v); }
  1033. template <typename T> inline T frac_impl(const T , int_type_tag) { return T(0); }
  1034. template <typename T> inline T trunc_impl(const T v, int_type_tag) { return v; }
  1035. template <typename T> inline T acos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1036. template <typename T> inline T acosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1037. template <typename T> inline T asin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1038. template <typename T> inline T asinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1039. template <typename T> inline T atan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1040. template <typename T> inline T atanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1041. template <typename T> inline T cos_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1042. template <typename T> inline T cosh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1043. template <typename T> inline T sin_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1044. template <typename T> inline T sinh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1045. template <typename T> inline T tan_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1046. template <typename T> inline T tanh_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1047. template <typename T> inline T cot_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1048. template <typename T> inline T sec_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1049. template <typename T> inline T csc_impl(const T , int_type_tag) { return std::numeric_limits<T>::quiet_NaN(); }
  1050. template <typename T>
  1051. inline bool is_integer_impl(const T& v, real_type_tag)
  1052. {
  1053. return std::equal_to<T>()(T(0),std::fmod(v,T(1)));
  1054. }
  1055. template <typename T>
  1056. inline bool is_integer_impl(const T&, int_type_tag)
  1057. {
  1058. return true;
  1059. }
  1060. }
  1061. template <typename Type>
  1062. struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; };
  1063. template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; };
  1064. template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; };
  1065. template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; };
  1066. template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; };
  1067. template <typename T>
  1068. inline int to_int32(const T v)
  1069. {
  1070. typename details::number_type<T>::type num_type;
  1071. return to_int32_impl(v,num_type);
  1072. }
  1073. template <typename T>
  1074. inline long long int to_int64(const T v)
  1075. {
  1076. typename details::number_type<T>::type num_type;
  1077. return to_int64_impl(v,num_type);
  1078. }
  1079. template <typename T>
  1080. inline bool is_nan(const T v)
  1081. {
  1082. typename details::number_type<T>::type num_type;
  1083. return is_nan_impl(v,num_type);
  1084. }
  1085. template <typename T>
  1086. inline T min(const T v0, const T v1)
  1087. {
  1088. typename details::number_type<T>::type num_type;
  1089. return min_impl(v0,v1,num_type);
  1090. }
  1091. template <typename T>
  1092. inline T max(const T v0, const T v1)
  1093. {
  1094. typename details::number_type<T>::type num_type;
  1095. return max_impl(v0,v1,num_type);
  1096. }
  1097. template <typename T>
  1098. inline T equal(const T v0, const T v1)
  1099. {
  1100. typename details::number_type<T>::type num_type;
  1101. return equal_impl(v0,v1,num_type);
  1102. }
  1103. template <typename T>
  1104. inline T nequal(const T v0, const T v1)
  1105. {
  1106. typename details::number_type<T>::type num_type;
  1107. return nequal_impl(v0,v1,num_type);
  1108. }
  1109. template <typename T>
  1110. inline T modulus(const T v0, const T v1)
  1111. {
  1112. typename details::number_type<T>::type num_type;
  1113. return modulus_impl(v0,v1,num_type);
  1114. }
  1115. template <typename T>
  1116. inline T pow(const T v0, const T v1)
  1117. {
  1118. typename details::number_type<T>::type num_type;
  1119. return pow_impl(v0,v1,num_type);
  1120. }
  1121. template <typename T>
  1122. inline T logn(const T v0, const T v1)
  1123. {
  1124. typename details::number_type<T>::type num_type;
  1125. return logn_impl(v0,v1,num_type);
  1126. }
  1127. template <typename T>
  1128. inline T root(const T v0, const T v1)
  1129. {
  1130. typename details::number_type<T>::type num_type;
  1131. return root_impl(v0,v1,num_type);
  1132. }
  1133. template <typename T>
  1134. inline T roundn(const T v0, const T v1)
  1135. {
  1136. typename details::number_type<T>::type num_type;
  1137. return roundn_impl(v0,v1,num_type);
  1138. }
  1139. template <typename T>
  1140. inline T hypot(const T v0, const T v1)
  1141. {
  1142. typename details::number_type<T>::type num_type;
  1143. return hypot_impl(v0,v1,num_type);
  1144. }
  1145. template <typename T>
  1146. inline T atan2(const T v0, const T v1)
  1147. {
  1148. typename details::number_type<T>::type num_type;
  1149. return atan2_impl(v0,v1,num_type);
  1150. }
  1151. template <typename T>
  1152. inline T shr(const T v0, const T v1)
  1153. {
  1154. typename details::number_type<T>::type num_type;
  1155. return shr_impl(v0,v1,num_type);
  1156. }
  1157. template <typename T>
  1158. inline T shl(const T v0, const T v1)
  1159. {
  1160. typename details::number_type<T>::type num_type;
  1161. return shl_impl(v0,v1,num_type);
  1162. }
  1163. template <typename T>
  1164. inline T and_opr(const T v0, const T v1)
  1165. {
  1166. typename details::number_type<T>::type num_type;
  1167. return and_impl(v0,v1,num_type);
  1168. }
  1169. template <typename T>
  1170. inline T nand_opr(const T v0, const T v1)
  1171. {
  1172. typename details::number_type<T>::type num_type;
  1173. return nand_impl(v0,v1,num_type);
  1174. }
  1175. template <typename T>

Large files files are truncated, but you can click here to view the full file