Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
62645a1
Fix ICE when dividing integral SIMD types.
hirschenberger Mar 25, 2015
6370f29
std: Stabilize parts of std::os::platform::io
alexcrichton Mar 26, 2015
df65f59
replace deprecated as_slice()
demelev Mar 30, 2015
2a89d69
libcore: Ensure min and max functions are consistent for equal inputs
Ryman Mar 30, 2015
f19e763
std: Stabilize the rest of Any/BoxAny
alexcrichton Mar 30, 2015
e17f4fc
convert: remove FromError, use From<E> instead
seanmonstar Mar 31, 2015
606f50c
Lex binary and octal literals more eagerly.
huonw Mar 30, 2015
a78d383
Update lib.rs
wettowelreactor Mar 31, 2015
edc096d
Document std::borrow with examples
steveklabnik Mar 24, 2015
fe8a660
Last docs for std::env
steveklabnik Mar 31, 2015
5872ae4
Indicate select! is code-like
frewsxcv Mar 31, 2015
5d0beb7
rollup merge of #23549: aturon/stab-num
alexcrichton Mar 31, 2015
03c2f33
rollup merge of #23669: steveklabnik/doc_std_borrow
alexcrichton Mar 31, 2015
9fc51ef
Stabilize `std::convert` and related code
aturon Mar 30, 2015
cf56162
Fix up iterator documentation with regards to for loop sugar
steveklabnik Mar 31, 2015
9ba7974
book: reword timer bit
Mar 31, 2015
d9a6e86
Fixup primitive.str docs
steveklabnik Mar 31, 2015
5cf126a
std: Remove #[old_orphan_check] from PartialEq
alexcrichton Mar 11, 2015
608fff8
rustc: Remove old_orphan_check entirely
alexcrichton Mar 31, 2015
e48c7c6
Fix spelling
steveklabnik Mar 31, 2015
71982aa
std: Add a process::exit function
alexcrichton Mar 31, 2015
b9ab5fe
Stabilize a few remaining stragglers
aturon Mar 31, 2015
1829974
rollup merge of #23704: hirschenberger/simd-intdiv-ice
alexcrichton Mar 31, 2015
890f0ab
rollup merge of #23766: alexcrichton/stabilize-raw-fd
alexcrichton Mar 31, 2015
d03120a
rollup merge of #23876: alexcrichton/stabilize-any
alexcrichton Mar 31, 2015
f6bd6b4
rollup merge of #23878: Ryman/stable_extremes
alexcrichton Mar 31, 2015
095f1fb
rollup merge of #23882: wettowelreactor/patch-2
alexcrichton Mar 31, 2015
5e0bda0
rollup merge of #23885: steveklabnik/doc_std_env
alexcrichton Mar 31, 2015
6d2c640
rollup merge of #23886: demelev/remove_as_slice_usage
alexcrichton Mar 31, 2015
acdb0f9
rollup merge of #23893: frewsxcv/patch-6
alexcrichton Mar 31, 2015
d4a2c94
std: Clean out #[deprecated] APIs
alexcrichton Mar 30, 2015
e3f2d45
rollup merge of #23872: huonw/eager-lexing
alexcrichton Mar 31, 2015
94137a3
Test fixes and rebase conflicts, round 1
alexcrichton Mar 31, 2015
da04788
rollup merge of #23875: aturon/revise-convert-2
alexcrichton Mar 31, 2015
e10ee2c
rollup merge of #23879: seanmonstar/del-from-error
alexcrichton Mar 31, 2015
554946c
rollup merge of #23873: alexcrichton/remove-deprecated
alexcrichton Mar 31, 2015
3053288
Test fixes and rebase conflicts, round 2
alexcrichton Mar 31, 2015
82889f7
rollup merge of #23902: freebroccolo/master
alexcrichton Mar 31, 2015
0cac5b6
rollup merge of #23906: steveklabnik/spellin
alexcrichton Mar 31, 2015
a37311d
rollup merge of #23907: alexcrichton/impl-exit
alexcrichton Mar 31, 2015
30283d4
rollup merge of #23908: aturon/stab-more-stragglers
alexcrichton Mar 31, 2015
3422be3
rollup merge of #23288: alexcrichton/issue-19470
alexcrichton Mar 31, 2015
8da0831
Move benchmark tests to unstable section
steveklabnik Mar 31, 2015
9ab6cc9
rollup merge of #23901: steveklabnik/fix_links_str
alexcrichton Mar 31, 2015
6659865
rollup merge of #23920: steveklabnik/gh23881
alexcrichton Mar 31, 2015
ac77392
std: Stabilize last bits of io::Error
alexcrichton Mar 31, 2015
85e997a
rollup merge of #23899: steveklabnik/gh23851
alexcrichton Mar 31, 2015
50b3ecf
rollup merge of #23919: alexcrichton/stabilize-io-error
alexcrichton Mar 31, 2015
55e531d
Add test for #17746
aturon Mar 31, 2015
371ba00
Add description of + for multiple trait bounds
steveklabnik Mar 31, 2015
72f5973
Test fixes and rebase conflicts, round 3
alexcrichton Mar 31, 2015
4f643d7
rollup merge of #23863: pnkfelix/arith-oflo-const-eval
alexcrichton Apr 1, 2015
1d5ef75
rollup merge of #23921: aturon/issue-17746
alexcrichton Apr 1, 2015
6ebb6e6
rollup merge of #23923: steveklabnik/gh23688
alexcrichton Apr 1, 2015
8dff0ac
Test fixes and rebase conflicts
alexcrichton Apr 1, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
libcore: Ensure min and max functions are consistent for equal inputs
  • Loading branch information
Ryman committed Mar 30, 2015
commit 2a89d695f4edb6fe8c7629f48908d3d3d9076426
14 changes: 9 additions & 5 deletions src/libcore/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,8 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {

/// Compare and return the minimum of two values.
///
/// Returns the first argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
Expand All @@ -373,11 +375,13 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn min<T: Ord>(v1: T, v2: T) -> T {
if v1 < v2 { v1 } else { v2 }
if v1 <= v2 { v1 } else { v2 }
}

/// Compare and return the maximum of two values.
///
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
/// ```
Expand All @@ -389,7 +393,7 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn max<T: Ord>(v1: T, v2: T) -> T {
if v1 > v2 { v1 } else { v2 }
if v2 >= v1 { v2 } else { v1 }
}

/// Compare and return the minimum of two values if there is one.
Expand Down Expand Up @@ -427,7 +431,7 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {

/// Compare and return the maximum of two values if there is one.
///
/// Returns the first argument if the comparison determines them to be equal.
/// Returns the second argument if the comparison determines them to be equal.
///
/// # Examples
///
Expand All @@ -452,8 +456,8 @@ pub fn partial_min<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
#[unstable(feature = "core")]
pub fn partial_max<T: PartialOrd>(v1: T, v2: T) -> Option<T> {
match v1.partial_cmp(&v2) {
Some(Less) => Some(v2),
Some(Equal) | Some(Greater) => Some(v1),
Some(Equal) | Some(Less) => Some(v2),
Some(Greater) => Some(v1),
None => None
}
}
Expand Down
58 changes: 35 additions & 23 deletions src/libcore/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,9 @@ pub trait Iterator {

/// Consumes the entire iterator to return the maximum element.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
Expand All @@ -732,16 +735,19 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
fn max(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
{
self.fold(None, |max, x| {
self.fold(None, |max, y| {
match max {
None => Some(x),
Some(y) => Some(cmp::max(x, y))
None => Some(y),
Some(x) => Some(cmp::max(x, y))
}
})
}

/// Consumes the entire iterator to return the minimum element.
///
/// Returns the leftmost element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
Expand All @@ -752,10 +758,10 @@ pub trait Iterator {
#[stable(feature = "rust1", since = "1.0.0")]
fn min(self) -> Option<Self::Item> where Self: Sized, Self::Item: Ord
{
self.fold(None, |min, x| {
self.fold(None, |min, y| {
match min {
None => Some(x),
Some(y) => Some(cmp::min(x, y))
None => Some(y),
Some(x) => Some(cmp::min(x, y))
}
})
}
Expand Down Expand Up @@ -799,7 +805,7 @@ pub trait Iterator {
Some(x) => {
match self.next() {
None => return OneElement(x),
Some(y) => if x < y {(x, y)} else {(y,x)}
Some(y) => if x <= y {(x, y)} else {(y, x)}
}
}
};
Expand All @@ -817,19 +823,19 @@ pub trait Iterator {
None => {
if first < min {
min = first;
} else if first > max {
} else if first >= max {
max = first;
}
break;
}
Some(x) => x
};
if first < second {
if first < min {min = first;}
if max < second {max = second;}
if first <= second {
if first < min { min = first }
if second >= max { max = second }
} else {
if second < min {min = second;}
if max < first {max = first;}
if second < min { min = second }
if first >= max { max = first }
}
}

Expand All @@ -839,6 +845,9 @@ pub trait Iterator {
/// Return the element that gives the maximum value from the
/// specified function.
///
/// Returns the rightmost element if the comparison determines two elements
/// to be equally maximum.
///
/// # Examples
///
/// ```
Expand All @@ -855,14 +864,14 @@ pub trait Iterator {
Self: Sized,
F: FnMut(&Self::Item) -> B,
{
self.fold(None, |max: Option<(Self::Item, B)>, x| {
let x_val = f(&x);
self.fold(None, |max: Option<(Self::Item, B)>, y| {
let y_val = f(&y);
match max {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val > y_val {
Some((x, x_val))
} else {
None => Some((y, y_val)),
Some((x, x_val)) => if y_val >= x_val {
Some((y, y_val))
} else {
Some((x, x_val))
}
}
}).map(|(x, _)| x)
Expand All @@ -871,6 +880,9 @@ pub trait Iterator {
/// Return the element that gives the minimum value from the
/// specified function.
///
/// Returns the leftmost element if the comparison determines two elements
/// to be equally minimum.
///
/// # Examples
///
/// ```
Expand All @@ -887,11 +899,11 @@ pub trait Iterator {
Self: Sized,
F: FnMut(&Self::Item) -> B,
{
self.fold(None, |min: Option<(Self::Item, B)>, x| {
let x_val = f(&x);
self.fold(None, |min: Option<(Self::Item, B)>, y| {
let y_val = f(&y);
match min {
None => Some((x, x_val)),
Some((y, y_val)) => if x_val < y_val {
None => Some((y, y_val)),
Some((x, x_val)) => if x_val <= y_val {
Some((x, x_val))
} else {
Some((y, y_val))
Expand Down
83 changes: 83 additions & 0 deletions src/test/run-pass/minmax-stability-issue-23687.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(core)]
use std::fmt::Debug;
use std::cmp::{self, PartialOrd, Ordering};
use std::iter::MinMaxResult::MinMax;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
struct Foo {
n: u8,
name: &'static str
}

impl PartialOrd for Foo {
fn partial_cmp(&self, other: &Foo) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Foo {
fn cmp(&self, other: &Foo) -> Ordering {
self.n.cmp(&other.n)
}
}

fn main() {
let a = Foo { n: 4, name: "a" };
let b = Foo { n: 4, name: "b" };
let c = Foo { n: 8, name: "c" };
let d = Foo { n: 8, name: "d" };
let e = Foo { n: 22, name: "e" };
let f = Foo { n: 22, name: "f" };

let data = [a, b, c, d, e, f];

// `min` should return the left when the values are equal
assert_eq!(data.iter().min(), Some(&a));
assert_eq!(data.iter().min_by(|a| a.n), Some(&a));
assert_eq!(cmp::min(a, b), a);
assert_eq!(cmp::min(b, a), b);
assert_eq!(cmp::partial_min(a, b), Some(a));
assert_eq!(cmp::partial_min(b, a), Some(b));

// `max` should return the right when the values are equal
assert_eq!(data.iter().max(), Some(&f));
assert_eq!(data.iter().max_by(|a| a.n), Some(&f));
assert_eq!(cmp::max(e, f), f);
assert_eq!(cmp::max(f, e), e);
assert_eq!(cmp::partial_max(e, f), Some(f));
assert_eq!(cmp::partial_max(f, e), Some(e));

// Similar for `min_max`
assert_eq!(data.iter().min_max(), MinMax(&a, &f));
assert_eq!(data[1..5].iter().min_max(), MinMax(&b, &e));
assert_eq!(data[2..4].iter().min_max(), MinMax(&c, &d));

let mut presorted = data.to_vec();
presorted.sort();
assert_stable(&presorted);

let mut presorted = data.to_vec();
presorted.sort_by(|a, b| a.cmp(b));
assert_stable(&presorted);

// Assert that sorted and min/max are the same
fn assert_stable<T: Ord + Debug>(presorted: &[T]) {
for slice in presorted.windows(2) {
let a = &slice[0];
let b = &slice[1];

assert_eq!(a, cmp::min(a, b));
assert_eq!(b, cmp::max(a, b));
}
}
}