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 >
70 template <
typename T >
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>(); }
95 template <
typename real_t >
98 using tree_t = boost::variant<
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)>;
149 : op(std::move(op)), rhs(std::move(rhs))
159 template <
typename real_t >
163 using op_t = std::function<real_t(real_t,real_t)>;
167 : op(std::move(op)), lhs(std::move(lhs)), rhs(std::move(rhs))
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);
305 if (holds_alternative<real_t>(lhs) && holds_alternative<real_t>(rhs)) {
306 return tree.
op(boost::get<real_t>(lhs), boost::get<real_t>(rhs));
313 auto rhs = boost::apply_visitor(*
this, tree.rhs.tree);
315 if (holds_alternative<real_t>(rhs)) {
316 return tree.op(boost::get<real_t>(rhs));
325 template <
typename real_t >
338 template <
typename real_t >
354 template <
typename Iterator >
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;
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)])
518 | (
'+' > primary [_val = _1])
520 [_val = binary_expr(_1, _2, _3)]
522 [_val = unary_expr(_1, _2)]
531 primary.name(
"primary");
533 using boost::spirit::qi::fail;
534 using boost::spirit::qi::on_error;
535 using boost::phoenix::bind;
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)
596 ast = detail::parse<real_t>(first, 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,
644 return parse<real_t>(str.begin(), str.end(), st);
Tps< T > sinh(const Tps< T > &x)
Hyperbolic sine.
Tps< T > sqrt(const Tps< T > &x)
Square root.
constexpr double c
The velocity of light in m/s.
Error handler for expectation errors.
std::map< std::string, result_type > symbol_table_t
Type of the symbol table.
Binary expression functor.
expr_ast & operator+=(expr_ast const &rhs)
Add a tree.
matheval::detail::grammar::constant_ constant
and that you know you can do these things To protect your we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights These restrictions translate to certain responsibilities for you if you distribute copies of the or if you modify it For if you distribute copies of such a whether gratis or for a you must give the recipients all the rights that you have You must make sure that receive or can get the source code And you must show them these terms so they know their rights We protect your rights with two distribute and or modify the software for each author s protection and we want to make certain that everyone understands that there is no warranty for this free software If the software is modified by someone else and passed we want its recipients to know that what they have is not the so that any problems introduced by others will not reflect on the original authors reputations any free program is threatened constantly by software patents We wish to avoid the danger that redistributors of a free program will individually obtain patent in effect making the program proprietary To prevent we have made it clear that any patent must be licensed for everyone s free use or not licensed at all The precise terms and conditions for distribution and modification follow GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR DISTRIBUTION AND MODIFICATION This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License The refers to any such program or and a work based on the Program means either the Program or any derivative work under copyright a work containing the Program or a portion of it
Tps< T > tan(const Tps< T > &x)
Tangent.
real_t evaluate(typename detail::eval_ast< real_t >::symbol_table_t const &st)
Evaluate the AST with a given symbol table.
T rad(T x)
Convert degrees to radians.
result_type operator()(expr_ast< real_t > const &ast) const
Recursively evaluate the AST.
result_type operator()(result_type n) const
Numbers evaluate to themselves.
qi::rule< Iterator, expr_ast< real_t >), ascii::space_type > factor
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
matheval::detail::grammar::ufunc_ ufunc
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
FTps< T, N > erf(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Error function.
binary_op(op_t op, expr_ast< real_t > lhs, expr_ast< real_t > rhs)
Save the operator and the argument trees.
result_type operator()(unary_op< real_t > const &tree) const
Evaluate a unary operator and optionally recurse its operand.
result_type operator()(nil) const
Empty nodes in the tree evaluate to 0.
expr_ast< real_t > rhs
Stored argument tree of second argument.
expr_ast()
Default constructor.
result_type operator()(unary_op< real_t > const &tree) const
Evaluate a unary operator and optionally recurse its operand.
detail::expr_ast< real_t > ast
result_type operator()(std::string const &c) const
Variables evaluate to their value in the symbol table.
bool holds_alternative(boost::variant< Ts...> const &v)
symbol table for unary functions like "abs"
Tps< T > exp(const Tps< T > &x)
Exponential.
qi::rule< Iterator, expr_ast< real_t >), ascii::space_type > term
expectation_handler err_handler
Store a unary operator and its argument tree.
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
PETE_TUTree< FnArcTan, typename T::PETE_Expr_t > atan(const PETE_Expr< T > &l)
detail::expr_ast< real_t > parse(Iterator first, Iterator last)
Parse an expression.
result_type operator()(binary_op< real_t > const &tree) const
Evaluate a binary operator and optionally recurse its operands.
expr_ast & operator-=(expr_ast const &rhs)
subtract a tree
Tps< T > tanh(const Tps< T > &x)
Hyperbolic tangent.
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.
eval_ast(symbol_table_t sym)
Constructor.
std::function< real_t(real_t)> op_t
Signature of a unary operator: op(x)
expr_ast(Expr other)
Copy constructor.
void parse(std::string const &str)
result_type operator()(std::string const &c) const
Variables do not evaluate.
PETE_TUTree< FnLog10, typename T::PETE_Expr_t > log10(const PETE_Expr< T > &l)
Unary expression functor.
symbol table for binary functions like "pow"
result_type operator()(real_t n) const
Numbers evaluate to themselves.
expr_ast & operator/=(expr_ast const &rhs)
Divide by a tree.
Tps< T > cos(const Tps< T > &x)
Cosine.
FTps< T, N > erfc(const FTps< T, N > &x, int trunc=(FTps< T, N >::EXACT))
Complementary error function.
PETE_TUTree< FnArcCos, typename T::PETE_Expr_t > acos(const PETE_Expr< T > &l)
real_t result_type
Necessary typedef for boost::apply_visitor
constexpr double alpha
The fine structure constant, no dimension.
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
Tps< T > log(const Tps< T > &x)
Natural logarithm.
Make boost::phoenix::function happy.
Store a binary operator and its argument trees.
T deg(T x)
Convert radians to degrees.
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.
grammar()
Constructor builds the grammar.
std::function< real_t(real_t, real_t)> op_t
Signature of a binary operator: op(x,y)
typename expr_ast< real_t >::tree_t result_type
Necessary typedef for boost::apply_visitor
bool operator()(U const &) const
qi::rule< Iterator, std::string()> variable
T isnan(T x)
isnan function with adjusted return type
qi::rule< Iterator, expr_ast< real_t >), ascii::space_type > primary
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
matheval::detail::grammar::bfunc_ bfunc
expr_ast< real_t > rhs
Stored argument tree.
real_t parse(Iterator first, Iterator last, typename detail::eval_ast< real_t >::symbol_table_t const &st)
Convenience function.
PETE_TUTree< FnArcSin, typename T::PETE_Expr_t > asin(const PETE_Expr< T > &l)
result_type operator()(nil) const
Empty nodes in the tree evaluate to 0.
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
Tps< T > sin(const Tps< T > &x)
Sine.
Tps< T > cosh(const Tps< T > &x)
Hyperbolic cosine.
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Evaluate the Abstract Syntax Tree.
unary_op(op_t op, expr_ast< real_t > rhs)
Save the operator and the argument tree.
Make boost::phoenix::function happy.
expr_ast & operator*=(expr_ast const &rhs)
Multiply by a tree.
void parse(Iterator first, Iterator last)
Parse an expression.
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
qi::rule< Iterator, expr_ast< real_t >), ascii::space_type > expression
result_type operator()(expr_ast< real_t > const &ast) const
Recursively evaluate the AST.
symbol table for constants like "pi"
result_type operator()(binary_op< real_t > const &tree) const
Evaluate a binary operator and optionally recurse its operands.
void operator()(Iterator first, Iterator last, boost::spirit::info const &info) const
Throw an exception saying where and why parsing failed.
T isinf(T x)
isinf function with adjusted return type
expr_ast< real_t > lhs
Stored argument tree of first argument.