Skip to content

Answer the indeterminate forms that are not quotients - #710

Merged
Rafael-SOWNet merged 1 commit into
ASC-Community:masterfrom
Rafael-SOWNet:feat/indeterminate-powers
Aug 4, 2026
Merged

Rafael-SOWNet merged 1 commit into
ASC-Community:masterfrom
Rafael-SOWNet:feat/indeterminate-powers

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Of the three indeterminate powers, only 1^oo had a rule — the second remarkable limit. 0^0 and oo^0 reached the descent, which substitutes each part's own limit and hands back 0^0, that is NaN: the claim that the limit does not exist. A product of something vanishing with something diverging had no reading either, unless one of its factors happened to be written as a reciprocal.

before after
lim x->0+ x^sin(x) NaN 1
lim x->0+ sin(x)^x NaN 1
lim x->0+ x^(1/ln(x)) NaN e
lim x->0+ x^(2/ln(x)) NaN e²
lim x->+oo (1/x)^(1/x) NaN 1
lim x->0+ sin(x)·ln(x) NaN 0
lim x->0+ sqrt(x)·ln(x) NaN 0
lim x->0+ x·cotan(x) NaN 1
lim x->0+ (1-cos(x))·cotan(x) NaN 0

19 of 20 measured cases against 9 before. x^(1/ln(x)) is the one worth naming: 0^0 is not always 1, which is the whole reason it is indeterminate, and here the exponent decides on e.

How

Both families go over to the textbook form — e^(g·ln f) for the power, and the diverging factor over the reciprocal of the vanishing one for the product.

The exponent is asked as a limit of its own rather than rewritten in place. A rewrite would only hand the descent a product it reads no better than the power, because the descent substitutes each part's limit and does not apply l'Hopital's rule to a part. Asking outright is what puts the whole machinery behind it — my first attempt did rewrite in place, and it regressed lim x->+oo x^(1/x) from 1 to NaN.

Two guards, both from measurement

The reciprocal split keeps precedence, but only when it produces something usable. x·e^(-x) splits into the clean x/e^x, and inverting the other half instead does not terminate — so the split goes first. But it can also hide the indeterminacy it was meant to expose: tan(x)·ln(x) has been written sin(x)/cos(x)·ln(x) by the time it arrives, and splitting gives sin(x)·ln(x)/cos(x), whose divisor tends to 1. So the split is used only when what it produces is genuinely 0/0 or oo/oo.

A base the library cannot differentiate is declined. Every route out of ln(f) runs through differentiating f, and Factorialf.InnerDifferentiate returns NaN outright — the digamma function is not implemented. Without this guard lim x->+oo ((x!)/x^x)^(1/x) had no answer either way and took twenty seconds not to find one; it showed up as a timeout in a 117-problem corpus that had been at zero all along. Caught before this was opened, not after.

What is deliberately unchanged

lim x->0 x^x still has no two-sided limit, and that is right rather than a gap. x^x is not real to the left of 0, so the 1 that comes back from that side is the complex continuation and not a limit for the right-hand one to agree with. Limits.TestNoLimit has pinned this all along; an earlier draft of mine made the two-sided case answer 1 and broke that test, which was the test being correct and me being wrong.

tan(x)·ln(x) at 0+ is the one measured case still missing. It arrives restructured as a Divf rather than a Mulf, so the product reading never sees it. It is NaN on master too, so this is a gap rather than a regression, and the fix belongs with whatever handles the restructuring.

Measurements

  • 25 new tests.
  • Suite: Failed: 0, Passed: 4597, Skipped: 14, Total: 4611, plus 127 F#.
  • 117-problem corpus: 111/117, 0 wrong / 0 error / 0 timeout.

Independent of #703 and #709.

Of the three indeterminate powers only 1^oo had a rule, the second remarkable
limit. 0^0 and oo^0 reached the descent, which substitutes each part's own limit
and hands back 0^0, that is NaN -- the claim that the limit does not exist. And
a product of something vanishing with something diverging had no reading either,
unless one of its factors happened to be written as a reciprocal.

Both go over to e^(g * ln f) and to the diverging factor over the reciprocal of
the vanishing one, which is the textbook move in each case.

The exponent is asked as a limit of its own rather than rewritten in place. A
rewrite would only hand the descent a product it reads no better than the power,
since the descent substitutes the parts' limits and does not apply l'Hopital's
rule to a part; asking outright is what puts the whole machinery behind it.

Two guards, both from measurement rather than caution:

  The reciprocal split keeps precedence where it gives the rule a quotient it
  can use, since x * e^(-x) comes out as the clean x / e^x and inverting the
  other half instead does not terminate. But it can also hide the indeterminacy
  it was meant to expose -- tan(x) * ln(x) splits into sin(x) * ln(x) / cos(x),
  whose divisor tends to 1 -- so it is used only when what it produces is 0/0 or
  oo/oo.

  A base the library cannot differentiate is declined. Every route out of ln(f)
  runs through differentiating f, and a factorial's derivative wants the digamma
  function and comes back NaN, so lim x->+oo ((x!) / x^x)^(1/x) had no answer
  either way and took twenty seconds not to find one.

x^x at 0 keeps having no two-sided limit, which is right rather than a gap: x^x
is not real to the left of 0, so the 1 that comes back from that side is the
complex continuation and not a limit to agree with. The suite pinned that
already and it still holds.

19 of 20 measured cases, against 9 before. tan(x) * ln(x) is the one left: it
arrives restructured as a quotient rather than a product, so the product reading
never sees it. It is NaN on master too.

25 new tests; suite 4597 passed, 0 failed; corpus 111/117 with 0 wrong, 0 error
and 0 timeout.
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 81.81818% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.82%. Comparing base (90c00a8) to head (1b1eb9b).
⚠️ Report is 82 commits behind head on master.

Files with missing lines Patch % Lines
...ath/Functions/Continuous/Limits/Transformations.cs 84.31% 4 Missing and 4 partials ⚠️
...ns/Continuous/Limits/Solvers/Solvers.Definition.cs 50.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #710      +/-   ##
==========================================
+ Coverage   80.99%   81.82%   +0.82%     
==========================================
  Files         155      159       +4     
  Lines       13687    13854     +167     
  Branches     1957     2345     +388     
==========================================
+ Hits        11086    11336     +250     
+ Misses       1990     1861     -129     
- Partials      611      657      +46     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Rafael-SOWNet
Rafael-SOWNet merged commit 9d2b01a into ASC-Community:master Aug 4, 2026
26 checks passed
@Rafael-SOWNet Rafael-SOWNet mentioned this pull request Aug 4, 2026
2 of 3 tasks
@Rafael-SOWNet
Rafael-SOWNet deleted the feat/indeterminate-powers branch August 4, 2026 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant