Skip to content

Fix NaN handling in LinearLocation/EdgeIntersection compareTo - #1229

Open
bjornharrtell wants to merge 1 commit into
locationtech:masterfrom
bjornharrtell:fix/1228-nan-compareto
Open

Fix NaN handling in LinearLocation/EdgeIntersection compareTo#1229
bjornharrtell wants to merge 1 commit into
locationtech:masterfrom
bjornharrtell:fix/1228-nan-compareto

Conversation

@bjornharrtell

Copy link
Copy Markdown
Contributor

Fixes #1228

LinearLocation.compareTo() and EdgeIntersection.compare() compared the floating-point fields (segmentFraction/dist) with raw </>, which are always false for NaN. This made compareTo fall through to return 0 ("equal") whenever a NaN was compared against any other value on the same segment/index, not just against another NaN.

Since equals() for both classes (added in #1201) is defined as compareTo(o) == 0, this made equals() non-transitive and inconsistent with hashCode() whenever NaN was involved (e.g. segmentFraction is NaN for zero-length line segments).

Fix

Replace the manual </> comparisons with Double.compare(), which gives NaN a well-defined, transitive ordering consistent with Double.hashCode()/Objects.hash() (already used by both classes' hashCode()). No behavior change for non-NaN values.

Tests

Added regression tests reproducing the transitivity/hashCode issue from the report:

  • LinearLocationTest.testEqualsHashCodeConsistentWithNaN
  • EdgeIntersectionTest.testEqualsHashCodeConsistentWithNaN

@bjornharrtell
bjornharrtell force-pushed the fix/1228-nan-compareto branch 5 times, most recently from 8c31be5 to d328bf5 Compare August 31, 2026 17:45
compareTo() used raw </> comparisons on segmentFraction/dist, which are
always false for NaN and made compareTo (and thus equals(), added in locationtech#1201)
fall through to 0 whenever NaN was compared to any other value on the same
segment/index. This broke transitivity of equals() and its consistency with
hashCode(). Use Double.compare() instead, matching Double's NaN ordering
semantics already used by hashCode().
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.

LinearLocation/EdgeIntersection equals() (added in #1201) is inconsistent with hashCode() and non-transitive when segmentFraction/dist is NaN

1 participant