From f82d1968479cdc3e8706094edeffeab969c47259 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Mon, 14 Sep 2026 00:07:16 +0000 Subject: [PATCH] An even power of the secant, cosine, sine or cosecant is written as the rational function of the tangent it is before the tangent substitution tests its rewriting Timofeev's `(sec^2 - 3 tan sqrt(4 sec^2 + 5 tan^2))/(sin^2 (4 sec^2 + 5 tan^2)^(3/2))` is `((1 + u^2) - 3u sqrt(4 + 9u^2))/(u^2 (4 + 9u^2)^(3/2))` under `u = tan(x)`, two terms the algebraic partial fractions and the rational integrator answer between them, and was declined: the tangent substitution replaces `tan(x)` and asks whether an `x` survives, and the secant and the sine survived. Its answer was pinned as declined-or-right, since the general substitution had once answered it wrongly on half the line by taking `sqrt(.../cos^2)` for `.../cos`. `sec^2 = 1 + tan^2`, `cos^2 = 1/(1 + tan^2)`, `sin^2 = tan^2/(1 + tan^2)` and `csc^2 = (1 + tan^2)/tan^2`, exactly and wherever both sides are defined, and so for every even power; the tangent substitution writes them so before its test, under a root or not, since the identities hold there too. An odd power is not a function of the tangent -- its sign is not -- and is left to survive and decline as before. Rubi sample: +1 (Timofeev 596), 0 wrong, 0 timeouts. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- .../Integration/IndefiniteIntegralSolver.cs | 22 +++++++++++++++++++ .../Calculus/ParityUnderASubstitutionTest.cs | 7 +++--- .../TangentSubstitutionIntegralTest.cs | 15 +++++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index a0e4ae565..dfe3e5b4c 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -3494,6 +3494,28 @@ node is Cotanf(var cotangentArgument) if (!expr.ContainsNode(tangent)) return null; + // An even power of the secant, cosine, sine or cosecant of x is a rational function + // of the tangent, exactly and wherever it is defined: `sec^2 = 1 + tan^2`, + // `cos^2 = 1/(1 + tan^2)`, `sin^2 = tan^2/(1 + tan^2)`. Timofeev's + // `(sec^2 - 3 tan sqrt(4 sec^2 + 5 tan^2))/(sin^2 (4 sec^2 + 5 tan^2)^(3/2))` is + // `((1 + u^2) - 3u sqrt(4 + 9u^2))/(u^2 (4 + 9u^2)^(3/2))` under the tangent, and was + // declined for the secant and the sine that survived the rewriting. An odd power is + // not a function of the tangent -- its sign is not -- and is left, to survive and + // decline as before. + var secantSquared = 1 + MathS.Sqr(tangent); + expr = expr.Replace(node => node switch + { + Powf(Secantf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0 + => MathS.Pow(secantSquared, even.EInteger.ToInt32Checked() / 2), + Powf(Cosf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0 + => MathS.Pow(secantSquared, -(even.EInteger.ToInt32Checked() / 2)), + Powf(Sinf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0 + => MathS.Pow(MathS.Sqr(tangent) / secantSquared, even.EInteger.ToInt32Checked() / 2), + Powf(Cosecantf(var a), Number.Integer even) when a == x && even.EInteger.IsEven && even.EInteger.Sign > 0 + => MathS.Pow(secantSquared / MathS.Sqr(tangent), even.EInteger.ToInt32Checked() / 2), + _ => node, + }); + var uSub = Variable.CreateUnique(expr, "u_tan"); var inU = expr.Substitute(tangent, uSub); if (inU.ContainsNode(x)) diff --git a/Sources/Tests/UnitTests/Calculus/ParityUnderASubstitutionTest.cs b/Sources/Tests/UnitTests/Calculus/ParityUnderASubstitutionTest.cs index 8eaf7bfb1..2f94077df 100644 --- a/Sources/Tests/UnitTests/Calculus/ParityUnderASubstitutionTest.cs +++ b/Sources/Tests/UnitTests/Calculus/ParityUnderASubstitutionTest.cs @@ -97,15 +97,16 @@ public void TheOtherFunctionsAreWrittenAsSineAndCosine(string integrand) /// simplification the substitution runs takes sqrt(.../cos(x)^2) as /// .../cos(x), its value where the cosine is positive and its negative /// elsewhere, and Timofeev's was answered wrongly on half the line that way. Declined - /// or right on both sides, never wrong. + /// or right on both sides, never wrong -- and answered now, by the tangent + /// substitution, which writes its even powers of the secant and the sine as the + /// rational functions of the tangent they are, exactly. /// [Theory] [InlineData("(sec(x)^2 - 3*sqrt(4*sec(x)^2 + 5*tan(x)^2)*tan(x))/(sin(x)^2*(4*sec(x)^2 + 5*tan(x)^2)^(3/2))")] public void AnOddComplementUnderARootIsNotWrittenSo(string integrand) { var integral = integrand.ToEntity().Integrate("x"); - if (integral.Stringize().Contains("integral(")) - return; // declined is a legitimate verdict; a wrong answer is not + Assert.DoesNotContain("integral(", integral.Stringize()); DifferentiatesBack(integrand, new[] { -2.6, -2.0, -0.4, 0.4, 2.0, 2.6 }); } diff --git a/Sources/Tests/UnitTests/Calculus/TangentSubstitutionIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/TangentSubstitutionIntegralTest.cs index 53ea52d82..a9ec46c42 100644 --- a/Sources/Tests/UnitTests/Calculus/TangentSubstitutionIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/TangentSubstitutionIntegralTest.cs @@ -82,6 +82,21 @@ private static void DifferentiatesBack(string integrand) [InlineData("tan(x)/(1 + tan(x)^2)")] public void AFunctionOfTheTangentAlone(string integrand) => DifferentiatesBack(integrand); + /// + /// An even power of the secant, cosine, sine or cosecant is a rational function of the + /// tangent, exactly and wherever it is defined, and is written as one before the test: + /// sec^2 = 1 + tan^2, cos^2 = 1/(1 + tan^2), sin^2 = tan^2/(1 + tan^2). + /// Timofeev's is ((1 + u^2) - 3u sqrt(4 + 9u^2))/(u^2 (4 + 9u^2)^(3/2)) under the + /// tangent, and was declined for the secant and the sine that survived. An odd power + /// is not a function of the tangent, and is left to decline as before. + /// + [Theory] + [InlineData("sec(x)^2*sqrt(tan(x))")] + [InlineData("sin(x)^2/(1 + tan(x))")] + [InlineData("csc(x)^4*tan(x)^(3/2)")] + [InlineData("(sec(x)^2 - 3*sqrt(4*sec(x)^2 + 5*tan(x)^2)*tan(x))/(sin(x)^2*(4*sec(x)^2 + 5*tan(x)^2)^(3/2))")] + public void AnEvenPowerOfTheOthersIsWrittenInTheTangent(string integrand) => DifferentiatesBack(integrand); + /// /// A power of the tangent, which the rewrite turns into an improper rational /// function — u^2/(1 + u^2) and u^3/(1 + u^2). These were declined while