Skip to content

fix(kernel): treat +0.0 and -0.0 as equal in Double/Float Order - #4893

Open
arimu1 wants to merge 1 commit into
typelevel:mainfrom
arimu1:fix/4807-option-signed-zero-eq
Open

fix(kernel): treat +0.0 and -0.0 as equal in Double/Float Order#4893
arimu1 wants to merge 1 commit into
typelevel:mainfrom
arimu1:fix/4807-option-signed-zero-eq

Conversation

@arimu1

@arimu1 arimu1 commented Aug 8, 2026

Copy link
Copy Markdown

Summary

Fixes #4807.

Order[Double].eqv / Order[Float].eqv use primitive ==, so positive and negative zero compare equal:

0.0 === -0.0 // true

compare previously delegated to java.lang.Double.compare / Float.compare, which implement a total order that distinguishes signed zeros. OptionOrder.eqv is derived from compare (compare == 0), so:

Option(0.0) === Option(-0.0) // was false

That disagreed with both bare === and Scala's Option(0.0) == Option(-0.0).

Change

  • DoubleOrder / FloatOrder.compare: use < / > / == so +0 and -0 are equal (matching eqv and IEEE floating equality). Fall back to java.lang.*.compare only when both relational and equality checks fail (NaN total ordering).
  • hash: canonicalize ±0 to +0 before hashing so Hash agrees with eqv for zeros (bit-pattern hashes previously differed).

Alternative considered

Making eqv use Double.compare(x, y) == 0 would also restore compare/eqv consistency, but would make 0.0 === -0.0 false and would make NaN === NaN true — a larger break from primitive == and from the behavior reported in #4807.

Tests

  • testsJVM/testOnly cats.tests.OrderSuite91/91 (Corretto 8 / Scala 2.13), including #4807 cases for Double and Float (bare ===, Order.compare/eqv, Hash, and Option ===/Order).

Checklist

  • Related issue linked (Fixes #4807)
  • Tests added / updated
  • Binary-compatible change (method bodies only)

Order[Double].compare used java.lang.Double.compare, which distinguishes
signed zeros, while eqv used primitive ==. OptionOrder.eqv derives from
compare, so Option(0.0) === Option(-0.0) was false despite 0.0 === -0.0.

Align compare with IEEE floating equality (+0 equals -0) and fall back
to Double/Float.compare only for NaN total ordering. Canonicalize zero
in hash so Hash agrees with eqv.

Fixes typelevel#4807
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.

catsSyntaxEq returns false for equality of positive and negative zero in Option

1 participant