Skip to content

Commit 8c47ef1

Browse files
Split an odd half power of a linear over the second power of x (b + c x) over its two linears (#1994)
(d + e x)^(7/2)/(b x + c x^2)^2 was answered by a rule late in the chain that writes the whole integrand as one rational function in t = sqrt(d + e x) with b e - c d written out, and whose reduction never put its coefficients in lowest terms: denominators like b^35 c^5 d^31 k^35, one coefficient of 155,000 characters copied into four arms, 937,000 characters in all. The rule that keeps x (b + c x) for a root above the bar now takes the second power as well as the third and up: in s = t^2 the integrand is a polynomial part and partial fractions over s - d and s + rho, rho = (b e - c d)/c, whose coefficients come from the Taylor series at each root, each linear's fractions asked as one question, with the atoms d, b e/c, e and P's coefficients named -- naming whole coefficients hid a cancellation. Rubi's 1.2.1.2:435 is 2,568 characters from 936,939, and 1.2.1.3:1386 3,933 from 939,897, in about 10 MB from 10-11 GB. Of 83 rows of 1.2.1.2 and 1.2.1.3 with a half-odd power of a linear over a power of b x + c x^2 or a + b x + c x^2, 20 are shorter and 63 unchanged, character for character, and no verdict is lost. The #1976 entry's two third-power figures follow. Part of #233. Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 20a4b39 commit 8c47ef1

4 files changed

Lines changed: 211 additions & 48 deletions

File tree

‎BREAKING-CHANGES.md‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4236,6 +4236,25 @@ in both quadratics, the cube's coefficients grow past what the reduction takes,
42364236
| `"(7 + 13*x)/((5 + x + 2*x^2)^3*sqrt(2 + x + 3*x^2))".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative |
42374237
| `"sqrt(a + a*sec(x))/(c + d*sec(x))^2".ToEntity().Integrate("x")` | `integral(...)` | an antiderivative in `tan(x/2)` |
42384238

4239+
### An odd half power of a linear over the second power of `x (b + c x)` is split over its two linears
4240+
4241+
**Answers where there were none.** `(d + e x)^(7/2)/(b x + c x^2)^2` and the rest of Rubi's 1.2.1.2 and 1.2.1.3
4242+
with a polynomial times an odd half power of a linear over the second power of `b x + c x^2` were declined. Under
4243+
`t = sqrt(d + e x)` the integrand is rational in `s = t^2`, and it is split there: its quotient by the denominator,
4244+
and its partial fractions over `s - d` and `s + (b e - c d)/c`, which are `x` and `b + c x`, with the coefficients
4245+
of the Taylor series at each root. On the way to this release these were answered as one rational function in
4246+
`t`, in 2,900 to 940,000 characters, and the third power and higher of the entry below in 10,000 to 66,000; split,
4247+
each is under 7,000, in megabytes where the second power took up to 11 GB
4248+
([#233](https://github.com/asc-community/AngouriMath/issues/233)).
4249+
4250+
| Input | Was (2.5.0) | Now |
4251+
|---|---|---|
4252+
| `"(d + k*x)^(7/2)/(b*x + c*x^2)^2".ToEntity().Integrate("x")` | `integral(...)` | 2,568 characters |
4253+
| `"(A + B*x)*(d + k*x)^(7/2)/(b*x + c*x^2)^2".ToEntity().Integrate("x")` | `integral(...)` | 3,933 characters |
4254+
| `"(d + k*x)^(1/2)/(b*x + c*x^2)^2".ToEntity().Integrate("x")` | `integral(...)` | 1,995 characters |
4255+
| `"(d + k*x)^(1/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 3,519 characters |
4256+
| `"(A + B*x)*(d + k*x)^(9/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 6,723 characters |
4257+
42394258
### Cube roots of two linears beside a power of a third, and an odd half power of a linear over a power of `x (b + c x)`, are integrated
42404259

42414260
**Answers where there were none.** `(a + b x)^(1/3) (c + d x)^(2/3)/(e + f x)^2` and its kin, Rubi's 1.1.1.3, and
@@ -4255,8 +4274,8 @@ higher. Each declines where its linears share a root, decided as a value
42554274
| `"(a + b*x)^(1/3)*(c + d*x)^(2/3)/(k + f*x)^2".ToEntity().Integrate("x")` | `integral(...)` | 2,243 characters |
42564275
| `"1/((a + b*x)^(1/3)*(c + d*x)^(2/3)*(k + f*x)^3)".ToEntity().Integrate("x")` | `integral(...)` | 2,242 characters |
42574276
| `"(a + b*x)^(4/3)/((c + d*x)^(4/3)*(k + f*x)^2)".ToEntity().Integrate("x")` | `integral(...)` | 1,327 characters |
4258-
| `"(d + k*x)^(1/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 10,875 characters |
4259-
| `"(A + B*x)*(d + k*x)^(1/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 14,763 characters |
4277+
| `"(d + k*x)^(1/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 3,519 characters |
4278+
| `"(A + B*x)*(d + k*x)^(1/2)/(b*x + c*x^2)^3".ToEntity().Integrate("x")` | `integral(...)` | 4,383 characters |
42604279

42614280
### Powers of two linears whose exponents sum to a whole number below `-2` are integrated
42624281

‎Sources/AngouriMath/Functions/Continuous/Integration/IndefiniteIntegralSolver.cs‎

Lines changed: 144 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14320,26 +14320,35 @@ static Entity Reduced(Entity constant)
1432014320
/// <summary>
1432114321
/// A polynomial times an odd half power of a linear over a whole power of a quadratic with
1432214322
/// a root at zero, <c>P(x) (d + e x)^(j/2)/(b x + c x^2)^m</c> with <c>j</c> odd and
14323-
/// positive and <c>m &gt;= 3</c>, under <c>t = sqrt(d + e x)</c> with the quadratic written
14324-
/// as its two linears, <c>x (b + c x)</c>.
14325-
/// </summary>
14326-
/// <remarks>
14327-
/// <para>
14328-
/// With <c>x = (t^2 - d)/e</c>, <c>b + c x = (c t^2 + r)/e</c> for <c>r = b e - c d</c>, and
14329-
/// <c>dx = 2 t dt/e</c>, the integrand is
14330-
/// <c>2 e^(2m - 1) P((t^2 - d)/e) t^(j + 1)/((t^2 - d)^m (c t^2 + r)^m)</c>, and exactly so:
14331-
/// <c>t^j</c> is <c>(d + e x)^(j/2)</c> for the principal root and every complex <c>x</c>.
14332-
/// The two factors below the bar have the resultant <c>b e</c>, and a compound coefficient
14333-
/// is named by a symbol of its own and written back into the answer, as in
14334-
/// <see cref="SolveCubeRootsOfTwoLinearsBesideAWholePowerOfAThird"/>.
14335-
/// </para>
14336-
/// <para>
14337-
/// Rubi's <c>(A + B x) (d + e x)^(j/2)/(b x + c x^2)^3</c> ran past the budget: the rational
14338-
/// function in <c>t</c> is answered in a second, and the substitution that reaches it is
14339-
/// late in the chain and multiplies the quadratic out. Only the root above the bar and a
14340-
/// third power or higher, with a symbol to name: the root below the bar, the second power,
14341-
/// and numbers for coefficients are answered as they are, and left to that. Declined where
14342-
/// <c>d</c> or <c>r</c> is zero as a value, the linear then sharing a root with the quadratic.
14323+
/// positive and <c>m &gt;= 2</c>, under <c>t = sqrt(d + e x)</c> with the quadratic written
14324+
/// as its two linears, <c>x (b + c x)</c>, and split over them.
14325+
/// </summary>
14326+
/// <remarks>
14327+
/// <para>
14328+
/// With <c>s = t^2</c>, <c>x = (s - d)/e</c>, <c>b + c x = c (s + rho)/e</c> for
14329+
/// <c>rho = r/c</c> and <c>r = b e - c d</c>, and <c>dx = 2 t dt/e</c>, the integrand is
14330+
/// <c>2 e^(2m - 1)/c^m N(s)/((s - d)^m (s + rho)^m)</c> with
14331+
/// <c>N(s) = s^((j + 1)/2) P((s - d)/e)</c>, and exactly so: <c>t^j</c> is
14332+
/// <c>(d + e x)^(j/2)</c> for the principal root and every complex <c>x</c>. That is its
14333+
/// quotient by the monic denominator, a polynomial in <c>s</c>, and its partial fractions
14334+
/// over <c>s - d</c> and <c>s + rho</c>, whose coefficients are those of the Taylor series
14335+
/// of <c>N</c> over the other power at each root. The roots are <c>b e/c</c> apart, which
14336+
/// is not zero. Each linear's fractions are asked as one question in <c>t</c>. Each of
14337+
/// <c>d</c>, <c>b e/c</c>, <c>e</c> and the coefficients of <c>P</c> that is compound is
14338+
/// named by a symbol of its own and written back into the answer, as in
14339+
/// <see cref="SolveCubeRootsOfTwoLinearsBesideAWholePowerOfAThird"/>, and <c>rho</c> is
14340+
/// written in them, so that a power of <c>x</c> in <c>P</c> cancels.
14341+
/// </para>
14342+
/// <para>
14343+
/// Rubi's <c>(A + B x) (d + e x)^(j/2)/(b x + c x^2)^3</c> ran past the budget: the
14344+
/// substitution that reaches it is late in the chain and multiplies the quadratic out.
14345+
/// Asked as one rational function in <c>t</c>, the second power came back in up to 940,000
14346+
/// characters and 11 GB, <c>(d + e x)^(7/2)/(b x + c x^2)^2</c> among them, and the third
14347+
/// in 10,000 to 66,000; split, each is under 7,000 characters, in megabytes. The first
14348+
/// power and numbers for coefficients are answered compactly as they are, and left to
14349+
/// that, and so is the root below the bar, which puts a power of <c>s</c> below it too.
14350+
/// Declined where <c>d</c> or <c>r</c> is zero as a value, the linear then sharing a root
14351+
/// with the quadratic.
1434314352
/// https://github.com/asc-community/AngouriMath/issues/233
1434414353
/// </para>
1434514354
/// </remarks>
@@ -14370,7 +14379,7 @@ static Entity Reduced(Entity constant)
1437014379
}
1437114380
if (root is not var (linear, half) || quadratic is not var (q, n) || half.Sign <= 0
1437214381
|| half.Multiply(ERational.FromInt32(2)) is not { } twice || !twice.IsInteger() || !twice.ToEInteger().CanFitInInt32()
14373-
|| n < 3 || n > MaximumQuadraticPowerUnderARoot)
14382+
|| n < 2 || n > MaximumQuadraticPowerUnderARoot)
1437414383
return null;
1437514384
var j = twice.ToEInteger().ToInt32Checked();
1437614385
if (j > MaximumHalfPowerOfTheLinear
@@ -14385,40 +14394,136 @@ static Entity Reduced(Entity constant)
1438514394
|| VanishesIdentically(e) || VanishesIdentically(d) || VanishesIdentically(r))
1438614395
return null;
1438714396

14397+
// P((t^2 - d)/e) e^degree as a polynomial in s = t^2, whose coefficient of s^l is the sum
14398+
// over i of p_i e^(degree - i) binomial(i, l) (-d)^(i - l), and with the quadratic's
14399+
// coefficients and r there is something to name, or the rules after this answer it.
14400+
var coefficients = new Entity[degree + 1];
14401+
for (var l = 0; l <= degree; l++)
14402+
{
14403+
Entity coefficient = Number.Integer.Zero;
14404+
foreach (var (i, p) in read.Select(pair => (pair.Key.ToInt32Checked(), pair.Value)).Where(pair => pair.Item1 >= l))
14405+
coefficient += p * MathS.Pow(e, degree - i) * Binomial(i, l) * MathS.Pow(-d, i - l);
14406+
coefficients[l] = VanishesIdentically(coefficient) ? Number.Integer.Zero : Reduced(coefficient);
14407+
}
14408+
if (coefficients.Concat(new[] { Reduced(-d), Reduced(c), Reduced(r) }).All(value => value is Number || IsAName(value)))
14409+
return null;
14410+
14411+
// The integrand is 2 e^(2n - 1 - degree)/c^n times N(s)/((s - d)^n (s + rho)^n) in
14412+
// s = t^2, with N = s^h P((s - d)/e) e^degree and rho = r/c: its polynomial part, and
14413+
// its partial fractions over s - d and s + rho, whose coefficients are those of the
14414+
// Taylor series at each root of N over the other power. The atoms are named and rho is
14415+
// written in them, so that a power of x in P cancels there.
14416+
var h = (j + 1) / 2;
1438814417
var t = Variable.CreateUnique(expr, "t_root");
1438914418
var named = new List<(Variable Name, Entity Value)>();
1439014419
Entity Named(Entity value)
1439114420
{
14392-
if (value is Number or Variable || value is Mulf(Number, Variable) || value is Powf(Variable, Number))
14421+
if (value is Number || IsAName(value))
1439314422
return value;
1439414423
var name = Variable.CreateUnique(expr + t + named.Aggregate((Entity)Number.Integer.Zero, (sum, pair) => sum + pair.Name), "k_named");
1439514424
named.Add((name, value));
1439614425
return name;
1439714426
}
14398-
// P((t^2 - d)/e) e^degree as a polynomial in t^2: the coefficient of t^(2l) is the sum
14399-
// over i of p_i e^(degree - i) binomial(i, l) (-d)^(i - l).
14400-
Entity above = Number.Integer.Zero;
14427+
var atD = Named(Reduced(d));
14428+
var delta = Named(Reduced(b * e / c));
14429+
var rho = delta - atD;
14430+
var slope = Named(Reduced(e));
14431+
var ofP = read.Select(pair => (Power: pair.Key.ToInt32Checked(), Coefficient: Named(Reduced(pair.Value)))).ToList();
14432+
var numerator = new Entity[h + degree + 1];
14433+
for (var l = 0; l < h; l++)
14434+
numerator[l] = Number.Integer.Zero;
1440114435
for (var l = 0; l <= degree; l++)
1440214436
{
1440314437
Entity coefficient = Number.Integer.Zero;
14404-
foreach (var (i, p) in read.Select(pair => (pair.Key.ToInt32Checked(), pair.Value)).Where(pair => pair.Item1 >= l))
14405-
coefficient += p * MathS.Pow(e, degree - i) * Binomial(i, l) * MathS.Pow(-d, i - l);
14406-
// t^0 is written as nothing: InnerSimplified makes it 1 provided t is not 0.
14407-
if (!VanishesIdentically(coefficient))
14408-
above += l == 0 ? Named(Reduced(coefficient)) : Named(Reduced(coefficient)) * MathS.Pow(t, 2 * l);
14438+
foreach (var (i, p) in ofP.Where(pair => pair.Power >= l))
14439+
coefficient += p * PowerOf(slope, degree - i) * Binomial(i, l) * PowerOf(-atD, i - l);
14440+
numerator[h + l] = Reduced(coefficient);
1440914441
}
14442+
// The shift a question in t is asked over, named apart from what it is in the atoms.
14443+
var shift = Named(Reduced(r / c));
1441014444
var square = MathS.Sqr(t);
14411-
var below = MathS.Pow(square + Named(Reduced(-d)), n) * MathS.Pow(Named(Reduced(c)) * square + Named(Reduced(r)), n);
14412-
// With nothing to name the coefficients are numbers, and the rules after this answer them.
14413-
if (named.Count == 0)
14414-
return null;
14415-
var inT = (MathS.Pow(t, j + 1) * above / below).InnerSimplified;
14416-
if (Integration.ComputeAsAQuestionOfItsOwn(inT, t, integrateByParts) is not { } answer
14417-
|| answer.Nodes.Any(node => node == MathS.NaN))
14418-
return null;
14445+
14446+
// The quotient by the monic (s - d)^n (s + rho)^n, integrated term by term.
14447+
Entity inT = Number.Integer.Zero;
14448+
if (numerator.Length > 2 * n)
14449+
{
14450+
var monic = new Entity[2 * n + 1];
14451+
for (var k = 0; k <= 2 * n; k++)
14452+
monic[k] = Number.Integer.Zero;
14453+
for (var first = 0; first <= n; first++)
14454+
for (var second = 0; second <= n; second++)
14455+
monic[first + second] += Binomial(n, first) * PowerOf(-atD, n - first) * Binomial(n, second) * PowerOf(rho, n - second);
14456+
var remainder = numerator.ToArray();
14457+
for (var top = numerator.Length - 1; top >= 2 * n; top--)
14458+
{
14459+
var quotient = Reduced(remainder[top]);
14460+
if (quotient == Number.Integer.Zero)
14461+
continue;
14462+
for (var k = 0; k < 2 * n; k++)
14463+
remainder[top - 2 * n + k] -= quotient * monic[k];
14464+
var power = 2 * (top - 2 * n) + 1;
14465+
inT += quotient * MathS.Pow(t, power) / power;
14466+
}
14467+
}
14468+
14469+
// Each power of s - d and of s + rho over a coefficient named apart, and each sum
14470+
// asked as one question: the answer over one quadratic is one piecewise in the sign
14471+
// of its constant.
14472+
var parts = new List<(Variable Name, Entity Value)>();
14473+
foreach (var (at, gap, linearInS) in new[] { (atD, delta, square - atD), (-rho, -delta, square + shift) })
14474+
{
14475+
Entity? fractions = null;
14476+
foreach (var (power, value) in TaylorCoefficients(at, gap).Select((value, m) => (n - m, value)))
14477+
{
14478+
if (VanishesIdentically(value))
14479+
continue;
14480+
var name = Variable.CreateUnique(expr + t + named.Concat(parts).Aggregate((Entity)Number.Integer.Zero, (sum, pair) => sum + pair.Name), "k_part");
14481+
parts.Add((name, value));
14482+
var term = name / (power == 1 ? linearInS : MathS.Pow(linearInS, power));
14483+
fractions = fractions is null ? term : fractions + term;
14484+
}
14485+
if (fractions is null)
14486+
continue;
14487+
if (Integration.ComputeAsAQuestionOfItsOwn(fractions, t, integrateByParts) is not { } part
14488+
|| part.Nodes.Any(node => node == MathS.NaN))
14489+
return null;
14490+
inT += part;
14491+
}
14492+
var answer = inT;
14493+
foreach (var (name, value) in parts)
14494+
answer = answer.Substitute(name, value);
1441914495
foreach (var (name, value) in named)
1442014496
answer = answer.Substitute(name, value);
14421-
return Reduced(2 * constant * MathS.Pow(e, 2 * n - 1 - degree)) * answer.Substitute(t, MathS.Sqrt(linear));
14497+
return Reduced(2 * constant * MathS.Pow(e, 2 * n - 1 - degree) / MathS.Pow(c, n)) * answer.Substitute(t, MathS.Sqrt(linear));
14498+
14499+
// The coefficients of u^0 to u^(n - 1) in N(at + u)/(u + gap)^n, in lowest terms.
14500+
Entity[] TaylorCoefficients(Entity at, Entity gap)
14501+
{
14502+
var shifted = new Entity[n];
14503+
for (var q = 0; q < n; q++)
14504+
{
14505+
Entity sum = Number.Integer.Zero;
14506+
for (var l = q; l < numerator.Length; l++)
14507+
if (numerator[l] != Number.Integer.Zero)
14508+
sum += numerator[l] * Binomial(l, q) * PowerOf(at, l - q);
14509+
shifted[q] = sum;
14510+
}
14511+
var series = new Entity[n];
14512+
for (var m = 0; m < n; m++)
14513+
{
14514+
Entity sum = Number.Integer.Zero;
14515+
for (var q = 0; q <= m; q++)
14516+
sum += shifted[q] * Binomial(n + m - q - 1, m - q) * Number.Integer.Create((m - q) % 2 == 0 ? 1 : -1) / MathS.Pow(gap, n + m - q);
14517+
series[m] = Reduced(sum);
14518+
}
14519+
return series;
14520+
}
14521+
14522+
static bool IsAName(Entity value)
14523+
=> value is Variable || value is Mulf(Number, Variable) || value is Powf(Variable, Number);
14524+
14525+
static Entity PowerOf(Entity @base, int power)
14526+
=> power == 0 ? Number.Integer.One : power == 1 ? @base : MathS.Pow(@base, power);
1442214527

1442314528
static Entity Reduced(Entity constant)
1442414529
=> constant.Vars.Any() ? Functions.PartialFractions.InLowestTermsOverTheSymbols(constant) : constant.InnerSimplified;

‎Sources/AngouriMath/Functions/Continuous/Integration/Integration.Definition.cs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -743,8 +743,8 @@ private static Entity WithItsPiecewiseSumsCombined(Entity expr)
743743
// roots with the coefficients named, before the polynomial term takes it a level down to
744744
// the substitution there, whose rational function ran past the budget.
745745
if ((answer = IndefiniteIntegralSolver.SolveCubeRootsOfTwoLinearsBesideAWholePowerOfAThird(expr, x, integrateByParts)) is { }) return answer;
746-
// And a root of a linear over a third power or higher of `b x + c x^2`, under the root,
747-
// the quadratic kept as its two linears: the substitution there multiplies it out.
746+
// And a root of a linear over a second power or higher of `b x + c x^2`, under the root,
747+
// split over the quadratic's two linears: the substitution there multiplies it out.
748748
if ((answer = IndefiniteIntegralSolver.SolveAnOddHalfPowerOfALinearOverAPowerOfAQuadraticWithARootAtZero(expr, x, integrateByParts)) is { }) return answer;
749749
if ((answer = IndefiniteIntegralSolver.SolveByWritingEachLinearOnce(expr, x, integrateByParts)) is { }) return answer;
750750
// The same with a symbol for an exponent, where the product is one power that is not

0 commit comments

Comments
 (0)