Skip to content

Prevent double-precision underflow in findEmpties for deep empty regions (#8108) - #8162

Open
davrens101 wants to merge 2 commits into
plotly:mainfrom
davrens101:fix/find-empties-underflow-8108
Open

davrens101 wants to merge 2 commits into
plotly:mainfrom
davrens101:fix/find-empties-underflow-8108

Conversation

@davrens101

Copy link
Copy Markdown

Prevent double-precision underflow in findEmpties for deep empty regions

Fixes #8108.

Root cause

In src/traces/heatmap/find_empties.js, empty (NaN / undefined) grid cells are flood-filled in layers to compute a distance/interpolation weight for contour, heatmap (with connectgaps: true), surface, and contourcarpet. In each layer, the cell weight decays geometrically by dividing by 20:

neighborCount = (sum of neighbor weights) / 20;
if(neighborCount) { ... }

When an empty region is deeper than ~249 layers along the propagation path, the geometric decay (1 / 20)^249 falls below Number.MIN_VALUE (≈ 4.94e-324, the smallest positive IEEE 754 float64). The quotient underflows to exactly 0. Consequently:

  1. if(neighborCount) evaluates to false even though the cell has valid non-zero neighbors.
  2. The cell is never marked as filled, leaving foundNewNeighbors = false.
  3. The function synchronously throws 'findEmpties iterated with no new neighbors', crashing the plot.

Solution

  1. Test if(neighborSum) instead of the divided quotient to check if neighbors exist.
  2. When neighborSum > 0 but neighborSum / 20 underflows to 0 in float64, clamp neighborCount to Number.MIN_VALUE.
  3. This maintains a strictly positive weight for valid neighbors, preserves monotonic sort order, and allows flood-fill to successfully complete without throwing.

Verification

  • Pre-fix reproduction:
    Added unit test should fill deep empty regions without floating-point underflow (#8108) in test/jasmine/tests/heatmap_test.js with a 5x250 empty strip (depth 250).
    Pre-fix result: Failed with Error: Expected function not to throw, but it threw 'findEmpties iterated with no new neighbors'.
  • Post-fix result:
    Test passes cleanly (51 of 51 SUCCESS in heatmap_test.js).
    All contour_test.js tests pass cleanly (27 of 27 SUCCESS).
  • Linter:
    Biome linter passes across the repository with 0 warnings/errors (Checked 2641 files in 1310ms. No fixes applied.).

Review and disclosure

AI assisted in investigating the root cause, developing the minimal clamp fix, and writing the regression test. Verified locally with Jasmine/Karma headless Chrome test runs and Biome lint.

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.

[BUG]: findEmpties throws "iterated with no new neighbors" for large NaN regions in contour (double-precision underflow)

1 participant