diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md
index 93b9519a0..03016eb5f 100644
--- a/BREAKING-CHANGES.md
+++ b/BREAKING-CHANGES.md
@@ -2760,6 +2760,21 @@ whatever `a` is ([#718](https://github.com/asc-community/AngouriMath/issues/718)
| `"sqrt(a + i*a*sinh(g + f*x))/x".ToEntity().Integrate("x")` | `integral(...)` | `Shi` and `Chi` of half of `f x` |
| `"1/sqrt(a + i*a*sinh(g + f*x))".ToEntity().Integrate("x")` | `integral(...)` | arctangents and logarithms of `e^((g + f x)/2)` |
+### A quadratic with an even root of a symbol among its coefficients is integrated where the root is imaginary
+
+**Answers where there were none.** `1/(b (c + d x)^2 + sqrt(-a))` was answered by arms on the sign
+of its discriminant `4 sqrt(-a) b d^2`, which is imaginary for every `a > 0` and has no sign there,
+so the answer had a value for no positive `a`. The arm off the real line that a quadratic with `i`
+among its coefficients takes, the arctangent, which uses nothing about its root but
+`sqrt(q)^2 = q`, is taken where an even root of a symbol is among them too. An odd root is real
+here and a root seen only squared leaves the discriminant real, so neither takes it. Rubi's 1.3.1
+([#233](https://github.com/asc-community/AngouriMath/issues/233)).
+
+| Input | Was (2.5.0) | Now |
+|---|---|---|
+| `"1/(b*(c + d*x)^2 + sqrt(-a))".ToEntity().Integrate("x")` | 920 characters, with no value at a real `x` for `a = 1.07` or `a = -1.3`; 570, with none for `a > 0`, on the unreleased master | 608 characters, the arctangent `provided not D in RR or D > 0` |
+| `"1/(x^2 + sqrt(a))".ToEntity().Integrate("x")` | 297 characters, with no value at a real `x` for `a = 1.07` or `a = -1.3`; 261, with none for `a < 0`, on the unreleased master | 286 characters |
+
### The arm for a quadratic off the real line excludes the arms on the sign of its discriminant
**Shorter answers.** An antiderivative over a quadratic with `i` among its coefficients has an arm
diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs
index d34fc7247..d3ff34dfb 100644
--- a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs
+++ b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs
@@ -819,8 +819,8 @@ private static Entity IntegrateOverRootOfQuadratic(
///
/// The arm that a piecewise on a sign owes a quadratic off the real line, answered by
/// wherever one of is not real;
- /// where none of them holds the imaginary unit, and the sign arms
- /// are left to decide.
+ /// where none of them holds the imaginary unit or an even root of a
+ /// symbol, and the sign arms are left to decide.
///
///
/// The sign arms choose between forms by which is real where the integrand is, and off
@@ -834,18 +834,43 @@ private static Entity IntegrateOverRootOfQuadratic(
/// came back as minus its integrand below -2. The arctangent and the logarithm use nothing about their root but
/// sqrt(q)^2 = q, and are antiderivatives off the real line as well.
/// https://github.com/asc-community/AngouriMath/issues/1598
+ ///
+ /// An even root of a symbol leaves the real line as the imaginary unit does, on half of the
+ /// symbol's values: 1/(b (c + d x)^2 + sqrt(-a)) has the discriminant
+ /// 4 sqrt(-a) b d^2, imaginary for every a > 0, and was answered with
+ /// nothing there, an antiderivative of a function with one. Rubi's 1.3.1. An odd root is
+ /// real here, (-8)^(1/3) = -2, and is left to the sign arms, and so is a root seen
+ /// only squared: the discriminant of a b - b^2 x^2 - x sqrt(b^2 - 4 a b^3) holds
+ /// sqrt(b^2 - 4 a b^3)^2, and is real.
+ /// https://github.com/asc-community/AngouriMath/issues/233
+ ///
///
private static Entity.Providedf? ArmOffTheRealLine(Entity form, params Entity[] coefficients)
{
Entity? offTheRealLine = null;
foreach (var coefficient in coefficients)
- if (coefficient.InnerSimplified.Nodes.Any(node => node is Entity.Number.Complex number && !number.ImaginaryPart.EDecimal.IsZero))
+ {
+ var simplified = coefficient.InnerSimplified;
+ if (simplified.Nodes.Any(node => node is Entity.Number.Complex number && !number.ImaginaryPart.EDecimal.IsZero)
+ || AnEvenRootOfASymbolNotSquared(simplified))
offTheRealLine = offTheRealLine is null
? !coefficient.In(AngouriMath.Core.Domain.Real)
: offTheRealLine | !coefficient.In(AngouriMath.Core.Domain.Real);
+ }
return offTheRealLine is null ? null : new Entity.Providedf(form, offTheRealLine);
}
+ // An even root of something with a symbol in it, anywhere but as the base of an even power.
+ private static bool AnEvenRootOfASymbolNotSquared(Entity expr) => expr switch
+ {
+ Entity.Powf(var root, Entity.Number.Integer { EInteger.IsEven: true }) when IsAnEvenRootOfASymbol(root) => false,
+ _ when IsAnEvenRootOfASymbol(expr) => true,
+ _ => expr.DirectChildren.Any(AnEvenRootOfASymbolNotSquared),
+ };
+
+ private static bool IsAnEvenRootOfASymbol(Entity expr)
+ => expr is Entity.Powf(var radicand, Entity.Number.Rational { ERational.Denominator.IsEven: true }) && radicand.Vars.Any();
+
///
/// ∫ (px + q)/(ax^2 + bx + c) dx, by writing the numerator as a multiple of the
/// denominator's derivative plus a constant:
diff --git a/Sources/Tests/UnitTests/Calculus/AnEvenRootOfASymbolInAQuadraticIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/AnEvenRootOfASymbolInAQuadraticIntegralTest.cs
new file mode 100644
index 000000000..717d73d1d
--- /dev/null
+++ b/Sources/Tests/UnitTests/Calculus/AnEvenRootOfASymbolInAQuadraticIntegralTest.cs
@@ -0,0 +1,57 @@
+//
+// 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 quadratic with an even root of a symbol among its coefficients is off the real line on
+ /// half of that symbol's values, as one with i in it is, and takes the arm there:
+ /// 1/(b (c + d x)^2 + sqrt(-a)) has the discriminant 4 sqrt(-a) b d^2, which has no
+ /// sign for a > 0, and the answer had no value for any positive a. Rubi's 1.3.1.
+ /// #233
+ ///
+ [Trait("Area", "Calculus")]
+ public sealed class AnEvenRootOfASymbolInAQuadraticIntegralTest
+ {
+ [Theory]
+ [InlineData("1/(b*(c + d*x)^2 + sqrt(-a))", "1.3")]
+ [InlineData("1/(b*(c + d*x)^2 + sqrt(-a))", "-1.3")]
+ [InlineData("1/(x^2 + sqrt(a))", "1.3")]
+ [InlineData("1/(x^2 + sqrt(a))", "-1.3")]
+ [InlineData("x/(x^2 + x + sqrt(a))", "-1.3")]
+ public void DifferentiatesBackOnEitherSideOfTheRoot(string integrand, string a)
+ {
+ var integral = integrand.ToEntity().Integrate("x");
+ Assert.DoesNotContain("integral(", integral.Stringize());
+ Entity Pinned(Entity e) => e.Substitute("a", a.ToEntity()).Substitute("b", 0.7).Substitute("c", 0.4).Substitute("d", 0.3);
+ var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
+ var original = Pinned(integrand.ToEntity());
+ var compared = 0;
+ foreach (var at in new[] { -1.7, -0.6, 0.3, 0.8, 1.3, 2.9 })
+ {
+ var want = original.Substitute("x", at).EvalNumerical();
+ if (want.IsNaN)
+ continue;
+ var got = derivative.Substitute("x", at).EvalNumerical();
+ compared++;
+ var size = Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart));
+ Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart) < 1e-9 * size,
+ $"d/dx of the antiderivative of {integrand} at a = {a} is {got} at x = {at}, where the integrand is {want}");
+ }
+ Assert.True(compared >= 5, $"only {compared} points could be compared for {integrand} at a = {a}");
+ }
+
+ // An odd root is real here, (-8)^(1/3) = -2, and leaves the arms on the sign as they were.
+ [Fact]
+ public void AnOddRootTakesNoArmOffTheRealLine()
+ => Assert.DoesNotContain("in RR", "1/(x^2 + a^(1/3))".ToEntity().Integrate("x").Stringize());
+ }
+}