Skip to content

Lay out the whole Newton grid, not one corner of it (#115) - #695

Merged
Rafael-SOWNet merged 2 commits into
ASC-Community:masterfrom
Rafael-SOWNet:fix/newton-grid-step-count
Aug 4, 2026
Merged

Rafael-SOWNet merged 2 commits into
ASC-Community:masterfrom
Rafael-SOWNet:fix/newton-grid-step-count

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

The defect

SolveNt searches from a grid of starting points. Each point's position is computed as

var xShare = ((EDecimal)x) / settings.StepCount.Re;

EDecimal's division operator carries no context, and PeterO's EDecimal answers NaN when the quotient does not terminate in base ten. Only step counts of the form 2^a * 5^b divide exactly. For 3, 6, 7, 9, 12, 21 and most other values, every share but the first came out NaN, and with it every starting point — so the search covered the single corner where both indices are zero, and said nothing about it.

The visible effect is that asking for a finer search made the answer worse:

StepCount real roots of x^3 - 2x found
8, 10, 16, 20, 40 -1.414214, 0, 1.414214
9, 12, 21, 41 1.414214

sin(x) - x/2 loses both outlying roots the same way. The default of (10, 10) divides exactly, which is why nothing caught this.

The fix

Divide with CtxDivide, which is what the rest of the library divides decimals with (Entity.Number.CtxDivide, Core/Entity/Continuous/Number/Operators.cs) and which rounds to the working precision. One line each for the real and imaginary share.

Nothing changes at any step count that already divided exactly, the default included. The full suite is unchanged: Failed: 0, Passed: 4018, Skipped: 14, Total: 4032.

Tests

Sources/Tests/UnitTests/Algebra/SolveTest/NewtonGridTest.cs, 9 cases. 5 of them fail without the source change (verified by reverting it in place and re-running):

  • EveryStepCountSearchesTheWholeRegion at 9, 21, 41
  • AFinerSearchKeepsWhatACoarserOneFound — states the broken property without naming a step count
  • AStepCountThatDoesNotDivideExactlyStillReachesTheOutlyingRoots

The four passing cases (8, 10, 12, 20) are there to pin that the working step counts stay working. 12 passes here because x^3 - 2x happens to be reachable from the corner; it is a NaN grid all the same.

What this does not do

This is not the whole of #115. arcsin(x) - x*pi/3 still returns {0} at the default step count: its other two roots are at ±1/2, inside (-1, 1), and the default grid has spacing 2 over [-10, 10], so it steps over them. At 40 steps it now finds 1/2 but not -1/2 — an asymmetry I have not diagnosed and am not guessing at here.

What this fixes is that raising the step count, the documented way to look harder, was not reliably possible. That is a prerequisite for the rest of #115 rather than the answer to it.

I also noticed but did not change that the grid samples To and never From — x runs 0 .. StepCount-1, so at the default the real starts are 10, 8, ..., -8 and -10 is never tried. Making the grid endpoint-inclusive changes the default sample points, which has a blast radius this fix does not, so it belongs in its own change if it is wanted.

🤖 Generated with Claude Code

The grid SolveNt starts from divides each index by the step count using
EDecimal's own operator, which carries no context and answers NaN wherever
the quotient does not terminate in base ten. Only step counts of the form
2^a * 5^b divide exactly, so for 3, 6, 7, 9, 12, 21 and most other values
every share but the first came out NaN, and with it every starting point:
the search covered the single corner where both indices are zero.

The visible effect is that asking for a finer search made the answer worse.
x^3 - 2x gives all three of its roots at the default 10 steps and only one
at 21; sin(x) - x/2 loses both outlying roots the same way. The default
divides exactly, which is why nothing caught it.

CtxDivide is what the rest of the library divides decimals with, and it
rounds to the working precision instead. Nothing changes at any step count
that already divided exactly, the default included.

This is not the whole of #115. arcsin(x) - x*pi/3 still returns {0} at the
default step count -- its other two roots lie inside (-1, 1), which a grid
of spacing 2 steps over -- and at 40 steps it now finds 1/2 but not -1/2,
which is a separate asymmetry not diagnosed here. What this fixes is that
raising the step count, the documented way to look harder, was not reliably
possible.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@codecov-commenter

codecov-commenter commented Aug 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.59%. Comparing base (90c00a8) to head (bc447f2).
⚠️ Report is 73 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #695      +/-   ##
==========================================
+ Coverage   80.99%   81.59%   +0.60%     
==========================================
  Files         155      157       +2     
  Lines       13687    13347     -340     
  Branches     1957     2198     +241     
==========================================
- Hits        11086    10891     -195     
+ Misses       1990     1849     -141     
+ Partials      611      607       -4     

☔ 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

Copy link
Copy Markdown
Member Author

CI, run on my fork across the full matrix, since the run here is held at action_required:

https://github.com/Rafael-SOWNet/AngouriMath/actions/runs/30919850130

job result tests
Test (ubuntu-latest) success Failed: 0, Passed: 4018, Skipped: 14, Total: 4032
Test (macos-latest) success Failed: 0, Passed: 4018, Skipped: 14, Total: 4032
Test (windows-latest) success Failed: 0, Passed: 4018, Skipped: 14, Total: 4032

The branch it ran on, ci-check/newton-grid, is this PR's head plus one commit that only touches .github/workflows/CSharpTest.yml (adding workflow_dispatch: and ci-check/** to the push branches, so the run can be triggered at all). Everything under Sources/ is byte-identical to this PR:

$ git diff --stat fix/newton-grid-step-count ci-check/newton-grid
 .github/workflows/CSharpTest.yml | 2 ++
 1 file changed, 2 insertions(+)

@Rafael-SOWNet
Rafael-SOWNet merged commit a2cc479 into ASC-Community:master Aug 4, 2026
26 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the fix/newton-grid-step-count branch August 4, 2026 20:49
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.

2 participants