Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2146,6 +2146,19 @@ is written in closed form. A quadratic that factors over linears is left to the
| `"(f + g*x)/((d + k*x)^2*(a + b*x + c*x^2)^3)".ToEntity().Integrate("x")` | `integral(...)` | 21,943 characters |
| `"(A + B*x + C*x^2)/((d + k*x)^3*(a + c*x^2)^3)".ToEntity().Integrate("x")` | `integral(...)` | 25,201 characters |

### A power of x beside a high power of a binomial in x^2 is left to the binomial rules

**Shorter answers.** The rule above took a power of x off `1/(x^4 (a + b x^2)^10)`, Rubi's 1.1.2.2, four times, over ten
levels of its recurrence each, and the answer's like terms were never gathered. Beside a power of x past the second
and a binomial in `x^2` to the sixth power or past it, it now declines, as it already did where the integrand is odd,
and the rules for `x^m (a + b x^2)^p` answer it. Beside `x^2` the two are a trade, shorter there at four times the
cost, and it is left as it was ([#233](https://github.com/asc-community/AngouriMath/issues/233)).

| Input | Was (2.5.0) | Now |
|---|---|---|
| `"1/(x^4*(a+b*x^2)^10)".ToEntity().Integrate("x")` | `integral(...)`; 75,607 characters on the unreleased master | 8,559 characters |
| `"1/(x^6*(a+b*x^2)^8)".ToEntity().Integrate("x")` | `integral(...)`; 33,638 characters on the unreleased master | 6,063 characters |

### An odd power of a quadratic's derivative over a power of the quadratic is integrated in the quadratic

**Shorter answers, and answers where there were none.** `(b + 2c x)^9/(a + b x + c x^2)^3` was answered through the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25984,14 +25984,19 @@ Entity TakeOut(Entity node)
// a second and ten levels of this ran past the budget.
if (Functions.PartialFractions.HoldsTheImaginaryUnit(quadratic) || linear is null && VanishesIdentically(a1))
return null;
// Nor beside a power of x where the integrand is odd and the power of the quadratic high:
// it is then x times a function of x^2, the substitution's under u = x^2, and peeling
// fifteen powers of x off `(b + 2 c x^2)/(x^15 (b + c x^2)^8)` here ran past the budget,
// where in u it is two linears. An even one, and a low power, are left here, where they
// were answered.
// Nor beside a power of x where the power of the quadratic is high. Odd, the integrand is
// x times a function of x^2, the substitution's under u = x^2, and peeling fifteen powers
// of x off `(b + 2 c x^2)/(x^15 (b + c x^2)^8)` here ran past the budget, where in u it is
// two linears. Even, and peeled past the second power of x, it is the binomial rules'
// `x^m (a + b x^2)^p`: peeled here four times over ten levels of the recurrence, Rubi's
// 1.1.2.2 `1/(x^4 (a + b x^2)^10)` came back in 75,607 characters, its like terms never
// gathered, and the binomial rules write 8,559. Beside `x^2` the two are a trade, shorter
// there at four times the cost, and it stays here. A low power is left here, where it was
// answered.
if (linear is not null && power >= 6 && VanishesIdentically(a1) && TreeAnalyzer.TryGetPolyLinear(linear, x, out _, out var interceptOfTheLinear)
&& VanishesIdentically(interceptOfTheLinear)
&& top.Keys.All(degree => degree.IsEven != (linearPower % 2 == 0)))
&& (top.Keys.All(degree => degree.IsEven != (linearPower % 2 == 0))
|| linearPower >= 3 && top.Keys.All(degree => degree.IsEven == (linearPower % 2 == 0))))
return null;
// A quadratic that factors over linears is the partial fractions' to take apart, and
// they do it cheaply: `(d + e x)^10/((d + e x) (a e + c d x))^4`, written out, went from
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//
// 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
{
/// <summary>
/// A power of x past the second beside a high power of a binomial in <c>x^2</c> is the binomial rules', even or odd:
/// the reduction over a power of a symbolic quadratic took the power of x off Rubi's 1.1.2.2
/// <c>1/(x^4 (a + b x^2)^10)</c> four times over ten levels each, and came back in 75,607 characters
/// with its like terms never gathered, where the binomial rules write 8,559.
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
/// </summary>
[Trait("Area", "Calculus")]
public sealed class APowerOfXBesideAHighPowerOfABinomialInXSquaredIntegralTest
{
[Theory]
[InlineData("1/(x^4*(a+b*x^2)^10)", 12000)]
[InlineData("1/(x^6*(a+b*x^2)^8)", 9000)]
public void IsAnsweredInFewCharacters(string integrand, int characters)
{
var integral = integrand.ToEntity().Integrate("x");
var text = integral.Stringize();
Assert.DoesNotContain("integral(", text);
Assert.True(text.Length < characters, $"the antiderivative of {integrand} is {text.Length} characters");
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7);
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
var original = Pinned(integrand.ToEntity());
foreach (var at in new[] { -1.7, -0.6, 0.4, 1.3, 2.2 })
{
var want = original.Substitute("x", at).EvalNumerical();
var got = derivative.Substitute("x", at).EvalNumerical();
Assert.False(got.IsNaN, $"d/dx of the antiderivative of {integrand} has no value at x = {at}, where the integrand is {want}");
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
}
}
}
}
Loading