diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 6faf6c53c..6dc517a3e 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -407,6 +407,19 @@ square and the cube keep the Hermite reduction's answers. Rubi's 1.1.3.8 `P(x) (
| `"(c + d*x)/(a + b*x^3)^4".ToEntity().Integrate("x")` | `integral(...)` | the same at the roots of `a + b x^3` |
| `"x^2/(a + b*x^5)^5".ToEntity().Integrate("x")` | `integral(...)` | four algebraic terms, and the integral of `x^2/(a + b x^5)` |
+### A difference is offered to the substitution search as a sum is
+
+**Answers where there were none.** `sin(1 + 2/(1 + x))` was answered under `u = 1 + x`, and
+`sin(1 + 2/(1 - x))` was declined: the substitution search offered every sum in the integrand as a
+candidate and no difference, so `u = 1 - x` was never tried. A difference in the integrand as asked
+is offered now as a sum is ([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"sin(1 + 2/(1 - x))".ToEntity().Integrate("x")` | `integral(...)` | in the sine and cosine integrals of `2/(1 - x)` |
+| `"cos(1 + 2/(x - 1))".ToEntity().Integrate("x")` | `integral(...)` | in the sine and cosine integrals of `2/(x - 1)` |
+| `"sin(p + k/(c - d*x))".ToEntity().Integrate("x")` | `integral(...)` | in the sine and cosine integrals of `k/(c - d x)` |
+
### A polynomial over a power of a trinomial past the square is integrated
`P(x)/(a + b x^n + c x^(2n))^k`, a polynomial over a power of a trinomial in `x^n` with symbols in
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 33b6f88f1..9c29ad3b2 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -26266,7 +26266,7 @@ private static bool IsAFunctionOfTheTangentAlone(Entity expr, Entity.Variable u)
// and not a subexpression anyone wrote: `1 + 2x^2` and `1 + 2x^2 + 4x^3` are
// the left-nested partial sums of Hearn's radicand `1 + 2x^2 + 4x^3 + x^4`,
// and each was half a second of rewriting and simplifying to be refused.
- if (u is Sumf && IsOnlyAPartialSum(expr, u))
+ if (u is Sumf or Minusf && IsOnlyAPartialSum(expr, u))
continue;
// A candidate that does not vary with x is no substitution at all, and its
@@ -27147,8 +27147,14 @@ bool APowerCanBeExact(int k)
case var special when IsASpecialFunction(special) && TheDifferentialCanBeThere(special, expr, x):
candidates.Add(node);
break;
- case Sumf(var aug, var add) when !rational && !large && node.Complexity <= LargestSumOffered:
- if (aug.ContainsNode(x) || add.ContainsNode(x)) candidates.Add(node); // Linear expressions ax + b
+ // A difference as a sum: `1 - x` below the bar of `sin(1 + 2/(1 - x))` is the
+ // substitution that `1 + x` is for `sin(1 + 2/(1 + x))`, and was never offered.
+ // In the question asked only: below it every substitution writes differences,
+ // `x = (u^2 - c)/d`, and offering them was two fifths more search on Rubi's
+ // `(c + d x)^(5/2)/(x (a + b x)^2)`, past the harness's patience.
+ case Sumf or Minusf when !rational && !large && node.Complexity <= LargestSumOffered
+ && (node is Sumf || Integration.AnsweringTheQuestionAsked):
+ if (node.DirectChildren.Any(child => child.ContainsNode(x))) candidates.Add(node); // Linear expressions ax + b
break;
}
// Sort by complexity - try simpler substitutions first
diff --git a/Sources/Tests/UnitTests/Calculus/DifferenceAsASubstitutionIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/DifferenceAsASubstitutionIntegralTest.cs
new file mode 100644
index 000000000..106ec07b7
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/DifferenceAsASubstitutionIntegralTest.cs
@@ -0,0 +1,50 @@
+//
+// 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 difference offered to the substitution search as a sum is: sin(1 + 2/(1 - x)) is
+ /// -sin(1 + 2/u) under u = 1 - x, as sin(1 + 2/(1 + x)) is
+ /// sin(1 + 2/u) under u = 1 + x, and only the second was answered.
+ /// #718
+ ///
+ ///
+ /// Checked by differentiating back with p = 0.3, k = 0.9, c = 1.1,
+ /// d = 0.7, on both sides of the pole of every row.
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class DifferenceAsASubstitutionIntegralTest
+ {
+ [Theory]
+ [InlineData("sin(1 + 2/(1 - x))")]
+ [InlineData("cos(1 + 2/(1 - x))")]
+ [InlineData("sin(1 + 2/(x - 1))")]
+ [InlineData("sin(1 + 2/(3 - 2*x))")]
+ [InlineData("sin(p + k/(c - d*x))")]
+ public void IsSubstitutedForAsASumIs(string integrand)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pinned(Entity e) => e.Substitute("p", 0.3).Substitute("k", 0.9).Substitute("c", 1.1).Substitute("d", 0.7);
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ foreach (var at in new[] { -1.0, 0.3, 0.8, 2.2, 3.0 })
+ {
+ 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) + Math.Abs((double)want.ImaginaryPart)),
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+ }
+}