Add builtin functions for calc
This commit is contained in:
parent
b3cbd2d499
commit
0ebb56eb7c
|
@ -1,9 +1,43 @@
|
||||||
#include "AST.h"
|
#include "AST.h"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <functional>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace calc {
|
namespace calc {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using d2dfn = double(*)(double);
|
||||||
|
std::function<double(const Variables&, const Functions&, FunctionArguments&)> wrap(std::function<double(double)> fn) {
|
||||||
|
return [fn](const Variables& vars, const Functions& funs, FunctionArguments& args) -> double{
|
||||||
|
if (args.size() != 1)
|
||||||
|
return 0;
|
||||||
|
return fn(args[0]->eval(vars, funs));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::function<double(const Variables&, const Functions&, FunctionArguments&)>> builtins =
|
||||||
|
{
|
||||||
|
{"if", [](const Variables& vars, const Functions& funs, FunctionArguments& args) -> double {
|
||||||
|
if (args.size() != 3)
|
||||||
|
return 0;
|
||||||
|
double test = args[0]->eval(vars, funs);
|
||||||
|
if (std::fabs(test) < 1e-8)
|
||||||
|
return args[2]->eval(vars, funs);
|
||||||
|
else
|
||||||
|
return args[1]->eval(vars, funs);
|
||||||
|
}},
|
||||||
|
{"sin", wrap((d2dfn)(std::sin))},
|
||||||
|
{"cos", wrap((d2dfn)(std::cos))},
|
||||||
|
{"tan", wrap((d2dfn)(std::tan))},
|
||||||
|
{"asin", wrap((d2dfn)(std::asin))},
|
||||||
|
{"acos", wrap((d2dfn)(std::acos))},
|
||||||
|
{"atan", wrap((d2dfn)(std::atan))},
|
||||||
|
{"abs", wrap((d2dfn)(std::fabs))}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Number::Number(double d) : m_val(d) {}
|
Number::Number(double d) : m_val(d) {}
|
||||||
double Number::eval(const Variables&, const Functions&) const {
|
double Number::eval(const Variables&, const Functions&) const {
|
||||||
return m_val;
|
return m_val;
|
||||||
|
@ -74,8 +108,13 @@ std::size_t FunctionArguments::size() const {
|
||||||
FunctionCall::FunctionCall(std::string name, std::unique_ptr<FunctionArguments>&& arguments) : m_name(name), m_arguments(std::move(arguments)) {}
|
FunctionCall::FunctionCall(std::string name, std::unique_ptr<FunctionArguments>&& arguments) : m_name(name), m_arguments(std::move(arguments)) {}
|
||||||
double FunctionCall::eval(const Variables& vars, const Functions& funs) const {
|
double FunctionCall::eval(const Variables& vars, const Functions& funs) const {
|
||||||
auto fp = funs.find(m_name);
|
auto fp = funs.find(m_name);
|
||||||
if (fp == funs.end())
|
if (fp == funs.end()) {
|
||||||
return 0;
|
if (builtins.count(m_name)) {
|
||||||
|
return builtins[m_name](vars, funs, *m_arguments);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Function& fun = *dynamic_cast<Function*>((fp->second.get()));
|
Function& fun = *dynamic_cast<Function*>((fp->second.get()));
|
||||||
|
|
||||||
if (m_arguments->size() != fun.getParams().size()) return 0;
|
if (m_arguments->size() != fun.getParams().size()) return 0;
|
||||||
|
|
Loading…
Reference in New Issue