diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 875f47412..abfa92ca4 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -491,6 +491,21 @@ taken apart into pieces each closed the same way
| `"(2 + x)/((2 + 4*x - 3*x^2)*(1 + 3*x + 2*x^2)^(3/2))".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative |
| `"1/((x^2 + 1)*sqrt(x^2 + x + 1))".ToEntity().Integrate("x")` | `integral(...)` | a logarithm and an arctangent |
+### A power of a multiple of a quadratic's derivative beside a power of the quadratic is a binomial
+
+**Improvement, not silent.** `(b d + 2 c d x)^m (a + b x + c x^2)^p`, with a power that is not whole,
+was declined or ran out of time. Under `t = b d + 2 c d x` the quadratic is
+`(t^2/d^2 - (b^2 - 4 a c))/(4 c)`, so the integrand is a binomial in `t`. That binomial is asked with
+its constant term named by a symbol of its own, since with `a - b^2/(4 c)` written in it the rules for
+a binomial ran out of time too. Rubi's 1.2.1.2
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"(a+b*x+c*x^2)^(3/2)/(b*d+2*c*d*x)^3".Integrate("x")` | `integral(...)` | the antiderivative |
+| `"(a+b*x+c*x^2)^(1/2)/(b*d+2*c*d*x)^7".Integrate("x")` | `integral(...)` | the antiderivative |
+| `"(b*d+2*c*d*x)^(5/2)/(a+b*x+c*x^2)^3".Integrate("x")` | `integral(...)` | the antiderivative |
+
### A polynomial over a power of a quadratic beside the root of another is integrated
`P/(A^k sqrt(B))`, `A` and `B` two different quadratics and `k` at least two, was left
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 8fc728331..031d3595f 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -14072,6 +14072,88 @@ bool MayBeARootOfASquare(Entity node, Entity.Variable x)
return assumed == Entity.Boolean.True ? answer : answer.Provided(assumed);
}
+ ///
+ /// A power of a linear that is a constant multiple of a quadratic's derivative, beside a
+ /// power of the quadratic, under the linear as the variable: with t = λ (b + 2 c x)
+ /// the quadratic a + b x + c x^2 is (t^2/λ^2 - Δ)/(4 c), with
+ /// Δ = b^2 - 4 a c, so t^m Q^p is a binomial in t. Rubi's 1.2.1.2,
+ /// (b d + 2 c d x)^m (a + b x + c x^2)^p, which it substitutes the same way.
+ ///
+ ///
+ /// The substitution is affine, so the integrand in t is the integrand exactly. The
+ /// quadratic is written in t from its coefficients rather than by substituting:
+ /// substituted, it keeps a linear term that is zero as a value and not as written, and the
+ /// rules for a binomial read α + β t^2. Only where a power is not whole: a rational
+ /// function is the partial fractions'.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ internal static Entity? SolveByTheDerivativeOfAQuadraticAsTheVariable(Entity expr, Entity.Variable x, bool integrateByParts)
+ {
+ if (!Integration.AnsweringTheQuestionAskedOrOneBelow)
+ return null;
+ Entity constant = Number.Integer.One;
+ (Entity Base, Entity Exponent)? linear = null, quadratic = null;
+ foreach (var (factor, underneath) in FactorsOfTheIntegrand(expr))
+ {
+ if (!factor.ContainsNode(x))
+ {
+ constant = underneath ? constant / factor : constant * factor;
+ continue;
+ }
+ var (@base, exponent) = factor is Powf(var b, var e) && !e.ContainsNode(x) ? (b, e) : (factor, (Entity)Number.Integer.One);
+ if (underneath)
+ exponent = (-exponent).InnerSimplified;
+ if (!TreeAnalyzer.TryGetPolynomial(@base, x, out var read) || read.Count == 0 || read.Keys.Any(k => k.Sign < 0)
+ || read.Values.Any(coefficient => coefficient.ContainsNode(x)))
+ return null;
+ var degree = read.Keys.Max()!;
+ if (degree.Equals(EInteger.One) && linear is null)
+ linear = (@base, exponent);
+ else if (degree.Equals(EInteger.FromInt32(2)) && quadratic is null)
+ quadratic = (@base, exponent);
+ else
+ return null;
+ }
+ if (linear is not var (l, m) || quadratic is not var (q, p) || m is Number.Integer && p is Number.Integer)
+ return null;
+ if (!TreeAnalyzer.TryGetPolyLinear(l, x, out var l1, out var l0)
+ || !TreeAnalyzer.TryGetPolyQuadratic(q, x, out var c2, out var c1, out var c0)
+ || VanishesIdentically(c2) || VanishesIdentically(l1)
+ // With no linear term the integrand is a binomial in x already, and taken as one in
+ // t it would be this question again with t scaled.
+ || VanishesIdentically(c1)
+ // The linear is a multiple of 2 c x + b where its root is the vertex's.
+ || !VanishesIdentically(2 * c2 * l0 - c1 * l1))
+ return null;
+ var lambda = Reduced(l1 / (2 * c2));
+ // Q = (t^2/λ^2 - Δ)/(4 c) = α + β t^2, each constant named by a symbol of its own where
+ // it is a compound of the coefficients, and written back into the answer: the rules for
+ // a binomial answer `t^(-7) sqrt(c t^2 + k)` in milliseconds, and with
+ // `a - b^2/(4 c)` for `k` they ran out of time.
+ var alpha = Reduced(-(c1 * c1 - 4 * c2 * c0) / (4 * c2));
+ var beta = Reduced(1 / (4 * c2 * lambda * lambda));
+ var t = Variable.CreateUnique(expr, "t_deriv");
+ var named = new List<(Variable Name, Entity Value)>();
+ Entity Named(Entity value)
+ {
+ if (value is Number or Variable || value is Mulf(Number, Variable) || value is Powf(Variable, Number))
+ return value;
+ var name = Variable.CreateUnique(expr + t + named.Aggregate((Entity)Number.Integer.Zero, (sum, pair) => sum + pair.Name), "k_named");
+ named.Add((name, value));
+ return name;
+ }
+ var inT = Reduced(constant / l1) * MathS.Pow(t, m) * MathS.Pow(Named(alpha) + Named(beta) * MathS.Sqr(t), p);
+ if (Integration.ComputeAsAQuestionOfItsOwn(inT, t, integrateByParts) is not { } answer
+ || answer.Nodes.Any(node => node == MathS.NaN))
+ return null;
+ foreach (var (name, value) in named)
+ answer = answer.Substitute(name, value);
+ return answer.Substitute(t, l);
+
+ static Entity Reduced(Entity constant)
+ => constant.Vars.Any() ? Functions.PartialFractions.InLowestTermsOverTheSymbols(constant) : constant.InnerSimplified;
+ }
+
///
/// A whole power of a product in which the variable stands beside a constant, written
/// as the product of the powers: (c x)^2 is c^2 x^2, exact for a whole
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
index dec7b78a0..5c9f91770 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
@@ -662,6 +662,9 @@ private static Entity Normalized(Entity expr, Entity.Variable x) =>
if ((answer = IndefiniteIntegralSolver.SolveAReciprocalOfAnInverseTrigonometricFunction(expr, x, integrateByParts)) is { }) return answer;
// A fractional power of a perfect square is the power of the modulus, sgn(P) P^(2r).
if ((answer = IndefiniteIntegralSolver.SolveByTakingARootOfAPerfectSquare(expr, x, integrateByParts)) is { }) return answer;
+ // A power of a multiple of a quadratic's derivative beside a power of the quadratic is
+ // a binomial in the derivative: `(b d + 2 c d x)^m (a + b x + c x^2)^p`.
+ if ((answer = IndefiniteIntegralSolver.SolveByTheDerivativeOfAQuadraticAsTheVariable(expr, x, integrateByParts)) is { }) return answer;
// x^(n - 1) g(x^n) with a symbolic n is g(u)/n under u = x^n.
if ((answer = IndefiniteIntegralSolver.SolveByAPowerOfTheVariableTimesAFunctionOfItsPower(expr, x, integrateByParts)) is { }) return answer;
// A whole power of a product of a constant and the variable, as the product of
diff --git a/Sources/Tests/UnitTests/Calculus/DerivativeOfAQuadraticAsTheVariableTest.cs b/Sources/Tests/UnitTests/Calculus/DerivativeOfAQuadraticAsTheVariableTest.cs
new file mode 100644
index 000000000..80e02dbbe
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/DerivativeOfAQuadraticAsTheVariableTest.cs
@@ -0,0 +1,56 @@
+//
+// 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 a multiple of a quadratic's derivative beside a power of the quadratic, Rubi's
+ /// 1.2.1.2 (b d + 2 c d x)^m (a + b x + c x^2)^p: under t = b d + 2 c d x the
+ /// quadratic is (t^2/d^2 - (b^2 - 4 a c))/(4 c), and the integrand a binomial in t.
+ /// #718
+ ///
+ ///
+ /// Each was declined, or ran past the corpus's budget; the binomial with a compound constant
+ /// term ran out of time too, and is asked with the constant named by a symbol of its own.
+ /// Checked by differentiating back with the symbols pinned, at points on both sides of the
+ /// derivative's root where the integrand is real.
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class DerivativeOfAQuadraticAsTheVariableTest
+ {
+ [Theory]
+ [InlineData("(a + b*x + c*x^2)^(3/2)/(b*d + 2*c*d*x)^3")]
+ [InlineData("(a + b*x + c*x^2)^(1/2)/(b*d + 2*c*d*x)^7")]
+ [InlineData("(a + b*x + c*x^2)^(5/2)/(b*d + 2*c*d*x)^5")]
+ [InlineData("(b*d + 2*c*d*x)^(5/2)/(a + b*x + c*x^2)^3")]
+ public void IsABinomialInTheDerivative(string integrand)
+ {
+ var integral = integrand.ToEntity().Integrate("x").Substitute("C", 0);
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pin(Entity e) => e.Substitute("a", 2.3).Substitute("b", 1.1).Substitute("c", 0.7).Substitute("d", 1.9);
+ var derivative = Pin(integral).Differentiate("x");
+ var original = Pin(integrand.ToEntity());
+ var compared = 0;
+ foreach (var at in new[] { -3.1, -1.4, 0.3, 0.9, 1.7 })
+ {
+ var want = original.Substitute("x", at).EvalNumerical();
+ if (want.IsNaN || Math.Abs((double)want.ImaginaryPart) > 1e-12 * Math.Max(1, Math.Abs((double)want.RealPart)))
+ continue;
+ var got = derivative.Substitute("x", at).EvalNumerical();
+ compared++;
+ var difference = Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart);
+ Assert.True(difference < 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}");
+ }
+ Assert.True(compared >= 3, $"only {compared} points where {integrand} is real");
+ }
+ }
+}