From 181d08aede422ca848a8528913fbc6440094183a Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Mon, 5 Oct 2026 10:39:10 +0000 Subject: [PATCH] A root over a number times 1 + i tan(z) is integrated as it is over a + i a tan(z) Under the tangent, 1 + i u beside 1 + u^2 shares the root u = i with it, and the root was taken out first only where a symbol stood below the bar; with numbers alone the split over the rationals and i was left to answer it, which it does for a polynomial above the bar and not for a root. sqrt(c + d tan(x))/(1 + i tan(x)) was declined where sqrt(c + d tan(x))/(a + i a tan(x)) is answered. The root is taken out beside anything above the bar that is not a polynomial now. Part of #1788. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 15 +++++++++++++++ .../Integration/IndefiniteIntegralSolver.cs | 15 ++++++++++----- .../ComplexCoefficientRationalIntegralTest.cs | 14 ++++++++++++++ 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 391832803..f982e10eb 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -572,6 +572,21 @@ and the two together are a polynomial in `e^(i z)` and its reciprocal, multiplie | `"sqrt(tan(c + d*x))*(A + B*tan(c + d*x))/(a + i*a*tan(c + d*x))".ToEntity().Integrate("x")` | `integral(...)` | arctangents and logarithms of `sqrt(tan(c + d x))` | | `"(a + i*a*tan(c + d*x))^2*(A + B*tan(c + d*x))/(q - i*q*tan(c + d*x))^4".ToEntity().Integrate("x")` | `integral(...)` | a sum of multiples of `e^(k i (c + d x))` | +### A root over a number times `1 + i tan(z)` is integrated as it is over `a + i a tan(z)` + +**Answers where there were none.** `sqrt(c + d tan(x))/(1 + i tan(x))` was declined, where +`sqrt(c + d tan(x))/(a + i a tan(x))` is answered. Under the tangent `1 + i u` beside `1 + u^2` shares +the root `u = i` with it, and the root was taken out first, as `i (u - i)^2 (u + i)`, only where a symbol +stood below the bar: with numbers alone the split over the rationals and `i` was left to answer it, +which it does for a polynomial above the bar and not for a root. The root is taken out beside anything +above the bar that is not a polynomial now +([#1788](https://github.com/asc-community/AngouriMath/issues/1788)). + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"sqrt(c + d*tan(x))/(1 + i*tan(x))".ToEntity().Integrate("x")` | `integral(...)` | arctangents and logarithms of `sqrt(c + d tan(x))` | +| `"(c + d*tan(x))^(3/2)/(1 + i*tan(x))".ToEntity().Integrate("x")` | `integral(...)` | the same, with a multiple of the root | + ### A polynomial over a power of one linear with a symbol in it is written in powers of the linear **Answers where there were none.** `t^9/(a + b t)^8` is a polynomial and eight powers of `1/(a + b t)`, diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index 838463566..6b4fcf2a8 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -782,7 +782,7 @@ is var (multiple, leftover) // `1/((a + i a tan(x)) (c + d tan(x)))`. The quadratic is written over the linears of // its roots and the shared one taken as one power, coprime and squarefree for the // splits below. - if (OverAComplexRootSharedWithAQuadratic(denominator, x) is { } overTheSharedRoot + if (OverAComplexRootSharedWithAQuadratic(numerator, denominator, x) is { } overTheSharedRoot && (SolveByPartialFractions(numerator / overTheSharedRoot, x, integrateByParts) ?? Integration.ComputeIndefiniteIntegral(numerator / overTheSharedRoot, x, integrateByParts)) is { } overTheComplexRoot) return overTheComplexRoot; @@ -14157,11 +14157,16 @@ private static bool IsASumOfMonomials(Entity expr, Entity.Variable x) /// where no quadratic shares such a root. (1 + i x)(1 + x^2) is /// i (x - i)^2 (x + i). /// - private static Entity? OverAComplexRootSharedWithAQuadratic(Entity denominator, Entity.Variable x) + private static Entity? OverAComplexRootSharedWithAQuadratic(Entity numerator, Entity denominator, Entity.Variable x) { - // With numbers only, the split over the rationals and the imaginary unit answers it as - // it is written. - if (!denominator.Vars.Any(symbol => symbol != x)) + // With numbers only below the bar and a polynomial above it, the split over the + // rationals and the imaginary unit answers it as it is written. Not with a root above + // it: `sqrt(c + d u)/((1 + i u)(1 + u^2))`, which the tangent substitution makes of + // `sqrt(c + d tan(x))/(1 + i tan(x))`, is a question for the substitution in the root, + // and in its variable the shared root is a quadratic beside a quartic, which nothing + // reads; with `a + i a u` for `1 + i u` it was answered, and with the number declined. + // https://github.com/asc-community/AngouriMath/issues/1788 + if (!denominator.Vars.Any(symbol => symbol != x) && TreeAnalyzer.TryGetPolynomial(numerator, x, out _)) return null; var written = new List<(Entity Base, EInteger Power)>(); Entity constant = Number.Integer.One; diff --git a/Sources/Tests/UnitTests/Calculus/ComplexCoefficientRationalIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/ComplexCoefficientRationalIntegralTest.cs index ce0e81b9a..1d51d9ba6 100644 --- a/Sources/Tests/UnitTests/Calculus/ComplexCoefficientRationalIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/ComplexCoefficientRationalIntegralTest.cs @@ -96,5 +96,19 @@ public void AnImaginaryMobiusPowerIsSettled(string integrand) return; DifferentiatesBack(integrand); } + + /// + /// A root above the bar and numbers below it: under the tangent 1 + i u beside + /// 1 + u^2 shares the root u = i with it, and that was taken out only where a + /// symbol stood below the bar, so a + i a tan(x) was answered and + /// 1 + i tan(x) declined. + /// https://github.com/asc-community/AngouriMath/issues/1788 + /// + [Theory] + [InlineData("sqrt(c + d*tan(x))/(1 + i*tan(x))")] + [InlineData("sqrt(c + d*tan(x))/(2 + 2*i*tan(x))")] + [InlineData("sqrt(c + d*tan(x))/(1 - i*tan(x))")] + [InlineData("(c + d*tan(x))^(3/2)/(1 + i*tan(x))")] + public void ARootOverANumberTimesAnImaginaryTangentSum(string integrand) => DifferentiatesBack(integrand); } }