From af0f4517864b7abf43b7871151f1880b51e673cc Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Sat, 10 Oct 2026 10:20:48 +0000 Subject: [PATCH 1/3] A power of a quadratic with symbols in its outer coefficients is integrated over the monic quadratic Part of #718. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 12 +++++ .../Integration/IntegralPatterns.cs | 45 ++++++++++++++++++- ...APowerOfAQuadraticMadeMonicIntegralTest.cs | 43 ++++++++++++++++++ 3 files changed, 98 insertions(+), 2 deletions(-) create mode 100644 Sources/Tests/UnitTests/Calculus/APowerOfAQuadraticMadeMonicIntegralTest.cs diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index a6f0a85da..9514772f1 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -177,6 +177,18 @@ the division's; with it on, the rounding is the setting's own and stays | `"(-60.5)!"` at 30 digits, downcasting off | `5.86118478907722232671451280188E-81` | `2.93059239453861116335725639905E-81` | | `"abs(75 + 316.22776601683796i)"`, downcasting off | `325` | `325.000000000000026076735749…` | +### A power of a quadratic with symbols in its outer coefficients is integrated over the monic quadratic + +**Answers where there were none.** `x^5/(a + b x + c x^2)^4` was declined, and so were `x^6` and `x^7` over the +fourth power and `x^5` and `x^7` over the fifth, Rubi's 1.2.1.2, while `x^5/(2 + b x + c x^2)^4` and +`x^5/(k + m x + x^2)^4` were answered. Where the reduction declines the quadratic as written, it is integrated as +`1/c^n` times the integral over `(x^2 + k x + m)^n`, with `k = b/c` and `m = a/c` fresh symbols while it is, and put +back after ([#718](https://github.com/asc-community/AngouriMath/issues/718)). + +| Input | Was (2.5.0) | Now | +|---|---|---| +| `"x^5/(a + b*x + c*x^2)^4".ToEntity().Integrate("x")` | `integral(...)` | the antiderivative, in three cases by the sign of `4 a/c - (b/c)^2`, with arctangents and logarithms | + ### `a + i a tan` beside the tangent's differential is lowered over its conjugate **Answers where there were none.** `sqrt(a + i a tan(x))/(c + d tan(x))^(3/2)` ran past thirty seconds: diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs index 23d22597c..e625ed9ce 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs @@ -528,8 +528,9 @@ _ when TryReadOverSquareTimesRoot(expr, x, out var overFactor, out var overRadic && repetitions.EInteger.ToInt32Checked() is var n and >= 2 && TreeAnalyzer.TryGetPolyQuadratic(repeated, x, out var qa, out var qb, out var qc) && (!numerator.ContainsNode(x) || !TreeAnalyzer.IsZero(qa)) - && IntegrateRationalOverPowerOfQuadratic(numerator, qa, qb, qc, repeated, n, x, - withoutTheFirstPower: TheFirstPowerCancels(numerator, qa, qb, qc, repeated, n, x)) is { } repeatedAnswer + && (IntegrateRationalOverPowerOfQuadratic(numerator, qa, qb, qc, repeated, n, x, + withoutTheFirstPower: TheFirstPowerCancels(numerator, qa, qb, qc, repeated, n, x)) + ?? OverThePowerOfTheMonicQuadraticInNamedCoefficients(numerator, qa, qb, qc, n, x)) is { } repeatedAnswer => repeatedAnswer, // ∫ (px + q)/(bx + c) dx, the same rewrite one degree down: the quotient is the @@ -1124,6 +1125,46 @@ private static Entity IntegrateLinearOverPowerOfQuadratic( LinearOverPowerOfLinear(p, q, b, c, power, x)); } + /// + /// ∫ N(x)/(a x^2 + b x + c)^n dx as 1/a^n times the integral over + /// (x^2 + k x + m)^n, with k = b/a and m = c/a each a fresh symbol + /// while it is integrated, where + /// declined the quadratic as written. + /// + /// + /// With symbols in both a and c the divisions by the quadratic leave + /// remainders the reduction cannot read as linear: x^5/(a + b x + c x^2)^4 was + /// declined, where x^5/(k + m x + x^2)^4 and x^5/(2 + b x + c x^2)^4 are + /// answered in a few hundred milliseconds. Rubi's 1.2.1.2. + /// https://github.com/asc-community/AngouriMath/issues/718 + /// + private static Entity? OverThePowerOfTheMonicQuadraticInNamedCoefficients( + Entity numerator, Entity a, Entity b, Entity c, int power, Entity.Variable x) + { + if (a is Entity.Number) + return null; + Entity everything = numerator + a + b + c; + var named = new List<(Entity.Variable Name, Entity Value)>(); + Entity Named(Entity value) + { + var written = value.InnerSimplified; + if (written is Entity.Variable or Entity.Number) + return written; + var name = Entity.Variable.CreateUnique(everything, "k_q"); + everything += name; + named.Add((name, written)); + return name; + } + var linear = Named(b / a); + var constant = Named(c / a); + var monic = MathS.Pow(x, 2) + linear * x + constant; + if (IntegrateRationalOverPowerOfQuadratic(numerator, Entity.Number.Integer.One, linear, constant, monic, power, x) is not { } answer) + return null; + foreach (var (name, value) in named) + answer = answer.Substitute(name, value); + return answer / MathS.Pow(a, power); + } + /// /// ∫ N(x)/(a x^2 + b x + c)^n dx for a numerator of any degree, or /// where the fraction is improper and this is not the rule for it. diff --git a/Sources/Tests/UnitTests/Calculus/APowerOfAQuadraticMadeMonicIntegralTest.cs b/Sources/Tests/UnitTests/Calculus/APowerOfAQuadraticMadeMonicIntegralTest.cs new file mode 100644 index 000000000..1badea1ad --- /dev/null +++ b/Sources/Tests/UnitTests/Calculus/APowerOfAQuadraticMadeMonicIntegralTest.cs @@ -0,0 +1,43 @@ +// +// 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 +{ + /// + /// A polynomial over a power of a quadratic with symbols in both outer coefficients is + /// integrated over the monic quadratic in named coefficients where the reduction declines + /// it as written. Rubi's 1.2.1.2. + /// #718 + /// + [Trait("Area", "Calculus")] + public sealed class APowerOfAQuadraticMadeMonicIntegralTest + { + [Theory] + [InlineData("x^5/(a + b*x + c*x^2)^4")] + [InlineData("x^7/(a + b*x + c*x^2)^5")] + public void DifferentiatesBack(string integrand) + { + var integral = integrand.ToEntity().Integrate("x"); + Assert.DoesNotContain("integral(", integral.Stringize()); + Entity Pinned(Entity e) => e.Substitute("a", 2).Substitute("b", 3).Substitute("c", 5); + var derivative = Pinned(integral.Substitute("C", 0)).Differentiate("x"); + var original = Pinned(integrand.ToEntity()); + foreach (var at in new[] { -1.7, -0.6, 0.45, 1.3 }) + { + var want = original.Substitute("x", at).EvalNumerical(); + var got = derivative.Substitute("x", at).EvalNumerical(); + Assert.True(Math.Abs((double)(got - want).RealPart) + Math.Abs((double)(got - want).ImaginaryPart) + < 1e-9 * Math.Max(1, Math.Abs((double)want.RealPart)), + $"d/dx of the antiderivative of {integrand} is {got} at x = {at}, where the integrand is {want}"); + } + } + } +} From ae8df47af67f31e129443bbe43c78c904374951c Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Sat, 10 Oct 2026 20:17:14 +0000 Subject: [PATCH 2/3] A leading coefficient that is a number as written is not named Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- .../Functions/Continuous/Integration/IntegralPatterns.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs index e625ed9ce..d34fc7247 100644 --- a/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs +++ b/Sources/AngouriMath/Functions/Continuous/Integration/IntegralPatterns.cs @@ -1135,13 +1135,16 @@ private static Entity IntegrateLinearOverPowerOfQuadratic( /// With symbols in both a and c the divisions by the quadratic leave /// remainders the reduction cannot read as linear: x^5/(a + b x + c x^2)^4 was /// declined, where x^5/(k + m x + x^2)^4 and x^5/(2 + b x + c x^2)^4 are - /// answered in a few hundred milliseconds. Rubi's 1.2.1.2. + /// answered in a few hundred milliseconds. Rubi's 1.2.1.2. A leading coefficient that is a + /// number as written, such as the 1 * 1^2 a substitution leaves, is not one: the + /// substitution that wrote (b d + 2 c d x)^8/(a + b x + c x^2)^3 in the quadratic + /// asks with one, and naming its other two took the answer from 65,236 characters to 202,057. /// https://github.com/asc-community/AngouriMath/issues/718 /// private static Entity? OverThePowerOfTheMonicQuadraticInNamedCoefficients( Entity numerator, Entity a, Entity b, Entity c, int power, Entity.Variable x) { - if (a is Entity.Number) + if (a.InnerSimplified is Entity.Number) return null; Entity everything = numerator + a + b + c; var named = new List<(Entity.Variable Name, Entity Value)>(); From 69e2da7bce0e2e30c5b264bdbdc4148c8b806b07 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Sun, 11 Oct 2026 09:01:36 +0000 Subject: [PATCH 3/3] Measure the entry's five rows on 2.5.0, master 78680f07 and the branch Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- BREAKING-CHANGES.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index 70c2b3d5a..efd821edf 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -183,11 +183,16 @@ the division's; with it on, the rounding is the setting's own and stays fourth power and `x^5` and `x^7` over the fifth, Rubi's 1.2.1.2, while `x^5/(2 + b x + c x^2)^4` and `x^5/(k + m x + x^2)^4` were answered. Where the reduction declines the quadratic as written, it is integrated as `1/c^n` times the integral over `(x^2 + k x + m)^n`, with `k = b/c` and `m = a/c` fresh symbols while it is, and put -back after ([#718](https://github.com/asc-community/AngouriMath/issues/718)). +back after. Each answer is in three cases by the sign of `4 a/c - (b/c)^2` +([#718](https://github.com/asc-community/AngouriMath/issues/718)). | Input | Was (2.5.0) | Now | |---|---|---| -| `"x^5/(a + b*x + c*x^2)^4".ToEntity().Integrate("x")` | `integral(...)` | the antiderivative, in three cases by the sign of `4 a/c - (b/c)^2`, with arctangents and logarithms | +| `"x^5/(a + b*x + c*x^2)^4".ToEntity().Integrate("x")` | `integral(...)` | 3,474 characters | +| `"x^6/(a + b*x + c*x^2)^4".ToEntity().Integrate("x")` | `integral(...)` | 4,142 characters | +| `"x^7/(a + b*x + c*x^2)^4".ToEntity().Integrate("x")` | `integral(...)` | 4,823 characters | +| `"x^5/(a + b*x + c*x^2)^5".ToEntity().Integrate("x")` | `integral(...)` | 4,066 characters | +| `"x^7/(a + b*x + c*x^2)^5".ToEntity().Integrate("x")` | `integral(...)` | 5,602 characters | ### `a + i a tan` beside the tangent's differential is lowered over its conjugate