Repository navigation
Fix gridRing silently returning wrong results when the ring wraps a pentagon (#1241) - #1245
4mthxmas20 wants to merge 17 commits into
Conversation
…entagon When a ring encircles pentagons without stepping on one, gridRingUnsafe's traversal is distorted by the enclosed face structure but still closes back on the origin, so the lastIndex guard did not detect the distortion and gridRing silently returned incorrect results instead of falling back to _gridRingInternal. gridRingUnsafe now checks that the ring contains no duplicate cells: a correct ring consists of exactly 6 * k distinct cells, so any duplicate indicates pentagonal distortion and the function returns E_PENTAGON so that gridRing falls back to the correct algorithm. Fixes uber#1241
…entagon When a ring encircles pentagons without stepping on one, gridRingUnsafe's traversal is distorted by the enclosed face structure but still closes back on the origin, so the lastIndex guard did not detect the distortion and gridRing silently returned incorrect results instead of falling back to _gridRingInternal. gridRingUnsafe now checks that the ring contains no duplicate cells: a correct ring consists of exactly 6 * k distinct cells, so any duplicate indicates pentagonal distortion and the function returns E_PENTAGON so that gridRing falls back to the correct algorithm. Fixes uber#1241
…entagon When a ring encircles pentagons without stepping on one, gridRingUnsafe's traversal is distorted by the enclosed face structure but still closes back on the origin, so the lastIndex guard did not detect the distortion and gridRing silently returned incorrect results instead of falling back to _gridRingInternal. gridRingUnsafe now checks that the ring contains no duplicate cells: a correct ring consists of exactly 6 * k distinct cells, so any duplicate indicates pentagonal distortion and the function returns E_PENTAGON so that gridRing falls back to the correct algorithm. Fixes uber#1241
…entagon When a ring encircles pentagons without stepping on one, gridRingUnsafe's traversal is distorted by the enclosed face structure but still closes back on the origin, so the lastIndex guard did not detect the distortion and gridRing silently returned incorrect results instead of falling back to _gridRingInternal. gridRingUnsafe now checks that the ring contains no duplicate cells: a correct ring consists of exactly 6 * k distinct cells, so any duplicate indicates pentagonal distortion and the function returns E_PENTAGON so that gridRing falls back to the correct algorithm. Fixes uber#1241
The entry will be re-added once the branch is updated with upstream master (the add/add conflict in the Unreleased section cannot be resolved without a real merge commit). See PR comment for the entry text.
|
Note on the changelog entry: per CONTRIBUTING.md, the intended entry for the Unreleased → Fixed section is: I temporarily reverted the changelog file on this branch because the Unreleased section has moved on master since this branch was cut, and any entry added from this branch produces an add/add merge conflict there (this PR branch was created from an older fork master, and I cannot merge upstream master into the branch via the API due to OAuth workflow-scope restrictions on the fork). Once a maintainer updates this branch with the latest master (the "Update branch" button), I will happily re-add the entry conflict-free — or feel free to add it directly; maintainer edits are enabled. |
|
From #1241:
It seems like this would be faster. Did you evaluate a solution that would use the You seem to have incorrect merge commit(s) in your branch which are causing Github to show unrelated changes (e.g. relating to integer overflow) in your PR. I'd suggest squash rebasing your branch. |
|
@isaacbrodsky Yes, I evaluated the
The false positives are inherent rather than incidental: a correct ring that wraps a pentagon legitimately ends with nonzero accumulated rotations (the holonomy is real even when the traversal is undistorted), so about a third of correct rings wrapping pentagons would be needlessly pushed onto the BFS fallback — the fast path would mostly stop being fast exactly where it matters. And the 60 false negatives are distorted rings where the perturbation happened to cancel back to 0. Since a correct ring consists of On the branch history: agreed, the stray diff comes from updating file contents over an outdated fork master via the API. I'll clean up the branch so the PR shows only the fix. |
Restore algos.c to base + only the gridRingUnsafe duplicate-cell check, so the PR diff shows just this fix (per review feedback).
Restore algos.c to base + only the gridRingUnsafe duplicate-cell check, so the PR diff shows just this fix (per review feedback).
Restore algos.c to base + only the gridRingUnsafe duplicate-cell check, so the PR diff shows just this fix (per review feedback).
Restore algos.c to base + only the gridRingUnsafe duplicate-cell check, so the PR diff shows just this fix (per review feedback).
|
@isaacbrodsky Branch cleaned up — the PR diff now shows only this fix (3 files, +98: the |
|
What about checking whether the ring traverses base cells on too many different faces? Could that be done reliably with cheaper checks? |
|
@isaacbrodsky Good question — I haven't measured a face-count variant yet, and it's cheap to test, so I'll prototype it: track the distinct faces (or base cells) traversed during the walk, flag when the count exceeds a threshold, and evaluate it against the same ground truth (all res 0–2 cells for k = 1..25, plus the pentagon-neighborhood corpora, 158k+ cases), reporting false positives/negatives and timings versus the duplicate check. Worth noting it's in the same family as the constant-cost guards tried on #1241 (rotation holonomy, step-reversal, corner-cell collision, pentagon-within-k via |
Summary
Fixes #1241.
gridRingUnsafecould silently return incorrect results when the ring encircles pentagons without stepping on one: the traversal is distorted by the enclosed face structure but still closes back on the origin, so the existinglastIndex != originguard does not detect the distortion andgridRingnever falls back to_gridRingInternal.This adds a closure check: a correct ring consists of exactly
6 * kdistinct cells, so any duplicate in the output indicates pentagonal distortion —gridRingUnsafenow returnsE_PENTAGONandgridRingfalls back to the correct algorithm. The fast path is preserved for all other rings: a correct ring has no duplicates by construction, so the check has no false positives. Verified againstgridDiskDistancesSafeas ground truth over all res 0–2 cells for k = 1..25 plus targeted pentagon-neighborhood corpora (158k+ cases, zero false positives/negatives).The duplicate check is O((6k)^2) integer comparisons with no allocations. Measured overhead: k=10: 0.8→1.4µs; k=100: 8→62µs — still orders of magnitude cheaper than the BFS fallback.
Tests
testGridRing.c: newgridRing_pentagonWrappedRingregression test — for the res-1 cell containing (0, 0) and k = 1..18, assertsgridRingoutput equalsgridDisk(k) - gridDisk(k-1). Fails before the fix, passes after.testGridRingUnsafe.c: newpentagonWrappedRingtest assertinggridRingUnsafereturnsE_PENTAGONfor k = 12..16 (covers the new failure branch).Note: the CHANGELOG entry is intentionally left out of the diff for now to avoid an add/add merge conflict in the Unreleased section — see my comment below for the exact entry text.