diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index dee44a680..50801077f 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -175,6 +175,20 @@ the working digits, or `MathS.Settings.PrecisionErrorZeroRange` where a caller h
still that integer, so `e^(-123.456)` is 0 as it was.
[#1338](https://github.com/asc-community/AngouriMath/issues/1338).
+### An arctangent over a power of `d (1 + i c x)` is integrated under the tangent
+
+**Answers where there were none.** `(a + b atan(c x))^2/(d + i c d x)^2` ran out of time, and so did seven more of
+Rubi's 5.3.4. Under `x = tan(u)/c`, `1 + i tan(u)` is `e^(i u)/cos(u)`, so `x^m (a + b atan(c x))^p/(d (1 ± i c x))^k`
+becomes a polynomial in `u` times exponentials and trigonometric functions, and is now integrated so
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"(a+b*atan(c*x))^2/(d+i*c*d*x)^2".ToEntity().Integrate("x")` | `integral(...)` | 267 characters |
+| `"x*(a+b*atan(c*x))^2/(d+i*c*d*x)^3".ToEntity().Integrate("x")` | `integral(...)` | 671 characters |
+| `"(a+b*atan(c*x))^2/(1+i*c*x)^4".ToEntity().Integrate("x")` | `integral(...)` | 731 characters |
+| `"(a+b*atan(c*x))^3/(d+i*c*d*x)^4".ToEntity().Integrate("x")` | `integral(...)` | 1,202 characters |
+
### A constant or an exponential evaluated at a higher precision than before has all of its digits
**More digits where there were a hundred.** `pi`, `e` and an exponential, evaluated once at one precision, went on
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 059da6cd5..d45ced639 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -29569,6 +29569,70 @@ Piecewise piecewise when piecewise.Cases.Any() => piecewise.Cases.First().Expres
return (alpha / (p0 * slope) * product).InnerSimplified;
}
+ ///
+ /// x^m (a + b atan(c x))^p over a power of d (1 +- i c x), under x = tan(u)/c, where
+ /// 1 + i tan(u) is e^(i u)/cos(u): the integrand in u is
+ /// (a + b u)^p (tan(u)/c)^m d^(-k) e^(-+i k u) cos(u)^k/(c cos(u)^2), a polynomial in u times
+ /// exponentials and trigonometric functions, and the answer is written back at u = atan(c x).
+ ///
+ ///
+ /// 1 + i tan(u) = (cos(u) + i sin(u))/cos(u) holds for every u where the tangent is defined,
+ /// and atan(c x) takes each real x into (-pi/2, pi/2), where it is. Rubi's 5.3.4
+ /// (a + b atan(c x))^2/(d + i c d x)^2 and seven like it ran out of time.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ internal static Entity? SolveAnArctangentOverAPowerOfOnePlusICXUnderTheTangent(Entity expr, Entity.Variable x, bool integrateByParts)
+ {
+ if (!Integration.AnsweringTheQuestionAsked)
+ return null;
+ var (numerator, denominator) = Functions.SingleQuotient.Of(expr);
+ Arctanf? arctangent = null;
+ Entity? rate = null;
+ foreach (var node in numerator.Nodes)
+ if (node is Arctanf found && found.ContainsNode(x))
+ {
+ if (arctangent is not null && arctangent != found)
+ return null;
+ if (!TreeAnalyzer.TryGetPolyLinear(found.Argument, x, out var slope, out var offset) || !Functions.PartialFractions.IsZeroAsAValue(offset))
+ return null;
+ (arctangent, rate) = (found, slope);
+ }
+ if (arctangent is null || rate is null)
+ return null;
+ // Below the bar one power of a linear d (1 + s i c x), s = +-1, and nothing else with x.
+ Entity? linear = null;
+ var k = 0;
+ Entity constant = Number.Integer.One;
+ foreach (var factor in Mulf.LinearChildren(denominator))
+ {
+ if (!factor.ContainsNode(x)) { constant *= factor; continue; }
+ var (b, e) = factor is Powf(var pb, Number.Integer { EInteger: var pe }) && pe.Sign > 0 && pe.CanFitInInt32() ? (pb, pe.ToInt32Unchecked()) : (factor, 1);
+ if (linear is not null)
+ return null;
+ (linear, k) = (b, e);
+ }
+ if (linear is null || !TreeAnalyzer.TryGetPolyLinear(linear, x, out var lSlope, out var lOffset) || Functions.PartialFractions.IsZeroAsAValue(lOffset))
+ return null;
+ // The ratio of slope to constant is +-i c.
+ var ratio = (lSlope / (lOffset * MathS.i * rate)).InnerSimplified;
+ int sign;
+ if (Functions.PartialFractions.IsZeroAsAValue((ratio - 1).InnerSimplified)) sign = 1;
+ else if (Functions.PartialFractions.IsZeroAsAValue((ratio + 1).InnerSimplified)) sign = -1;
+ else return null;
+ var u = Variable.CreateUnique(expr, "u_atan");
+ // Above the bar: a power of x and the function of the arctangent.
+ var above = numerator.Substitute(arctangent, u);
+ if (above.Substitute(x, Number.Integer.Zero).ContainsNode(x))
+ return null;
+ var inU = above.Substitute(x, MathS.Tan(u) / rate)
+ * MathS.Pow(lOffset, Number.Integer.Create(-k)) * MathS.Pow(MathS.e, -sign * k * MathS.i * u) * (k == 2 ? Number.Integer.One : MathS.Pow(MathS.Cos(u), Number.Integer.Create(k - 2)))
+ / (constant * rate);
+ if (Integration.ComputeAsAQuestionOfItsOwn(inU.InnerSimplified, u, integrateByParts) is not { } integrated)
+ return null;
+ var answer = integrated.Substitute(u, arctangent).InnerSimplified;
+ return Functions.PartialFractions.DerivativeDiffersWhereReal(answer, expr, x) ? null : answer;
+ }
+
///
/// A power of a constant multiple of a radicand that a logarithm holds under a root,
/// written over that radicand: acosh(c x) is ln(c x + sqrt(c^2 x^2 - 1)),
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
index ac9d425d0..382365c1e 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
@@ -664,6 +664,9 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
// A sum free of the variable that comes to a number multiplied out, as that number,
// before anything reads a coefficient or an exponent in it: `2 + 2 a - 2 (1 + a)`.
if ((answer = IndefiniteIntegralSolver.SolveByFoldingConstantSumsToTheirNumbers(expr, x, integrateByParts)) is { }) return answer;
+ // An arctangent over a power of d (1 +- i c x), under x = tan(u)/c, where 1 + i tan(u) is
+ // e^(i u)/cos(u): the rules below ran out of time on `(a + b atan(c x))^2/(d + i c d x)^2`.
+ if ((answer = IndefiniteIntegralSolver.SolveAnArctangentOverAPowerOfOnePlusICXUnderTheTangent(expr, x, integrateByParts)) is { }) return answer;
// An exponential of i times an inverse trigonometric function written algebraically, at the
// question asked, before the rules that spent the budget: `e^(3 i atan(a + b x))/x^2` ran out of
// time where, rewritten, it is answered in half a second. It is asked again in its place below.
diff --git a/Sources/Tests/UnitTests/Calculus/AnArctangentOverAPowerOfOnePlusICXIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/AnArctangentOverAPowerOfOnePlusICXIntegralTest.cs
new file mode 100644
index 000000000..034341b47
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/AnArctangentOverAPowerOfOnePlusICXIntegralTest.cs
@@ -0,0 +1,59 @@
+//
+// 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
+{
+ ///
+ /// x^m (a + b atan(c x))^p over a power of d (1 +- i c x), under x = tan(u)/c, where
+ /// 1 + i tan(u) is e^(i u)/cos(u): Rubi's 5.3.4.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class AnArctangentOverAPowerOfOnePlusICXIntegralTest
+ {
+ private static void DifferentiatesBack(string integrand, params (string, double)[] pins)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+
+ var pinned = integral.Substitute("C", 0);
+ Entity original = integrand.ToEntity();
+ foreach (var (name, value) in pins)
+ {
+ pinned = pinned.Substitute(name, value);
+ original = original.Substitute(name, value);
+ }
+ var derivative = pinned.Differentiate("x");
+ foreach (var at in new[] { -2.3, -0.7, 0.4, 1.9 })
+ {
+ var got = derivative.Substitute("x", at).EvalNumerical();
+ var want = original.Substitute("x", at).EvalNumerical();
+ var difference = Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart);
+ var scale = Math.Max(1.0, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart));
+ Assert.True(difference / scale < 1e-8,
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+
+ // d with the sign that keeps the argument real at every sampled x, and |d| below 2/2.3^2
+ // so that the inverse sine and cosine stay inside [-1, 1]; off it the exact checks hold too.
+ [Theory]
+ [InlineData("(a+b*atan(c*x))^2/(d+i*c*d*x)^2")]
+ [InlineData("x*(a+b*atan(c*x))^2/(d+i*c*d*x)^3")]
+ [InlineData("(a+b*atan(c*x))^3/(d+i*c*d*x)^4")]
+ [InlineData("(a+b*atan(c*x))/(d-i*c*d*x)^3")]
+ public void IsAnsweredAndDifferentiatesBack(string integrand)
+ {
+ DifferentiatesBack(integrand, ("a", 0.6), ("b", 1.25), ("c", 0.4), ("d", 1.5));
+ DifferentiatesBack(integrand, ("a", -1.5), ("b", -0.25), ("c", -2), ("d", 0.4));
+ }
+ }
+}