You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

350 regels
11 KiB

  1. //
  2. // LolRemez — Remez algorithm implementation
  3. //
  4. // Copyright © 2005—2015 Sam Hocevar <sam@hocevar.net>
  5. //
  6. // This program is free software. It comes without any warranty, to
  7. // the extent permitted by applicable law. You can redistribute it
  8. // and/or modify it under the terms of the Do What the Fuck You Want
  9. // to Public License, Version 2, as published by the WTFPL Task Force.
  10. // See http://www.wtfpl.net/ for more details.
  11. //
  12. #pragma once
  13. //
  14. // Powerful arithmetic expression parser/evaluator
  15. //
  16. // Usage:
  17. // expression e;
  18. // e.parse(" 2*x^3 + 3 * sin(x - atan(x))");
  19. // auto y = e.eval("1.5");
  20. //
  21. #include "pegtl.hh"
  22. namespace grammar
  23. {
  24. using namespace pegtl;
  25. enum class id : uint8_t
  26. {
  27. /* Variables and constants */
  28. x,
  29. constant,
  30. /* Unary functions/operators */
  31. plus, minus, abs,
  32. sqrt, cbrt,
  33. exp, exp2, log, log2, log10,
  34. sin, cos, tan,
  35. asin, acos, atan,
  36. sinh, cosh, tanh,
  37. /* Binary functions/operators */
  38. add, sub, mul, div,
  39. atan2, pow,
  40. min, max,
  41. };
  42. struct expression
  43. {
  44. /*
  45. * Evaluate expression at x
  46. */
  47. lol::real eval(lol::real const &x) const
  48. {
  49. /* Use a stack */
  50. lol::array<lol::real> stack;
  51. for (int i = 0; i < m_ops.count(); ++i)
  52. {
  53. /* Rules that do not consume stack elements */
  54. if (m_ops[i].m1 == id::x)
  55. {
  56. stack.push(x);
  57. continue;
  58. }
  59. else if (m_ops[i].m1 == id::constant)
  60. {
  61. stack.push(m_constants[m_ops[i].m2]);
  62. continue;
  63. }
  64. /* All other rules consume at least the head of the stack */
  65. lol::real head = stack.pop();
  66. switch (m_ops[i].m1)
  67. {
  68. case id::plus: stack.push(head); break;
  69. case id::minus: stack.push(-head); break;
  70. case id::abs: stack.push(fabs(head)); break;
  71. case id::sqrt: stack.push(sqrt(head)); break;
  72. case id::cbrt: stack.push(cbrt(head)); break;
  73. case id::exp: stack.push(exp(head)); break;
  74. case id::exp2: stack.push(exp2(head)); break;
  75. case id::log: stack.push(log(head)); break;
  76. case id::log2: stack.push(log2(head)); break;
  77. case id::log10: stack.push(log10(head)); break;
  78. case id::sin: stack.push(sin(head)); break;
  79. case id::cos: stack.push(cos(head)); break;
  80. case id::tan: stack.push(tan(head)); break;
  81. case id::asin: stack.push(asin(head)); break;
  82. case id::acos: stack.push(acos(head)); break;
  83. case id::atan: stack.push(atan(head)); break;
  84. case id::sinh: stack.push(sinh(head)); break;
  85. case id::cosh: stack.push(cosh(head)); break;
  86. case id::tanh: stack.push(tanh(head)); break;
  87. case id::add: stack.push(stack.pop() + head); break;
  88. case id::sub: stack.push(stack.pop() - head); break;
  89. case id::mul: stack.push(stack.pop() * head); break;
  90. case id::div: stack.push(stack.pop() / head); break;
  91. case id::atan2: stack.push(atan2(stack.pop(), head)); break;
  92. case id::pow: stack.push(pow(stack.pop(), head)); break;
  93. case id::min: stack.push(min(stack.pop(), head)); break;
  94. case id::max: stack.push(max(stack.pop(), head)); break;
  95. case id::x:
  96. case id::constant:
  97. /* Already handled above */
  98. break;
  99. }
  100. }
  101. ASSERT(stack.count() == 1);
  102. return stack.pop();
  103. }
  104. private:
  105. lol::array<id, int> m_ops;
  106. lol::array<lol::real> m_constants;
  107. private:
  108. struct r_expr;
  109. // r_ <- <blank> *
  110. struct _ : star<space> {};
  111. // r_constant <- <digit> + ( "." <digit> * ) ? ( [eE] [+-] ? <digit> + ) ?
  112. struct r_constant : seq<plus<digit>,
  113. opt<seq<one<'.'>,
  114. star<digit>>>,
  115. opt<seq<one<'e', 'E'>,
  116. opt<one<'+', '-'>>,
  117. plus<digit>>>> {};
  118. // r_var <- "x"
  119. struct r_var : pegtl_string_t("x") {};
  120. // r_binary_call <- <r_binary_fun> "(" r_expr "," r_expr ")"
  121. struct r_binary_fun : sor<pegtl_string_t("atan2"),
  122. pegtl_string_t("pow"),
  123. pegtl_string_t("min"),
  124. pegtl_string_t("max")> {};
  125. struct r_binary_call : seq<r_binary_fun,
  126. _, one<'('>,
  127. _, r_expr,
  128. _, one<','>,
  129. _, r_expr,
  130. _, one<')'>> {};
  131. // r_unary_call <- <r_unary_fun> "(" r_expr ")"
  132. struct r_unary_fun : sor<pegtl_string_t("abs"),
  133. pegtl_string_t("sqrt"),
  134. pegtl_string_t("cbrt"),
  135. pegtl_string_t("exp"),
  136. pegtl_string_t("exp2"),
  137. pegtl_string_t("log"),
  138. pegtl_string_t("log2"),
  139. pegtl_string_t("log10"),
  140. pegtl_string_t("sin"),
  141. pegtl_string_t("cos"),
  142. pegtl_string_t("tan"),
  143. pegtl_string_t("asin"),
  144. pegtl_string_t("acos"),
  145. pegtl_string_t("atan"),
  146. pegtl_string_t("sinh"),
  147. pegtl_string_t("cosh"),
  148. pegtl_string_t("tanh")> {};
  149. struct r_unary_call : seq<r_unary_fun,
  150. _, one<'('>,
  151. _, r_expr,
  152. _, one<')'>> {};
  153. // r_call <- r_binary_call / r_unary_call
  154. struct r_call : sor<r_binary_call,
  155. r_unary_call> {};
  156. // r_parentheses <- "(" r_expr ")"
  157. struct r_parentheses : seq<one<'('>,
  158. pad<r_expr, space>,
  159. one<')'>> {};
  160. // r_terminal <- r_call / r_var / r_constant / r_parentheses
  161. struct r_terminal : sor<r_call,
  162. r_var,
  163. r_constant,
  164. r_parentheses> {};
  165. // r_signed <- "-" r_signed / "+" r_signed / r_terminal
  166. struct r_signed;
  167. struct r_minus : seq<one<'-'>, _, r_signed> {};
  168. struct r_signed : sor<r_minus,
  169. seq<one<'+'>, _, r_signed>,
  170. r_terminal> {};
  171. // r_exponent <- ( "^" / "**" ) r_signed
  172. struct r_exponent : seq<pad<sor<one<'^'>,
  173. string<'*', '*'>>, space>,
  174. r_signed> {};
  175. // r_factor <- r_signed ( r_exponent ) *
  176. struct r_factor : seq<r_signed,
  177. star<r_exponent>> {};
  178. // r_mul <- "*" r_factor
  179. // r_div <- "/" r_factor
  180. // r_term <- r_factor ( r_mul / r_div ) *
  181. struct r_mul : seq<_, one<'*'>, _, r_factor> {};
  182. struct r_div : seq<_, one<'/'>, _, r_factor> {};
  183. struct r_term : seq<r_factor,
  184. star<sor<r_mul, r_div>>> {};
  185. // r_add <- "+" r_term
  186. // r_sub <- "-" r_term
  187. // r_expr <- r_term ( r_add / r_sub ) *
  188. struct r_add : seq<_, one<'+'>, _, r_term> {};
  189. struct r_sub : seq<_, one<'-'>, _, r_term> {};
  190. struct r_expr : seq<r_term,
  191. star<sor<r_add, r_sub>>> {};
  192. // r_stmt <- r_expr <end>
  193. struct r_stmt : must<pad<r_expr, space>, pegtl::eof> {};
  194. //
  195. // Default actions
  196. //
  197. template<typename R>
  198. struct action : nothing<R> {};
  199. template<id OP>
  200. struct generic_action
  201. {
  202. static void apply(action_input const &in, expression *that)
  203. {
  204. UNUSED(in);
  205. that->m_ops.push(OP, -1);
  206. }
  207. };
  208. public:
  209. /*
  210. * Parse arithmetic expression in x, e.g. 2*x+3
  211. */
  212. void parse(std::string const &str)
  213. {
  214. m_ops.empty();
  215. m_constants.empty();
  216. pegtl::parse_string<r_stmt, action>(str, "expression", this);
  217. }
  218. };
  219. //
  220. // Rule specialisations for simple operators
  221. //
  222. template<> struct expression::action<expression::r_var> : generic_action<id::x> {};
  223. template<> struct expression::action<expression::r_exponent> : generic_action<id::pow> {};
  224. template<> struct expression::action<expression::r_mul> : generic_action<id::mul> {};
  225. template<> struct expression::action<expression::r_div> : generic_action<id::div> {};
  226. template<> struct expression::action<expression::r_add> : generic_action<id::add> {};
  227. template<> struct expression::action<expression::r_sub> : generic_action<id::sub> {};
  228. template<> struct expression::action<expression::r_minus> : generic_action<id::minus> {};
  229. //
  230. // Rule specialisations for unary and binary function calls
  231. //
  232. template<>
  233. struct expression::action<expression::r_binary_call>
  234. {
  235. static void apply(action_input const &in, expression *that)
  236. {
  237. struct { id ret; char const *name; } lut[] =
  238. {
  239. { id::atan2, "atan2" },
  240. { id::pow, "pow" },
  241. { id::min, "min" },
  242. { id::max, "max" },
  243. };
  244. for (auto pair : lut)
  245. {
  246. if (strncmp(in.string().c_str(), pair.name, strlen(pair.name)) != 0)
  247. continue;
  248. that->m_ops.push(pair.ret, -1);
  249. return;
  250. }
  251. }
  252. };
  253. template<>
  254. struct expression::action<expression::r_unary_call>
  255. {
  256. static void apply(action_input const &in, expression *that)
  257. {
  258. struct { id ret; char const *name; } lut[] =
  259. {
  260. { id::abs, "abs" },
  261. { id::sqrt, "sqrt" },
  262. { id::cbrt, "cbrt" },
  263. { id::exp2, "exp2" },
  264. { id::exp, "exp" },
  265. { id::log10, "log10" },
  266. { id::log2, "log2" },
  267. { id::log, "log" },
  268. { id::sinh, "sinh" },
  269. { id::cosh, "cosh" },
  270. { id::tanh, "tanh" },
  271. { id::sin, "sin" },
  272. { id::cos, "cos" },
  273. { id::tan, "tan" },
  274. { id::asin, "asin" },
  275. { id::acos, "acos" },
  276. { id::atan, "atan" },
  277. };
  278. for (auto pair : lut)
  279. {
  280. if (strncmp(in.string().c_str(), pair.name, strlen(pair.name)) != 0)
  281. continue;
  282. that->m_ops.push(pair.ret, -1);
  283. return;
  284. }
  285. }
  286. };
  287. template<>
  288. struct expression::action<expression::r_constant>
  289. {
  290. static void apply(action_input const &in, expression *that)
  291. {
  292. /* FIXME: check if the constant is already in the list */
  293. that->m_ops.push(id::constant, that->m_constants.count());
  294. that->m_constants.push(lol::real(in.string().c_str()));
  295. }
  296. };
  297. } /* namespace grammar */
  298. using grammar::expression;