diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 34988dd16..3273ba5bf 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -429,6 +429,24 @@ root of a linear, the linear radical substitution gets there first
| `"sin(a + b/sqrt(c + d*x))/(e + f*x)".ToEntity().Integrate("x")` | `integral(...)` | 1,114 characters |
| `"sin(a + b/sqrt(c + d*x))/(e + f*x)^2".ToEntity().Integrate("x")` | `integral(...)` | 2,288 characters |
+### A symbolic trinomial in x^2 beside a root of a quadratic is split over its factors
+
+**Answers where there were none.** `sqrt(d + k x^2)/(a + b x^2 + c x^4)` and its kin were declined, most of them
+past any budget. The trinomial is written over its factors in x^2 now, with its roots named: `c (x^2 - r)(x^2 - s)`
+where they are real, and `c (x^2 + p x + m)(x^2 - p x + m)` where they are a conjugate pair. Each factor is a quadratic
+the existing rules close beside the root. The answer is a piecewise on the sign of `b^2 - 4 a c`, and the second
+case is most of its length ([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"x^2*sqrt(d + k*x^2)/(a + b*x^2 + c*x^4)".ToEntity().Integrate("x")` | `integral(...)` | 29,139 characters |
+| `"sqrt(d + k*x^2)/(x^2*(a + b*x^2 + c*x^4))".ToEntity().Integrate("x")` | `integral(...)` | 10,736 characters |
+| `"(d + k*x^2)^(3/2)/(a + b*x^2 + c*x^4)".ToEntity().Integrate("x")` | `integral(...)` | 31,242 characters |
+| `"x^4*(d + k*x^2)^(3/2)/(a + b*x^2 + c*x^4)".ToEntity().Integrate("x")` | `integral(...)` | 41,265 characters |
+| `"x^2*sqrt(1 - x^2)/(a + b*x^2 + c*x^4)".ToEntity().Integrate("x")` | `integral(...)` | 8,502 characters |
+| `"x^4/((a + b*x^2 + c*x^4)*sqrt(d + k*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 28,551 characters |
+| `"1/(x^2*(a + b*x^2 + c*x^4)*sqrt(d + k*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 10,194 characters |
+
### A power of the cosine beside a secant binomial is integrated in the cosine
**Answers where there were none.** `cos(c + d x)^2/(a + b sec(c + d x))` was declined, and so were the cosine's powers
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 11ef427c4..f8bbfe1c3 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -18722,6 +18722,104 @@ static Entity WithoutConditions(Entity coefficient)
return answer.Nodes.Any(node => node is Number.Complex { IsNaN: true }) ? null : answer;
}
+ ///
+ /// A rational function with a trinomial in the square below the bar, beside a root of a
+ /// quadratic, taken apart over the trinomial's factors in the square: where its roots in
+ /// x^2 are real, a + b x^2 + c x^4 is c (x^2 - r) (x^2 - s) with
+ /// r, s = (-b -+ sqrt(b^2 - 4 a c))/(2c), and where they are a conjugate pair it is
+ /// c (x^2 + p x + m) (x^2 - p x + m) with m = sqrt(a/c) and
+ /// p = sqrt(2 m - b/c). Each factor is a quadratic the rule before this one splits
+ /// the integrand over and closes beside the root, and the answer is the piecewise of the
+ /// two on the sign of the discriminant. Rubi's 1.2.2.4
+ /// sqrt(d + e x^2)/(a + b x^2 + c x^4) was declined.
+ ///
+ ///
+ /// Asked with r, s, m and p symbols of their own and written
+ /// back after: the integrand so written is an integrand for every value of them, and the
+ /// one asked for at theirs. Named, each stays one atom through the split: with
+ /// (sqrt(b^2 - 4 a c) - b)/(2c) in place of r the split declined
+ /// x^2 sqrt(d + e x^2)/(a + b x^2 + c x^4), and over x^2 - r it is 1,458
+ /// characters (#1877
+ /// was the same with a quadratic). The real roots' writing alone is not enough: with
+ /// r complex the pieces' cases read the sign of a number off the real line, and the
+ /// answer was NaN wherever b^2 < 4 a c. Not where the discriminant vanishes,
+ /// the generic case's. With a symbol in the trinomial only, and in a function of x^2 only.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ internal static Entity? SolveATrinomialInTheSquareBesideTheRootOfAQuadratic(Entity expr, Entity.Variable x)
+ {
+ // A function of x^2: every x in an even power of it, the root's quadratic among them.
+ // `sqrt(x)/(a + b x^2 + c x^4)^2` is not one, and a power of x to an odd degree below
+ // the bar is a function of x^2 after u = x^2, which reads it more shortly.
+ if (!expr.Nodes.Any(node => node is Powf(var radicand, Number.Rational { ERational.Denominator: var half })
+ && half.Equals(EInteger.FromInt32(2)) && radicand.ContainsNode(x)
+ && TreeAnalyzer.TryGetPolyQuadratic(radicand, x, out var squared, out _, out _) && !VanishesIdentically(squared))
+ || expr.Nodes.Count(node => node == x) != expr.Nodes.Count(node => node is Powf(var @base, Number.Integer { EInteger.IsEven: true }) && @base == x))
+ return null;
+ var (_, denominator) = Functions.SingleQuotient.Of(expr);
+ Entity? trinomial = null;
+ (Entity A, Entity B, Entity C)? read = null;
+ foreach (var factor in Mulf.LinearChildren(denominator))
+ {
+ var @base = factor is Powf(var repeated, Number.Integer { EInteger.Sign: > 0 }) ? repeated : factor;
+ if (@base is not (Sumf or Minusf) || !@base.ContainsNode(x) || !@base.Vars.Any(symbol => symbol != x)
+ || !TreeAnalyzer.TryGetPolynomial(@base, x, out var monomials)
+ || monomials.Count != 3
+ || !monomials.TryGetValue(EInteger.Zero, out var a)
+ || !monomials.TryGetValue(EInteger.FromInt32(2), out var b)
+ || !monomials.TryGetValue(EInteger.FromInt32(4), out var c))
+ continue;
+ if (trinomial is not null && trinomial != @base)
+ return null;
+ trinomial = @base;
+ read = (a, b, c);
+ }
+ if (trinomial is null || read is not var (constant, middle, leading)
+ || VanishesIdentically(leading) || VanishesIdentically(middle))
+ return null;
+ var discriminant = (middle * middle - 4 * constant * leading).InnerSimplified;
+ if (VanishesIdentically(discriminant))
+ return null;
+ // Two writings of the trinomial, each real where it is taken, its roots and
+ // coefficients named so that each stays one atom through the split. Two real roots
+ // in x^2: c (x^2 - r) (x^2 - s). None: the roots are a conjugate pair and the pieces' cases
+ // read the sign of an imaginary q, so it is the product of two real quadratics
+ // c (x^2 + p x + m) (x^2 - p x + m) with m = sqrt(a/c) and p = sqrt(2 m - b/c), both
+ // real there since b^2 < 4 a c makes a/c positive and |b/c| < 2 m. Each is an
+ // identity in its symbols, so each answer is an antiderivative wherever its symbols
+ // are what they stand for. A root twice, where the discriminant vanishes, is the
+ // case the generic answer leaves, as `ln(a x + b)/a` leaves a = 0.
+ var square = MathS.Pow(x, Number.Integer.Create(2));
+ var r = Variable.CreateUnique(expr, "r");
+ var s = Variable.CreateUnique(expr + r, "s");
+ var m = Variable.CreateUnique(expr + r + s, "m");
+ var p = Variable.CreateUnique(expr + r + s + m, "p");
+ var q = MathS.Sqrt(discriminant);
+ var writings = new (Entity Written, Entity[] Named, Entity[] Values, Entity Condition)[]
+ {
+ (leading * (square - r) * (square - s),
+ new Entity[] { r, s }, new[] { (q - middle) / (2 * leading), (-q - middle) / (2 * leading) }, discriminant > 0),
+ (leading * (square + p * x + m) * (square - p * x + m),
+ new Entity[] { m, p }, new[] { MathS.Sqrt(constant / leading), MathS.Sqrt(2 * MathS.Sqrt(constant / leading) - middle / leading) }, discriminant < 0),
+ };
+ var cases = new List();
+ foreach (var (overTheRoots, named, values, condition) in writings)
+ {
+ var written = expr.Replace(node => node == trinomial ? overTheRoots : node);
+ if (SolveARationalFunctionBesideTheRootOfAQuadratic(written, x) is not { } inNamed)
+ return null;
+ var answered = inNamed;
+ for (var i = named.Length - 1; i >= 0; i--)
+ answered = answered.Substitute(named[i], values[i]);
+ answered = answered.InnerSimplified;
+ if (answered.Nodes.Any(node => node is Number.Complex { IsNaN: true }))
+ return null;
+ cases.Add(new Providedf(answered, condition));
+ }
+ var answer = MathS.Piecewise(cases);
+ return Functions.PartialFractions.DerivativeHoldsAtSampledPoints(answer, expr, x) ? answer : null;
+ }
+
///
/// A piece over a whole power of , beside its root, as the one
/// half-odd power the two are: (g + h x)/(Q^j sqrt(Q)) is
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
index bea48da67..3ccccf2e2 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs
@@ -666,6 +666,10 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
// the question asked only, and the polynomial term below writes `1/u` as `u^(-1)` and
// asks that a level down: `1/(e^atanh(a x) (c - c/(a x))^(3/2))` reached it nowhere.
if ((answer = IndefiniteIntegralSolver.SolveByWritingEachLinearOnce(expr, x, integrateByParts)) is { }) return answer;
+ // A symbolic trinomial in x^2 below the bar beside a root of a quadratic, over its roots
+ // in x^2, before anything reads the trinomial whole: asked of it, the routes below ran
+ // past a minute on Rubi's 1.2.2.4 `sqrt(d + e x^2)/(x^2 (a + b x^2 + c x^4))`.
+ if ((answer = IndefiniteIntegralSolver.SolveATrinomialInTheSquareBesideTheRootOfAQuadratic(expr, x)) is { }) return answer;
// A linear under a power inside a sum, written as the variable: `x^3/(a + b (c + d x)^3)`.
// Before the polynomial term, which takes the leading coefficient out of a power of
// the sum and writes what is left out in powers of x, where the linear is gone; and
diff --git a/Sources/Tests/UnitTests/Calculus/ATrinomialInTheSquareBesideARootIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/ATrinomialInTheSquareBesideARootIntegralTest.cs
new file mode 100644
index 000000000..e526c1012
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/ATrinomialInTheSquareBesideARootIntegralTest.cs
@@ -0,0 +1,61 @@
+//
+// 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 with a symbolic trinomial in x^2 below the bar, beside a root of a
+ /// quadratic: taken apart over the trinomial's roots in x^2 where they are real, and over two
+ /// real quadratics where they are a conjugate pair. Rubi's 1.2.2.4, written here with
+ /// k for e, which is Euler's number.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class ATrinomialInTheSquareBesideARootIntegralTest
+ {
+ private static void DifferentiatesBack(string integrand, params (string, double)[] pins)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+
+ // Pinned before it is differentiated: the answer is a piecewise on the sign of the
+ // discriminant, read where it is a number.
+ 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[] { -0.7, -0.3, 0.4, 0.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("x^2*sqrt(d+k*x^2)/(a+b*x^2+c*x^4)")]
+ [InlineData("sqrt(d+k*x^2)/(x^2*(a+b*x^2+c*x^4))")]
+ [InlineData("sqrt(1-x^2)/(x^2*(a+b*x^2+c*x^4))")]
+ public void IsAnsweredAndDifferentiatesBack(string integrand)
+ {
+ // Two real roots in x^2, then a conjugate pair.
+ DifferentiatesBack(integrand, ("a", 1), ("b", 5), ("c", 2), ("d", 1.5), ("k", 2));
+ DifferentiatesBack(integrand, ("a", 2), ("b", 1), ("c", 1.5), ("d", 1.25), ("k", 3));
+ }
+ }
+}