Skip to content

Commit dd4ebcb

Browse files
Integrate a power of x beside a binomial in an odd negative power of x on both sides of 0 (#2038)
SolveByTakingAPowerOfXOutOfAFractionalPower took x^(j p) out of a sum of whole powers of x under a fractional power p: for sqrt(a + b/x^3)/x it wrote x^(-3/2) sqrt(a x^3 + b), which has no value at a negative x, where a + b/x^3 is real, and fourteen of Rubi's 1.1.3.2 x^m (a + b/x^3)^(k/2) were answered for a positive x only. Past an odd j other than 1 and -1, where j p is not whole, the rule now declines, and the substitution in the root answers them on both sides: sqrt(a + b/x^3)/x is a function of u = sqrt(a + b/x^3). Where j p is whole, x^(j p) is real on both sides and the rule is kept: (a x^3 + b x^6)^(5/3), Rubi's 1.2.3.2, is x^5 times a power of a + b x^3. Chain against master 2a98be4: the 14 partial answers of 1.1.3.2 are solved on both sides, and the first version's guard, on the odd power alone, lost 1.2.3.2:8; keyed on j p it is answered again, 15 of 15 alone in the probe. 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 49bf5d1 commit dd4ebcb

3 files changed

Lines changed: 105 additions & 1 deletion

File tree

‎BREAKING-CHANGES.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,21 @@ discriminant is zero is now one linear twice ([#233](https://github.com/asc-comm
299299
| `"1/((a*g+b*g*x)^3*(A+B*ln(k*(a+b*x)/(c+d*x)))^2)".ToEntity().Integrate("x")` | no answer in twenty seconds | 644 characters, two powers of t |
300300
| `"1/(x^2*(A+B*ln(k*x))^2)".ToEntity().Integrate("x")` | `integral(...)` | 133 characters, `Ei(-(A/B + ln(k x)))`, where before this change master gave an answer with no value at any point |
301301

302+
### A power of x beside a binomial in an odd negative power of x is integrated on both sides of 0
303+
304+
**Answers where there were none.** `sqrt(a + b/x^3)/x` and thirteen more of Rubi's 1.1.3.2,
305+
`x^m (a + b/x^3)^(k/2)`, were declined. `a + b/x^3` is real on both sides of 0, and they are answered
306+
there in the variable under the root, where taking `x^(-3/2)` out of it would leave an answer for a
307+
positive x only ([#233](https://github.com/asc-community/AngouriMath/issues/233)).
308+
309+
| Input | Was (2.5.0) | Now |
310+
|---|---|---|
311+
| `"sqrt(a+b/x^3)/x".ToEntity().Integrate("x")` | `integral(...)` | 455 characters |
312+
| `"sqrt(a+b/x^3)/x^7".ToEntity().Integrate("x")` | `integral(...)` | 101 characters |
313+
| `"(a+b/x^3)^(3/2)*x^2".ToEntity().Integrate("x")` | `integral(...)` | 842 characters |
314+
| `"x^5/sqrt(a+b/x^3)".ToEntity().Integrate("x")` | `integral(...)` | 831 characters |
315+
| `"x^2/(a+b/x^3)^(3/2)".ToEntity().Integrate("x")` | `integral(...)` | 911 characters |
316+
302317
### The last digits of an evaluated sine, cosine, tangent, arcsine or arctangent
303318

304319
**Silent, and in the hundredth digit.** `EvalNumerical` at the default hundred digits gives the

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31474,12 +31474,25 @@ bool MayBeARootOfASquare(Entity node, Entity.Variable x)
3147431474
// minute of search to be declined, where as written it is five seconds. Past those
3147531475
// nothing reads the sum as written, and the factor below answers both sides:
3147631476
// `x/sqrt(a x + b x^4)`. An even power comes out as its sign, and a fractional one
31477-
// is real for a positive x only, as the sum already was.
31477+
// beside a power of x that is not whole is real for a positive x only, as the sum
31478+
// already was.
3147831479
if (lowest is Number.Integer { EInteger.IsEven: false } odd && odd.EInteger.Abs().Equals(EInteger.One)
3147931480
&& !sum.Nodes.Any(node => node is Powf(var @base, var r) && @base == x && r is not Number.Integer)
3148031481
&& (Mulf.LinearChildren(rest).Where(part => part.ContainsNode(x)).ToList() is not [Sumf or Minusf]
3148131482
|| Sumf.LinearChildren(rest).All(term => PowerOfX(term, x) is (_, Number.Integer { EInteger: var degree }) && degree.CompareTo(1) <= 0 && degree.Sign >= 0)))
3148231483
continue;
31484+
// And x to any other odd power out of a sum of whole powers under a power p that
31485+
// leaves `x^(j p)` fractional: the sum is real on both sides of 0 and `x^(j p)` is
31486+
// not, and the answer came out for a positive x only. The substitution answers it
31487+
// on both: `sqrt(a + b/x^3)/x` is a function of `u = sqrt(a + b/x^3)`, where taking
31488+
// out `x^(-3/2)` left Rubi's 1.1.3.2 with no value at a negative x where the
31489+
// integrand is real. A whole `j p` is real on both sides, and the factor in front
31490+
// is constant on each: `(a x^3 + b x^6)^(5/3)` is `x^5` times a power of
31491+
// `a + b x^3`, Rubi's 1.2.3.2.
31492+
if (lowest is Number.Integer { EInteger.IsEven: false } oddPast && !oddPast.EInteger.Abs().Equals(EInteger.One)
31493+
&& (oddPast * power).Evaled is not Number.Integer
31494+
&& !sum.Nodes.Any(node => node is Powf(var @base, var r) && @base == x && r is not Number.Integer))
31495+
continue;
3148331496
// The rest of the integrand a constant times the sum's derivative is the plain
3148431497
// substitution's, u = the sum, which answers it as a power of u, where the sum
3148531498
// with x taken out is a search: `(x - 3 sqrt(x))^(2/3) (2 sqrt(x) - 3)/sqrt(x)`
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//
2+
// Copyright (c) 2019-2026 Angouri.
3+
// AngouriMath is licensed under MIT.
4+
// Details: https://github.com/asc-community/AngouriMath/blob/master/LICENSE.md.
5+
// Website: https://am.angouri.org.
6+
//
7+
8+
using System;
9+
using AngouriMath.Extensions;
10+
using Xunit;
11+
12+
namespace AngouriMath.Tests.Calculus
13+
{
14+
/// <summary>
15+
/// <c>a + b/x^3</c> is real on both sides of 0, and taking <c>x^(-3/2)</c> out of its root, as
16+
/// <c>sqrt(a + b/x^3) = K x^(-3/2) sqrt(a x^3 + b)</c>, left an answer with no value at a negative
17+
/// x where the integrand is real: Rubi's 1.1.3.2 <c>x^m (a + b/x^3)^(k/2)</c>, fourteen of them. The
18+
/// substitution under the root answers on both sides.
19+
/// <a href="https://github.com/asc-community/AngouriMath/issues/233">#233</a>
20+
/// </summary>
21+
[Trait("Area", "Calculus")]
22+
public sealed class APowerOfXOutOfABinomialInAnOddNegativePowerIntegralTest
23+
{
24+
[Theory]
25+
[InlineData("sqrt(a+b/x^3)/x")]
26+
[InlineData("sqrt(a+b/x^3)/x^7")]
27+
[InlineData("(a+b/x^3)^(3/2)*x^2")]
28+
[InlineData("(a+b/x^3)^(3/2)/x^10")]
29+
[InlineData("x^5/sqrt(a+b/x^3)")]
30+
[InlineData("x^2/(a+b/x^3)^(3/2)")]
31+
public void DifferentiatesBackOnBothSidesOfZero(string integrand)
32+
{
33+
var integral = integrand.ToEntity().Integrate("x");
34+
Assert.DoesNotContain("integral(", integral.Stringize());
35+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7);
36+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
37+
var original = Pinned(integrand.ToEntity());
38+
// a + b/x^3 is positive below the root of -b/a, about -0.81, and above 0.
39+
foreach (var at in new[] { -2.3, -1.7, -1.1, 0.4, 1.3, 2.2 })
40+
{
41+
var want = original.Substitute("x", at).EvalNumerical();
42+
var got = derivative.Substitute("x", at).EvalNumerical();
43+
Assert.False(got.IsNaN, $"d/dx of the antiderivative of {integrand} has no value at x = {at}, where the integrand is {want}");
44+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
45+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
46+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
47+
}
48+
}
49+
50+
/// <summary>
51+
/// And an odd power taken out where <c>j p</c> is whole, which is real on both sides: Rubi's
52+
/// 1.2.3.2 <c>(a x^3 + b x^6)^(5/3)</c> is <c>x^5</c> times a power of <c>a + b x^3</c>, and a
53+
/// guard on the odd power alone declined it.
54+
/// </summary>
55+
[Fact]
56+
public void TakesAnOddPowerOutWhereItsPowerIsWhole()
57+
{
58+
const string integrand = "(a*x^3+b*x^6)^(5/3)";
59+
var integral = integrand.ToEntity().Integrate("x");
60+
Assert.DoesNotContain("integral(", integral.Stringize());
61+
Entity Pinned(Entity e) => e.Substitute("a", 1.3).Substitute("b", 0.7);
62+
var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x");
63+
var original = Pinned(integrand.ToEntity());
64+
// a x^3 + b x^6 is positive below the root of -a/b, about -1.23, and above 0.
65+
foreach (var at in new[] { -2.3, -1.7, -1.4, 0.4, 1.3, 2.2 })
66+
{
67+
var want = original.Substitute("x", at).EvalNumerical();
68+
var got = derivative.Substitute("x", at).EvalNumerical();
69+
Assert.False(got.IsNaN, $"d/dx of the antiderivative of {integrand} has no value at x = {at}, where the integrand is {want}");
70+
Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart)
71+
< 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart) + Math.Abs((double)want.ImaginaryPart)),
72+
$"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}");
73+
}
74+
}
75+
}
76+
}

0 commit comments

Comments
 (0)