You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
1^oo evaluates to 1, so lim x->+oo (x-5)^x / x^x gives 1 where it is e^(-5) #738
1 ^ oo is an indeterminate form, and AngouriMath evaluates it as 1:
"1 ^ (+oo)".ToEntity().EvalNumerical()// 1
That reaches the limits machinery as a wrong answer:
is
gives
lim x->+oo (x - 5) ^ x / x ^ x
e ^ (-5)
1
lim x->+oo (x + 1) ^ x / x ^ x
e
1
Written as a single power the same limits are correct, which is what locates the cause:
gives
lim x->+oo ((x - 5) / x) ^ x
1 / e ^ 5 ✅
lim x->+oo (1 - 5/x) ^ x
1 / e ^ 5 ✅
And the neighbouring quotients, where the base ratio does not tend to 1, are right: (2 * x) ^ x / x ^ x gives +oo, and (x ^ 2) ^ x / x ^ x gives +oo.
Cause
Two things, and they are separable.
The ordering.ApplySecondRemarkable -- the rule that reads a 1 ^ oo -- runs at the top of LimitFunctional.ComputeLimit, before anything is simplified. At that point (x - 5) ^ x / x ^ x is a Divf, not a 1 ^ oo, so the rule has nothing to match on. The descent's Divf case then calls ComputeLimitImpl, which begins with expr.Simplify(), and that turns the quotient into ((x - 5) / x) ^ x -- a 1 ^ oo which nothing will now re-read, because the rule that reads one has already run.
The evaluation. Substitution then puts x -> +oo into it, and the evaluator answers 1 ^ (+oo) = 1 rather than declining.
Simplify() is right here and the second remarkable limit is right here; what is wrong is that a form created by simplification is judged by rules that ran before it existed.
Note on the fix
The second half reaches everything that evaluates a power, not just limits, so it wants its own measurement rather than being bundled into a limits change -- 1 ^ oo giving NaN is correct for a limit but a much wider change than this issue. The first half is narrower: re-applying the remarkable limits after the simplification inside ComputeLimitImpl, or matching the quotient shape before it is simplified.
Found while checking that #736 had not traded one wrong answer for another. It had not -- this reproduces on stock master (318ac9f3) independently of that change.
Traced both halves. There are two independent routes to the wrong 1, and which one an expression takes depends on whether substituting the destination yields NaN or an exact 1. That is why the two examples in the report behave differently under a partial fix.
Route 1 -- SolveBySubstitution
(x + 1) ^ x / x ^ x simplifies to (1 + 1/x) ^ x. Substituting x -> +oo:
1 + 1/(+oo) => 1 (exactly, since 1/(+oo) is 0)
(1 + 1/(+oo)) ^ (+oo) => 1
So LimitSolvers.SolveBySubstitution gets a clean finite value and returns it. Note that lim x->+oo (1 + 1/x) ^ xon its own is correct (e) -- it is caught by ApplySecondRemarkable at the top of ComputeLimit. The quotient form only becomes a 1 ^ ooafter the Simplify() inside ComputeLimitImpl, by which time that rule has already run.
Route 2 -- the Powf descent
(x - 5) ^ x / x ^ x simplifies to ((x - 5) / x) ^ x, and substituting there gives (+oo - 5) / (+oo) = NaN, so SolveBySubstitution correctly declines. The 1 comes from Powf.ComputeLimitDivideEtImpera instead (Limit.Classes.cs), whose switch has
({IsFinite: true } lim1,{} exp)=>New(lim1,exp),
Reaching that case means the exponent's limit is not finite, so with a base tending to 1 it builds 1 ^ x -- and 1 ^ xsimplifies to 1. The neighbouring case ({ } bas, { IsFinite: true } lim2) has the same hazard for oo ^ 0.
This is exactly what the IsDeterminate remark in Transformations.cs already warns about:
Powers are not asked this question. The arithmetic answers 1 ^ (+oo) with 1 and (+oo) ^ 0 with 1, and as limits both are indeterminate [...] so a power settled this way would be settled wrongly.
IsDeterminate is kept away from powers for that reason, but the Powf descent substitutes a part's limit without consulting it.
What a fix needs
Both routes, and they are the same principle -- do not let the arithmetic's reading of an indeterminate power stand as a limit:
SolveBySubstitution must decline when the substituted expression holds a 1 ^ oo or oo ^ 0.
The Powf descent must not replace a base whose limit is 1 while the exponent still diverges, nor an exponent whose limit is 0 while the base diverges.
I implemented (2) alone and measured it, which is what separated the routes:
master
with (2) only
(x - 5) ^ x / x ^ x (is e ^ (-5))
1
unevaluated
(x + 1) ^ x / x ^ x (is e)
1
1 -- unchanged
((x - 5) / x) ^ x
1 / e ^ 5 ✅
1 / e ^ 5 ✅
(1 + 1/x) ^ x
e ✅
e ✅
So (2) turns one wrong answer into no answer and leaves the other untouched. I have not raised a PR for it: half of this class would look fixed while the other half was still wrong, which is worse than the current state being plainly wrong.
Sequencing note
With both guards in, these expressions fall through to SolveAsIndeterminatePower (which wants an exponent tending to 0, so it declines here), l'Hopital, SolveByRewriting and finally Gruntz. Gruntz is the one that should answer them -- but only with #736 in, since (1 + 1/x) ^ x is a moving-exponent power and that is precisely what #736 fixes the reading of. So this is best done on top of #736 rather than in parallel with it, or the guards will convert wrong answers into missing ones rather than into right ones.
Also worth recording: 1 ^ oo = 1 is the IEEE 754 convention for pow, so the evaluator is not simply wrong to do it -- which is why the fix belongs in the limits path rather than in the arithmetic.
The ordering half of this is fixed in #739. The evaluation half — 1 ^ (+oo) giving 1 — is untouched, so this issue stays open for it.
The fix is the narrower of the two options the report suggested: re-applying the remarkable limits after the simplification, rather than matching the quotient shape before it. The rule is asked a second time inside SimplifyAndComputeLimitToInfinity, which is where the expression is in the form the solvers read it in and where every destination has already been normalised to +oo.
Worth recording, because the earlier tracing predicted otherwise on both counts:
It closes both routes at once. Both SolveBySubstitution (where (1 + 1/x)^x substitutes to an exact 1^(+oo)) and the Powf descent (where ((x - 5)/x)^x builds 1^x, which simplifies to 1) run through that one point after the simplification has created the form, so a single re-read catches them both. The half-fixed state that made the earlier attempt not worth raising does not arise.
It does not need Compare a moving-exponent power against the right thing (#735) #736 underneath it. The expectation was that guarding these would convert wrong answers into missing ones unless Gruntz could pick them up. It does not come to that — the rewrite answers them outright rather than dropping them through.
Measured at x -> +oo, against stock master (318ac9f3):
is
was
now
(x - 5)^x / x^x
e^(-5)
1
1/e^5 (309 ms)
(x + 1)^x / x^x
e
1
e (16 ms)
(x + 3)^x / x^x
e^3
1
e^3 (21 ms)
x^x / (x + 1)^x
e^(-1)
1
1/e (57 ms)
x^x / (x - 5)^x
e^5
1
e^5 (50 ms)
(2x + 1)^x / (2x)^x
e^(1/2)
1
sqrt(e) (59 ms)
(x - 1)^x / x^x
e^(-1)
unevaluated, 5.2 s
1/e, 163 ms
The neighbouring quotients are untouched: (2x)^x / x^x and (x^2)^x / x^x still +oo, x^x / (2x)^x still 0, and the single-power forms that were always right still are.
One case in the same family it does not reach: (x^2 + 1)^x / (x^2)^x, where Simplify never gathers the quotient into a single power, so no 1^oo is created for anything to re-read. That one declines rather than answering wrongly, and its cause is in the simplification — filed as #740.
Full suite 4909 passed / 0 failed, F# 130/130, corpus 112/117 with 0 wrong, 0 error, 0 timeout.
The neighbouring cases from the report are still right too — (2 * x) ^ x / x ^ x and (x ^ 2) ^ x / x ^ x both give +oo.
The ordering half landed in #739, and the remaining wrong answers in this family were closed by the indeterminate-power work in #760 and the Stirling series in #764/#766.
The evaluation half is unchanged and I do not think it should be treated as a bug:
"1 ^ (+oo)".ToEntity().EvalNumerical()// still 1
That is a convention rather than an error. SymPy answers 1; Mathematica answers Indeterminate. Both are defensible, and the choice has consequences beyond this issue, so it is a maintainer's call rather than mine.
What has changed is that nothing depends on it any more: the two wrong answers this issue was filed for are gone, and I know of no remaining wrong answer that comes from 1 ^ oo evaluating to 1.
So this can be closed as reported-and-fixed, or kept open narrowed to "should 1 ^ oo be 1 or indeterminate" — whichever you prefer. I have not changed the evaluation and will not without a decision here.
Closing: the behaviour this issue reports is fixed. Re-measured on master (21f0d16) rather than relying on the earlier comment:
reported
now
lim x->+oo (x - 5) ^ x / x ^ x
1
1 / e ^ 5 ✅
lim x->+oo (1 + 1/x) ^ x
—
e ✅
e^(-5) is what the title asks for.
On the part that has not changed:1 ^ (+oo) still evaluates to 1. That is deliberate rather than overlooked — it is the SymPy and IEEE 754 convention (pow(1, ∞) = 1), and the limit machinery no longer routes through it: the indeterminate form is now detected and resolved before evaluation gets a chance to return 1. That is why the limits are right while the evaluation is unchanged.
If the convention itself should change, that is a separate decision with a much wider blast radius than this issue, and worth its own thread.
Activity
Rafael-SOWNet commentedon Aug 5, 2026
Traced both halves. There are two independent routes to the wrong
1, and which one an expression takes depends on whether substituting the destination yieldsNaNor an exact1. That is why the two examples in the report behave differently under a partial fix.Route 1 --
SolveBySubstitution(x + 1) ^ x / x ^ xsimplifies to(1 + 1/x) ^ x. Substitutingx -> +oo:So
LimitSolvers.SolveBySubstitutiongets a clean finite value and returns it. Note thatlim x->+oo (1 + 1/x) ^ xon its own is correct (e) -- it is caught byApplySecondRemarkableat the top ofComputeLimit. The quotient form only becomes a1 ^ ooafter theSimplify()insideComputeLimitImpl, by which time that rule has already run.Route 2 -- the
Powfdescent(x - 5) ^ x / x ^ xsimplifies to((x - 5) / x) ^ x, and substituting there gives(+oo - 5) / (+oo)=NaN, soSolveBySubstitutioncorrectly declines. The1comes fromPowf.ComputeLimitDivideEtImperainstead (Limit.Classes.cs), whose switch hasReaching that case means the exponent's limit is not finite, so with a base tending to 1 it builds
1 ^ x-- and1 ^ xsimplifies to1. The neighbouring case({ } bas, { IsFinite: true } lim2)has the same hazard foroo ^ 0.This is exactly what the
IsDeterminateremark inTransformations.csalready warns about:IsDeterminateis kept away from powers for that reason, but thePowfdescent substitutes a part's limit without consulting it.What a fix needs
Both routes, and they are the same principle -- do not let the arithmetic's reading of an indeterminate power stand as a limit:
SolveBySubstitutionmust decline when the substituted expression holds a1 ^ oooroo ^ 0.Powfdescent must not replace a base whose limit is 1 while the exponent still diverges, nor an exponent whose limit is 0 while the base diverges.I implemented (2) alone and measured it, which is what separated the routes:
(x - 5) ^ x / x ^ x(ise ^ (-5))1(x + 1) ^ x / x ^ x(ise)11-- unchanged((x - 5) / x) ^ x1 / e ^ 5✅1 / e ^ 5✅(1 + 1/x) ^ xe✅e✅So (2) turns one wrong answer into no answer and leaves the other untouched. I have not raised a PR for it: half of this class would look fixed while the other half was still wrong, which is worse than the current state being plainly wrong.
Sequencing note
With both guards in, these expressions fall through to
SolveAsIndeterminatePower(which wants an exponent tending to 0, so it declines here), l'Hopital,SolveByRewritingand finally Gruntz. Gruntz is the one that should answer them -- but only with #736 in, since(1 + 1/x) ^ xis a moving-exponent power and that is precisely what #736 fixes the reading of. So this is best done on top of #736 rather than in parallel with it, or the guards will convert wrong answers into missing ones rather than into right ones.Also worth recording:
1 ^ oo = 1is the IEEE 754 convention forpow, so the evaluator is not simply wrong to do it -- which is why the fix belongs in the limits path rather than in the arithmetic.Rafael-SOWNet commentedon Aug 5, 2026
The ordering half of this is fixed in #739. The evaluation half —
1 ^ (+oo)giving1— is untouched, so this issue stays open for it.The fix is the narrower of the two options the report suggested: re-applying the remarkable limits after the simplification, rather than matching the quotient shape before it. The rule is asked a second time inside
SimplifyAndComputeLimitToInfinity, which is where the expression is in the form the solvers read it in and where every destination has already been normalised to+oo.Worth recording, because the earlier tracing predicted otherwise on both counts:
SolveBySubstitution(where(1 + 1/x)^xsubstitutes to an exact1^(+oo)) and thePowfdescent (where((x - 5)/x)^xbuilds1^x, which simplifies to1) run through that one point after the simplification has created the form, so a single re-read catches them both. The half-fixed state that made the earlier attempt not worth raising does not arise.Measured at
x -> +oo, against stockmaster(318ac9f3):(x - 5)^x / x^xe^(-5)11/e^5(309 ms)(x + 1)^x / x^xe1e(16 ms)(x + 3)^x / x^xe^31e^3(21 ms)x^x / (x + 1)^xe^(-1)11/e(57 ms)x^x / (x - 5)^xe^51e^5(50 ms)(2x + 1)^x / (2x)^xe^(1/2)1sqrt(e)(59 ms)(x - 1)^x / x^xe^(-1)1/e, 163 msThe neighbouring quotients are untouched:
(2x)^x / x^xand(x^2)^x / x^xstill+oo,x^x / (2x)^xstill0, and the single-power forms that were always right still are.One case in the same family it does not reach:
(x^2 + 1)^x / (x^2)^x, whereSimplifynever gathers the quotient into a single power, so no1^oois created for anything to re-read. That one declines rather than answering wrongly, and its cause is in the simplification — filed as #740.Full suite 4909 passed / 0 failed, F# 130/130, corpus 112/117 with 0 wrong, 0 error, 0 timeout.
Re-read the second remarkable limit after simplification (#738) (#739)
Rafael-SOWNet commentedon Aug 6, 2026
Status update: both limits this issue reported now answer correctly, and what is left is not a defect.
Measured on stock
master(184dd5a):lim x->+oo (x - 5) ^ x / x ^ xe ^ (-5)1 / e ^ 5✅lim x->+oo (x + 1) ^ x / x ^ xee✅The neighbouring cases from the report are still right too —
(2 * x) ^ x / x ^ xand(x ^ 2) ^ x / x ^ xboth give+oo.The ordering half landed in #739, and the remaining wrong answers in this family were closed by the indeterminate-power work in #760 and the Stirling series in #764/#766.
The evaluation half is unchanged and I do not think it should be treated as a bug:
That is a convention rather than an error. SymPy answers
1; Mathematica answersIndeterminate. Both are defensible, and the choice has consequences beyond this issue, so it is a maintainer's call rather than mine.What has changed is that nothing depends on it any more: the two wrong answers this issue was filed for are gone, and I know of no remaining wrong answer that comes from
1 ^ ooevaluating to1.So this can be closed as reported-and-fixed, or kept open narrowed to "should
1 ^ oobe1or indeterminate" — whichever you prefer. I have not changed the evaluation and will not without a decision here.Rafael-SOWNet commentedon Aug 8, 2026
Closing: the behaviour this issue reports is fixed. Re-measured on
master(21f0d16) rather than relying on the earlier comment:lim x->+oo (x - 5) ^ x / x ^ x11 / e ^ 5✅lim x->+oo (1 + 1/x) ^ xe✅e^(-5)is what the title asks for.On the part that has not changed:
1 ^ (+oo)still evaluates to1. That is deliberate rather than overlooked — it is the SymPy and IEEE 754 convention (pow(1, ∞) = 1), and the limit machinery no longer routes through it: the indeterminate form is now detected and resolved before evaluation gets a chance to return1. That is why the limits are right while the evaluation is unchanged.If the convention itself should change, that is a separate decision with a much wider blast radius than this issue, and worth its own thread.