diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 3547f0dd3..62e2ea2ab 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -302,6 +302,24 @@ rules' already
| `"asin(sqrt(1 + x) - sqrt(x))".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative in `arcsin(sqrt(1 + x) - sqrt(x))` |
| `"x^3*atan(-sqrt(x)+sqrt(1+x))".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative in the arctangent |
+### A sum of two squares below the bar, beside a repeated factor, is split over its conjugates
+
+**Answers where there were none.** `(c + d tan(x))^(3/2)/(a + b tan(x))^2` was declined in 2.5.0 and ran
+past two minutes since. Under `u = tan(x)` and `t = sqrt(c + d u)` the `1 + u^2` the tangent leaves is
+`(t^2 - c)^2 + d^2`, a quartic beside the square of `a d + b (t^2 - c)`, and the Hermite reduction
+solved for the numerators over it with the symbols in every entry. A written sum of two squares
+`P^2 + Q^2`, the greater of their degrees two, beside a repeated factor, is `(P - i Q)(P + i Q)` below
+the bar now, and over those every factor is one the split by residues reads -- under a root of the
+quotient of two such linears the sum is `(b - d t^2)^2 + (c t^2 - a)^2`. Rubi's 4.3.2.1
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"(c + d*tan(x))^(3/2)/(a + b*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)`; past two minutes on the unreleased master | arctangents and logarithms of `sqrt(c + d tan(x))`, in two seconds |
+| `"(c + d*tan(x))^(5/2)/(a + b*tan(x))^2".ToEntity().Integrate("x")` | `integral(...)` | the same |
+| `"(c + d*tan(x))^(3/2)/(a + b*tan(x))^3".ToEntity().Integrate("x")` | `integral(...)` | the same |
+| `"1/((a + b*tan(x))^(3/2)*(c + d*tan(x))^(3/2))".ToEntity().Integrate("x")` | `integral(...)`; past a minute on the unreleased master | in the root of the quotient of the two, in a second |
+
### A function of `x^n` for a symbolic `n` beside a power of `x` is integrated in a power of `x`
**Answers where there were none.** `x^(-1 + 4n)/(a + b x^n + c x^(2n))` and the rest of Rubi's
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 31ec42351..a5964c8bd 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -847,6 +847,19 @@ is var (multiple, leftover)
?? Integration.ComputeIndefiniteIntegral(inY, y, integrateByParts)) is { } inTheShiftedVariable)
return inTheShiftedVariable.Substitute(y, (x + shift).InnerSimplified);
+ // A written factor that is a sum of two squares, `P^2 + Q^2` with the greater of their
+ // degrees two, beside a repeated factor: it is `(P - i Q)(P + i Q)`, and over those two
+ // the split by residues above reads every factor. `1 + u^2` beside a root of a
+ // linear is `(t^2 - c)^2 + d^2` under `t = sqrt(c + d u)`, a quartic nothing splits, and
+ // the Hermite reduction below solved for its numerators with the symbols in every entry:
+ // `(c + d tan(x))^(3/2)/(a + b tan(x))^2` ran past two minutes. Once: what this writes
+ // has no such factor left.
+ if (Mulf.LinearChildren(denominator).Any(f => f.ContainsNode(x) && f is Powf(_, Number.Integer { EInteger.Sign: > 0 } e) && e != Number.Integer.One)
+ && OverTheConjugatesOfASumOfTwoSquares(denominator, x) is { } overTheConjugates
+ && (SolveByPartialFractions(numerator / overTheConjugates, x, integrateByParts)
+ ?? Integration.ComputeIndefiniteIntegral(numerator / overTheConjugates, x, integrateByParts)) is { } overConjugates)
+ return overConjugates;
+
// A denominator with a written repeated factor takes the Hermite reduction first:
// the rational part of the answer in one linear solve, and what is left is a proper
// fraction over a squarefree denominator for the splits below. `(1 + x^2)/(x (1 + x^3)^2)`
@@ -14363,6 +14376,43 @@ private static bool IsASumOfMonomials(Entity expr, Entity.Variable x)
return changed ? product : null;
}
+ ///
+ /// with every written factor P^2 + Q^2, P and
+ /// Q polynomials in the greater of whose degrees is two, written
+ /// as (P - i Q)(P + i Q), with its power; where there is none,
+ /// or where nothing in the quotient is a symbol: with numbers alone the split over the reals
+ /// reads a biquadratic as it is. Not of the first degree: (a + b x)^2 + k^2 is a
+ /// quadratic every rule reads, by an arctangent.
+ ///
+ private static Entity? OverTheConjugatesOfASumOfTwoSquares(Entity denominator, Entity.Variable x)
+ {
+ static int? DegreeOfAPolynomial(Entity expr, Entity.Variable x)
+ => !expr.ContainsNode(x) ? 0
+ : TreeAnalyzer.TryGetPolynomial(expr, x, out var read) && read.Count > 0 && read.Values.All(coefficient => !coefficient.ContainsNode(x))
+ && read.Keys.All(power => power.Sign >= 0 && power.CanFitInInt32())
+ ? read.Keys.Max()!.ToInt32Unchecked() : null;
+ if (!denominator.Vars.Any(symbol => symbol != x))
+ return null;
+ var changed = false;
+ Entity product = Number.Integer.One;
+ foreach (var factor in Mulf.LinearChildren(denominator))
+ {
+ var (@base, power) = factor is Powf(var b, Number.Integer { EInteger.Sign: > 0 } p) ? (b, p) : (factor, Number.Integer.One);
+ if (@base is Sumf(Powf(var first, Number.Integer(2)), Powf(var second, Number.Integer(2)))
+ && (first.ContainsNode(x) || second.ContainsNode(x))
+ && DegreeOfAPolynomial(first, x) is { } firstDegree && DegreeOfAPolynomial(second, x) is { } secondDegree
+ && System.Math.Max(firstDegree, secondDegree) == 2)
+ {
+ var (minus, plus) = (first - MathS.i * second, first + MathS.i * second);
+ product *= power == Number.Integer.One ? minus * plus : MathS.Pow(minus, power) * MathS.Pow(plus, power);
+ changed = true;
+ continue;
+ }
+ product *= factor;
+ }
+ return changed ? product : null;
+ }
+
///
/// with every quadratic factor that has a root off the real line
/// in common with a linear factor beside it written as its leading coefficient times the
diff --git a/Sources/Tests/UnitTests/Calculus/SumOfTwoSquaresBelowTheBarIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/SumOfTwoSquaresBelowTheBarIntegralTest.cs
new file mode 100644
index 000000000..ef3a1a731
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/SumOfTwoSquaresBelowTheBarIntegralTest.cs
@@ -0,0 +1,55 @@
+//
+// 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 sum of two squares below the bar beside a repeated factor, written over its two
+ /// conjugates. Under u = tan(x) and t = sqrt(c + d u), the 1 + u^2 of
+ /// Rubi's 4.3.2.1 (c + d tan(x))^(3/2)/(a + b tan(x))^2 is (t^2 - c)^2 + d^2,
+ /// a quartic beside the square of a d + b (t^2 - c); the Hermite reduction solved for
+ /// its numerators with the symbols in every entry and ran past two minutes. Written as
+ /// (t^2 - c - i d)(t^2 - c + i d), every factor is one the split by residues reads.
+ /// #718
+ ///
+ ///
+ /// Under a root of the quotient of two such linears the sum is (b - d t^2)^2 + (c t^2 - a)^2,
+ /// both parts in t, and its conjugates are quadratics as well. The integrands are real
+ /// where a + b tan(x) and c + d tan(x) are positive, which the points are.
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class SumOfTwoSquaresBelowTheBarIntegralTest
+ {
+ [Theory]
+ [InlineData("(c + d*tan(x))^(3/2)/(a + b*tan(x))^2")]
+ [InlineData("(c + d*tan(x))^(5/2)/(a + b*tan(x))^2")]
+ [InlineData("(c + d*tan(x))^(3/2)/(a + b*tan(x))^3")]
+ [InlineData("x^4/((a*d + (x^2 - c)*b)^2*((x^2 - c)^2 + d^2))")]
+ [InlineData("1/((a + b*tan(x))^(3/2)*(c + d*tan(x))^(3/2))")]
+ [InlineData("1/((a + b*tan(x))^(5/2)*(c + d*tan(x))^(3/2))")]
+ public void OverItsConjugates(string integrand)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7).Substitute("c", 1.1).Substitute("d", 0.6);
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ foreach (var at in new[] { 0.2, 0.5, 0.9, 1.2 })
+ {
+ 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)),
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+ }
+}