37 for (
const auto& entry : functions) {
38 if (
name == entry.name) {
39 return entry.function;
49 auto result = SymbolicExpr::log(arguments[0], arguments[1]);
51 }
catch (
const std::bad_alloc&) {
53 "log expression allocation failed",
55 }
catch (
const std::exception& error) {
63 auto result = SymbolicExpr::atan2(arguments[0], arguments[1]);
65 }
catch (
const std::bad_alloc&) {
67 "atan2 expression allocation failed",
69 }
catch (
const std::exception& error) {
76 auto variable = std::dynamic_pointer_cast<const VariableNode>(
79 return fail(
"Integral variable must be a symbol");
92 }
catch (
const std::bad_alloc&) {
94 "Integral expression allocation failed",
96 }
catch (
const std::exception& error) {
102 auto variable = std::dynamic_pointer_cast<const VariableNode>(
104 auto direction = std::dynamic_pointer_cast<const VariableNode>(
108 return fail(
"limit variable and direction must be symbols");
113 }
else if (
direction->name() ==
"below" ||
117 }
else if (
direction->name() ==
"above" ||
122 return fail(
"invalid limit direction");
131 auto variable = std::dynamic_pointer_cast<const VariableNode>(
133 auto index = std::dynamic_pointer_cast<const NumberNode>(
136 return fail(
"RootOf variable and index are invalid");
139 if (std::holds_alternative<BigInt>(index->value())) {
140 index_value = std::get<BigInt>(index->value());
142 const auto&
rational = std::get<Rational>(index->value());
144 return fail(
"RootOf index must be an integer");
148 const auto converted = index_value.try_to_int64();
149 if (!converted || *converted < 0) {
150 return fail(
"RootOf index is negative or too large");
154 static_cast<std::size_t
>(*converted));
162 return clamp(arguments[0], arguments[1], arguments[2]);
166 const std::vector<ExprPtr>& arguments) {
167 if (
auto unary = find_unary_function(
name)) {
168 if (arguments.size() == 1) {
169 return unary(arguments[0]);
171 if (
name ==
"log" && arguments.size() == 2) {
174 return fail(
"invalid argument count for function '" +
name +
"'");
177 static const struct {
179 Constructor construct;
181 std::size_t alternative_arity;
192 for (
const auto& entry : functions) {
193 if (
name == entry.name) {
194 if (arguments.size() != entry.arity &&
195 arguments.size() != entry.alternative_arity) {
196 return fail(
"invalid argument count for function '" +
name +
"'");
198 return (this->*entry.construct)(arguments);
201 if (!arguments.empty() && (
name ==
"max" ||
name ==
"min")) {
209 const std::string&
name,
const std::vector<ExprPtr>& arguments) {
211 std::vector<std::shared_ptr<const SymbolicNode>> nodes;
212 nodes.reserve(arguments.size());
213 for (
const auto& argument : arguments) {
216 "function arguments cannot be null",
222 name, std::move(nodes));
224 }
catch (
const std::bad_alloc&) {
226 "function expression allocation failed",
228 }
catch (
const std::exception& error) {
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(ExprPtr value)
ExprResult apply_log(const std::vector< ExprPtr > &arguments)
ExprResult uninterpreted_function(const std::string &name, const std::vector< ExprPtr > &arguments)
ExprResult function_node(const std::string &name, const std::vector< ExprPtr > &arguments, FunctionNode::FuncType type)
ExprResult apply_function(const std::string &name, const std::vector< ExprPtr > &arguments)
ExprResult apply_clamp(const std::vector< ExprPtr > &arguments)
ExprResult apply_atan2(const std::vector< ExprPtr > &arguments)
ExprParser(std::string source)
ExprResult apply_limit(const std::vector< ExprPtr > &arguments)
ExprResult apply_integral(const std::vector< ExprPtr > &arguments)
ExprResult apply_rootof(const std::vector< ExprPtr > &arguments)
ExprResult fail(std::string message) const
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const Node > make_node(Args &&... args)
UnaryFunction find_unary_function(const std::string &name)
ExprResult(*)(const ExprPtr &) UnaryFunction
ExprResult expression_failure(CasErrc code, std::string message, const char *operation)
constexpr const char * kParseOperation
const std::string & variable
ExprResult exp(const ExprPtr &expression, ComputationContext &context)
ExprResult log10(const ExprPtr &expression, ComputationContext &context)
ExprResult ceil(const ExprPtr &expression, ComputationContext &context)
ExprResult real(const ExprPtr &expression, ComputationContext &context)
ExprResult acos(const ExprPtr &expression, ComputationContext &context)
const std::string const LimitExprPtr LimitDirection direction
Result< ExprPtr > ExprResult
ExprResult conj(const ExprPtr &expression, ComputationContext &context)
ExprResult atan(const ExprPtr &expression, ComputationContext &context)
ExprResult clamp(const ExprPtr &expression, const ExprPtr &lower, const ExprPtr &upper, ComputationContext &context)
ExprResult asin(const ExprPtr &expression, ComputationContext &context)
RootOfConstructionResult make_rootof_checked(const std::shared_ptr< SymbolicExpr > &polynomial, const std::string &variable, std::size_t index, ComputationContext &context)
ExprResult sin(const ExprPtr &expression, ComputationContext &context)
ExprResult tan(const ExprPtr &expression, ComputationContext &context)
ExprResult cos(const ExprPtr &expression, ComputationContext &context)
std::shared_ptr< SymbolicExpr > ExprPtr
ExprResult sqrt(const ExprPtr &expression, ComputationContext &context)
ExprResult log(const ExprPtr &expression, ComputationContext &context)
LimitDirection
Direction from which a limit approaches its point.
ExprResult floor(const ExprPtr &expression, ComputationContext &context)
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)
ExprResult abs(const ExprPtr &expression, ComputationContext &context)
__attribute__((visibility("default"))) Result< EqvProfile > eqv_profile_from_name(const std const std::string & name
ExprResult rational(const Rational &value)
ExprResult round(const ExprPtr &expression, ComputationContext &context)