65 template <
typename T >
66 constexpr T
sgn(T x) {
return (T{0} < x) - (x < T{0}); }
69 template <
typename T >
70 T
isnan(T x) {
return std::isnan(x); }
73 template <
typename T >
74 T
isinf(T x) {
return std::isinf(x); }
77 template <
typename T >
81 template <
typename T >
86 template <
typename real_t >
struct expr_ast;
87 template <
typename real_t >
struct unary_op;
88 template <
typename real_t >
struct binary_op;
102 if (
this != &other) {
103 ptr = std::make_unique<T>(*other.
ptr);
113 explicit operator T&() {
return *
ptr; }
114 explicit operator const T&()
const {
return *
ptr; }
127 template <
typename real_t >
159 template <
typename Expr>
173 template <
typename real_t >
177 using op_t = std::function<real_t(real_t)>;
193 if (
this != &other) {
195 rhs = std::make_unique<expr_ast<real_t>>(*other.rhs);
210 template < typename real_t >
214 using op_t = std::function<real_t(real_t, real_t)>;
225 lhs(
std::make_unique<
expr_ast<real_t>>(*other.lhs)),
232 if (
this != &other) {
234 lhs = std::make_unique<expr_ast<real_t>>(*other.lhs);
235 rhs = std::make_unique<expr_ast<real_t>>(*other.rhs);
252 template < typename real_t >
258 template <
typename real_t >
264 template <
typename real_t >
270 template <
typename real_t >
282 template <
typename real_t >
307 auto it = st.find(c);
308 if (it == st.end()) {
309 throw std::invalid_argument(
"Unknown variable " + c);
317 return std::visit(*
this, ast.
tree);
323 return tree.
op(std::visit(*
this, tree.
lhs->tree),
324 std::visit(*
this, tree.
rhs->tree));
330 return tree.
op(std::visit(*
this, tree.
rhs->tree));
336 return std::visit(*
this, w.get().tree);
342 return (*
this)(w.get());
348 return (*
this)(w.get());
370 return std::visit(*
this, ast.
tree);
375 auto lhs = std::visit(*
this, tree.
lhs->tree);
376 auto rhs = std::visit(*
this, tree.
rhs->tree);
380 if (
auto l = std::get_if<real_t>(&lhs)) {
381 if (
auto r = std::get_if<real_t>(&rhs)) {
382 return tree.
op(*l, *r);
390 auto rhs = std::visit(*
this, tree.
rhs->tree);
392 if (
auto r = std::get_if<real_t>(&rhs)) {
400 return std::visit(*
this, w.get().tree);
405 return (*
this)(w.get());
410 return (*
this)(w.get());
415 template <
typename real_t>
419 : input_(input), pos_(0) {}
424 auto result = parseExpression();
426 if (pos_ < input_.length()) {
427 throw std::runtime_error(
"Unexpected characters at end of expression");
437 while (pos_ < input_.length() && std::isspace(
static_cast<unsigned char>(input_[pos_]))) {
444 if (pos_ < input_.length() && input_[pos_] == c) {
451 bool match(
const std::string& str) {
453 if (input_.compare(pos_, str.length(), str) == 0) {
454 pos_ += str.length();
462 throw std::runtime_error(std::string(
"Expected '") + c +
"'");
467 auto result = parseTerm();
470 result += parseTerm();
471 }
else if (match(
'-')) {
472 result -= parseTerm();
481 auto result = parseFactor();
484 result *= parseFactor();
485 }
else if (match(
'/')) {
487 }
else if (match(
'%')) {
488 auto fmod =
static_cast<real_t(*)(real_t,real_t)
>(&std::fmod);
498 auto lhs = parsePrimary();
501 auto rhs = parseFactor();
502 auto pow =
static_cast<real_t(*)(real_t,real_t)
>(&std::pow);
512 if (std::isdigit(
static_cast<unsigned char>(input_[pos_])) ||
513 (pos_ < input_.length() && input_[pos_] ==
'.')) {
514 return parseNumber();
519 auto result = parseExpression();
529 return parsePrimary();
533 std::string identifier = parseIdentifier();
534 if (identifier.empty()) {
535 throw std::runtime_error(
"Unexpected character");
539 for (
const auto& c : getConstants()) {
540 if (identifier == c.first) {
546 for (
const auto& f : getBinaryFunctions()) {
547 if (identifier == f.first) {
549 auto arg1 = parseExpression();
551 auto arg2 = parseExpression();
558 for (
const auto& f : getUnaryFunctions()) {
559 if (identifier == f.first) {
561 auto arg = parseExpression();
574 bool has_dot =
false;
575 bool has_exp =
false;
577 if (pos_ < input_.length() && (input_[pos_] ==
'+' || input_[pos_] ==
'-')) {
581 while (pos_ < input_.length()) {
582 char c = input_[pos_];
583 if (std::isdigit(
static_cast<unsigned char>(c))) {
585 }
else if (c ==
'.' && !has_dot) {
588 }
else if ((c ==
'e' || c ==
'E') && !has_exp) {
591 if (pos_ >= input_.length() ||
592 (!std::isdigit(
static_cast<unsigned char>(input_[pos_])) &&
593 input_[pos_] !=
'+' && input_[pos_] !=
'-')) {
594 throw std::runtime_error(
"Expected exponent digits at position " + std::to_string(pos_));
596 if (input_[pos_] ==
'+' || input_[pos_] ==
'-') pos_++;
597 if (pos_ >= input_.length() || !std::isdigit(
static_cast<unsigned char>(input_[pos_]))) {
598 throw std::runtime_error(
"Expected exponent digits at position " + std::to_string(pos_));
607 std::string_view sv(input_.data() + start, pos_ - start);
608 real_t value =
static_cast<real_t
>(std::stod(std::string(sv)));
611 throw std::runtime_error(
"Invalid number");
614 throw std::runtime_error(
"Expected number");
620 if (pos_ < input_.length() && (std::isalpha(
static_cast<unsigned char>(input_[pos_])) || input_[pos_] ==
'_')) {
622 while (pos_ < input_.length() &&
623 (std::isalnum(
static_cast<unsigned char>(input_[pos_])) || input_[pos_] ==
'_')) {
626 return std::string(input_.substr(start, pos_ - start));
631 static const std::array<std::pair<std::string_view, real_t>, 4>&
getConstants() {
632 static const std::array<std::pair<std::string_view, real_t>, 4> constants = {{
634 {
"epsilon", std::numeric_limits<real_t>::epsilon()},
635 {
"phi", (1.0 + std::sqrt(5.0)) / 2.0},
641 static const std::array<std::pair<std::string_view, typename unary_op<real_t>::op_t>, 31>&
getUnaryFunctions() {
642 static const std::array<std::pair<std::string_view, typename unary_op<real_t>::op_t>, 31> funcs = {{
643 {
"abs",
static_cast<real_t(*)(real_t)
>(&std::abs)},
644 {
"acos",
static_cast<real_t(*)(real_t)
>(&std::acos)},
645 {
"acosh",
static_cast<real_t(*)(real_t)
>(&std::acosh)},
646 {
"asin",
static_cast<real_t(*)(real_t)
>(&std::asin)},
647 {
"asinh",
static_cast<real_t(*)(real_t)
>(&std::asinh)},
648 {
"atan",
static_cast<real_t(*)(real_t)
>(&std::atan)},
649 {
"atanh",
static_cast<real_t(*)(real_t)
>(&std::atanh)},
650 {
"cbrt",
static_cast<real_t(*)(real_t)
>(&std::cbrt)},
651 {
"ceil",
static_cast<real_t(*)(real_t)
>(&std::ceil)},
652 {
"cos",
static_cast<real_t(*)(real_t)
>(&std::cos)},
653 {
"cosh",
static_cast<real_t(*)(real_t)
>(&std::cosh)},
654 {
"deg2rad",
static_cast<real_t(*)(real_t)
>(&math::deg)},
655 {
"erf",
static_cast<real_t(*)(real_t)
>(&std::erf)},
656 {
"erfc",
static_cast<real_t(*)(real_t)
>(&std::erfc)},
657 {
"exp",
static_cast<real_t(*)(real_t)
>(&std::exp)},
658 {
"exp2",
static_cast<real_t(*)(real_t)
>(&std::exp2)},
659 {
"floor",
static_cast<real_t(*)(real_t)
>(&std::floor)},
660 {
"isinf",
static_cast<real_t(*)(real_t)
>(&math::isinf)},
661 {
"isnan",
static_cast<real_t(*)(real_t)
>(&math::isnan)},
662 {
"log",
static_cast<real_t(*)(real_t)
>(&std::log)},
663 {
"log2",
static_cast<real_t(*)(real_t)
>(&std::log2)},
664 {
"log10",
static_cast<real_t(*)(real_t)
>(&std::log10)},
665 {
"rad2deg",
static_cast<real_t(*)(real_t)
>(&math::rad)},
666 {
"round",
static_cast<real_t(*)(real_t)
>(&std::round)},
667 {
"sgn",
static_cast<real_t(*)(real_t)
>(&math::sgn)},
668 {
"sin",
static_cast<real_t(*)(real_t)
>(&std::sin)},
669 {
"sinh",
static_cast<real_t(*)(real_t)
>(&std::sinh)},
670 {
"sqrt",
static_cast<real_t(*)(real_t)
>(&std::sqrt)},
671 {
"tan",
static_cast<real_t(*)(real_t)
>(&std::tan)},
672 {
"tanh",
static_cast<real_t(*)(real_t)
>(&std::tanh)},
673 {
"tgamma",
static_cast<real_t(*)(real_t)
>(&std::tgamma)}
678 static const std::array<std::pair<std::string_view, typename binary_op<real_t>::op_t>, 4>&
getBinaryFunctions() {
679 static const std::array<std::pair<std::string_view, typename binary_op<real_t>::op_t>, 4> funcs = {{
680 {
"atan2",
static_cast<real_t(*)(real_t,real_t)
>(&std::atan2)},
681 {
"max",
static_cast<real_t(*)(real_t,real_t)
>(&std::fmax)},
682 {
"min",
static_cast<real_t(*)(real_t,real_t)
>(&std::fmin)},
683 {
"pow",
static_cast<real_t(*)(real_t,real_t)
>(&std::pow)}
697 template <
typename real_t,
typename Iterator>
699 std::string input(first, last);
701 return parser.
parse();
714 template <
typename real_t >
727 template <
typename Iterator >
728 void parse(Iterator first, Iterator last)
730 ast = detail::parse<real_t>(first, last);
736 parse(str.begin(), str.end());
764 template <
typename real_t,
typename Iterator >
765 real_t
parse(Iterator first, Iterator last,
769 parser.
parse(first, last);
774 template <
typename real_t >
775 real_t
parse(std::string
const& str,
778 return parse<real_t>(str.begin(), str.end(), st);
Tps< T > pow(const Tps< T > &x, int y)
Integer power.
PETE_TBTree< FnFmod, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > fmod(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
constexpr double e
The value of.
constexpr double pi
The value of.
expr_ast< real_t > parse(Iterator first, Iterator last)
Parse an expression.
constexpr T rad(T x)
Convert degrees to radians.
T isinf(T x)
isinf function with adjusted return type
T isnan(T x)
isnan function with adjusted return type
constexpr T deg(T x)
Convert radians to degrees.
constexpr T sgn(T x)
Sign function.
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.
expr_ast(Expr other)
Copy constructor.
std::variant< nil, real_t, std::string, recursive_wrapper< expr_ast< real_t > >, recursive_wrapper< binary_op< real_t > >, recursive_wrapper< unary_op< real_t > > > tree_t
Store a unary operator and its argument tree.
unary_op(const unary_op &other)
unary_op & operator=(unary_op &&) noexcept=default
unary_op(unary_op &&) noexcept=default
unary_op(op_t op, expr_ast< real_t > rhs)
Save the operator and the argument tree.
std::unique_ptr< expr_ast< real_t > > rhs
Stored 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.
binary_op & operator=(binary_op &&) noexcept=default
binary_op(op_t op, expr_ast< real_t > lhs, expr_ast< real_t > rhs)
Save the operator and the argument trees.
binary_op(binary_op &&) noexcept=default
std::function< real_t(real_t, real_t)> op_t
Signature of a binary operator: op(x,y)
binary_op(const binary_op &other)
std::unique_ptr< expr_ast< real_t > > lhs
Stored argument tree of first argument.
std::unique_ptr< expr_ast< real_t > > rhs
Stored argument tree of second argument.
recursive_wrapper(recursive_wrapper &&other) noexcept=default
recursive_wrapper & operator=(recursive_wrapper &&other) noexcept=default
recursive_wrapper & operator=(const recursive_wrapper &other)
recursive_wrapper(const T &t)
recursive_wrapper(const recursive_wrapper &other)
Evaluate the Abstract Syntax Tree.
result_type operator()(recursive_wrapper< expr_ast< real_t > > const &w) const
Handle recursive_wrapper for expr_ast.
real_t result_type
Necessary typedef for 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::unordered_map< std::string, result_type > symbol_table_t
Type of the symbol table.
result_type operator()(recursive_wrapper< binary_op< real_t > > const &w) const
Handle recursive_wrapper for binary_op.
result_type operator()(recursive_wrapper< unary_op< real_t > > const &w) const
Handle recursive_wrapper for unary_op.
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.
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()(recursive_wrapper< expr_ast< real_t > > const &w) const
Handle recursive_wrapper for expr_ast.
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 visitor.
result_type operator()(recursive_wrapper< binary_op< real_t > > const &w) const
Handle recursive_wrapper for binary_op.
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.
result_type operator()(recursive_wrapper< unary_op< real_t > > const &w) const
Handle recursive_wrapper for unary_op.
bool match(const std::string &str)
expr_ast< real_t > parsePrimary()
static const std::array< std::pair< std::string_view, typename unary_op< real_t >::op_t >, 31 > & getUnaryFunctions()
static const std::array< std::pair< std::string_view, real_t >, 4 > & getConstants()
static const std::array< std::pair< std::string_view, typename binary_op< real_t >::op_t >, 4 > & getBinaryFunctions()
std::string parseIdentifier()
SimpleMathParser(std::string_view input)
expr_ast< real_t > parseTerm()
expr_ast< real_t > parseExpression()
expr_ast< real_t > parse()
expr_ast< real_t > parseFactor()
expr_ast< real_t > parseNumber()
void parse(Iterator first, Iterator last)
Parse an expression.
real_t evaluate(typename detail::eval_ast< real_t >::symbol_table_t const &st) const
Evaluate the AST with a given symbol table.
detail::expr_ast< real_t > ast
void parse(std::string const &str)