diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index ae2a54fa6..0c3b37ae9 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -466,6 +466,24 @@ the first power: for a higher power the secant's own rules answer
| `"cos(c + d*x)^2*(A + B*sec(c + d*x) + C*sec(c + d*x)^2)/(a + b*sec(c + d*x))".ToEntity().Integrate("x")` | `integral(...)` | 12,065 characters |
| `"sin(x)^2/(a + b*csc(x))".ToEntity().Integrate("x")` | `integral(...)` | 898 characters |
+### A linear with a symbolic slope beside a root of a quadratic with no linear term is integrated
+
+**Answers where there were none.** `sqrt(a + c x^2)/(x (d + k x))` was declined where `sqrt(a + b x + c x^2)/(x (d + k x))`
+was answered. The rule for a constant over a linear beside the root works at the linear's root `p = -d/k`. Without
+a linear term, the quadratic's value there came back with `provided not k = 0` attached, and the table read no
+quadratic through that condition. The value is read without the condition now: a linear's slope is not zero. A
+linear with the imaginary unit in it is still declined there, as it was by accident before
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"sqrt(a + c*x^2)/(x*(d + k*x))".ToEntity().Integrate("x")` | `integral(...)` | 1,362 characters |
+| `"sqrt(a + c*x^2)/(x^3*(d + k*x))".ToEntity().Integrate("x")` | `integral(...)` | 1,710 characters |
+| `"1/(x*(d + k*x)*sqrt(a + c*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 1,067 characters |
+| `"1/(x*(d + k*x)*(a + c*x^2)^(3/2))".ToEntity().Integrate("x")` | `integral(...)` | 1,769 characters |
+| `"1/(x^3*(d + k*x)^2*sqrt(a + c*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 2,801 characters |
+| `"sqrt(a + c/x^2)/(d + k*x)".ToEntity().Integrate("x")` | `integral(...)` | 1,373 characters |
+
### One linear twice is not two linear powers
**Answers that had no value.** `(a c + b c x)^(-3 - 2 p) (f + g x) (a^2 + 2 a b x + b^2 x^2)^p` was answered
diff --git a/Sources/AngouriMath/Functions/Algebra/Polynomials/PartialFractions.cs b/Sources/AngouriMath/Functions/Algebra/Polynomials/PartialFractions.cs
index 2f440cab6..8091a8004 100644
--- a/Sources/AngouriMath/Functions/Algebra/Polynomials/PartialFractions.cs
+++ b/Sources/AngouriMath/Functions/Algebra/Polynomials/PartialFractions.cs
@@ -696,7 +696,7 @@ private static Entity ExpandedOverTheSymbols(Entity expr)
}
/// Whether a number off the real line is among the nodes of .
- private static bool HoldsTheImaginaryUnit(Entity expr)
+ internal static bool HoldsTheImaginaryUnit(Entity expr)
=> expr.Nodes.Any(node => node is Complex number && number is not Real && !number.ImaginaryPart.IsZero);
///
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index fa107a045..d33acb453 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -18095,12 +18095,20 @@ Dictionary PowerOfQ(int j)
foreach (var coefficient in new[] { a, b, c, m, n, numerator, constant })
if (coefficient.Evaled is Number.Complex and not Number.Real)
return null;
+ // And a pole off the real line is not one: the answer is written with the sign of
+ // x - p, and nothing checks it after. `1 + i a x` beside a root, what
+ // `e^(3 i atan(a x))` is written as, has its pole at `i/a`.
+ if (Functions.PartialFractions.HoldsTheImaginaryUnit(m) || Functions.PartialFractions.HoldsTheImaginaryUnit(n))
+ return null;
// (x - p) with p = -n/m, and K = numerator/(m constant).
var p = (-n / m).InnerSimplified;
var k = (numerator / (m * constant)).InnerSimplified;
- var atP = (a * p * p + b * p + c).InnerSimplified;
- var slopeAtP = (2 * a * p + b).InnerSimplified;
+ // Bare: `3 (-d/k)^2 + 2` comes back `... provided not k = 0`, the linear's own slope
+ // not vanishing, and the table read no quadratic in t through the condition --
+ // `1/((d + k x) sqrt(2 + 3 x^2))` was declined where `1/((d + x) sqrt(2 + 3 x^2))` was not.
+ var atP = Functions.PartialFractions.Bare((a * p * p + b * p + c).InnerSimplified);
+ var slopeAtP = Functions.PartialFractions.Bare((2 * a * p + b).InnerSimplified);
var t = Variable.CreateUnique(expr, "t_recip");
var inT = 1 / MathS.Pow(atP * MathS.Sqr(t) + slopeAtP * t + a, Number.Rational.Create(1, 2));
if (IntegralPatterns.TryStandardIntegrals(inT, t) is not { } g)
@@ -18489,12 +18497,13 @@ static Entity WithoutConditions(Entity coefficient)
if (coefficient.Evaled is Number.Complex and not Number.Real)
return null;
var p = (-n / m).InnerSimplified;
- var atP = (a * p * p + b * p + c).InnerSimplified;
+ // Bare, as in the rule for a single linear: the slope's condition is not a case.
+ var atP = Functions.PartialFractions.Bare((a * p * p + b * p + c).InnerSimplified);
// A root of the radicand leaves a linear under the root, which is not this.
if (VanishesIdentically(atP)
|| Functions.PartialFractions.TaylorCoefficientsAtTheRoot(numerator, p, power, x) is not { } taylor)
return null;
- var slopeAtP = (2 * a * p + b).InnerSimplified;
+ var slopeAtP = Functions.PartialFractions.Bare((2 * a * p + b).InnerSimplified);
var t = Variable.CreateUnique(expr, "t_recip");
// P(p + 1/t) t^(k - 1) is the sum of the Taylor coefficients times t^(k - 1 - j), and
// (x - p)^k is L^k/m^k.
diff --git a/Sources/Tests/UnitTests/Calculus/APoleWithASymbolicSlopeBesideARootIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/APoleWithASymbolicSlopeBesideARootIntegralTest.cs
new file mode 100644
index 000000000..96d8b1356
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/APoleWithASymbolicSlopeBesideARootIntegralTest.cs
@@ -0,0 +1,62 @@
+//
+// 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 constant over a linear with a symbolic slope beside the root of a quadratic with no
+ /// linear term: the quadratic's value at the pole came back with the slope's condition on it,
+ /// and the table read no quadratic through it. Rubi's 1.2.1.4
+ /// sqrt(a + c x^2)/(x (d + e x)), written here with k for e, which is
+ /// Euler's number.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class APoleWithASymbolicSlopeBesideARootIntegralTest
+ {
+ 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 carries `sgn(x + d/k)`, whose
+ // derivative is read where its argument 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[] { -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("1/((d+k*x)*sqrt(2+3*x^2))")]
+ [InlineData("sqrt(a+c*x^2)/(x*(d+k*x))")]
+ [InlineData("1/(x^2*(d+k*x)*sqrt(a+c*x^2))")]
+ [InlineData("1/(x*(d+k*x)^2*sqrt(a+c*x^2))")]
+ public void IsAnsweredAndDifferentiatesBack(string integrand)
+ {
+ DifferentiatesBack(integrand, ("a", 2), ("c", 1.5), ("d", 1.25), ("k", 2));
+ DifferentiatesBack(integrand, ("a", -1), ("c", 2), ("d", -0.5), ("k", 1.5));
+ }
+ }
+}