diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index e89c879dd..66bfaa7fd 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -312,6 +312,20 @@ an arm for each sign of a quantity that is not real, `x^2 provided not x = 0` be
| `"piecewise(2 * x provided not x = 0, 3 * x ^ 2 provided i - 1 < 0)".ToEntity().InnerSimplified` | `NaN` | `2 * x` where `x` is not 0 |
| `"piecewise(1 provided i < 0, 2 provided i > 0)".ToEntity().InnerSimplified` | `NaN` | `NaN`, as before: no case holds |
+### A power of x times a power of a function of another power of x is integrated under that power
+
+**Answers where there were none.** `x^3 (a + b atanh(c x^2))^2` ran out of time, and so did ten more of Rubi's 3.4, 5.3.2
+and 7.3.2. `x^m F(x^n)^p`, with `F` a sum holding an inverse tangent, inverse hyperbolic tangent or logarithm of
+`x^n` and `p` at least 2, is now integrated under `t = x^n` wherever `(m + 1)/n` is whole
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"x^3*(a+b*atanh(c*x^2))^2".ToEntity().Integrate("x")` | `integral(...)` | 308 characters |
+| `"(a+b*atan(c*x^2))^2/x^5".ToEntity().Integrate("x")` | `integral(...)` | 870 characters |
+| `"(a+b*atanh(c*x^(3/2)))^2/x^4".ToEntity().Integrate("x")` | `integral(...)` | 330 characters |
+| `"(a+b*ln(c*(d+k/x^(2/3))^n))^2/x^5".ToEntity().Integrate("x")` | `integral(...)` | 2,034 characters |
+
### Zero times a power with a non-real exponent is zero where the power is defined
**A value where there was NaN.** `0 b^i` simplified to NaN, and so did `b^i - b^i`. That in turn made `x b^i`'s
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index b838c5e66..5e97ce0ba 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -26286,6 +26286,67 @@ when two.Equals(EInteger.FromInt32(2)) && e1 == MathS.e && e2 == MathS.e
return answer.Nodes.Any(node => node == MathS.NaN) ? null : answer;
}
+ ///
+ /// A power of x times a whole power, past the first, of a sum holding an inverse function or a
+ /// logarithm of a power of x, x^m (a + b atanh(c x^n))^p, under t = x^n where
+ /// (m + 1)/n is whole: x^m dx = t^((m + 1)/n - 1) dt/n.
+ ///
+ ///
+ /// The rules before it timed out on Rubi's 5.3.2 (a + b atan(c x^2))^2/x^5 and 7.3.2
+ /// x^3 (a + b atanh(c x^2))^2, (a + b atanh(c/x^2))^2/x^5 and
+ /// (a + b atanh(c x^(3/2)))^2/x^4, each a problem in t they answer in a second.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ internal static Entity? SolveAPowerOfXTimesAFunctionOfAnotherUnderThatPower(Entity expr, Entity.Variable x)
+ {
+ if (!Integration.AnsweringTheQuestionAsked)
+ return null;
+ // The factors of a product and a quotient, each with the sign of its exponent.
+ static IEnumerable<(Entity Factor, bool Below)> Factors(Entity e, bool below) => e switch
+ {
+ Mulf(var l, var r) => Factors(l, below).Concat(Factors(r, below)),
+ Divf(var l, var r) => Factors(l, below).Concat(Factors(r, !below)),
+ _ => new[] { (e, below) }
+ };
+ ERational m = ERational.Zero;
+ Entity? function = null;
+ Entity constant = Number.Integer.One;
+ foreach (var (factor, below) in Factors(expr, false))
+ {
+ if (!factor.ContainsNode(x))
+ constant = below ? constant / factor : constant * factor;
+ else if (factor == x)
+ m = below ? m - ERational.One : m + ERational.One;
+ else if (factor is Powf(var b0, Number.Rational { ERational: var r }) && b0 == x)
+ m = below ? m - r : m + r;
+ else if (function is null && !below && factor is Powf(var sum, Number.Integer { EInteger: var power }) && power.CompareTo(EInteger.FromInt32(2)) >= 0)
+ function = factor;
+ else
+ return null;
+ }
+ if (function is null)
+ return null;
+ // The one power of x the function is written in, and an inverse function or a logarithm of it.
+ var powers = function.Nodes.Where(node => node is Powf(var b1, Number.Rational) && b1 == x).Distinct().ToList();
+ if (powers.Count != 1 || powers[0] is not Powf(_, Number.Rational { ERational: var n }) || n.IsZero || n.Equals(ERational.One))
+ return null;
+ var t = Variable.CreateUnique(expr, "t_pow");
+ var inT = function.Substitute(powers[0], t);
+ if (inT.ContainsNode(x)
+ || !inT.Nodes.Any(node => node is Arcsinf or Arccosf or Arctanf or Arccotanf or Logf && node.ContainsNode(t)))
+ return null;
+ // PeterO keeps a quotient as written: -4/2 has the denominator 2 until it is reduced.
+ var k = ((m + ERational.One) / n).ToLowestTerms();
+ if (!k.Denominator.Equals(EInteger.One) || !k.Numerator.CanFitInInt32())
+ return null;
+ var exponent = k.Numerator.ToInt32Unchecked() - 1;
+ var inTWhole = (exponent == 0 ? inT : MathS.Pow(t, Number.Integer.Create(exponent)) * inT).InnerSimplified;
+ if (Integration.ComputeAsAQuestionOfItsOwn(inTWhole, t, integrateByParts: true) is not { } integrated)
+ return null;
+ var answer = (constant / Number.Rational.Create(n.Numerator, n.Denominator) * integrated.Substitute(t, powers[0])).InnerSimplified;
+ return answer.Nodes.Any(node => node == MathS.NaN) ? null : answer;
+ }
+
///
/// A rational function of a sine, or of a cosine, over a quadratic in it with a symbol
/// among the coefficients: sin(x)/(a + b sin(x) + c sin(x)^2), and the same with
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
index 9b1b2855b..fd7ca2fdb 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
@@ -680,6 +680,9 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
// A power of a sine, cosine or hyperbolic one over a binomial in a power of it, over the
// binomial's roots, before the rules that spent the budget on `sinh(y)^4/(a + b sinh(y)^3)`.
if ((answer = IndefiniteIntegralSolver.SolveAPowerOverABinomialInAPowerOfASineOverItsRoots(expr, x)) is { }) return answer;
+ // A power of x times a power of a sum holding an inverse function of x^n, under t = x^n,
+ // before the rules that timed out on `x^3 (a + b atanh(c x^2))^2`.
+ if ((answer = IndefiniteIntegralSolver.SolveAPowerOfXTimesAFunctionOfAnotherUnderThatPower(expr, x)) is { }) return answer;
// A polynomial in a sine or a cosine over a whole power of a binomial in it, in powers of the
// binomial, before the half-angle wrote 30 million characters for `(A + B cos + C cos^2)/(a + b cos)^4`.
if ((answer = IndefiniteIntegralSolver.SolveAPolynomialInASineOverAPowerOfABinomialInItInPowersOfTheBinomial(expr, x)) is { }) return answer;
diff --git a/Sources/Tests/UnitTests/Calculus/APowerOfXTimesAFunctionOfAnotherIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/APowerOfXTimesAFunctionOfAnotherIntegralTest.cs
new file mode 100644
index 000000000..78e3c8eba
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/APowerOfXTimesAFunctionOfAnotherIntegralTest.cs
@@ -0,0 +1,57 @@
+//
+// 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 power of x times a power of a sum holding an inverse function of another power of x, under
+ /// t = x^n: Rubi's 5.3.2 and 7.3.2 x^m (a + b atanh(c x^n))^2, which timed out.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class APowerOfXTimesAFunctionOfAnotherIntegralTest
+ {
+ 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}");
+ }
+ }
+
+ [Theory]
+ [InlineData("(a+b*atan(c*x^2))^2/x^5")]
+ [InlineData("x^3*(a+b*atanh(c*x^2))^2")]
+ [InlineData("(a+b*atanh(c/x^2))^2/x^5")]
+ [InlineData("x^11*(a+b*atanh(c*x^3))^2")]
+ public void IsAnsweredAndDifferentiatesBack(string integrand)
+ {
+ DifferentiatesBack(integrand, ("a", 1.3), ("b", 0.7), ("c", 0.3));
+ DifferentiatesBack(integrand, ("a", -2), ("b", 1.5), ("c", -0.2));
+ }
+ }
+}