diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index c384c4056..20966b9bd 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -382,6 +382,20 @@ right answers were declined after seconds | `"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 cosine beside a power of `a + i a tan` is read as one of the secant + +**Answers where there were none, and shorter ones.** `sqrt(a + i a tan(x))/(k cos(x))^(3/2)` was declined: +the rule that integrates a power of `a + i a tan(z)` beside a power of the secant as the exponential it is, +where the powers add up to a whole number, read the secant only, and the cosine below the bar is the same +power of it with its sign turned. It reads the cosine too now, the factors kept as they are written; the +rows the rule for any powers answered in `u` before are answered by it instead, and shorter +([#718](https://github.com/asc-community/AngouriMath/issues/718)). + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"sqrt(a + i*a*tan(x))/(k*cos(x))^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | in `e^(i x)`, 533 characters | +| `"(k*cos(x))^(3/2)*sqrt(a + i*a*tan(x))".ToEntity().Integrate("x")` | `integral(...)`; 763 characters on the unreleased master | 172 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 627e98652..6407188ca 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -26935,7 +26935,7 @@ bool ARootOfTheTangent(Entity node) /// internal static Entity? SolveAPowerOfAnImaginaryTangentBesideAPowerOfTheSecant(Entity expr, Entity.Variable x, bool integrateByParts) { - if (!expr.Nodes.Any(node => node is Secantf) || !expr.Nodes.Any(node => node is Tanf)) + if (!expr.Nodes.Any(node => node is Secantf or Cosf) || !expr.Nodes.Any(node => node is Tanf)) return null; Entity? argument = null; var plus = false; @@ -26964,16 +26964,21 @@ bool ARootOfTheTangent(Entity node) (tangentPower, argument, plus) = (power, tangentOf, isPlus); continue; } - var secant = @base switch + // A power of the cosine is one of the secant with the sign of the power turned: + // `sqrt(a + i a tan(z))/(e cos(z))^(3/2)` adds up to 2 as `sqrt(a + i a tan(z)) (e sec(z))^(3/2)` + // does, the factors themselves kept as they are written. + var (trigonometric, turned) = @base switch { - Secantf => @base, - Mulf(var left, Secantf right) when !left.ContainsNode(x) => right, - Mulf(Secantf left, var right) when !right.ContainsNode(x) => left, - _ => null + Secantf => (@base, false), + Cosf => (@base, true), + Mulf(var left, var right) when !left.ContainsNode(x) && right is Secantf or Cosf => (right, right is Cosf), + Mulf(var left, var right) when !right.ContainsNode(x) && left is Secantf or Cosf => (left, left is Cosf), + _ => ((Entity?)null, false) }; - if (secant is not Secantf(var secantOf) || secantPower is not null || argument is not null && argument != secantOf) + var secantOf = trigonometric switch { Secantf(var inner) => inner, Cosf(var inner) => inner, _ => null }; + if (secantOf is null || secantPower is not null || argument is not null && argument != secantOf) return null; - (secantPower, argument) = (power, secantOf); + (secantPower, argument) = (turned ? (power is Number.Rational turnedPower ? -turnedPower : (-power).InnerSimplified) : power, secantOf); } if (tangentPower is null || secantPower is null || argument is null || tangentPower is Number.Integer && secantPower is Number.Integer diff --git a/Sources/Tests/UnitTests/Calculus/ImaginaryTangentBesideTheSecantIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/ImaginaryTangentBesideTheSecantIntegralTest.cs index 24fbbf784..081ee026b 100644 --- a/Sources/Tests/UnitTests/Calculus/ImaginaryTangentBesideTheSecantIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/ImaginaryTangentBesideTheSecantIntegralTest.cs @@ -34,6 +34,8 @@ public sealed class ImaginaryTangentBesideTheSecantIntegralTest [InlineData("(k*sec(c + d*x))^(-4 - n)*(a + i*a*tan(c + d*x))^n")] [InlineData("(k*sec(c + d*x))^(-1 - n)*(a + i*a*tan(c + d*x))^n")] [InlineData("(a + i*a*tan(c + d*x))^n/(k*sec(c + d*x))^n")] + [InlineData("sqrt(a + i*a*tan(x))/(k*cos(x))^(3/2)")] + [InlineData("(k*cos(c + d*x))^(5/2)/sqrt(a + i*a*tan(c + d*x))")] public void AsTheExponentialItIs(string integrand) { var integral = integrand.ToEntity().Integrate("x");