18#define BOOST_SPIRIT_QI_DEBUG
21#define _USE_MATH_DEFINES
24#include <boost/fusion/include/adapt_struct.hpp>
25#include <boost/fusion/include/io.hpp>
26#include <boost/phoenix.hpp>
27#include <boost/phoenix/object.hpp>
28#include <boost/spirit/include/qi.hpp>
38namespace qi = boost::spirit::qi;
39namespace ascii = boost::spirit::ascii;
40namespace phx = boost::phoenix;
45 virtual double Eval()
const {
return 0; }
47 const std::unordered_map<std::string, double> &variables)
const {
61template <
typename Expr>
63 return std::make_shared<Expr>(t);
83 double Eval()
const override {
return value; }
85 const std::unordered_map<std::string, double> &variables)
const override {
109 Variable(
const std::string &value =
"") : value(value) {}
116 double Eval()
const override {
return 0; }
118 const std::unordered_map<std::string, double> &variables)
const override {
119 auto it = variables.find(value);
120 if (it != variables.end())
123 throw std::invalid_argument(
"Variable not found: " + value);
138 template <
typename V>
154 template <
typename L,
typename R>
156 : op(op), left(
Clone(left)), right(
Clone(right)) {}
161 return left->Eval() + right->Eval();
163 return left->Eval() - right->Eval();
165 return left->Eval() * right->Eval();
167 return left->Eval() / right->Eval();
169 return pow(left->Eval(), right->Eval());
171 return static_cast<double>(AsInteger(left->Eval()) ^
172 AsInteger(right->Eval()));
174 throw std::invalid_argument(
"Unknown binary operator");
181 const std::unordered_map<std::string, double> &variables)
const override {
184 return left->Eval(variables) + right->Eval(variables);
186 return left->Eval(variables) - right->Eval(variables);
188 return left->Eval(variables) * right->Eval(variables);
190 return left->Eval(variables) / right->Eval(variables);
192 return pow(left->Eval(variables), right->Eval(variables));
194 return static_cast<double>(AsInteger(left->Eval(variables)) ^
195 AsInteger(right->Eval(variables)));
197 throw std::invalid_argument(
"Unknown binary operator");
209 static long long AsInteger(
double value) {
210 if (!std::isfinite(value))
211 throw std::invalid_argument(
212 "Bitwise XOR ('^') requires finite integer operands, got: " +
213 std::to_string(value));
215 const double rounded = std::round(value);
217 if (std::abs(value - rounded) > 1e-9)
218 throw std::invalid_argument(
219 "Bitwise XOR ('^') requires integer operands, got: " +
220 std::to_string(value));
224 if (std::abs(rounded) > 4.5e15)
225 throw std::invalid_argument(
226 "Bitwise XOR ('^') operand is out of the supported integer range: " +
227 std::to_string(value));
229 return static_cast<long long>(rounded);
237 template <
typename,
typename,
typename>
242 template <
typename C,
typename L,
typename R>
254 template <
typename R>
260 return right->Eval();
262 return -right->Eval();
264 throw std::invalid_argument(
"Unknown unary operator");
271 const std::unordered_map<std::string, double> &variables)
const override {
274 return right->Eval(variables);
276 return -right->Eval(variables);
278 throw std::invalid_argument(
"Unknown unary operator");
289 template <
typename,
typename>
294 template <
typename C,
typename R>
304 template <
typename F>
306 : func(func), param(
Clone(param)) {}
310 return sin(param->Eval());
311 else if (func ==
"cos")
312 return cos(param->Eval());
313 else if (func ==
"tan")
314 return tan(param->Eval());
315 else if (func ==
"exp")
316 return exp(param->Eval());
317 else if (func ==
"ln")
318 return log(param->Eval());
319 else if (func ==
"sqrt")
320 return sqrt(param->Eval());
322 throw std::invalid_argument(
"Unknown function");
328 const std::unordered_map<std::string, double> &variables)
const override {
330 return sin(param->Eval(variables));
331 else if (func ==
"cos")
332 return cos(param->Eval(variables));
333 else if (func ==
"tan")
334 return tan(param->Eval(variables));
335 else if (func ==
"exp")
336 return exp(param->Eval(variables));
337 else if (func ==
"ln")
338 return log(param->Eval(variables));
339 else if (func ==
"sqrt")
340 return sqrt(param->Eval(variables));
342 throw std::invalid_argument(
"Unknown function");
353 template <
typename,
typename,
typename>
358 template <
typename Params>
371 template <
typename E>
374 double Eval()
const override {
return expr->Eval(); }
377 const std::unordered_map<std::string, double> &variables)
const override {
378 return expr->Eval(variables);
AbstractSyntaxTree(AbstractSyntaxTree &&)=default
AbstractSyntaxTree(const AbstractSyntaxTree &)=default
AbstractSyntaxTree()=default
virtual ~AbstractSyntaxTree()=default
virtual double Eval(const std::unordered_map< std::string, double > &variables) const
virtual double Eval() const
AbstractSyntaxTree & operator=(const AbstractSyntaxTree &)=default
AbstractSyntaxTree & operator=(AbstractSyntaxTree &&)=default
double Eval() const override
double Eval(const std::unordered_map< std::string, double > &variables) const override
BinaryOperator(char op, const L &left, const R &right)
double Eval() const override
Constant & operator=(int value)
Constant & operator=(double value)
double Eval(const std::unordered_map< std::string, double > &variables) const override
friend AbstractSyntaxTreePtr Clone(Expression const &e)
double Eval() const override
double Eval(const std::unordered_map< std::string, double > &variables) const override
Function(const std::string &func, const F ¶m)
double Eval() const override
double Eval(const std::unordered_map< std::string, double > &variables) const override
UnaryOperator(char op, const R &right)
double Eval() const override
double Eval(const std::unordered_map< std::string, double > &variables) const override
Variable & operator=(int value)
double Eval() const override
Variable(const std::string &value="")
double Eval(const std::unordered_map< std::string, double > &variables) const override
phx::function< MakeFunctionExpression > MakeFunction
phx::function< MakeUnaryExpression > MakeUnary
phx::function< MakeBinaryExpression > MakeBinary
static AbstractSyntaxTreePtr Clone(Expr const &t)
std::shared_ptr< AbstractSyntaxTree > AbstractSyntaxTreePtr
phx::function< MakeVariableExpression > MakeVariable
phx::function< MakeConstantExpression > MakeConstant
BinaryOperator operator()(C op, const L &lhs, const R &rhs) const
Constant operator()(C op) const
Function operator()(const std::string &funcName, const Params ¶ms) const
UnaryOperator operator()(C op, const R &rhs) const
Variable operator()(V v) const