1 // Copyright 2023 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package cmp provides types and functions related to comparing 6 // ordered values. 7 package cmp 8 9 // Ordered is a constraint that permits any ordered type: any type 10 // that supports the operators < <= >= >. 11 // If future releases of Go add new ordered types, 12 // this constraint will be modified to include them. 13 // 14 // Note that floating-point types may contain NaN ("not-a-number") values. 15 // An operator such as == or < will always report false when 16 // comparing a NaN value with any other value, NaN or not. 17 // See the [Compare] function for a consistent way to compare NaN values. 18 type Ordered interface { 19 ~int | ~int8 | ~int16 | ~int32 | ~int64 | 20 ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | 21 ~float32 | ~float64 | 22 ~string 23 } 24 25 // Less reports whether x is less than y. 26 // For floating-point types, a NaN is considered less than any non-NaN, 27 // and -0.0 is not less than (is equal to) 0.0. 28 func Less[T Ordered](x, y T) bool { 29 return (isNaN(x) && !isNaN(y)) || x < y 30 } 31 32 // Compare returns 33 // 34 // -1 if x is less than y, 35 // 0 if x equals y, 36 // +1 if x is greater than y. 37 // 38 // For floating-point types, a NaN is considered less than any non-NaN, 39 // a NaN is considered equal to a NaN, and -0.0 is equal to 0.0. 40 func Compare[T Ordered](x, y T) int { 41 xNaN := isNaN(x) 42 yNaN := isNaN(y) 43 if xNaN { 44 if yNaN { 45 return 0 46 } 47 return -1 48 } 49 if yNaN { 50 return +1 51 } 52 if x < y { 53 return -1 54 } 55 if x > y { 56 return +1 57 } 58 return 0 59 } 60 61 // isNaN reports whether x is a NaN without requiring the math package. 62 // This will always return false if T is not floating-point. 63 func isNaN[T Ordered](x T) bool { 64 return x != x 65 } 66 67 // Or returns the first of its arguments that is not equal to the zero value. 68 // If no argument is non-zero, it returns the zero value. 69 func Or[T comparable](vals ...T) T { 70 var zero T 71 for _, val := range vals { 72 if val != zero { 73 return val 74 } 75 } 76 return zero 77 } 78