From 9db8fba325ed72835d8c0b1bfbdae331e8679476 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Fri, 23 Oct 2026 03:35:05 +0000 Subject: [PATCH] Read a linear exponent written as a negation in the gamma rule The rule for a power beside an exponential of a power read its exponent term by term, so e^(-a - b x) was answered and e^(-(a + b x)) was declined, though they are one function. The second is how gamma(2, a + b x) is elementary, e^(-(a + b x)) (1 + a + b x), and how a hyperbolic function of a + b x arrives as exponentials. A linear exponent written otherwise is now read as its offset and rate. Rubi's suite on the harness that reads GAMMA, against master 3dc5ac6b: 48,634 -> 48,700 of 49,052, 0 wrong, no solved row lost. The gains are 23 in 6.2.1, 20 in 6.1.1, 9 in 6.7.1, 7 in 2.1, 7 in 8.6 (x^(p/3) gamma(2, a + b x) and (c + d x)^m gamma(1, a + b x)) and 1 in 2.3. Three rows of 6.1.1, (c + d x)^m (a + i a sinh(e + f x))^k, move from a quick decline to the harness's timeout: the library answers them in 0.4 s, correctly at x = 0.35, 0.9, 1.45, 18.1 and -12.7, and the harness's recheck at far points at 300 and 2,000 digits evaluates the gamma function there: 22 to 26 s for the derivative at one point at 300. 8.6:249, solved in 21 s in the base run, times out alone on both builds. Part of #2075. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 1 + .../Continuous/Integration/IntegralPatterns.cs | 14 +++++++++++++- ...PowerBesideAnExponentialOfAPowerIntegralTest.cs | 4 ++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 3d83a5225..7ecac3822 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -161,6 +161,7 @@ as `a - b = 0`, as a statement's own solve reads it: `"x + 1 = 3".Solve("x")` wa | `"x^m*gamma(n, b*x)".ToEntity().Integrate("x")` | a `FunctionArgumentCountException` | `(x ^ (m + 1) * gamma(n, b * x) - x ^ m * (b * x) ^ (-m) * gamma(n + m + 1, b * x) / b) / (m + 1) + C` | | `"gamma(0, a + b*x)/(c + d*x)^2".ToEntity().Integrate("x")` | a `FunctionArgumentCountException` | `-gamma(0, a + b x)/(d (c + d x))` and two exponential integrals, of `a + b x` and of `b (c + d x)/d` | | `"x^(1/3)*e^(-x)".ToEntity().Integrate("x")` | `integral(x ^ (1/3) * e ^ (-x), x)` | `-gamma(4/3, x) + C` | +| `"x^(1/3)*gamma(2, a + b*x)".ToEntity().Integrate("x")` | a `FunctionArgumentCountException` | `-b * e ^ (-a) * x ^ (7/3) * (b * x) ^ (-7/3) * gamma(7/3, b * x) + -(1 + a) * e ^ (-a) * x ^ (4/3) * (b * x) ^ (-4/3) * gamma(4/3, b * x) + C` | | `"(c + d*x)^m*e^(a + b*x)".ToEntity().Integrate("x")` | `integral((c + d * x) ^ m * e ^ (a + b * x), x)` | `e ^ (a - b * c / d) * (c + d * x) ^ m * (-b * (c + d * x) / d) ^ (-m) * gamma(m + 1, -b * (c + d * x) / d) / b + C` | | `"x^31*e^(-x)".ToEntity().Integrate("x")` | a sum of 32 terms, 6,172 characters | `-gamma(32, x) + C` | | `"integral(e^(x^3), x, 0, 1)".ToEntity().Simplify()` | `integral(e ^ x ^ 3, x, 0, 1)` | `(gamma(1/3, -1) - (-2/3)!) / 3`, which is `1.3419044179774…` | diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs index 25dfb935c..52254ec9d 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs @@ -435,7 +435,19 @@ private static bool TakeMomentFactor(Entity factor, bool inverted, Entity.Variab degree = read; } else - return null; + { + term = null; + break; + } + // Or a linear written otherwise, as the negation -(a + b x) is, which is how gamma(2, a + b x) is + // elementary: e^(-(a + b x)) (1 + a + b x). https://github.com/asc-community/AngouriMath/issues/2075 + if (term is null && TreeAnalyzer.TryGetPolyLinear(exponent, x, out var slopeOfTheExponent, out var offsetOfTheExponent) + && !TreeAnalyzer.IsZero(slopeOfTheExponent)) + { + constant = offsetOfTheExponent; + term = (slopeOfTheExponent * x).InnerSimplified; + degree = Entity.Number.Integer.One; + } if (term is null || degree is null || TreeAnalyzer.IsZero(degree)) return null; diff --git a/Sources/Tests/UnitTests/Calculus/APowerBesideAnExponentialOfAPowerIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/APowerBesideAnExponentialOfAPowerIntegralTest.cs index 4a6c6f022..cae26c093 100644 --- a/Sources/Tests/UnitTests/Calculus/APowerBesideAnExponentialOfAPowerIntegralTest.cs +++ b/Sources/Tests/UnitTests/Calculus/APowerBesideAnExponentialOfAPowerIntegralTest.cs @@ -69,6 +69,10 @@ public void AHighWholePowerIsOneGammaFunction() [Theory] [InlineData("(c + d*x)^m*e^(a + b*x)")] + // A linear exponent written as a negation, which is how gamma(2, a + b x) is elementary. + [InlineData("x^(1/3)*e^(-(a + b*x))")] + [InlineData("x^(1/3)*gamma(2, a + b*x)")] + [InlineData("gamma(2, a + b*x)/x^(4/3)")] [InlineData("(c + d*x)^(1/3)*f^(a + b*x)")] [InlineData("e^(a + b*x)/(c + d*x)^(4/3)")] public void APowerOfALinearBesideAnExponentialOfAnother(string integrand) => DifferentiatesBack(integrand);