//===----------------------------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

/// A type that can be compared using the relational operators `<`, `<=`, `>=`,
/// and `>`.
///
/// The `Comparable` protocol is used for types that have an inherent order,
/// such as numbers and strings. Many types in the standard library already
/// conform to the `Comparable` protocol. Add `Comparable` conformance to your
/// own custom types when you want to be able to compare instances using
/// relational operators or use standard library methods that are designed for
/// `Comparable` types.
///
/// The most familiar use of relational operators is to compare numbers, as in
/// the following example:
///
///     let currentTemp = 73
///
///     if currentTemp >= 90 {
///         print("It's a scorcher!")
///     } else if currentTemp < 65 {
///         print("Might need a sweater today.")
///     } else {
///         print("Seems like picnic weather!")
///     }
///     // Prints "Seems like picnic weather!"
///
/// You can use special versions of some sequence and collection operations
/// when working with a `Comparable` type. For example, if your array's
/// elements conform to `Comparable`, you can call the `sort()` method without
/// using arguments to sort the elements of your array in ascending order.
///
///     var measurements = [1.1, 1.5, 2.9, 1.2, 1.5, 1.3, 1.2]
///     measurements.sort()
///     print(measurements)
///     // Prints "[1.1, 1.2, 1.2, 1.3, 1.5, 1.5, 2.9]"
///
/// Conforming to the Comparable Protocol
/// =====================================
///
/// Types with Comparable conformance implement the less-than operator (`<`)
/// and the equal-to operator (`==`). These two operations impose a strict
/// total order on the values of a type, in which exactly one of the following
/// must be true for any two values `a` and `b`:
///
/// - `a == b`
/// - `a < b`
/// - `b < a`
///
/// In addition, the following conditions must hold:
///
/// - `a < a` is always `false` (Irreflexivity)
/// - `a < b` implies `!(b < a)` (Asymmetry)
/// - `a < b` and `b < c` implies `a < c` (Transitivity)
///
/// To add `Comparable` conformance to your custom types, define the `<` and
/// `==` operators as static methods of your types. The `==` operator is a
/// requirement of the `Equatable` protocol, which `Comparable` extends---see
/// that protocol's documentation for more information about equality in
/// Swift. Because default implementations of the remainder of the relational
/// operators are provided by the standard library, you'll be able to use
/// `!=`, `>`, `<=`, and `>=` with instances of your type without any further
/// code.
///
/// As an example, here's an implementation of a `Date` structure that stores
/// the year, month, and day of a date:
///
///     struct Date {
///         let year: Int
///         let month: Int
///         let day: Int
///     }
///
/// To add `Comparable` conformance to `Date`, first declare conformance to
/// `Comparable` and implement the `<` operator function.
///
///     extension Date: Comparable {
///         static func < (lhs: Date, rhs: Date) -> Bool {
///             if lhs.year != rhs.year {
///                 return lhs.year < rhs.year
///             } else if lhs.month != rhs.month {
///                 return lhs.month < rhs.month
///             } else {
///                 return lhs.day < rhs.day
///             }
///         }
///
/// This function uses the least specific nonmatching property of the date to
/// determine the result of the comparison. For example, if the two `year`
/// properties are equal but the two `month` properties are not, the date with
/// the lesser value for `month` is the lesser of the two dates.
///
/// Next, implement the `==` operator function, the requirement inherited from
/// the `Equatable` protocol.
///
///         static func == (lhs: Date, rhs: Date) -> Bool {
///             return lhs.year == rhs.year && lhs.month == rhs.month
///                 && lhs.day == rhs.day
///         }
///     }
///
/// Two `Date` instances are equal if each of their corresponding properties is
/// equal.
///
/// Now that `Date` conforms to `Comparable`, you can compare instances of the
/// type with any of the relational operators. The following example compares
/// the date of the first moon landing with the release of David Bowie's song
/// "Space Oddity":
///
///     let spaceOddity = Date(year: 1969, month: 7, day: 11)   // July 11, 1969
///     let moonLanding = Date(year: 1969, month: 7, day: 20)   // July 20, 1969
///     if moonLanding > spaceOddity {
///         print("Major Tom stepped through the door first.")
///     } else {
///         print("David Bowie was following in Neil Armstrong's footsteps.")
///     }
///     // Prints "Major Tom stepped through the door first."
///
/// Note that the `>` operator provided by the standard library is used in this
/// example, not the `<` operator implemented above.
///
/// - Note: A conforming type may contain a subset of values which are treated
///   as exceptional---that is, values that are outside the domain of
///   meaningful arguments for the purposes of the `Comparable` protocol. For
///   example, the special "not a number" value for floating-point types
///   (`FloatingPoint.nan`) compares as neither less than, greater than, nor
///   equal to any normal floating-point value. Exceptional values need not
///   take part in the strict total order.
public protocol Comparable: Equatable, ~Copyable, ~Escapable {
  /// Returns a Boolean value indicating whether the value of the first
  /// argument is less than that of the second argument.
  ///
  /// This function is the only requirement of the `Comparable` protocol. The
  /// remainder of the relational operator functions are implemented by the
  /// standard library for any type that conforms to `Comparable`.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  static func < (lhs: borrowing Self, rhs: borrowing Self) -> Bool

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is less than or equal to that of the second argument.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is greater than or equal to that of the second argument.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool

  /// Returns a Boolean value indicating whether the value of the first
  /// argument is greater than that of the second argument.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool
}

extension Comparable where Self: ~Copyable & ~Escapable {
  /// Returns a Boolean value indicating whether the value of the first argument
  /// is greater than that of the second argument.
  ///
  /// This is the default implementation of the greater-than operator (`>`) for
  /// any type that conforms to `Comparable`.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  @inlinable
  @_preInverseGenerics
  public static func > (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
    return rhs < lhs
  }

  /// Returns a Boolean value indicating whether the value of the first argument
  /// is less than or equal to that of the second argument.
  ///
  /// This is the default implementation of the less-than-or-equal-to
  /// operator (`<=`) for any type that conforms to `Comparable`.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  @inlinable
  @_preInverseGenerics
  public static func <= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
    return !(rhs < lhs)
  }

  /// Returns a Boolean value indicating whether the value of the first argument
  /// is greater than or equal to that of the second argument.
  ///
  /// This is the default implementation of the greater-than-or-equal-to operator
  /// (`>=`) for any type that conforms to `Comparable`.
  ///
  /// - Parameters:
  ///   - lhs: A value to compare.
  ///   - rhs: Another value to compare.
  /// - Returns: `true` if `lhs` is greater than or equal to `rhs`; otherwise,
  ///   `false`.
  @inlinable
  @_preInverseGenerics
  public static func >= (lhs: borrowing Self, rhs: borrowing Self) -> Bool {
    return !(lhs < rhs)
  }
}
