14 const std::string& input_var,
15 const std::string& output_var,
17 const std::string& operation) {
18 auto step =
context.consume_steps(1, operation);
19 if (!step)
return step;
22 "transform expression cannot be null",
25 if (input_var.empty() || output_var.empty()) {
27 "transform variable names cannot be empty",
30 if (input_var == output_var) {
32 "input and output variables must be distinct",
38 const std::shared_ptr<const SymbolicNode>& node) {
43 std::shared_ptr<SymbolicExpr> expr,
44 const std::string& operation) {
48 "transform construction produced a null expression",
55 "transform is outside the current evaluated support domain",
66 const std::shared_ptr<SymbolicExpr>& lhs,
67 const std::shared_ptr<SymbolicExpr>&
rhs) {
77 const std::shared_ptr<const SymbolicNode>& node) {
78 const auto number = std::dynamic_pointer_cast<const NumberNode>(node);
79 if (!number)
return std::nullopt;
80 if (std::holds_alternative<BigInt>(number->value())) {
81 return Rational(std::get<BigInt>(number->value()));
83 return std::get<Rational>(number->value());
86 auto result = BigInt::factorial_checked(n,
context);
87 if (!result)
throw result.error();
88 return std::move(result.value());
90std::pair<std::shared_ptr<SymbolicExpr>,std::shared_ptr<SymbolicExpr>>
94 if (!
mul)
return {SymbolicExpr::number(1),
e};
95 std::vector<std::shared_ptr<const SymbolicNode>> cp, vp;
96 for (
auto&
op :
mul->operands()) {
99 if (cp.empty())
return {SymbolicExpr::number(1),
e};
100 if (vp.empty())
return {
e, SymbolicExpr::number(1)};
109 const std::shared_ptr<const SymbolicNode>& argument,
const std::string&
variable) {
110 auto symbol = std::dynamic_pointer_cast<const VariableNode>(argument);
111 if (symbol && !symbol->is_constant() && symbol->name() ==
variable) {
114 auto product = std::dynamic_pointer_cast<const MultiplyNode>(argument);
115 if (!product || product->operands().size() != 2) {
118 for (std::size_t i = 0; i < 2; ++i) {
119 symbol = std::dynamic_pointer_cast<const VariableNode>(product->operands()[i]);
120 const auto& other = product->operands()[1 - i];
121 if (!symbol || symbol->is_constant() || symbol->name() !=
variable)
continue;
131 const std::shared_ptr<const SymbolicNode>& expression,
134 std::dynamic_pointer_cast<const PowerNode>(expression);
135 if (!power)
return false;
137 std::dynamic_pointer_cast<const VariableNode>(power->base());
138 return base && !base->is_constant() && base->name() ==
variable &&
143 const std::shared_ptr<const SymbolicNode>& argument,
150 !(*coefficient < Rational(0))) {
153 return -*coefficient;
157 const std::shared_ptr<const SymbolicNode>& factor,
158 const std::string&
variable, Rational& coefficient,
159 bool& has_variable_square) {
161 coefficient = coefficient * *number;
165 has_variable_square =
true;
171 Rational coefficient(1);
172 bool has_variable_square =
false;
173 for (
const auto& factor : product.
operands()) {
175 factor,
variable, coefficient, has_variable_square)) {
179 return has_variable_square && coefficient < Rational(0)
180 ? std::optional<Rational>(-coefficient)
186 const std::shared_ptr<SymbolicExpr>& expression,
188 if (!expression || !
detail::node(expression))
return std::nullopt;
189 const auto function = std::dynamic_pointer_cast<const FunctionNode>(
195 const auto product = std::dynamic_pointer_cast<const MultiplyNode>(
197 if (!product)
return std::nullopt;
199 return te_gaussian_product_rate(*product,
variable);
203 const std::shared_ptr<SymbolicExpr>& expression,
210 const auto function = std::dynamic_pointer_cast<const FunctionNode>(
213 function->arguments().size() != 1) {
218 if (!rate)
return std::nullopt;
222bool te_is_trig(
const std::shared_ptr<SymbolicExpr>& expression,
223 const std::string&
variable,
bool& is_sin,
224 std::shared_ptr<SymbolicExpr>& frequency) {
238 return frequency !=
nullptr;
const std::vector< std::shared_ptr< const SymbolicNode > > & operands() const noexcept
static Result failure(CasErrc code, std::string message, std::string operation={})
static Result success(T value)
static std::shared_ptr< const SymbolicNode > create_number(const ::LMCAS::BigInt &v)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
bool contains_node_type(const SymbolicNodePtr &root)
std::shared_ptr< const Node > make_node(Args &&... args)
const std::string & variable
__attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult surface_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::string & v
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
ExprResult mul(const ExprPtr &lhs, const ExprPtr &rhs, ComputationContext &context)
const VectorField const VectorField & c
bool expression_depends_on_variable(const detail::SymbolicNodePtr &expression, const std::string &variable, detail::RewriteBudget *budget)
const ExprPtr RelationOp op
std::optional< int > exact_small_integer_node(const detail::SymbolicNodePtr &node, int min_value, int max_value)
Result< Verified< EvaluatedTransform > > TransformEngineResult
ExprResult function(const std::string &name, std::vector< ExprPtr > arguments)