56 return (
T{0} < x) - (x <
T{0});
74 return x * (std::numbers::pi_v<T> / 180.0);
80 return x * (180.0 / std::numbers::pi_v<T>);
86 template <
typename real_t>
88 template <
typename real_t>
90 template <
typename real_t>
106 if (
this != &other) {
107 ptr = std::make_unique<T>(*other.
ptr);
118 operator const T&()
const {
return *
ptr; }
131 template <
typename real_t>
160 template <
typename Expr>
174 template <
typename real_t>
177 using op_t = std::function<real_t(real_t)>;
189 if (
this != &other) {
191 rhs = std::make_unique<expr_ast<real_t>>(*other.rhs);
205 template <typename real_t>
208 using op_t = std::function<real_t(real_t, real_t)>;
218 lhs(
std::make_unique<
expr_ast<real_t>>(*other.lhs)),
224 if (
this != &other) {
226 lhs = std::make_unique<expr_ast<real_t>>(*other.lhs);
227 rhs = std::make_unique<expr_ast<real_t>>(*other.rhs);
242 template <typename real_t>
247 template <
typename real_t>
252 template <
typename real_t>
257 template <
typename real_t>
268 template <
typename real_t>
291 auto it = st.find(c);
292 if (it == st.end()) {
293 throw std::invalid_argument(
"Unknown variable " + c);
300 return std::visit(*
this, ast.
tree);
306 std::visit(*
this, tree.
lhs->tree), std::visit(*
this, tree.
rhs->tree));
311 return tree.
op(std::visit(*
this, tree.
rhs->tree));
316 return std::visit(*
this, w.get().tree);
321 return (*
this)(w.get());
326 return (*
this)(w.get());
333 template <
typename T>
337 template <
typename U>
339 return std::is_same<U, T>::value;
343 template <
typename T,
typename... Ts>
348 template <
typename real_t>
364 return std::visit(*
this, ast.
tree);
369 auto lhs = std::visit(*
this, tree.
lhs->tree);
370 auto rhs = std::visit(*
this, tree.
rhs->tree);
374 if (holds_alternative<real_t>(lhs) && holds_alternative<real_t>(rhs)) {
375 return tree.
op(std::get<real_t>(lhs), std::get<real_t>(rhs));
382 auto rhs = std::visit(*
this, tree.
rhs->tree);
384 if (holds_alternative<real_t>(rhs)) {
385 return tree.
op(std::get<real_t>(rhs));
392 return std::visit(*
this, w.get().tree);
397 return (*
this)(w.get());
402 return (*
this)(w.get());
408 template <
typename real_t>
416 auto result = parseExpression();
418 if (pos_ < input_.length()) {
419 throw std::runtime_error(
"Unexpected characters at end of expression");
429 while (pos_ < input_.length()
430 && std::isspace(
static_cast<unsigned char>(input_[pos_]))) {
437 if (pos_ < input_.length() && input_[pos_] == c) {
444 bool match(
const std::string& str) {
446 if (input_.compare(pos_, str.length(), str) == 0) {
447 pos_ += str.length();
455 throw std::runtime_error(std::string(
"Expected '") + c +
"'");
460 auto result = parseTerm();
463 result += parseTerm();
464 }
else if (match(
'-')) {
465 result -= parseTerm();
474 auto result = parseFactor();
477 result *= parseFactor();
478 }
else if (match(
'/')) {
481 }
else if (match(
'%')) {
482 auto fmod =
static_cast<real_t (*)(real_t, real_t)
>(&std::fmod);
492 auto result = parsePrimary();
493 while (match(
"**")) {
494 auto pow =
static_cast<real_t (*)(real_t, real_t)
>(&std::pow);
504 if (std::isdigit(
static_cast<unsigned char>(input_[pos_]))
505 || (pos_ < input_.length() && input_[pos_] ==
'.')) {
506 return parseNumber();
511 auto result = parseExpression();
522 return parsePrimary();
526 std::string identifier = parseIdentifier();
527 if (identifier.empty()) {
528 throw std::runtime_error(
"Unexpected character");
532 const auto& constants = getConstants();
533 if (constants.find(identifier) != constants.end()) {
538 const auto& ufuncs = getUnaryFunctions();
539 if (ufuncs.find(identifier) != ufuncs.end()) {
541 auto arg = parseExpression();
547 const auto& bfuncs = getBinaryFunctions();
548 if (bfuncs.find(identifier) != bfuncs.end()) {
550 auto arg1 = parseExpression();
552 auto arg2 = parseExpression();
564 bool has_dot =
false;
565 bool has_exp =
false;
567 if (pos_ < input_.length() && (input_[pos_] ==
'+' || input_[pos_] ==
'-')) {
571 while (pos_ < input_.length()) {
572 char c = input_[pos_];
573 if (std::isdigit(
static_cast<unsigned char>(c))) {
575 }
else if (c ==
'.' && !has_dot) {
578 }
else if ((c ==
'e' || c ==
'E') && !has_exp) {
581 if (pos_ < input_.length()
582 && (input_[pos_] ==
'+' || input_[pos_] ==
'-')) {
593 static_cast<real_t
>(std::stod(input_.substr(start, pos_ - start)));
596 throw std::runtime_error(
"Invalid number");
599 throw std::runtime_error(
"Expected number");
605 if (pos_ < input_.length()
606 && (std::isalpha(
static_cast<unsigned char>(input_[pos_]))
607 || input_[pos_] ==
'_')) {
609 while (pos_ < input_.length()
610 && (std::isalnum(
static_cast<unsigned char>(input_[pos_]))
611 || input_[pos_] ==
'_')) {
614 return input_.substr(start, pos_ - start);
620 static const std::map<std::string, real_t> constants = {
621 {
"e", std::numbers::e_v<real_t>},
622 {
"epsilon", std::numeric_limits<real_t>::epsilon()},
623 {
"phi", (1.0 + std::sqrt(5.0)) / 2.0},
624 {
"pi", std::numbers::pi_v<real_t>}};
628 static const std::map<std::string, typename unary_op<real_t>::op_t>&
630 static const std::map<std::string, typename unary_op<real_t>::op_t> funcs = {
631 {
"abs",
static_cast<real_t (*)(real_t)
>(&std::abs)},
632 {
"acos",
static_cast<real_t (*)(real_t)
>(&std::acos)},
633 {
"acosh",
static_cast<real_t (*)(real_t)
>(&std::acosh)},
634 {
"asin",
static_cast<real_t (*)(real_t)
>(&std::asin)},
635 {
"asinh",
static_cast<real_t (*)(real_t)
>(&std::asinh)},
636 {
"atan",
static_cast<real_t (*)(real_t)
>(&std::atan)},
637 {
"atanh",
static_cast<real_t (*)(real_t)
>(&std::atanh)},
638 {
"cbrt",
static_cast<real_t (*)(real_t)
>(&std::cbrt)},
639 {
"ceil",
static_cast<real_t (*)(real_t)
>(&std::ceil)},
640 {
"cos",
static_cast<real_t (*)(real_t)
>(&std::cos)},
641 {
"cosh",
static_cast<real_t (*)(real_t)
>(&std::cosh)},
642 {
"deg2rad",
static_cast<real_t (*)(real_t)
>(&math::deg)},
643 {
"erf",
static_cast<real_t (*)(real_t)
>(&std::erf)},
644 {
"erfc",
static_cast<real_t (*)(real_t)
>(&std::erfc)},
645 {
"exp",
static_cast<real_t (*)(real_t)
>(&std::exp)},
646 {
"exp2",
static_cast<real_t (*)(real_t)
>(&std::exp2)},
647 {
"floor",
static_cast<real_t (*)(real_t)
>(&std::floor)},
648 {
"isinf",
static_cast<real_t (*)(real_t)
>(&math::isinf)},
649 {
"isnan",
static_cast<real_t (*)(real_t)
>(&math::isnan)},
650 {
"log",
static_cast<real_t (*)(real_t)
>(&std::log)},
651 {
"log2",
static_cast<real_t (*)(real_t)
>(&std::log2)},
652 {
"log10",
static_cast<real_t (*)(real_t)
>(&std::log10)},
653 {
"rad2deg",
static_cast<real_t (*)(real_t)
>(&math::rad)},
654 {
"round",
static_cast<real_t (*)(real_t)
>(&std::round)},
655 {
"sgn",
static_cast<real_t (*)(real_t)
>(&math::sgn)},
656 {
"sin",
static_cast<real_t (*)(real_t)
>(&std::sin)},
657 {
"sinh",
static_cast<real_t (*)(real_t)
>(&std::sinh)},
658 {
"sqrt",
static_cast<real_t (*)(real_t)
>(&std::sqrt)},
659 {
"tan",
static_cast<real_t (*)(real_t)
>(&std::tan)},
660 {
"tanh",
static_cast<real_t (*)(real_t)
>(&std::tanh)},
661 {
"tgamma",
static_cast<real_t (*)(real_t)
>(&std::tgamma)}};
665 static const std::map<std::string, typename binary_op<real_t>::op_t>&
667 static const std::map<std::string, typename binary_op<real_t>::op_t> funcs = {
668 {
"atan2",
static_cast<real_t (*)(real_t, real_t)
>(&std::atan2)},
669 {
"max",
static_cast<real_t (*)(real_t, real_t)
>(&std::fmax)},
670 {
"min",
static_cast<real_t (*)(real_t, real_t)
>(&std::fmin)},
671 {
"pow",
static_cast<real_t (*)(real_t, real_t)
>(&std::pow)}};
684 template <
typename real_t,
typename Iterator>
686 std::string input(first, last);
688 return parser.
parse();
700 template <
typename real_t>
713 template <
typename Iterator>
714 void parse(Iterator first, Iterator last) {
715 ast = detail::parse<real_t>(first, last);
719 void parse(std::string
const& str) {
parse(str.begin(), str.end()); }
742 template <
typename real_t,
typename Iterator>
744 Iterator first, Iterator last,
747 parser.
parse(first, last);
753 template <
typename real_t>
756 return parse<real_t>(str.begin(), str.end(), st);
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.
bool match(const std::string &str)
expr_ast< real_t > parsePrimary()
SimpleMathParser(const std::string &input)
static const std::map< std::string, typename unary_op< real_t >::op_t > & getUnaryFunctions()
static const std::map< std::string, real_t > & getConstants()
std::string parseIdentifier()
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()
static const std::map< std::string, typename binary_op< real_t >::op_t > & getBinaryFunctions()
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.
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.
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.
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.
bool holds_alternative(std::variant< Ts... > const &v)
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.
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.
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.
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.
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
expr_ast(Expr other)
Copy constructor.
bool operator()(U const &) const
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)
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)