From c4ad9d2f96e07de94043d55e72b5a64dc509cea5 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Tue, 6 Oct 2026 21:40:04 +0000 Subject: [PATCH] An odd power of the secant over a whole power of a + i a tan is integrated in the sum Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 17 ++++++++++++ .../Integration/IndefiniteIntegralSolver.cs | 27 ++++++++++++------- ...BesideAnImaginaryTangentSumIntegralTest.cs | 1 + 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 8bf45eebb..c384c4056 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -365,6 +365,23 @@ quotient of two such linears the sum is `(b - d t^2)^2 + (c t^2 - a)^2`. Rubi's | `"(c + d*tan(x))^(3/2)/(a + b*tan(x))^3".ToEntity().Integrate("x")` | `integral(...)` | the same | | `"1/((a + b*tan(x))^(3/2)*(c + d*tan(x))^(3/2))".ToEntity().Integrate("x")` | `integral(...)`; past a minute on the unreleased master | in the root of the quotient of the two, in a second | +### An odd power of the secant over a whole power of `a + i a tan` is integrated in the sum + +**Answers where there were none.** `sec(x)^5/(a + i a tan(x))^2` was declined: the rule that integrates +a power of the secant beside a power of `a + i a tan` in `u = a + i a tan(z)` left whole powers on both +to the rules for the sine and the cosine, which answer `cos(x)^5/(a + i a tan(x))^3` and +`sec(x)^3/(a + i a tan(x))^4` and not `sec(x)^5/(a + i a tan(x))^2`. It takes an odd power `s` of the +secant over the sum's `n`-th where `s + 2 n = 1`, which in `u` is a whole power of `2 a - u` over the root of `u`. And it checks the antiderivative it finds in `u` on the +path, `u = a + i a t` for a real `t`, where it checked the answer in `x`: the expression in `x` carries a +factor constant on intervals and was large enough that the sampled evaluations could not decide, so +right answers were declined after seconds +([#718](https://github.com/asc-community/AngouriMath/issues/718)). + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"sec(x)^5/(a + i*a*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)` | 2,431 characters | +| `"sec(x)^7/(a + i*a*tan(x))^3".ToEntity().Integrate("x")` | `integral(...)` | 3,774 characters | + ### A power of the secant beside a power of `a + i a tan` is integrated in the sum, whatever the powers **Answers where there were none.** `sec(x)^3 sqrt(a + i a tan(x))` was declined, with the rest of diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index fa6842798..627e98652 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -27079,10 +27079,14 @@ static Entity SumOfThePowers(Entity first, Entity second) || !TreeAnalyzer.TryGetPolyLinear(argument, x, out var slope, out _) || TreeAnalyzer.IsZero(slope)) return null; secantPower = secantPower is Number ? secantPower : secantPower.InnerSimplified; - // Whole powers on both are a rational function of the sine and the cosine, which the - // rules for those answer in a fraction of a second, where in u they ran past five: - // `cos(x)^5/(a + i a tan(x))^3`. - if (sumPower is Number.Integer && secantPower is Number.Integer) + // Whole powers on both are left to the rules for the sine and the cosine, which answer + // `cos(x)^5/(a + i a tan(x))^3` and `sec(x)^3/(a + i a tan(x))^4` in a fraction of a second + // where in u they ran past five -- but for an odd power s of the secant over the sum's n-th + // with s + 2 n = 1. Then u^n (sec(z)^2)^((s - 2)/2) is a whole power of 2 A - u over the root + // of u, which is answered in a second, and `sec(x)^5/(a + i a tan(x))^2` was declined by + // every route but this. + if (sumPower is Number.Integer { EInteger: var whole } && secantPower is Number.Integer { EInteger: var secant } + && !(secant + whole * 2).Equals(EInteger.One)) return null; Entity constantTerm = Number.Integer.Zero; foreach (var term in Sumf.LinearChildren(sum)) @@ -27102,14 +27106,19 @@ static Entity SumOfThePowers(Entity first, Entity second) // The antiderivative in u was found for a real u, and its conditions say so -- a radicand // at least zero -- where u = A + i A tan(z) is not real: kept, they hold nowhere on the // path and the answer has no value at all. The formula is an antiderivative wherever it is - // analytic, so the conditions go, each piecewise taken arm by arm, and an answer is kept - // only where its derivative is the integrand at the sampled points. + // analytic, so the conditions go, each piecewise taken arm by arm, and a formula is kept + // only where its derivative in u is the integrand in u on the path, u = A + i A t for a + // real t, at the sampled points: checked in x, through the factor constant on intervals, + // the expression was large enough that the evaluations could not decide, and right + // answers were declined after seconds. + var onThePath = Variable.CreateUnique(inU + a, "t_path"); + var path = a + MathS.i * a * onThePath; + var integrandOnThePath = inU.Substitute(u, path); foreach (var arm in new[] { 0, -1 }) { var formula = WithoutConditions(inUAnswer, arm); - var answer = expr * formula.Substitute(u, sum) / differentiatesBackTo; - if (Functions.PartialFractions.DerivativeHoldsAtSampledPoints(answer, expr, x)) - return answer; + if (Functions.PartialFractions.HoldsAtSampledPoints(formula.Differentiate(u).Substitute(u, path), integrandOnThePath, onThePath)) + return expr * formula.Substitute(u, sum) / differentiatesBackTo; if (!inUAnswer.Nodes.Any(node => node is Piecewise)) break; } diff --git a/Sources/Tests/UnitTests/Calculus/SecantBesideAnImaginaryTangentSumIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/SecantBesideAnImaginaryTangentSumIntegralTest.cs index 2bd431a9b..0e82d4345 100644 --- a/Sources/Tests/UnitTests/Calculus/SecantBesideAnImaginaryTangentSumIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/SecantBesideAnImaginaryTangentSumIntegralTest.cs @@ -27,6 +27,7 @@ public sealed class SecantBesideAnImaginaryTangentSumIntegralTest [InlineData("(k*cos(x))^(3/2)*sqrt(a + i*a*tan(x))")] [InlineData("cos(x)^9*(a + i*a*tan(x))^(7/2)")] [InlineData("(m*sec(x))^(2/3)*(a + i*a*tan(x))^(5/3)")] + [InlineData("sec(x)^5/(a + i*a*tan(x))^2")] public void InTheSum(string integrand) { var integral = integrand.ToEntity().Integrate("x");