Skip to content

Commit

Permalink
fix(cmp): handle NaN values properly
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Aug 5, 2023
1 parent a7a7ea4 commit e1a2e06
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
6 changes: 6 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,9 @@ issues:
text: "comment on exported const .+ should be of the form"
- linters: [revive]
text: "exported const .+ should have comment"

# False positive.
- path: internal/cmp
linters: [gocritic]
source: "return x != x"
text: "dupSubExpr"
36 changes: 28 additions & 8 deletions internal/cmp/cmp.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,34 @@ package cmp

import "golang.org/x/exp/constraints"

// Compare is a comparator.
func Compare[T constraints.Ordered](a, b T) int {
switch {
case a < b:
return -1
case a > b:
return 1
default:
// Ordered is a type alias to [constraints.Ordered].
type Ordered = constraints.Ordered

// Compare returns
//
// -1 if x is less than y,
// 0 if x equals y,
// +1 if x is greater than y.
//
// For floating-point types, a NaN is considered less than any non-NaN,
// a NaN is considered equal to a NaN, and -0.0 is equal to 0.0.
func Compare[T Ordered](x, y T) int {
xNaN := isNaN(x)
yNaN := isNaN(y)
if xNaN && yNaN {
return 0
}
if xNaN || x < y {
return -1
}
if yNaN || x > y {
return +1
}
return 0
}

// isNaN reports whether x is a NaN without requiring the math package.
// This will always return false if T is not floating-point.
func isNaN[T Ordered](x T) bool {
return x != x
}

0 comments on commit e1a2e06

Please sign in to comment.