diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 1880f261b..33e0d7dfa 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -249,6 +249,24 @@ roots, `1 - x^2`, is taken as its two ([#718](https://github.com/asc-community/A
| `"1/((1 - x^2)*(a + b*x^3))".ToEntity().Integrate("x")` | `integral(...)` | 1,600 characters |
| `"1/(x*(1 - x^2)*(a + b*x^3))".ToEntity().Integrate("x")` | `integral(...)` | 1,637 characters |
+### A sine's binomial cube below the bar is split over the cube's two factors
+
+**Answers where there were none.** `csc(c + d x)/(a + b sin(c + d x)^3)` was declined, and so were the second to fifth
+powers of the cosecant and the second and fourth powers of the secant over the same block (Rubi's 4.1.7). With `a`
+and `b` symbols the block has no rational factor, so the split over a symbolic quadratic in the sine had nothing to
+split. It is written `b (s + r)(s^2 - r s + r^2)` now, with `r = (a/b)^(1/3)`, which that split answers
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"csc(c + d*x)/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 5,058 characters |
+| `"csc(c + d*x)^2/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 4,866 characters |
+| `"csc(c + d*x)^3/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 5,382 characters |
+| `"csc(c + d*x)^4/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 5,426 characters |
+| `"csc(c + d*x)^5/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 5,958 characters |
+| `"sec(c + d*x)^2/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 7,010 characters |
+| `"sec(c + d*x)^4/(a + b*sin(c + d*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 11,646 characters |
+
### A symbol shared by a numerator sum's coefficients is taken out before the partial fractions
**Answers where there were none.** `(b d + 2c d x)^9/(a + b x + c x^2)^3` ran past a minute, where
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index ff16fe0f5..5df2d1209 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -23744,10 +23744,59 @@ static bool IsASumOfPowersOfX(Entity sum, Entity.Variable x)
return null;
if (OverASymbolicQuadraticInTheFunction(inS, s, w, function == sine, argument, rate, x, integrateByParts) is { } answer)
return answer;
+ if (WithASymbolicBinomialCubeFactored(inS, s, w) is { } cube
+ && OverASymbolicQuadraticInTheFunction(cube.Factored, s, w, function == sine, argument, rate, x, integrateByParts) is { } inR)
+ return inR.Substitute(cube.R, cube.Root);
}
return null;
}
+ ///
+ /// with one factor a + b s^3 below the bar, a symbol in it,
+ /// written b (s + r)(s^2 - r s + r^2) for a fresh r whose cube is a/b:
+ /// a linear and a quadratic with a symbol in it, which the rule above splits over. Null
+ /// where there is no such factor or more than one.
+ ///
+ ///
+ /// Rubi's 4.1.7: csc(x)/(a + b sin(x)^3) and its even powers of the cosecant and
+ /// the secant were declined. Under the half-angle the cube is a sextic in t with
+ /// symbols in every coefficient. The identity holds for any cube root of a/b.
+ /// https://github.com/asc-community/AngouriMath/issues/718
+ ///
+ private static (Entity Factored, Variable R, Entity Root)? WithASymbolicBinomialCubeFactored(Entity inS, Variable s, Variable w)
+ {
+ var combined = Functions.SingleQuotient.Combine(inS).InnerSimplified;
+ if (combined is Providedf(var bare, _))
+ combined = bare;
+ var (numerator, denominator) = Functions.SingleQuotient.Of(combined);
+ Entity? cube = null;
+ Entity rest = Number.Integer.One;
+ Entity free = Number.Integer.Zero, leading = Number.Integer.Zero;
+ foreach (var factor in Mulf.LinearChildren(denominator))
+ {
+ if (factor is not (Sumf or Minusf) || factor.ContainsNode(w)
+ || !TreeAnalyzer.TryGetPolynomial(factor, s, out var read)
+ || read.Count != 2 || !read.ContainsKey(EInteger.Zero) || !read.ContainsKey(EInteger.FromInt32(3))
+ || read.Values.Any(coefficient => coefficient.ContainsNode(s))
+ || !factor.Vars.Any(v => v != s))
+ {
+ rest = rest == Number.Integer.One ? factor : rest * factor;
+ continue;
+ }
+ if (cube is not null)
+ return null;
+ cube = factor;
+ free = read[EInteger.Zero];
+ leading = read[EInteger.FromInt32(3)];
+ }
+ if (cube is null || Functions.PartialFractions.IsZeroAsAValue(free) || Functions.PartialFractions.IsZeroAsAValue(leading))
+ return null;
+ var r = Variable.CreateUnique(inS, "r_cube");
+ var factored = leading * (s + r) * (MathS.Pow(s, 2) - r * s + MathS.Pow(r, 2));
+ var below = rest == Number.Integer.One ? factored : rest * factored;
+ return (numerator / below, r, MathS.Pow(free / leading, Number.Rational.Create(1, 3)));
+ }
+
///
/// The rule above in , for the function that
/// stands for and its complement: null where the integrand is
diff --git a/Sources/Tests/UnitTests/Calculus/ABinomialCubeInTheSineIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/ABinomialCubeInTheSineIntegralTest.cs
new file mode 100644
index 000000000..c6bfe2dd6
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/ABinomialCubeInTheSineIntegralTest.cs
@@ -0,0 +1,44 @@
+//
+// 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 of the sine over a + b sin^3, the cube written
+ /// b (s + r)(s^2 - r s + r^2) with r^3 = a/b and split over its factors. Rubi's 4.1.7.
+ /// #718
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class ABinomialCubeInTheSineIntegralTest
+ {
+ [Theory]
+ [InlineData("csc(c + d*x)/(a + b*sin(c + d*x)^3)")]
+ [InlineData("csc(c + d*x)^2/(a + b*sin(c + d*x)^3)")]
+ [InlineData("csc(c + d*x)^3/(a + b*sin(c + d*x)^3)")]
+ [InlineData("sec(c + d*x)^2/(a + b*sin(c + d*x)^3)")]
+ public void DifferentiatesBack(string integrand)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pinned(Entity e) => e.Substitute("a", 2).Substitute("b", 3).Substitute("c", "1/4".ToEntity()).Substitute("d", "3/2".ToEntity());
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ foreach (var at in new[] { "0.35", "0.6", "1.1", "1.4" })
+ {
+ var want = original.Substitute("x", at.ToEntity()).EvalNumerical();
+ var got = derivative.Substitute("x", at.ToEntity()).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)),
+ $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
+ }
+ }
+ }
+}