Repository navigation
Decline a substitution of x by itself in the multiplicative exponential solver - #2432
Merged
Rafael-SOWNet merged 1 commit intoNov 13, 2026
Conversation
…al solver (#2424) Solving (-2)^x + 4^x = 0 overflowed the stack. The linear exponential solver writes it as t^ln(-2) + t^ln(4) in t = e^x. The multiplicative solver then picks a power of t to substitute only where every exponent is real, and ln(-2) is not. So the substitution fell back to t itself, which renamed the variable and asked the same equation again without end. x^i + x = 0 and x^(1 + i) + x = 0 overflowed the same way. The substitution is declined now, and the equation goes on to the other routes. Newton's method then answers it, and two of its checks let non-roots through. It counted a point as converged when its last step was under 1e-6. Near t = 0, where both terms vanish, the steps are that small while the point is still 18% of its own size from where it settles. Points like that came back as roots, 0.0004 and 0.23 from the nearest one. Below 1 the step is measured against the point now; from 1 up the test is unchanged, so the change can only drop a point, never add one. And it compiles 0^i to 0, so x^i + x = 0 had 0 among its roots. The check against the equation kept it, because a residual that is not finite counted as no evidence. That protects a root found in decimals, where rounding or overflow can leave no value at a genuine root. A function undefined at exact arguments, 0^i or 1/0, has neither excuse, and is now evidence against the root, in Newton's check and in the solver's own. Every root answered for (-2)^x + 4^x, (-3)^x + 9^x, (-2)^x - 4^x and (-2)^x + 2^x lies on x = (ln(-s) + 2 pi i k) / (ln a - ln b), within 2e-15. The family itself is #2319. Stack overflow -> about 400 ms each. In the Solving tests and the other users of Newton's method, the new rule rejected no root. Solving tests 1890 passed, CasBench 120/121 with 0 wrong, RootCheck 596/596 clean, all as on master. Closes #2424. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2432 +/- ##
==========================================
- Coverage 86.81% 86.81% -0.01%
==========================================
Files 312 312
Lines 69551 69564 +13
Branches 20316 20322 +6
==========================================
+ Hits 60383 60392 +9
- Misses 4932 4938 +6
+ Partials 4236 4234 -2
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
Rafael-SOWNet
deleted the
feature/a-negative-base-exponential-does-not-recurse
branch
November 13, 2026 19:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2424.
(-2)^x + 4^x = 0took the process down with a stack overflow. The cycle isSolve → SolveInverting → ExponentialSolver.SolveMultiplicative → Solve:SolveLinearrewrites(-2)^x + 4^xast^ln(-2) + t^ln(4)int = e^x.SolveMultiplicativechooses a proper powert^unitonly when every exponent is real.ln(-2) = ln 2 + iπis not real, so the substitution staystitself.tby itself only renames the variable, so the solver solved the same equation again, forever.A negative base was only one way in. Any non-real numeric exponent overflowed the same way on 2.6.0 and on master:
x^i + x = 0,x^(1+i) + x = 0,x^i + x^(2*i) = 0.The fix declines a substitution of
xby itself, since it is a renaming and never a step. With the cycle gone, Newton's method answers these equations, and two more changes keep its answers roots:t = 0that every term shares, the iteration crawled in steps under 1e-6 while still about 18% of |t| from where it settles, and returned points 0.0004 and 0.23 from the nearest root. The step is now measured against |value| below 1 and is unchanged from 1 up, so this can only drop a point, never add one.x^i + x = 0would otherwise answer0, where0^ihas no value. A decimal argument never counts as undefined, so a root found in decimals still survives rounding and overflow. Across 2184 existing tests, the new rule fired only in its own test.With principal powers, the roots of
a^x + s·b^x = 0arex = (ln(−s) + 2πik)/(ln a − ln b). Every root below lies on that family, within 2e-15.(-2)^x + 4^x(-3)^x + 9^x(-2)^x - 4^x(-2)^x + 2^x{ -5, -3, -1, 1, 3 }x^i + x{ -e^(π/2) i, e^(-π/2) i }x^i + x^(2*i){ e^π }x^(1+i) + x0, e^−5π, e^−3π, e^−π, e^π(0^(1+i)is 0, so 0 is a root)Each takes 290–470 ms. The answers are the roots inside Newton's search region, not the whole infinite family: that is #2319's question, and its rates have no common real unit here. The rows are in BREAKING-CHANGES.md.
Checked on this branch:
🤖 Generated with Claude Code