27#define BOOST_RESULT_OF_USE_DECLTYPE
28#define BOOST_SPIRIT_USE_PHOENIX_V3
29#include <boost/math/constants/constants.hpp>
30#include <boost/spirit/include/phoenix.hpp>
31#include <boost/spirit/include/qi.hpp>
32#include <boost/variant.hpp>
39 namespace qi = boost::spirit::qi;
40 namespace ascii = boost::spirit::ascii;
61 template <
typename T >
62 T sgn(
T x) {
return (
T{0} < x) - (x <
T{0}); }
65 template <
typename T >
69 template <
typename T >
73 template <
typename T >
74 T deg(
T x) {
return x*boost::math::constants::radian<T>(); }
77 template <
typename T >
78 T rad(
T x) {
return x*boost::math::constants::degree<T>(); }
84 template <
typename real_t >
struct unary_op;
85 template <
typename real_t >
struct binary_op;
94 template <
typename real_t >
101 , boost::recursive_wrapper<expr_ast<real_t>>
102 , boost::recursive_wrapper<binary_op<real_t>>
103 , boost::recursive_wrapper<unary_op<real_t>>
126 template <
typename Expr>
140 template <
typename real_t >
158 template <
typename real_t >
177 template <
typename real_t >
183 template <
typename real_t >
189 template <
typename real_t >
195 template <
typename real_t >
207 template <
typename real_t >
232 auto it =
st.find(
c);
233 if (it ==
st.end()) {
234 throw std::invalid_argument(
"Unknown variable " +
c);
242 return boost::apply_visitor(*
this, ast.
tree);
249 boost::apply_visitor(*
this, tree.
lhs.tree),
250 boost::apply_visitor(*
this, tree.
rhs.tree)
258 boost::apply_visitor(*
this, tree.
rhs.tree)
270 return std::is_same<U, T>::value;
274 template <
typename T,
typename... Ts>
294 return boost::apply_visitor(*
this, ast.
tree);
299 auto lhs = boost::apply_visitor(*
this, tree.
lhs.tree);
300 auto rhs = boost::apply_visitor(*
this, tree.
rhs.tree);
304 if (holds_alternative<real_t>(lhs) && holds_alternative<real_t>(rhs)) {
305 return tree.
op(boost::get<real_t>(lhs), boost::get<real_t>(rhs));
312 auto rhs = boost::apply_visitor(*
this, tree.
rhs.tree);
314 if (holds_alternative<real_t>(rhs)) {
315 return tree.
op(boost::get<real_t>(rhs));
324 template <
typename real_t >
337 template <
typename real_t >
353 template <
typename Iterator >
356 std::stringstream msg;
360 << std::string{first, last}
363 throw std::runtime_error(msg.str());
371 template <
typename real_t,
typename Iterator >
374 Iterator, expr_ast<real_t>(), ascii::space_type
379 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
expression;
380 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
term;
381 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
factor;
382 qi::rule<Iterator, expr_ast<real_t>(), ascii::space_type>
primary;
387 : boost::spirit::qi::symbols<
388 typename std::iterator_traits<Iterator>::value_type,
395 (
"e" , boost::math::constants::e<real_t>() )
396 (
"epsilon", std::numeric_limits<real_t>::epsilon())
397 (
"phi" , boost::math::constants::phi<real_t>() )
398 (
"pi" , boost::math::constants::pi<real_t>() )
405 : boost::spirit::qi::symbols<
406 typename std::iterator_traits<Iterator>::value_type,
407 typename unary_op<real_t>::op_t
413 (
"abs" ,
static_cast<real_t(*)(real_t)
>(&
std::abs ))
414 (
"acos" ,
static_cast<real_t(*)(real_t)
>(&
std::acos ))
415 (
"acosh" ,
static_cast<real_t(*)(real_t)
>(&std::acosh ))
416 (
"asin" ,
static_cast<real_t(*)(real_t)
>(&
std::asin ))
417 (
"asinh" ,
static_cast<real_t(*)(real_t)
>(&std::asinh ))
418 (
"atan" ,
static_cast<real_t(*)(real_t)
>(&
std::atan ))
419 (
"atanh" ,
static_cast<real_t(*)(real_t)
>(&std::atanh ))
420 (
"cbrt" ,
static_cast<real_t(*)(real_t)
>(&std::cbrt ))
421 (
"ceil" ,
static_cast<real_t(*)(real_t)
>(&
std::ceil ))
422 (
"cos" ,
static_cast<real_t(*)(real_t)
>(&
std::cos ))
423 (
"cosh" ,
static_cast<real_t(*)(real_t)
>(&
std::cosh ))
424 (
"deg2rad",
static_cast<real_t(*)(real_t)
>(&
math::deg ))
425 (
"erf" ,
static_cast<real_t(*)(real_t)
>(&
std::erf ))
426 (
"erfc" ,
static_cast<real_t(*)(real_t)
>(&
std::erfc ))
427 (
"exp" ,
static_cast<real_t(*)(real_t)
>(&
std::exp ))
428 (
"exp2" ,
static_cast<real_t(*)(real_t)
>(&std::exp2 ))
429 (
"floor" ,
static_cast<real_t(*)(real_t)
>(&
std::floor ))
430 (
"isinf" ,
static_cast<real_t(*)(real_t)
>(&
math::isinf))
431 (
"isnan" ,
static_cast<real_t(*)(real_t)
>(&
math::isnan))
432 (
"log" ,
static_cast<real_t(*)(real_t)
>(&
std::log ))
433 (
"log2" ,
static_cast<real_t(*)(real_t)
>(&std::log2 ))
434 (
"log10" ,
static_cast<real_t(*)(real_t)
>(&
std::log10 ))
435 (
"rad2deg",
static_cast<real_t(*)(real_t)
>(&
math::rad ))
436 (
"round" ,
static_cast<real_t(*)(real_t)
>(&std::round ))
437 (
"sgn" ,
static_cast<real_t(*)(real_t)
>(&
math::sgn ))
438 (
"sin" ,
static_cast<real_t(*)(real_t)
>(&
std::sin ))
439 (
"sinh" ,
static_cast<real_t(*)(real_t)
>(&
std::sinh ))
440 (
"sqrt" ,
static_cast<real_t(*)(real_t)
>(&
std::sqrt ))
441 (
"tan" ,
static_cast<real_t(*)(real_t)
>(&
std::tan ))
442 (
"tanh" ,
static_cast<real_t(*)(real_t)
>(&
std::tanh ))
443 (
"tgamma" ,
static_cast<real_t(*)(real_t)
>(&std::tgamma))
450 : boost::spirit::qi::symbols<
451 typename std::iterator_traits<Iterator>::value_type,
452 typename binary_op<real_t>::op_t
458 (
"atan2",
static_cast<real_t(*)(real_t,real_t)
>(&
std::atan2))
459 (
"max" ,
static_cast<real_t(*)(real_t,real_t)
>(&std::fmax ))
460 (
"min" ,
static_cast<real_t(*)(real_t,real_t)
>(&std::fmin ))
461 (
"pow" ,
static_cast<real_t(*)(real_t,real_t)
>(&
std::pow ))
469 using boost::spirit::qi::real_parser;
470 using boost::spirit::qi::real_policies;
471 real_parser<real_t,real_policies<real_t>>
real;
473 using boost::spirit::lexeme;
474 using boost::spirit::qi::_1;
475 using boost::spirit::qi::_2;
476 using boost::spirit::qi::_3;
477 using boost::spirit::qi::_4;
478 using boost::spirit::qi::_val;
480 using boost::spirit::qi::alnum;
481 using boost::spirit::qi::raw;
483 boost::phoenix::function<unary_expr_<real_t>> unary_expr;
484 boost::phoenix::function<binary_expr_<real_t>> binary_expr;
486 auto fmod =
static_cast<real_t(*)(real_t,real_t)
>(&
std::fmod);
487 auto pow =
static_cast<real_t(*)(real_t,real_t)
>(&
std::pow);
491 >> *( (
'+' >
term [_val += _1])
492 | (
'-' >
term [_val -= _1])
498 >> *( (
'*' >
factor [_val *= _1])
499 | (
'/' >
factor [_val /= _1])
500 | (
'%' >
factor [_val = binary_expr(
fmod, _val, _1)])
506 >> *( (
"**" >
factor [_val = binary_expr(
pow, _val, _1)])
511 raw[lexeme[
alpha >> *(alnum |
'_')]];
516 | (
'-' >
primary [_val = unary_expr(std::negate<real_t>{}, _1)])
519 [_val = binary_expr(_1, _2, _3)]
521 [_val = unary_expr(_1, _2)]
532 using boost::spirit::qi::fail;
533 using boost::spirit::qi::on_error;
534 using boost::phoenix::bind;
553 template <
typename real_t,
typename Iterator>
559 bool r = qi::phrase_parse(first, last, g, ascii::space, ast);
561 if (!r || first != last) {
562 std::string rest(first, last);
563 throw std::runtime_error(
"Parsing failed at " + rest);
579 template <
typename real_t >
592 template <
typename Iterator >
593 void parse(Iterator first, Iterator last)
595 ast = detail::parse<real_t>(first, last);
601 parse(str.begin(), str.end());
629 template <
typename real_t,
typename Iterator >
630 real_t
parse(Iterator first, Iterator last,
634 parser.
parse(first, last);
639 template <
typename real_t >
640 real_t
parse(std::string
const &str,
643 return parse<real_t>(str.begin(), str.end(), st);
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
FTps< T, N > erf(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Error function.
FTps< T, N > erfc(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Complementary error function.
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Tps< T > cos(const Tps< T > &x)
Cosine.
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Tps< T > tan(const Tps< T > &x)
Tangent.
Tps< T > exp(const Tps< T > &x)
Exponential.
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Tps< T > tanh(const Tps< T > &x)
Hyperbolic tangent.
Tps< T > sin(const Tps< T > &x)
Sine.
Tps< T > sqrt(const Tps< T > &x)
Square root.
PETE_TUTree< FnLog10, typename T::PETE_Expr_t > log10(const PETE_Expr< T > &l)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
py::list function(PolynomialPatch *patch, py::list point)
constexpr double alpha
The fine structure constant, no dimension.
constexpr double c
The velocity of light in m/s.
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.
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 & 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.
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
symbol table for constants like "pi"
symbol table for unary functions like "abs"
symbol table for binary functions like "pow"
void parse(Iterator first, Iterator last)
Parse an expression.
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.