diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 9856efc6bd8a4..8e4201f4e8f63 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -908,6 +908,73 @@ pub macro PartialOrd($item:item) { /* compiler built-in */ } +/// Compares two values and returns them in order. +/// +/// Returns the arguments in the order they were passed in if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_pair)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::min_max(1, 2), (1, 2)); +/// assert_eq!(cmp::min_max(2, 2), (2, 2)); +/// assert_eq!(cmp::min_max(3, 2), (2, 3)); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_min_max_pair", issue = "none")] +pub fn min_max(v1: T, v2: T) -> (T, T) { + min_max_by(v1, v2, Ord::cmp) +} + +/// Returns two values in order with respect to the specified comparison function. +/// +/// Returns the arguments in the order they were passed in if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_pair)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::min_max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), (1, -2)); +/// assert_eq!(cmp::min_max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), (-2, 2)); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_min_max_pair", issue = "none")] +pub fn min_max_by Ordering>(v1: T, v2: T, compare: F) -> (T, T) { + match compare(&v1, &v2) { + Ordering::Less | Ordering::Equal => (v1, v2), + Ordering::Greater => (v2, v1), + } +} + +/// Returns two values in order based on the values they return from the specified function. +/// +/// Returns the arguments in the order they were passed in if the comparison determines them to be equal. +/// +/// # Examples +/// +/// ``` +/// #![feature(cmp_min_max_pair)] +/// +/// use std::cmp; +/// +/// assert_eq!(cmp::min_max_by_key(-2, 1, |x: &i32| x.abs()), (1, -2)); +/// assert_eq!(cmp::min_max_by_key(-2, 2, |x: &i32| x.abs()), (-2, 2)); +/// ``` +#[inline] +#[must_use] +#[unstable(feature = "cmp_min_max_pair", issue = "none")] +pub fn min_max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> (T, T) { + min_max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +} + /// Compares and returns the minimum of two values. /// /// Returns the first argument if the comparison determines them to be equal. @@ -947,13 +1014,11 @@ pub fn min(v1: T, v2: T) -> T { #[must_use] #[unstable(feature = "cmp_min_max_by", issue = "64460")] pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { - match compare(&v1, &v2) { - Ordering::Less | Ordering::Equal => v1, - Ordering::Greater => v2, - } + let (min, _max) = min_max_by(v1, v2, compare); + min } -/// Returns the element that gives the minimum value from the specified function. +/// Returns the value that gives the minimum value from the specified function. /// /// Returns the first argument if the comparison determines them to be equal. /// @@ -970,8 +1035,9 @@ pub fn min_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[unstable(feature = "cmp_min_max_by", issue = "64460")] -pub fn min_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - min_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +pub fn min_by_key K, K: Ord>(v1: T, v2: T, f: F) -> T { + let (min, _max) = min_max_by_key(v1, v2, f); + min } /// Compares and returns the maximum of two values. @@ -1013,13 +1079,11 @@ pub fn max(v1: T, v2: T) -> T { #[must_use] #[unstable(feature = "cmp_min_max_by", issue = "64460")] pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { - match compare(&v1, &v2) { - Ordering::Less | Ordering::Equal => v2, - Ordering::Greater => v1, - } + let (_min, max) = min_max_by(v1, v2, compare); + max } -/// Returns the element that gives the maximum value from the specified function. +/// Returns the value that gives the maximum value from the specified function. /// /// Returns the second argument if the comparison determines them to be equal. /// @@ -1036,8 +1100,9 @@ pub fn max_by Ordering>(v1: T, v2: T, compare: F) -> T { #[inline] #[must_use] #[unstable(feature = "cmp_min_max_by", issue = "64460")] -pub fn max_by_key K, K: Ord>(v1: T, v2: T, mut f: F) -> T { - max_by(v1, v2, |v1, v2| f(v1).cmp(&f(v2))) +pub fn max_by_key K, K: Ord>(v1: T, v2: T, f: F) -> T { + let (_min, max) = min_max_by_key(v1, v2, f); + max } // Implementation of PartialEq, Eq, PartialOrd and Ord for primitive types diff --git a/src/libcore/tests/cmp.rs b/src/libcore/tests/cmp.rs index 4086917780fa4..659d137d72329 100644 --- a/src/libcore/tests/cmp.rs +++ b/src/libcore/tests/cmp.rs @@ -58,6 +58,29 @@ fn test_ord_min_max_by_key() { assert_eq!(cmp::max_by_key(2, -1, f), 2); } +#[test] +fn test_ord_min_max_pair() { + assert_eq!(cmp::min_max(1, 2), (1, 2)); + assert_eq!(cmp::min_max(2, 1), (1, 2)); + assert_eq!(cmp::min_max(1, 1), (1, 1)); +} + +#[test] +fn test_ord_min_max_by_pair() { + let f = |x: &i32, y: &i32| x.abs().cmp(&y.abs()); + assert_eq!(cmp::min_max_by(1, -1, f), (1, -1)); + assert_eq!(cmp::min_max_by(1, -2, f), (1, -2)); + assert_eq!(cmp::min_max_by(2, -1, f), (-1, 2)); +} + +#[test] +fn test_ord_min_max_by_key_pair() { + let f = |x: &i32| x.abs(); + assert_eq!(cmp::min_max_by_key(1, -1, f), (1, -1)); + assert_eq!(cmp::min_max_by_key(1, -2, f), (1, -2)); + assert_eq!(cmp::min_max_by_key(2, -1, f), (-1, 2)); +} + #[test] fn test_ordering_reverse() { assert_eq!(Less.reverse(), Greater); diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 524c38a7ab4c1..7e6c4c656e3d6 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -35,6 +35,7 @@ #![feature(iter_is_partitioned)] #![feature(iter_order_by)] #![feature(cmp_min_max_by)] +#![feature(cmp_min_max_pair)] #![feature(iter_map_while)] #![feature(const_slice_from_raw_parts)] #![feature(const_raw_ptr_deref)]