18 if (!exact || (*exact != Rational(1, 2) && *exact != Rational(-1, 2))) {
29 if (!polynomial) {
throw polynomial.error(); }
30 if (!polynomial.value() || polynomial.value()->degree() != 2) {
return false; }
31 const auto& coefficients = polynomial.value()->coeffs;
32 if (coefficients[1] != Rational(0) ||
33 (coefficients[2] != Rational(1) && coefficients[2] != Rational(-1))) {
42 const std::string& var,
45 auto pw = std::dynamic_pointer_cast<const PowerNode>(node);
46 if (!pw) {
return false; }
47 auto en = std::dynamic_pointer_cast<const NumberNode>(pw->exponent());
48 if (!en) {
return false; }
50 auto radicand = pw->base();
52 if (outer && *outer == Rational(-1)) {
53 if (
const auto* root =
dynamic_cast<const PowerNode*
>(radicand.get())) {
55 if (!inner || *inner != Rational(1, 2)) {
return false; }
56 radicand = root->base();
57 }
else if (
const auto* root =
dynamic_cast<const FunctionNode*
>(radicand.get());
59 root->arguments().size() == 1) {
60 radicand = root->arguments()[0];
71 if (c2 < Rational(0) && c0 > Rational(0)) { out.
pattern = 1; out.
a_sq = c0; }
72 else if (c2 > Rational(0) && c0 > Rational(0)) { out.
pattern = 2; out.
a_sq = c0; }
73 else if (c2 > Rational(0) && c0 < Rational(0)) { out.
pattern = 3; out.
a_sq = Rational(0) - c0; }
80Result<std::optional<detail::IntegralParts>> Integrator::try_trig_substitution(
81 const SymbolicExpr& expr,
const std::string& var,
82 ComputationContext&
context,
int)
try {
83 detail::RewriteBudget transform_budget(
context, (
context).limits().max_recursion_depth,
84 (
context).limits().max_ast_nodes,
"transform");
87 auto x = SymbolicExpr::variable(var);
97 return std::optional<detail::IntegralParts>{};
100 auto a_sq_expr = SymbolicExpr::number(qr.a_sq);
101 auto a_expr = SymbolicExpr::sqrt(a_sq_expr);
104 auto x_sq = SymbolicExpr::power(x, SymbolicExpr::number(2));
105 auto make_radicand = [&]() -> std::shared_ptr<SymbolicExpr> {
107 return SymbolicExpr::add(a_sq_expr, SymbolicExpr::multiply(SymbolicExpr::number(-1), x_sq));
109 return SymbolicExpr::add(a_sq_expr, x_sq);
110 return SymbolicExpr::add(x_sq, SymbolicExpr::multiply(SymbolicExpr::number(-1), a_sq_expr));
112 auto x_over_a = SymbolicExpr::divide(x, a_expr);
114 auto arcsin = [&](
const std::shared_ptr<SymbolicExpr>&
u) {
118 auto ln = [&](
const std::shared_ptr<SymbolicExpr>&
u) {
return SymbolicExpr::ln(
u); };
122 if (qr.pattern == 1) {
127 if (qr.pattern == 2) {
129 auto rad = SymbolicExpr::sqrt(SymbolicExpr::add(x_sq, a_sq_expr));
134 auto rad = SymbolicExpr::sqrt(SymbolicExpr::add(x_sq,
135 SymbolicExpr::multiply(SymbolicExpr::number(-1), a_sq_expr)));
140 auto rad = SymbolicExpr::sqrt(make_radicand());
141 auto half = SymbolicExpr::number(
Rational(1, 2));
142 if (qr.pattern == 1) {
144 auto term1 = SymbolicExpr::multiply(SymbolicExpr::multiply(half, x), rad);
145 auto term2 = SymbolicExpr::multiply(SymbolicExpr::multiply(half, a_sq_expr), arcsin(x_over_a));
149 if (qr.pattern == 2) {
151 auto lrad = SymbolicExpr::sqrt(SymbolicExpr::add(x_sq, a_sq_expr));
152 auto term1 = SymbolicExpr::multiply(SymbolicExpr::multiply(half, x), rad);
153 auto term2 = SymbolicExpr::multiply(SymbolicExpr::multiply(half, a_sq_expr),
154 ln(SymbolicExpr::add(x, lrad)));
159 auto lrad = SymbolicExpr::sqrt(SymbolicExpr::add(x_sq,
160 SymbolicExpr::multiply(SymbolicExpr::number(-1), a_sq_expr)));
161 auto term1 = SymbolicExpr::multiply(SymbolicExpr::multiply(half, x), rad);
162 auto term2 = SymbolicExpr::multiply(
163 SymbolicExpr::multiply(SymbolicExpr::multiply(SymbolicExpr::number(-1), half), a_sq_expr),
164 ln(SymbolicExpr::add(x, lrad)));
函数节点,表示数学函数调用(三角函数、对数、特殊函数等)。
FuncType type() const noexcept
bool trigsub_match_radical(const std::shared_ptr< const SymbolicNode > &node, const std::string &var, ComputationContext &context, QuadRadical &out)
bool trigsub_quadratic_coefficients(const detail::SymbolicNodePtr &radicand, const std::string &var, ComputationContext &context, Rational &c0, Rational &c2)
bool trigsub_half_exponent(const NumberNode &number, Rational &exponent)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
std::shared_ptr< const SymbolicNode > SymbolicNodePtr
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
std::shared_ptr< const Node > make_node(Args &&... args)
std::optional< Rational > exact_rational_value(const NumberNode &number)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
const std::vector< Polynomial< BigInt > > const BigInt ComputationContext & context
@ Rational
Rational numbers
Result< OptionalRationalPolynomial > recognize_rational_polynomial(const SymbolicExpr &expression, const std::string &variable, ComputationContext &context)
__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 & u