Skip to content

Settle a difference of squared reciprocals instead of denying it (#727) - #728

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
fix/squared-reciprocal-differences
Aug 5, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
fix/squared-reciprocal-differences

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Closes #727.

lim x->0 (1/x^2 - 1/sin(x)^2) answered NaN, which is not "unevaluated" but the claim
that the limit does not exist. It is -1/3. The mirrored difference was the same, and
csc(x)^2 - 1/x^2 came back unevaluated where it is 1/3.

before after
lim x->0 (1/x^2 - 1/sin(x)^2) NaN -1/3
lim x->0 (1/sin(x)^2 - 1/x^2) NaN 1/3
lim x->0 (csc(x)^2 - 1/x^2) unevaluated 1/3

The unsquared forms already answered, so this sits next to #714 rather than being a
regression of it.

Two causes.

The difference is put over a common denominator already, and what comes out is an
ordinary 0/0 -- (sin(x)^2 - x^2) / (x^2 * sin(x)^2). l'Hopital's rule refused its
first step. The rule's growth guard allowed a quotient eight more nodes than the one it
came from, which is what growth looks like when the divisor is a power of the variable:
differentiating that shrinks it, so only the dividend grows and it grows by addition. A
divisor that is a product of vanishing factors grows by the product rule instead, so
the chain grows before it collapses -- 17 -> 26 -> 33 -> 46 nodes -- and four steps
then settle it. The guard is now the larger of eight nodes and three fifths again:
proportional where the growth is proportional, unchanged for the small quotients it was
measured on.

That rule is wider than the old one everywhere, so no chain that reached an answer before
is turned away now, and it costs nothing on the shape the flat budget was measured
against: x^(3/2) * sqrt(1 + 1/x^2) / x^2 at +oo grows 19 -> 31 nodes at its first
step, over both budgets, so it stops where it stopped before and still answers 0 in
240 ms.

The cosecant is a separate cause. csc(x) is written 1/sin(x) in front of the descent,
so csc(x)^2 arrives as (1/sin(x))^2 with its denominator inside the power, and
SplitProduct did not look there -- the term was read as having no denominator and the
sum was never combined at all. Only whole powers are split this way: (a/b)^n is
a^n/b^n exactly for those, while at a half it is not (sqrt(1/(-1)) is i and
sqrt(1)/sqrt(-1) is -i), and the limit of the rewritten form would be the limit of a
different function.

Measured. 4855 unit tests and 130 F# tests pass. The 117-problem solver corpus is
unchanged at 112/117 with no wrong answers, errors or timeouts, and its total time is
within noise of where it was.

🤖 Generated with Claude Code

lim x->0 (1/x^2 - 1/sin(x)^2) answered NaN, which is not "unevaluated" but
the claim that the limit does not exist. It is -1/3. The mirrored difference
was the same and csc(x)^2 - 1/x^2 came back unevaluated where it is 1/3.

The difference is put over a common denominator already, and what comes out
is an ordinary 0/0 -- (sin(x)^2 - x^2) / (x^2 * sin(x)^2). l'Hopital's rule
refused its first step. The rule's growth guard allowed eight nodes, which is
what growth looks like when the divisor is a power of the variable:
differentiating that shrinks it, so only the dividend grows and it grows by
addition. A divisor that is a product of vanishing factors grows by the
product rule instead, so the chain grows before it collapses -- 17 -> 26 ->
33 -> 46 nodes -- and four steps then settle it. The guard is now the larger
of eight nodes and three fifths again, proportional where the growth is
proportional and unchanged for the small quotients it was measured on.

It is wider than the old rule everywhere, so nothing that answered before is
turned away now, and it costs nothing on the shape the flat budget was
measured against: x^(3/2) * sqrt(1 + 1/x^2) / x^2 at +oo grows 19 -> 31
nodes at its first step, which is over both budgets, so it stops where it
stopped before and still answers 0 in 240 ms. That step adds twelve nodes
and the next twenty-six; the old comment's eighteen was measured on an
earlier build and is corrected here.

The cosecant is a second cause, not the same one. csc(x) is written 1/sin(x)
in front of the descent, so csc(x)^2 arrives as (1/sin(x))^2 with its
denominator inside the power, and SplitProduct did not look there -- the term
was read as having no denominator and the sum was never combined at all.
Only whole powers are split this way: (a/b)^n is a^n/b^n exactly for those,
while at a half it is not, and the limit of the rewritten form would be the
limit of a different function.

lim x->0 (1/x^2 - 1/sin(x)^2)  NaN -> -1/3
lim x->0 (1/sin(x)^2 - 1/x^2)  NaN -> 1/3
lim x->0 (csc(x)^2 - 1/x^2)    unevaluated -> 1/3

4855 unit tests and 130 F# tests pass; corpus unchanged at 112/117 with no
wrong answers, errors or timeouts, and its total time within noise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Rafael-SOWNet
Rafael-SOWNet merged commit 0cb3249 into master Aug 5, 2026
24 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the fix/squared-reciprocal-differences branch August 5, 2026 12:48
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.

lim x->0 (1/x^2 - 1/sin(x)^2) answers NaN, which claims the limit does not exist

1 participant