From 746bd78249ba4e42e92cf10e0f2a34c56f96d8e1 Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Thu, 12 Nov 2026 04:42:17 +0000 Subject: [PATCH] Read a product with a power for a factor by the exponent's limit in a limit A one-sided 0 * oo with a power u^v for a factor, v tending to a constant c other than 0, is read as (other * u^c) * u^(v - c) wherever u^(v - c) tends to a finite real other than 0; the principal power splits that way for any u. (tan(x) + 1)^(x^(x - 1)) at 0 from the right has the exponent tan(x) * x^(x - 1), tan(x) / x times x^x, and is e now, where l'Hopital's rule differentiated x^(x - 1) and did not finish. tan(x) * x^(x - 1) there takes 0.21 s, from 2.5 s. Co-Authored-By: Claude Opus 5.5 --- BREAKING-CHANGES.md | 14 +++++++ .../Limits/Solvers/Limit.Classes.cs | 26 +++++++++++++ .../APowerIsSplitAtItsExponentsLimitTest.cs | 38 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 Sources/Tests/UnitTests/Calculus/APowerIsSplitAtItsExponentsLimitTest.cs diff --git a/BREAKING-CHANGES.md b/BREAKING-CHANGES.md index a832e432d..829994cba 100644 --- a/BREAKING-CHANGES.md +++ b/BREAKING-CHANGES.md @@ -57,6 +57,20 @@ divisor answers at once. A two-sided limit is not changed. Found by limitcheck; | `"arcsin(-x * log(-1, x))".ToEntity().Limit("x", 0, ApproachFrom.Right)` | `limitright(arcsin(-x * log(-1, x)), x, 0)` | `0` | | `"x * log(2 + x, x)".ToEntity().Limit("x", 0, ApproachFrom.Right)` | `0` after 27 s | `0` in 0.25 s | +### A product with a power for a factor is read by the power's exponent's limit in a one-sided limit + +**Silent: a one-sided limit of a product whose factors tend to 0 and to an infinity, one of them a power `u^v` whose +exponent tends to a constant `c` other than 0, is read as `(other * u^c) * u^(v - c)`** wherever `u^(v - c)` tends to a +finite real other than 0. The principal power splits that way for any `u`. `(tan(x) + 1)^(x^(x - 1))` at 0 from the +right has the exponent `tan(x) * x^(x - 1)`, which is `tan(x) / x` times `x^x` and tends to 1, so the limit is `e`. +l'Hôpital's rule differentiated `x^(x - 1)` instead, and did not finish. A two-sided limit is not changed. Found by +limitcheck; no issue was filed. + +| Input | Was (2.6.0) | Now | +|---|---|---| +| `"(tan(x) + 1)^(x^(x - 1))".ToEntity().Limit("x", 0, ApproachFrom.Right)` | `limitright((tan(x) + 1) ^ x ^ (x - 1), x, 0)` | `e` | +| `"tan(x) * x^(x - 1)".ToEntity().Limit("x", 0, ApproachFrom.Right)` | `1` after 11 s | `1` in 0.21 s | + ### A derivative keeps an exponent that is not rational exact **Silent: the power rule writes a constant exponent that is not rational as it is, where it wrote its decimal diff --git a/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs b/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs index 91e2600b1..ac169479f 100644 --- a/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs +++ b/Sources/AngouriMath/Functions/Continuous/Limits/Solvers/Limit.Classes.cs @@ -116,6 +116,17 @@ partial record Mulf && AsTheWholeLimit(distributed, x, dist, side) is { } termByTerm && termByTerm.Evaled != MathS.NaN) return termByTerm; + // So, with a power u^v for one factor whose exponent tends to a constant c other than 0, is the + // product read as (other * u^c) * u^(v - c), where u^(v - c) has a finite limit other than 0. That + // holds for the principal power, e^(v ln u) being e^(c ln u) e^((v - c) ln u). The exponent of + // (tan(x) + 1)^(x^(x - 1)) at 0 from the right is (tan(x) + 1 - 1) * x^(x - 1), and l'Hopital's rule + // differentiated x^(x - 1) for longer than any caller waits, where tan(x) / x tends to 1 and x^x to 1. + if (side is not ApproachFrom.BothSides && !IsComparingSides + && multiplierLimit is { } zeroOrInfinity7 && multiplicandLimit is { } zeroOrInfinity8 + && IsZeroTimesAnInfinity(zeroOrInfinity7, zeroOrInfinity8) + && (ByTheExponentsLimit(Multiplicand, Multiplier, x, dist, side) ?? ByTheExponentsLimit(Multiplier, Multiplicand, x, dist, side)) + is { } byTheExponentsLimit) + return byTheExponentsLimit; var (mp, md) = (multiplierLimit, multiplicandLimit) switch { @@ -266,6 +277,21 @@ private static bool IsAnIndeterminateQuotient(Entity dividend, Entity divisor) _ => false, }; + /// + /// The limit of power * other read as (other * u^c) * u^(v - c), for a power u^v whose exponent + /// tends to a constant c other than 0 and where u^(v - c) tends to a finite real other than 0. + /// + private static Entity? ByTheExponentsLimit(Entity power, Entity other, Variable x, Entity dist, ApproachFrom side) + { + if (power is not Powf(var @base, var exponent) || !exponent.ContainsNode(x) + || exponent.ComputeLimitDivideEtImpera(x, dist, side)?.Evaled is not Real { IsFinite: true, IsZero: false, IsNaN: false } constant + || MathS.Pow(@base, (exponent - constant).InnerSimplified).ComputeLimitDivideEtImpera(x, dist, side)?.Evaled + is not Real { IsFinite: true, IsZero: false, IsNaN: false } rest + || AsTheWholeLimit(other * MathS.Pow(@base, constant), x, dist, side)?.Evaled is not Number { IsNaN: false } head) + return null; + return (head * rest).Evaled; + } + /// Whether two factors' limits make a product 0 * oo. private static bool IsZeroTimesAnInfinity(Entity first, Entity second) => (first.Evaled, second.Evaled) switch diff --git a/Sources/Tests/UnitTests/Calculus/APowerIsSplitAtItsExponentsLimitTest.cs b/Sources/Tests/UnitTests/Calculus/APowerIsSplitAtItsExponentsLimitTest.cs new file mode 100644 index 000000000..02917aba9 --- /dev/null +++ b/Sources/Tests/UnitTests/Calculus/APowerIsSplitAtItsExponentsLimitTest.cs @@ -0,0 +1,38 @@ +// +// 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 System.Threading.Tasks; +using AngouriMath.Core; +using AngouriMath.Extensions; +using Xunit; + +namespace AngouriMath.Tests.Calculus +{ + /// + /// A product tending to 0 * oo with a power u^v for a factor, v tending to a constant c other than 0, is read as + /// (other * u^c) * u^(v - c). (tan(x) + 1)^(x^(x - 1)) at 0 from the right has the exponent tan(x) * x^(x - 1), which is + /// tan(x) / x times x^x, and l'Hopital's rule differentiated x^(x - 1) for longer than any caller waits. + /// Found by limitcheck; no issue was filed. + /// + [Trait("Area", "Calculus")] + public sealed class APowerIsSplitAtItsExponentsLimitTest + { + [Theory] + [InlineData("(tan(x) + 1)^(x^(x - 1))", "e")] + [InlineData("tan(x) * x^(x - 1)", "1")] + [InlineData("sin(x) * x^(x - 1)", "1")] + [InlineData("x^2 * x^(x - 3)", "+oo")] + [InlineData("ln(x) * x^(x + 1)", "0")] + public void TheLimitFromTheRightIsAnswered(string input, string expected) + { + var limit = Task.Run(() => input.ToEntity().Limit("x", 0, ApproachFrom.Right)); + Assert.True(limit.Wait(TimeSpan.FromSeconds(30)), $"the limit of {input} did not finish"); + Assert.Equal(expected.ToEntity().Evaled, limit.Result.Evaled); + } + } +}