diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index ed52626dd..e9ae2c6a1 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -326,6 +326,21 @@ improper fraction is declined before the first division rather than after the la | `"(1 - b*x^2)^3/(c*(1 - b*x^2) + a*d*x^2)^3".ToEntity().Integrate("x")` | no answer within a minute | the antiderivative | | `"(a + b*x)^(5/2)/(c + d*x)^4".ToEntity().Integrate("x")` | `integral(...)` | the antiderivative | +### The Hermite reduction's system is solved in one order whatever the spelling + +**Faster, and not a different value.** The reduction of a rational integrand with a repeated factor +below the bar solves one linear system for the rational part, and took its rows in the order the +powers of `x` were met, which follows how the factors are written. With symbols in the coefficients +the elimination's pivots followed that order, and in one order the solution came out as quotients of +polynomials of the thirty-sixth degree in the symbols that nothing reduced: +`x/((1 + x^2)^3 (2 a x + b (x^2 + 1)))` took 42 s, and with `(x^2 + 1)^3` below the bar 1 s. The rows +are ordered by their power of `x` now. Where the order mattered, the antiderivative's coefficients can +come out reduced where they were not. + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"x/((1 + x^2)^3*(2*a*x + b*(x^2 + 1)))".ToEntity().Integrate("x")` | `integral(...)` | the antiderivative, in about half a second, as with `(x^2 + 1)^3` | + ### A symbolic parameter no longer stops a rational integrand being integrated `1/(8 + x^3)` and `1/(16 - x^4)` are answered at once. `1/(a^3 + x^3)` and `1/(a^4 - x^4)` were not, diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs index a268e555e..9965d1608 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs @@ -12766,7 +12766,12 @@ private static Entity SquarefreePartAsWritten(Entity denominator, Entity.Variabl ? PolynomialProduct(PolynomialProduct(abovePoly, dSquared), qSquared) : PolynomialProduct(PolynomialProduct(abovePoly, dSquared), squarefreePoly); - var powers = columns.SelectMany(c => c.Keys).Concat(targetRead.Keys).Distinct().ToList(); + // The rows by their power of x, not in the order the dictionaries met them: that order + // is the spelling's, and the elimination's pivots follow it. `(1 + x^2)^3` below the bar + // where `(x^2 + 1)^3` is written left the solution in coefficients of the thirty-sixth + // degree in the symbols that nothing cancelled, and the logarithmic part they made was + // forty seconds of declining; in the one order both are under a second. + var powers = columns.SelectMany(c => c.Keys).Concat(targetRead.Keys).Distinct().OrderBy(power => power).ToList(); var width = columns.Count; var matrix = new Entity[powers.Count][]; var rhs = new Entity[powers.Count]; diff --git a/Sources/Tests/UnitTests/Calculus/RationalFactorsBesideASymbolicQuadraticTest.cs b/Sources/Tests/UnitTests/Calculus/RationalFactorsBesideASymbolicQuadraticTest.cs index f43db2ae2..a6fd0788b 100644 --- a/Sources/Tests/UnitTests/Calculus/RationalFactorsBesideASymbolicQuadraticTest.cs +++ b/Sources/Tests/UnitTests/Calculus/RationalFactorsBesideASymbolicQuadraticTest.cs @@ -124,5 +124,18 @@ private static void AnswersAndDifferentiatesBack(string integrand) [InlineData("tan(x)^4/(a+b*csc(x))")] [InlineData("sin(x)^2/(a+b*cos(x))")] public void TheNeighboursStayAnswered(string integrand) => AnswersAndDifferentiatesBack(integrand); + + /// + /// The same integrand with `1 + x^2` written either way round. The Hermite reduction's + /// system took its rows in the order its dictionaries met the powers, which is the + /// spelling's, and with `(1 + x^2)^3` below the bar the solution came out in coefficients + /// of the thirty-sixth degree in the symbols that nothing cancelled: forty seconds of + /// declining their logarithmic part before the answer, where `(x^2 + 1)^3` took one. + /// + [Theory] + [InlineData("x/((1+x^2)^3*(2*a*x+b*(x^2+1)))")] + [InlineData("x/((x^2+1)^3*(2*a*x+b*(x^2+1)))")] + [InlineData("4*x*(1-x^2)^2/((1+x^2)^3*(2*a*x+b*(1+x^2)))")] + public void EitherSpellingOfOnePlusTheSquare(string integrand) => AnswersAndDifferentiatesBack(integrand); } }