diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index b962bfd10..963779013 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -793,6 +793,23 @@ wherever the cosine is negative; they are answered with the rest now
| `"sqrt(c*sec(x))*sqrt(a + i*a*tan(x))".ToEntity().Integrate("x")` | `integral(...)` | the integrand times an antiderivative in `e^(i x/2)` over its derivative |
| `"(c*sec(x))^(5/2)/(a + i*a*tan(x))^(5/2)".ToEntity().Integrate("x")` | `integral(...)` | the integrand times a power of `e^(i x)` |
+### A rational function of the tangent beside a power of `a + i a tan` is integrated in that sum
+
+**Answers where there were none.** `(A + B tan(c + d x))/sqrt(a + i a tan(c + d x))` and the rest of
+Rubi's 4.3.3.1 with a whole power of the tangent or cotangent beside `A + B tan` over a power of
+`a + i a tan` ran past the budget, whole powers and half-odd ones alike. With `S = a ± i a tan(z)`,
+`tan(z)` is `(S - a)/(± i a)` and `dz = c dS/(S (S - 2a))`, so each is a rational function of `S`
+beside a power of it, whose factors `S`, `S - 2a` and `S - a` have no imaginary root. Beside a
+second such sum, `q - i q tan(z)`, which is linear in `S`, the sum under a power that is not whole is
+the variable: `(a + i a tan(z))/(q - i q tan(z))^(3/2)`, from 4.3.2.1, ran past the budget as well
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"tan(c + d*x)^2*(k + q*tan(c + d*x))/sqrt(a + i*a*tan(c + d*x))".ToEntity().Integrate("x")` | `integral(...)` | powers of `sqrt(a + i a tan(c + d x))` and, piecewise in the sign of `a`, an arctangent or a logarithm of it |
+| `"cot(c + d*x)^2*(k + q*tan(c + d*x))/(a + i*a*tan(c + d*x))^4".ToEntity().Integrate("x")` | `integral(...)` | powers and logarithms of `a + i a tan(c + d x)`, of `a - i a tan(c + d x)` and of `tan(c + d x)` |
+| `"(a + i*a*tan(c + d*x))/(q - i*q*tan(c + d*x))^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | `-2 i a (q - i q tan(c + d x))^(-3/2)/(3d)`, written longer |
+
### A rational function with complex coefficients is integrated through its real and imaginary parts
**Answers where there were none.** `1/((1 + i x)^2 (1 + x^2))` was declined: the rational
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 10e0310fe..5bc58433b 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -25289,6 +25289,145 @@ static bool IsAWholeNumberOfSteps(ERational difference)
return Integration.ComputeAsAQuestionOfItsOwn(expanded.Expand().InnerSimplified, x, integrateByParts);
}
+ ///
+ /// A rational function of tan(z) beside a power of S = a + c tan(z) with
+ /// c = ±i a, below the bar or not whole, integrated in S: tan(z) is
+ /// (S - a)/c, and since c^2 = -a^2, dS/dz = c sec(z)^2 = S (S - 2a)/c, so
+ /// dz = c dS/(S (S - 2a)).
+ ///
+ ///
+ ///
+ /// Rubi's cot(c + d x)^3 (A + B tan(c + d x))/(a + i a tan(c + d x))^2 and the rest of
+ /// its 4.3.3.1 with a power of the tangent beside (A + B tan) over a power of
+ /// a + i a tan ran past the budget, whole powers and half-odd ones alike: under
+ /// u = tan(z) each is a rational function over 1 + i u and 1 - i u with
+ /// symbols in every coefficient. In S the factors are S, S - 2a and,
+ /// from a cotangent, S - a, with no imaginary root among them, and the same
+ /// integrands are a second or two; a half-odd power of S is a root of a linear.
+ ///
+ ///
+ /// Exact wherever the integrand is defined: the substitution is the identity
+ /// sec(z)^2 = 1 + tan(z)^2 read in S, and the power of S is the
+ /// integrand's own. Only whole powers of the tangent and cotangent of z beside it,
+ /// and nothing else in x; a base standing only to positive whole powers is a polynomial in
+ /// the tangent, which the rules for those answer.
+ ///
+ ///
+ /// Beside a second such sum of the same argument, q - i q tan(z), which is linear in
+ /// the first, the one under a power that is not whole is the variable and the other a whole
+ /// power of a linear in it: (a + i a tan(z))/(q - i q tan(z))^(3/2), Rubi's 4.3.2.1,
+ /// ran past the budget too.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ ///
+ internal static Entity? SolveInTheImaginarySumOfAConstantAndATangent(Entity expr, Entity.Variable x, bool integrateByParts)
+ {
+ var sums = new List<(Entity Base, Entity Constant, Entity Coefficient, Entity Argument)>();
+ foreach (var node in expr.Nodes)
+ {
+ if (node is not (Sumf or Minusf) || !node.ContainsNode(x) || sums.Any(found => found.Base == node))
+ continue;
+ Entity sum = Number.Integer.Zero;
+ Entity? factor = null, inner = null;
+ var read = true;
+ foreach (var term in Sumf.LinearChildren(node))
+ {
+ if (!term.ContainsNode(x))
+ {
+ sum = sum == Number.Integer.Zero ? term : sum + term;
+ continue;
+ }
+ if (factor is not null)
+ {
+ read = false;
+ break;
+ }
+ Entity product = Number.Integer.One;
+ foreach (var piece in Mulf.LinearChildren(term))
+ {
+ if (piece is Tanf(var y) && inner is null)
+ inner = y;
+ else if (!piece.ContainsNode(x))
+ product = product == Number.Integer.One ? piece : product * piece;
+ else
+ {
+ read = false;
+ break;
+ }
+ }
+ if (!read || inner is null)
+ {
+ read = false;
+ break;
+ }
+ factor = product;
+ }
+ if (!read || factor is null || inner is null || sum == Number.Integer.Zero)
+ continue;
+ var ratio = Functions.PartialFractions.Bare((factor / sum).InnerSimplified);
+ if (ratio.Evaled is not Number.Complex)
+ ratio = Functions.PartialFractions.Bare(ratio.Simplify());
+ if (ratio.Evaled != MathS.i.Evaled && ratio.Evaled != (-MathS.i).Evaled)
+ continue;
+ sums.Add((node, sum, factor, inner));
+ }
+ // Two such sums, `a + i a tan(z)` and `c - i c tan(z)`, are each linear in the other: in
+ // the one under a power that is not whole the other is a whole power of a linear, where
+ // in the other it would be the root of one. Where both or neither are, declined.
+ bool NotWhole(Entity sum) => expr.Nodes.Any(node => node is Powf(var b, Number.Rational p) && b == sum && p is not Number.Integer);
+ var chosen = sums.Count switch
+ {
+ 1 => sums[0],
+ 2 when NotWhole(sums[0].Base) != NotWhole(sums[1].Base) => NotWhole(sums[0].Base) ? sums[0] : sums[1],
+ _ => default,
+ };
+ var (@base, constant, coefficient, argument) = chosen;
+ if (@base is null || constant is null || coefficient is null || argument is null
+ || !TreeAnalyzer.TryGetPolyLinear(argument, x, out var rate, out _) || rate.ContainsNode(x)
+ || rate.Evaled is Number.Complex { IsZero: true })
+ return null;
+ // Below the bar, or to a power that is not whole: a positive whole power alone is a
+ // polynomial in the tangent.
+ var below = Functions.SingleQuotient.Of(Functions.SingleQuotient.Combine(expr)).Denominator;
+ if (!below.Nodes.Contains(@base)
+ && !expr.Nodes.Any(node => node is Powf(var b, Number.Rational p) && b == @base && p is not Number.Integer))
+ return null;
+ var s = Variable.CreateUnique(expr, "s_imaginary_tangent");
+ var tangent = (s - constant) / coefficient;
+ // The other sum, `q + c' tan(z)`, written as the linear in `S` it is, `(c'/c) (S - r)`
+ // for `r = a - q c/c'`, its root spelled `2 a` where it is that: there it cancels the
+ // `S - 2a` of `dz` as written, where `q + c' (S - a)/c` cancelled nothing, and the pole
+ // it left made `(a + i a tan(z))^2/sqrt(q - i q tan(z))` fourteen thousand characters.
+ Entity? other = null, otherInS = null;
+ if (sums.Count == 2)
+ {
+ var (otherBase, otherConstant, otherCoefficient, _) = sums[0].Base == @base ? sums[1] : sums[0];
+ var ratio = Functions.PartialFractions.InLowestTermsOverTheSymbols(otherCoefficient / coefficient);
+ var root = Functions.PartialFractions.InLowestTermsOverTheSymbols(constant - otherConstant * coefficient / otherCoefficient);
+ if (Functions.PartialFractions.IsZeroAsAValue(root - 2 * constant))
+ root = 2 * constant;
+ (other, otherInS) = (otherBase, ratio * (s - root));
+ }
+ var rewritten = expr.Replace(node => node == @base ? s : other is not null && node == other ? otherInS! : node).Replace(node => node switch
+ {
+ Tanf(var y) when y == argument => tangent,
+ Cotanf(var y) when y == argument => 1 / tangent,
+ _ => node,
+ });
+ if (rewritten.ContainsNode(x))
+ return null;
+ // No power that is not whole but of S itself: a root of the tangent is a root of
+ // `(S - a)/c` with `c` imaginary, and taken apart over the constant it changed its
+ // branch -- `cot(z)^(3/2) (A + B tan(z))/(a + i a tan(z))^2` and `tan(z)^(8/3)/(a + i a tan(z))`
+ // came back wrong at every point.
+ if (rewritten.Nodes.Any(node => node is Powf(var radicand, var power) && power is not Number.Integer && radicand != s))
+ return null;
+ var inS = (rewritten * coefficient / (s * (s - 2 * constant)) / rate).InnerSimplified;
+ if (Integration.ComputeAsAQuestionOfItsOwn(inS, s, integrateByParts) is not { } inTermsOfS)
+ return null;
+ return inTermsOfS.Substitute(s, @base);
+ }
+
///
/// A + i A tan(z) is A e^(i z)/cos(z), and A + i A cot(z) is
/// i A e^(-i z)/sin(z) -- exactly, wherever the tangent is defined, since
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
index 61702adbe..b7cf7cf7c 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
@@ -675,6 +675,8 @@ private static Entity Normalized(Entity expr, Entity.Variable x) =>
// product and takes it apart, and so answers (c sec)^(5/2)/(a + i a tan)^(5/2) with the
// wrong constant wherever the cosine is negative.
if ((answer = IndefiniteIntegralSolver.SolveAPowerOfAnImaginaryTangentBesideAPowerOfTheSecant(expr, x, integrateByParts)) is { }) return answer;
+ // A rational function of the tangent beside a power of a + i a tan(z), in that sum.
+ if ((answer = IndefiniteIntegralSolver.SolveInTheImaginarySumOfAConstantAndATangent(expr, x, integrateByParts)) is { }) return answer;
if ((answer = IndefiniteIntegralSolver.SolveByWritingAnImaginaryTangentAsAnExponential(expr, x, integrateByParts)) is { }) return answer;
// And `A cos(z) + i A sin(z)`, which is `A e^(i z)`, where no rotation is real.
if ((answer = IndefiniteIntegralSolver.SolveByWritingAnImaginarySumOfACosineAndASineAsAnExponential(expr, x, integrateByParts)) is { }) return answer;
diff --git a/Sources/Tests/UnitTests/Calculus/RationalInTheTangentBesideAnImaginarySumIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/RationalInTheTangentBesideAnImaginarySumIntegralTest.cs
new file mode 100644
index 000000000..32b0ad7ba
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/RationalInTheTangentBesideAnImaginarySumIntegralTest.cs
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2019-2026 Angouri.
+// AngouriMath is licensed under MIT.
+// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
+// Website: https://am.angouri.org.
+//
+
+using System;
+using AngouriMath.Extensions;
+using Xunit;
+
+namespace AngouriMath.Tests.Calculus
+{
+ ///
+ /// A rational function of tan(z) beside a power of S = a ± i a tan(z), integrated
+ /// in S, where dz = c dS/(S (S - 2a)): the factors are S, S - 2a and
+ /// S - a, with no imaginary root among them. Beside q - i q tan(z), a linear in
+ /// S, the sum under a power that is not whole is the variable. Rubi's 4.3.3.1 and 4.3.2.1.
+ /// #718
+ ///
+ /// Compared as complex numbers, the integrand being complex.
+ [Trait("Area", "Calculus")]
+ public sealed class RationalInTheTangentBesideAnImaginarySumIntegralTest
+ {
+ [Theory]
+ [InlineData("cot(c + d*x)^3*(k + q*tan(c + d*x))/(a + i*a*tan(c + d*x))")]
+ [InlineData("cot(c + d*x)*(k + q*tan(c + d*x))/(a + i*a*tan(c + d*x))^2")]
+ [InlineData("tan(c + d*x)^2*(k + q*tan(c + d*x))/sqrt(a + i*a*tan(c + d*x))")]
+ [InlineData("(k + q*tan(c + d*x))/(a - i*a*tan(c + d*x))^(3/2)")]
+ [InlineData("cot(c + d*x)^2*(k + q*tan(c + d*x))/(a + i*a*tan(c + d*x))^4")]
+ [InlineData("(a + i*a*tan(c + d*x))/(q - i*q*tan(c + d*x))^(3/2)")]
+ [InlineData("sqrt(q - i*q*tan(c + d*x))/(a + i*a*tan(c + d*x))")]
+ [InlineData("(a + i*a*tan(c + d*x))^2/sqrt(q - i*q*tan(c + d*x))")]
+ public void IsIntegratedInTheSum(string integrand)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("c", 0.4).Substitute("d", 1.1)
+ .Substitute("k", 1.1).Substitute("q", 0.6);
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ foreach (var at in new[] { -1.1, -0.6, 0.3, 0.9 })
+ {
+ var want = original.Substitute("x", at).EvalNumerical();
+ var got = derivative.Substitute("x", at).EvalNumerical();
+ Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
+ < 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+ }
+}