diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 9efef8955..2321ca0cd 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -419,6 +419,20 @@ leading coefficient once expanded, and declined: it is read expanded and bare no
| `"sin(x)/(a+b*sin(x))^3".Integrate("x")`, Rubi's 4.1.2.1 row 242 | `integral(...)` | the antiderivative |
| `"4*x*(1+x^2)/(a*x^2+2*b*x+a)^3".Integrate("x")` | `integral(...)` | the antiderivative |
+### `x^2` over a three-quarter power of a quadratic binomial beside another is integrated where that is elementary
+
+**Answers where there were none.** `x^2/((A + B x^2)^(3/4) (C + D x^2))` at `B C - 2 A D = 0`, Rubi's
+1.1.2.4, is the difference of the two functions whose sum answers `1/((A + B x^2)^(1/4) (C + D x^2))`
+at that ratio (the entry below), with another constant, and was declined. It is answered by the
+signs of `A` and `B` now, each form checked at points in its sign case
+([#718](https://github.com/asc-community/AngouriMath/issues/718)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"x^2/((a - b*x^2)^(3/4)*(2*a - b*x^2))".ToEntity().Integrate("x")` | `integral(...)` | an arctangent and an inverse hyperbolic tangent, by the signs of `a` and `b` |
+| `"x^2/((-2 + 3*x^2)*(-1 + 3*x^2)^(3/4))".ToEntity().Integrate("x")` | `integral(...)` | `(arctan(u) - artanh(u))/(3 sqrt(6))`, `u = sqrt(3) x/(sqrt(2) (-1 + 3 x^2)^(1/4))` |
+| `"x^2/((2 - 3*x^2)^(3/4)*(4 - 3*x^2))".ToEntity().Integrate("x")` | `integral(...)` | an arctangent and an inverse hyperbolic tangent |
+
### A cube or fourth root of a quadratic binomial beside another is integrated where that is elementary
**Answers where there were none.** `1/((A + B x^2)^(1/3) (C + D x^2))` is an elliptic integral
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
index 858c776e3..e9de4b8d8 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs
@@ -4372,13 +4372,33 @@ private static bool TryReadAsABinomialIn(Entity expr, Entity.Variable x, out Ent
/// it holds.
/// https://github.com/asc-community/AngouriMath/issues/718
///
+ ///
+ /// x^2/((A + B x^2)^(3/4) (C + D x^2)) at the same ratio is the same two functions'
+ /// difference where the quarter power is their sum, with another constant -- Rubi's
+ /// 1.1.2.4, x^2/((a - b x^2)^(3/4) (2 a - b x^2)), which was declined:
+ ///
+ /// A > 0, B > 0: -(atan(A^(3/4) (1 + s/sqrt(A))/(x y r)) - artanh(A^(3/4) (1 - s/sqrt(A))/(x y r)))/(A^(1/4) r^3)
+ /// A > 0, B < 0: (atan(A^(3/4) (1 - s/sqrt(A))/(x y r)) - artanh(A^(3/4) (1 + s/sqrt(A))/(x y r)))/(A^(1/4) r^3)
+ /// A < 0: (atan(u) - artanh(u))/((-A)^(1/4) sqrt(2) r^3)
+ ///
+ /// each times B/D as before, the constants solved for from the two functions'
+ /// derivatives and checked at points in every sign case.
+ ///
///
internal static Entity? SolveAnEllipticLookingQuotientOfBinomials(Entity expr, Entity.Variable x)
{
var (numerator, denominator) = Functions.SingleQuotient.Of(expr);
- if (numerator.ContainsNode(x))
- return null;
+ // Or c x^2 above, beside a three-quarter power below.
+ var squareAbove = false;
Entity constant = numerator;
+ if (numerator.ContainsNode(x))
+ {
+ if (!TreeAnalyzer.TryGetPolynomial(numerator, x, out var above) || above.Count != 1
+ || !above.TryGetValue(EInteger.FromInt32(2), out var squared) || squared.ContainsNode(x))
+ return null;
+ squareAbove = true;
+ constant = squared;
+ }
Entity? radicand = null;
var order = 0;
Entity? other = null;
@@ -4386,8 +4406,11 @@ private static bool TryReadAsABinomialIn(Entity expr, Entity.Variable x, out Ent
{
if (!factor.ContainsNode(x))
constant = constant / factor;
- else if (radicand is null && factor is Powf(var @base, Number.Rational power) && power.ERational.Numerator.Equals(EInteger.One)
- && (power.ERational.Denominator.Equals(EInteger.FromInt32(3)) || power.ERational.Denominator.Equals(EInteger.FromInt32(4))))
+ else if (radicand is null && factor is Powf(var @base, Number.Rational power)
+ && (squareAbove
+ ? power.ERational.Equals(ERational.Create(3, 4))
+ : power.ERational.Numerator.Equals(EInteger.One)
+ && (power.ERational.Denominator.Equals(EInteger.FromInt32(3)) || power.ERational.Denominator.Equals(EInteger.FromInt32(4)))))
{
radicand = @base;
order = power.ERational.Denominator.ToInt32Unchecked();
@@ -4427,7 +4450,34 @@ Entity Negative(Entity q) => twelfth * q / a * (MathS.Hyperbolic.Artanh(MathS.Po
var ratio = LowestOverTheSymbols(B / A);
answer = BySign(ratio, Positive(MathS.Sqrt(ratio)), Negative(MathS.Sqrt(LowestOverTheSymbols(-ratio))));
}
- else if (order == 4 && VanishesIdentically(B * C - 2 * A * D))
+ else if (order == 4 && squareAbove && VanishesIdentically(B * C - 2 * A * D))
+ {
+ var s = MathS.Sqrt(radicand);
+ var threeQuarters = Number.Rational.Create(3, 4);
+ var quarter = Number.Rational.Create(1, 4);
+ Entity BothPositive()
+ {
+ var r = MathS.Sqrt(B);
+ return -(MathS.Arctan(MathS.Pow(A, threeQuarters) * (1 + s / MathS.Sqrt(A)) / (x * y * r))
+ - MathS.Hyperbolic.Artanh(MathS.Pow(A, threeQuarters) * (1 - s / MathS.Sqrt(A)) / (x * y * r))) / (MathS.Pow(A, quarter) * MathS.Pow(r, 3));
+ }
+ Entity SlopeNegative()
+ {
+ var r = MathS.Sqrt(-B);
+ return (MathS.Arctan(MathS.Pow(A, threeQuarters) * (1 - s / MathS.Sqrt(A)) / (x * y * r))
+ - MathS.Hyperbolic.Artanh(MathS.Pow(A, threeQuarters) * (1 + s / MathS.Sqrt(A)) / (x * y * r))) / (MathS.Pow(A, quarter) * MathS.Pow(r, 3));
+ }
+ Entity ConstantNegative()
+ {
+ var r = MathS.Sqrt(B);
+ var u = x * r / (MathS.Pow(-A, quarter) * y * MathS.Sqrt(2));
+ return (MathS.Arctan(u) - MathS.Hyperbolic.Artanh(u)) / (MathS.Pow(-A, quarter) * MathS.Sqrt(2) * MathS.Pow(r, 3));
+ }
+ var toTheRatio = LowestOverTheSymbols(B / D);
+ var form = BySigns(A, B, BothPositive(), SlopeNegative(), ConstantNegative());
+ answer = toTheRatio == Number.Integer.One ? form : toTheRatio * form;
+ }
+ else if (order == 4 && !squareAbove && VanishesIdentically(B * C - 2 * A * D))
{
var s = MathS.Sqrt(radicand);
var threeQuarters = Number.Rational.Create(3, 4);
diff --git a/Sources/Tests/UnitTests/Calculus/EllipticLookingQuotientOfBinomialsTest.cs b/Sources/Tests/UnitTests/Calculus/EllipticLookingQuotientOfBinomialsTest.cs
index 15283ea63..5da884f8f 100644
--- a/Sources/Tests/UnitTests/Calculus/EllipticLookingQuotientOfBinomialsTest.cs
+++ b/Sources/Tests/UnitTests/Calculus/EllipticLookingQuotientOfBinomialsTest.cs
@@ -76,6 +76,21 @@ public void AtTheRatioWhereItIsElementary(string integrand, double a, double b,
public void WithNumbers(string integrand, double[] points)
=> DifferentiatesBack(integrand, points);
+ ///
+ /// x^2 over the three-quarter power at the fourth root's ratio, the same two
+ /// functions' difference: for each sign of b with a positive, for a
+ /// negative, and with numbers. Rubi's 1.1.2.4.
+ ///
+ [Theory]
+ [InlineData("x^2/((a + b*x^2)^(3/4)*(2*a + b*x^2))", 1.3, 0.7, new[] { 0.3, 0.9, 1.7, -0.6 })]
+ [InlineData("x^2/((a + b*x^2)^(3/4)*(2*a + b*x^2))", 1.3, -0.7, new[] { 0.3, 0.9, 1.1, -0.6 })]
+ [InlineData("x^2/((a + b*x^2)^(3/4)*(2*a + b*x^2))", -1.3, 0.7, new[] { 1.5, 2.0, 2.6, -1.8 })]
+ [InlineData("x^2/((a - b*x^2)^(3/4)*(2*a - b*x^2))", 1.3, 0.7, new[] { 0.3, 0.9, 1.1, -0.6 })]
+ [InlineData("x^2/((-2 + 3*x^2)*(-1 + 3*x^2)^(3/4))", 0, 0, new[] { 0.7, 1.1, 1.9, -1.3 })]
+ [InlineData("x^2/((2 - 3*x^2)^(3/4)*(4 - 3*x^2))", 0, 0, new[] { 0.2, 0.5, 0.7, -0.4 })]
+ public void XSquaredOverTheThreeQuarterPower(string integrand, double a, double b, double[] points)
+ => DifferentiatesBack(integrand, points, ("a", a), ("b", b));
+
///
/// Across 0, where the cube root's answers are written over x: the value is the one
/// quadrature gives.