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. 7package 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. 18type 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. 28func 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. 40func 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. 63func 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. 69func 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