diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 8624d1d63..8e9ed4435 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -447,6 +447,19 @@ case is most of its length ([#718](https://github.com/asc-community/AngouriMath/ | `"x^4/((a + b*x^2 + c*x^4)*sqrt(d + k*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 28,551 characters | | `"1/(x^2*(a + b*x^2 + c*x^4)*sqrt(d + k*x^2))".ToEntity().Integrate("x")` | `integral(...)` | 10,194 characters | +### A polynomial of degree six with a large leading coefficient is factored + +**Answers where there were none.** The factoring clears a leading coefficient by rescaling the variable, and declined +when that raised it past 2^512. Over the square of `(x^2 + 6)^3 + 324 x^3` the resultant the integrator factors is a sextic +with a 107-bit leading coefficient, which needs 2^535. Up to degree six the bound is now 2^1024; past it, it stays +([#718](https://github.com/asc-community/AngouriMath/issues/718)). + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"x^8/(216+108*x^2+324*x^3+18*x^4+x^6)^2".ToEntity().Integrate("x")` | `integral(...)` | 381 characters, a sum over the roots of the sextic | +| `"x^5/(216+108*x^2+324*x^3+18*x^4+x^6)^2".ToEntity().Integrate("x")` | `integral(...)` | 377 characters | +| `"x^2/(216+108*x^2+324*x^3+18*x^4+x^6)^2".ToEntity().Integrate("x")` | `integral(...)` | 394 characters | + ### A rational function past the twelfth degree is reduced by Hermite's method **Answers where there were none.** The integrator read a denominator of degree twelve at most, so a derivative over diff --git a/Sources/AngouriMath/Functions/Algebra/Polynomials/PolynomialFactorization.cs b/Sources/AngouriMath/Functions/Algebra/Polynomials/PolynomialFactorization.cs index 58acb124d..67770ad61 100644 --- a/Sources/AngouriMath/Functions/Algebra/Polynomials/PolynomialFactorization.cs +++ b/Sources/AngouriMath/Functions/Algebra/Polynomials/PolynomialFactorization.cs @@ -91,6 +91,18 @@ internal static class PolynomialFactorization [ConstantField] private static readonly EInteger MaxMonicScale = EInteger.FromInt32(2).Pow(512); + /// + /// The same, up to : a sextic of Rubi's 1.3.1 whose leading + /// coefficient is 107 bits needs 2^535, and is factored in a quarter of a second. Past + /// that degree the bound stays: 1/(1 + cosh(x)^5) asks for a hundred and twenty + /// polynomials of degree eight and nine at 2^580 to 2^880, a second each and none of them + /// needed, and went from 7 seconds to 72 with the higher bound for every degree. + /// + [ConstantField] + private static readonly EInteger MaxLowDegreeMonicScale = EInteger.FromInt32(2).Pow(1024); + + private const int MaxLowDegree = 6; + /// /// written as a product of powers of irreducible polynomials /// over Q, or where it is not a polynomial in @@ -267,7 +279,7 @@ internal static bool IsWorthFactoringToSolve(Entity expr, Variable x) return FactorMonic(primitive); var degree = primitive.Degree; - if (lead.Abs().Pow(degree - 1).CompareTo(MaxMonicScale) > 0) + if (lead.Abs().Pow(degree - 1).CompareTo(degree <= MaxLowDegree ? MaxLowDegreeMonicScale : MaxMonicScale) > 0) return null; var scaled = new EInteger[degree + 1]; diff --git a/Sources/Tests/UnitTests/Calculus/RothsteinTragerTest.cs b/Sources/Tests/UnitTests/Calculus/RothsteinTragerTest.cs index 2ae06ec6b..7a2a5ba67 100644 --- a/Sources/Tests/UnitTests/Calculus/RothsteinTragerTest.cs +++ b/Sources/Tests/UnitTests/Calculus/RothsteinTragerTest.cs @@ -119,5 +119,17 @@ public void TheArctangentsAreContinuous() [InlineData("x^2/(x^4 + x^3 + 1)")] public void AResidueOfDegreeThreeIsASumOverRoots(string integrand) => Assert.Contains(DifferentiatesBack(integrand, TheLine).Nodes, node => node is Entity.SumOverSetf); + + /// + /// Over a square, the resultant of what Hermite's reduction leaves has a 107-bit leading + /// coefficient, and clearing it rescales a sextic past 2^512, where the factoring declined. + /// Rubi's 1.3.1 over ((x^2 + 6)^3 + 324 x^3)^2, whose first power was answered. + /// #718 + /// + [Theory] + [InlineData("x^8/(216+108*x^2+324*x^3+18*x^4+x^6)^2")] + [InlineData("x^2/(216+108*x^2+324*x^3+18*x^4+x^6)^2")] + public void ALargeLeadingCoefficientOfTheResultantIsCleared(string integrand) + => Assert.Contains(DifferentiatesBack(integrand, TheLine).Nodes, node => node is Entity.SumOverSetf); } }