27#define BOOST_PHOENIX_STL_TUPLE_H_
28#define BOOST_RESULT_OF_USE_DECLTYPE
30#include <boost/math/constants/constants.hpp>
31#include <boost/phoenix.hpp>
32#include <boost/spirit/include/qi.hpp>
33#include <boost/variant.hpp>
40 namespace qi = boost::spirit::qi;
41 namespace ascii = boost::spirit::ascii;
62 template <
typename T >
63 T
sgn(T x) {
return (T{0} < x) - (x < T{0}); }
66 template <
typename T >
67 T
isnan(T x) {
return std::isnan(x); }
70 template <
typename T >
71 T
isinf(T x) {
return std::isinf(x); }
74 template <
typename T >
75 T
deg(T x) {
return x*boost::math::constants::radian<T>(); }
78 template <
typename T >
79 T
rad(T x) {
return x*boost::math::constants::degree<T>(); }
85 template <
typename real_t >
struct unary_op;
86 template <
typename real_t >
struct binary_op;
95 template <
typename real_t >
102 , boost::recursive_wrapper<expr_ast<real_t>>
103 , boost::recursive_wrapper<binary_op<real_t>>
104 , boost::recursive_wrapper<unary_op<real_t>>
127 template <
typename Expr>
141 template <
typename real_t >
145 using op_t = std::function<real_t(real_t)>;
159 template <
typename real_t >
163 using op_t = std::function<real_t(real_t,real_t)>;
178 template <
typename real_t >
184 template <
typename real_t >
190 template <
typename real_t >
196 template <
typename real_t >
208 template <
typename real_t >
233 auto it =
st.find(
c);
234 if (it ==
st.end()) {
235 throw std::invalid_argument(
"Unknown variable " +
c);
243 return boost::apply_visitor(*
this, ast.
tree);
250 boost::apply_visitor(*
this, tree.
lhs.tree),
251 boost::apply_visitor(*
this, tree.
rhs.tree)
259 boost::apply_visitor(*
this, tree.
rhs.tree)
271 return std::is_same<U, T>::value;
275 template <
typename T,
typename... Ts>
295 return boost::apply_visitor(*
this, ast.
tree);
300 auto lhs = boost::apply_visitor(*
this, tree.
lhs.tree);
301 auto rhs = boost::apply_visitor(*
this, tree.
rhs.tree);
306 return tree.
op(boost::get<real_t>(lhs), boost::get<real_t>(rhs));
313 auto rhs = boost::apply_visitor(*
this, tree.
rhs.tree);
316 return tree.
op(boost::get<real_t>(rhs));
325 template <
typename real_t >
338 template <
typename real_t >
354 template <
typename Iterator >
356 boost::spirit::info
const& info)
const {
357 std::stringstream msg;
361 << std::string{first, last}
364 throw std::runtime_error(msg.str());
372 template <
typename real_t,
typename Iterator >
375 Iterator, expr_ast<real_t>(), ascii::space_type
380 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
expression;
381 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
term;
382 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
factor;
383 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
primary;
388 : boost::spirit::qi::symbols<
389 typename std::iterator_traits<Iterator>::value_type,
396 (
"e" , boost::math::constants::e<real_t>() )
397 (
"epsilon", std::numeric_limits<real_t>::epsilon())
398 (
"phi" , boost::math::constants::phi<real_t>() )
399 (
"pi" , boost::math::constants::pi<real_t>() )
406 : boost::spirit::qi::symbols<
407 typename std::iterator_traits<Iterator>::value_type,
408 typename unary_op<real_t>::op_t
414 (
"abs" ,
static_cast<real_t(*)(real_t)
>(&std::abs ))
415 (
"acos" ,
static_cast<real_t(*)(real_t)
>(&std::acos ))
416 (
"acosh" ,
static_cast<real_t(*)(real_t)
>(&std::acosh ))
417 (
"asin" ,
static_cast<real_t(*)(real_t)
>(&std::asin ))
418 (
"asinh" ,
static_cast<real_t(*)(real_t)
>(&std::asinh ))
419 (
"atan" ,
static_cast<real_t(*)(real_t)
>(&std::atan ))
420 (
"atanh" ,
static_cast<real_t(*)(real_t)
>(&std::atanh ))
421 (
"cbrt" ,
static_cast<real_t(*)(real_t)
>(&std::cbrt ))
422 (
"ceil" ,
static_cast<real_t(*)(real_t)
>(&std::ceil ))
423 (
"cos" ,
static_cast<real_t(*)(real_t)
>(&std::cos ))
424 (
"cosh" ,
static_cast<real_t(*)(real_t)
>(&std::cosh ))
425 (
"deg2rad",
static_cast<real_t(*)(real_t)
>(&
math::deg ))
426 (
"erf" ,
static_cast<real_t(*)(real_t)
>(&std::erf ))
427 (
"erfc" ,
static_cast<real_t(*)(real_t)
>(&std::erfc ))
428 (
"exp" ,
static_cast<real_t(*)(real_t)
>(&std::exp ))
429 (
"exp2" ,
static_cast<real_t(*)(real_t)
>(&std::exp2 ))
430 (
"floor" ,
static_cast<real_t(*)(real_t)
>(&std::floor ))
431 (
"isinf" ,
static_cast<real_t(*)(real_t)
>(&
math::isinf))
432 (
"isnan" ,
static_cast<real_t(*)(real_t)
>(&
math::isnan))
433 (
"log" ,
static_cast<real_t(*)(real_t)
>(&std::log ))
434 (
"log2" ,
static_cast<real_t(*)(real_t)
>(&std::log2 ))
435 (
"log10" ,
static_cast<real_t(*)(real_t)
>(&std::log10 ))
436 (
"rad2deg",
static_cast<real_t(*)(real_t)
>(&
math::rad ))
437 (
"round" ,
static_cast<real_t(*)(real_t)
>(&std::round ))
438 (
"sgn" ,
static_cast<real_t(*)(real_t)
>(&
math::sgn ))
439 (
"sin" ,
static_cast<real_t(*)(real_t)
>(&std::sin ))
440 (
"sinh" ,
static_cast<real_t(*)(real_t)
>(&std::sinh ))
441 (
"sqrt" ,
static_cast<real_t(*)(real_t)
>(&std::sqrt ))
442 (
"tan" ,
static_cast<real_t(*)(real_t)
>(&std::tan ))
443 (
"tanh" ,
static_cast<real_t(*)(real_t)
>(&std::tanh ))
444 (
"tgamma" ,
static_cast<real_t(*)(real_t)
>(&std::tgamma))
451 : boost::spirit::qi::symbols<
452 typename std::iterator_traits<Iterator>::value_type,
453 typename binary_op<real_t>::op_t
459 (
"atan2",
static_cast<real_t(*)(real_t,real_t)
>(&std::atan2))
460 (
"max" ,
static_cast<real_t(*)(real_t,real_t)
>(&std::fmax ))
461 (
"min" ,
static_cast<real_t(*)(real_t,real_t)
>(&std::fmin ))
462 (
"pow" ,
static_cast<real_t(*)(real_t,real_t)
>(&std::pow ))
470 using boost::spirit::qi::real_parser;
471 using boost::spirit::qi::real_policies;
472 real_parser<real_t,real_policies<real_t>>
real;
474 using boost::spirit::lexeme;
475 using boost::spirit::qi::_1;
476 using boost::spirit::qi::_2;
477 using boost::spirit::qi::_3;
478 using boost::spirit::qi::_4;
479 using boost::spirit::qi::_val;
480 using boost::spirit::qi::alpha;
481 using boost::spirit::qi::alnum;
482 using boost::spirit::qi::raw;
484 boost::phoenix::function<unary_expr_<real_t>> unary_expr;
485 boost::phoenix::function<binary_expr_<real_t>> binary_expr;
487 auto fmod =
static_cast<real_t(*)(real_t,real_t)
>(&std::fmod);
488 auto pow =
static_cast<real_t(*)(real_t,real_t)
>(&std::pow);
492 >> *( (
'+' >
term [_val += _1])
493 | (
'-' >
term [_val -= _1])
499 >> *( (
'*' >
factor [_val *= _1])
500 | (
'/' >
factor [_val /= _1])
501 | (
'%' >
factor [_val = binary_expr(
fmod, _val, _1)])
507 >> *( (
"**" >
factor [_val = binary_expr(
pow, _val, _1)])
512 raw[lexeme[alpha >> *(alnum |
'_')]];
517 | (
'-' >
primary [_val = unary_expr(std::negate<real_t>{}, _1)])
520 [_val = binary_expr(_1, _2, _3)]
522 [_val = unary_expr(_1, _2)]
533 using boost::spirit::qi::fail;
534 using boost::spirit::qi::on_error;
535 using boost::phoenix::bind;
536 using boost::phoenix::ref;
554 template <
typename real_t,
typename Iterator>
560 bool r = qi::phrase_parse(first, last, g, ascii::space, ast);
562 if (!r || first != last) {
563 std::string rest(first, last);
564 throw std::runtime_error(
"Parsing failed at " + rest);
580 template <
typename real_t >
593 template <
typename Iterator >
594 void parse(Iterator first, Iterator last)
602 parse(str.begin(), str.end());
630 template <
typename real_t,
typename Iterator >
631 real_t
parse(Iterator first, Iterator last,
635 parser.
parse(first, last);
640 template <
typename real_t >
641 real_t
parse(std::string
const &str,
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
constexpr double c
The velocity of light in m/s.
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
real_t parse(Iterator first, Iterator last, typename detail::eval_ast< real_t >::symbol_table_t const &st)
Convenience function.
detail::expr_ast< real_t > parse(Iterator first, Iterator last)
Parse an expression.
bool holds_alternative(boost::variant< Ts... > const &v)
T isinf(T x)
isinf function with adjusted return type
T isnan(T x)
isnan function with adjusted return type
T rad(T x)
Convert degrees to radians.
T deg(T x)
Convert radians to degrees.
Store a unary operator and its argument tree.
expr_ast< real_t > rhs
Stored argument tree.
unary_op(op_t op, expr_ast< real_t > rhs)
Save the operator and the argument tree.
std::function< real_t(real_t)> op_t
Signature of a unary operator: op(x).
Store a binary operator and its argument trees.
expr_ast< real_t > lhs
Stored argument tree of first argument.
binary_op(op_t op, expr_ast< real_t > lhs, expr_ast< real_t > rhs)
Save the operator and the argument trees.
std::function< real_t(real_t, real_t)> op_t
Signature of a binary operator: op(x,y).
expr_ast< real_t > rhs
Stored argument tree of second argument.
expr_ast & operator-=(expr_ast const &rhs)
subtract a tree
expr_ast()
Default constructor.
expr_ast & operator/=(expr_ast const &rhs)
Divide by a tree.
expr_ast & operator*=(expr_ast const &rhs)
Multiply by a tree.
expr_ast & operator+=(expr_ast const &rhs)
Add a tree.
boost::variant< nil, real_t, std::string, boost::recursive_wrapper< expr_ast< real_t > >, boost::recursive_wrapper< binary_op< real_t > >, boost::recursive_wrapper< unary_op< real_t > > > tree_t
expr_ast(Expr other)
Copy constructor.
Evaluate the Abstract Syntax Tree.
real_t result_type
Necessary typedef for boost::apply_visitor.
result_type operator()(binary_op< real_t > const &tree) const
Evaluate a binary operator and optionally recurse its operands.
result_type operator()(result_type n) const
Numbers evaluate to themselves.
result_type operator()(nil) const
Empty nodes in the tree evaluate to 0.
result_type operator()(expr_ast< real_t > const &ast) const
Recursively evaluate the AST.
std::map< std::string, result_type > symbol_table_t
Type of the symbol table.
result_type operator()(unary_op< real_t > const &tree) const
Evaluate a unary operator and optionally recurse its operand.
eval_ast(symbol_table_t sym)
Constructor.
result_type operator()(std::string const &c) const
Variables evaluate to their value in the symbol table.
bool operator()(U const &) const
result_type operator()(binary_op< real_t > const &tree) const
Evaluate a binary operator and optionally recurse its operands.
result_type operator()(nil) const
Empty nodes in the tree evaluate to 0.
result_type operator()(unary_op< real_t > const &tree) const
Evaluate a unary operator and optionally recurse its operand.
result_type operator()(real_t n) const
Numbers evaluate to themselves.
typename expr_ast< real_t >::tree_t result_type
Necessary typedef for boost::apply_visitor.
result_type operator()(std::string const &c) const
Variables do not evaluate.
result_type operator()(expr_ast< real_t > const &ast) const
Recursively evaluate the AST.
Unary expression functor.
expr_ast< real_t > operator()(typename unary_op< real_t >::op_t op, expr_ast< real_t > const &rhs) const
Create a new AST containing the unary function.
Make boost::phoenix::function happy.
Binary expression functor.
expr_ast< real_t > operator()(typename binary_op< real_t >::op_t op, expr_ast< real_t > const &lhs, expr_ast< real_t > const &rhs) const
Create a new AST containing the binary function.
Make boost::phoenix::function happy.
Error handler for expectation errors.
void operator()(Iterator first, Iterator last, boost::spirit::info const &info) const
Throw an exception saying where and why parsing failed.
grammar()
Constructor builds the grammar.
qi::rule< Iterator, expr_ast< real_t >(), ascii::space_type > expression
qi::rule< Iterator, expr_ast< real_t >(), ascii::space_type > factor
qi::rule< Iterator, expr_ast< real_t >(), ascii::space_type > primary
expectation_handler err_handler
qi::rule< Iterator, expr_ast< real_t >(), ascii::space_type > term
matheval::detail::grammar::ufunc_ ufunc
matheval::detail::grammar::bfunc_ bfunc
matheval::detail::grammar::constant_ constant
qi::rule< Iterator, std::string()> variable
detail::expr_ast< real_t > ast
void parse(std::string const &str)
real_t evaluate(typename detail::eval_ast< real_t >::symbol_table_t const &st)
Evaluate the AST with a given symbol table.
void parse(Iterator first, Iterator last)
Parse an expression.