cmp.mx raw

   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 | ~int64 |
  20  		~uint | ~uint8 | ~uint16 | ~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