11std::shared_ptr<SymbolicExpr>
make_sin_scaled(
const BigInt& scale,
const std::string& var) {
12 auto v = SymbolicExpr::variable(var);
13 if (scale == BigInt(1)) {
return SymbolicExpr::sin(
v); }
14 auto cx = SymbolicExpr::multiply(SymbolicExpr::number(scale),
v);
15 return SymbolicExpr::sin(cx);
18std::shared_ptr<SymbolicExpr>
make_cos_scaled(
const BigInt& scale,
const std::string& var) {
19 auto v = SymbolicExpr::variable(var);
20 if (scale == BigInt(1)) {
return SymbolicExpr::cos(
v); }
21 auto cx = SymbolicExpr::multiply(SymbolicExpr::number(scale),
v);
22 return SymbolicExpr::cos(cx);
25 return BigInt::ncr(BigInt(degree), BigInt(selected_degree));
31int trig_match_of_var(
const std::shared_ptr<const SymbolicNode>& node,
const std::string& var) {
32 auto fn = std::dynamic_pointer_cast<const FunctionNode>(node);
33 if (!fn) {
return -1; }
34 if (fn->arguments().size() != 1) {
return -1; }
35 auto v = std::dynamic_pointer_cast<const VariableNode>(fn->arguments()[0]);
36 if (!
v ||
v->is_constant() ||
v->name() != var) {
return -1; }
39 case FT::Sin:
return 0;
40 case FT::Cos:
return 1;
41 case FT::Tan:
return 2;
42 case FT::Sec:
return 3;
49 (
context).limits().max_ast_nodes,
"transform");
52 if (!simp) {
return false; }
54 if (!number) {
return false; }
56 if (!degree) {
return false; }
65 const std::string& var,
73 auto pn = std::dynamic_pointer_cast<const PowerNode>(node);
74 if (!pn) {
return false; }
76 if (base_kind < 0) {
return false; }
88 std::vector<std::shared_ptr<const SymbolicNode>> factors;
90 factors =
mul->operands();
95 for (
const auto& f : factors) {
100 if (p > std::numeric_limits<int>::max() - m) {
return false; }
102 }
else if (kind == 1) {
103 if (p > std::numeric_limits<int>::max() - n) {
return false; }
109 if (m == 0 && n == 0) {
return false; }
117 int kind = -1, p = 0;
119 if (kind != 2) {
return false; }
126 int kind = -1, p = 0;
128 if (kind != 3) {
return false; }
134std::shared_ptr<SymbolicExpr> integrate_odd_case(
135 int m,
int n,
const BigInt& scale,
const std::string& var);
136std::shared_ptr<SymbolicExpr> integrate_even_case(
137 int m,
int n,
const BigInt& scale,
const std::string& var);
140 int m,
int n,
const BigInt& scale,
const std::string& var) {
142 if (m < 0 || n < 0) {
return nullptr; }
144 if (m == 0 && n == 0) {
146 return SymbolicExpr::variable(var);
148 if ((m % 2 == 1) || (n % 2 == 1)) {
155 int m,
int n,
const BigInt& scale,
const std::string& var) {
157 if (scale == BigInt(0)) {
return nullptr; }
166 bool peel_sin = (m % 2 == 1);
169 BigInt sign_factor(1);
170 bool u_is_cos =
false;
188 std::vector<std::shared_ptr<const SymbolicNode>> add_terms;
189 for (
int i = 0; i <= k; ++i) {
191 const BigInt alternating_sign((i % 2) == 0 ? 1 : -1);
192 BigInt numerator = sign_factor * alternating_sign * binomial;
193 int u_pow = 2 * i + other_pow + 1;
197 std::shared_ptr<SymbolicExpr> u_to_pow;
201 u_to_pow = SymbolicExpr::power(u_expr, SymbolicExpr::number(u_pow));
205 auto coeff = SymbolicExpr::number(Rational(numerator,
denominator));
206 auto term = SymbolicExpr::multiply(coeff, u_to_pow);
210 if (add_terms.empty()) {
return SymbolicExpr::number(0); }
211 if (add_terms.size() == 1) {
218 int m,
int n,
const BigInt& scale,
const std::string& var) {
220 if ((m % 2 != 0) || (n % 2 != 0)) {
return nullptr; }
228 std::vector<BigInt>
a(K + 1, BigInt(0));
229 for (
int i = 0; i <= p; ++i) {
231 const BigInt alternating_sign((i % 2) == 0 ? 1 : -1);
232 for (
int j = 0; j <= q; ++j) {
234 a[i + j] += alternating_sign * bp * bq;
241 std::vector<std::shared_ptr<const SymbolicNode>> add_terms;
242 for (
int k = 0; k <= K; ++k) {
243 if (
a[k] == 0) {
continue; }
246 if (!inner) {
return nullptr; }
247 auto coeff = SymbolicExpr::number(Rational(
a[k],
denominator));
248 auto term = SymbolicExpr::multiply(coeff, inner);
252 if (add_terms.empty()) {
return SymbolicExpr::number(0); }
253 if (add_terms.size() == 1) {
261 if (n < 0) {
return nullptr; }
262 auto v = SymbolicExpr::variable(var);
270 auto cos_x = SymbolicExpr::cos(
v);
271 auto ln_cos = SymbolicExpr::ln(cos_x);
272 return SymbolicExpr::multiply(SymbolicExpr::number(-1), ln_cos);
277 auto tan_x = SymbolicExpr::tan(
v);
278 std::shared_ptr<SymbolicExpr> tan_pow_term;
280 tan_pow_term = tan_x;
282 tan_pow_term = SymbolicExpr::power(tan_x, SymbolicExpr::number(n - 1));
284 auto first = SymbolicExpr::multiply(
sym_rational(1, n - 1), tan_pow_term);
287 if (!rest) {
return nullptr; }
288 auto neg_rest = SymbolicExpr::multiply(SymbolicExpr::number(-1), rest);
289 return SymbolicExpr::add(first, neg_rest);
294 if (n < 2 || (n % 2) != 0) {
return nullptr; }
297 auto v = SymbolicExpr::variable(var);
298 auto tan_x = SymbolicExpr::tan(
v);
299 auto make_sec_x = [&]() -> std::shared_ptr<SymbolicExpr> {
309 auto sec_x = make_sec_x();
310 std::shared_ptr<SymbolicExpr> sec_pow;
314 sec_pow = SymbolicExpr::power(sec_x, SymbolicExpr::number(n - 2));
318 auto inner = SymbolicExpr::multiply(sec_pow, tan_x);
319 auto first = SymbolicExpr::multiply(
sym_rational(1, n - 1), inner);
323 if (!rest) {
return nullptr; }
324 auto coeff = SymbolicExpr::number(Rational(BigInt(n - 2), BigInt(n - 1)));
325 auto second = SymbolicExpr::multiply(coeff, rest);
327 return SymbolicExpr::add(first, second);
332Result<std::optional<detail::IntegralParts>> Integrator::try_trig_combination(
333 const SymbolicExpr& expr,
const std::string& var,
334 ComputationContext& computation,
int) {
335 std::shared_ptr<SymbolicExpr> primitive;
337 if (extract_sin_cos_powers(expr, var, m, n, computation)) {
338 if (m < 0 || n < 0 || n > 8 || m > 8 - n) {
339 return std::optional<detail::IntegralParts>{};
345 if (power < 2 || power > 8) {
return std::optional<detail::IntegralParts>{}; }
348 if (power < 2 || power > 8 || power % 2 != 0) {
349 return std::optional<detail::IntegralParts>{};
354 if (!primitive) {
return std::optional<detail::IntegralParts>{}; }
355 return std::optional<detail::IntegralParts>{{*primitive, zero_}};
std::shared_ptr< SymbolicExpr > integrate_sec_power(int n, const std::string &var)
int trig_match_of_var(const std::shared_ptr< const SymbolicNode > &node, const std::string &var)
std::shared_ptr< SymbolicExpr > integrate_odd_case(int m, int n, const BigInt &scale, const std::string &var)
bool extract_sin_cos_powers(const SymbolicExpr &expr, const std::string &var, int &m_out, int &n_out, ComputationContext &context)
std::shared_ptr< SymbolicExpr > integrate_even_case(int m, int n, const BigInt &scale, const std::string &var)
bool extract_tan_power(const SymbolicExpr &expr, const std::string &var, int &n_out, ComputationContext &context)
BigInt trig_binomial(int degree, int selected_degree)
bool trig_extract_nonneg_int(const std::shared_ptr< const SymbolicNode > &exp_node, int °ree_out, ComputationContext &context)
std::shared_ptr< SymbolicExpr > make_sin_scaled(const BigInt &scale, const std::string &var)
std::shared_ptr< SymbolicExpr > integrate_tan_power(int n, const std::string &var)
bool extract_sec_power(const SymbolicExpr &expr, const std::string &var, int &n_out, ComputationContext &context)
std::shared_ptr< SymbolicExpr > integrate_sin_m_cos_n(int m, int n, const BigInt &scale, const std::string &var)
std::shared_ptr< SymbolicExpr > make_cos_scaled(const BigInt &scale, const std::string &var)
bool trig_extract_factor(const std::shared_ptr< const SymbolicNode > &node, const std::string &var, int &kind_out, int &power_out, ComputationContext &context)
std::shared_ptr<::LMCAS::SymbolicExpr > make_expression_ptr(SymbolicNodePtr root)
const SymbolicNodePtr & node(const ::LMCAS::SymbolicExpr &expression) noexcept
inline ::LMCAS::SymbolicExpr expression_from_node(SymbolicNodePtr root)
std::shared_ptr< const Node > make_node(Args &&... args)
SymbolicNodePtr normalize_node(const SymbolicNodePtr &node, RewriteBudget &budget, const FactsQuery &facts, Domain domain)
__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)
std::shared_ptr< SymbolicExpr > sym_rational(const BigInt &numerator, const BigInt &denominator)
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string const std::shared_ptr< SymbolicExpr > & a
std::optional< int > integration_bounded_exponent(const NumberNode &number, int minimum_exponent, int maximum_exponent)
const ExprPtr & denominator
__attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) VectorCalculusExprResult curve_integral_scalar_checked(const std __attribute__((visibility("default"))) std const VectorField const std::string & t