std::vec: make the sorting closure use Ordering rather than just being

(implicitly) less_eq.
This commit is contained in:
Huon Wilson 2013-12-20 14:42:00 +11:00
parent 1b1e4caa79
commit 2e8c522c62
15 changed files with 118 additions and 140 deletions

View File

@ -148,7 +148,7 @@ impl Iterator<Path> for GlobIterator {
fn list_dir_sorted(path: &Path) -> ~[Path] {
match io::result(|| fs::readdir(path)) {
Ok(mut children) => {
children.sort_by(|p1, p2| p2.filename() <= p1.filename());
children.sort_by(|p1, p2| p2.filename().cmp(&p1.filename()));
children
}
Err(..) => ~[]

View File

@ -231,11 +231,7 @@ mod tests {
fn test_top_and_pop() {
let data = ~[2u, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
let mut sorted = data.clone();
<<<<<<< HEAD
sorted.sort(|x, y| x.le(y));
=======
sorted.sort();
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
let mut heap = PriorityQueue::from_vec(data);
while !heap.is_empty() {
assert_eq!(heap.top(), sorted.last());

View File

@ -19,6 +19,25 @@ use std::util;
// NB: this can probably be rewritten in terms of num::Num
// to be less f64-specific.
fn f64_cmp(x: f64, y: f64) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
if y.is_nan() {
Less
} else if x.is_nan() {
Greater
} else if x < y {
Less
} else if x == y {
Equal
} else {
Greater
}
}
fn f64_sort(v: &mut [f64]) {
v.sort_by(|x: &f64, y: &f64| f64_cmp(*x, *y));
}
/// Trait that provides simple descriptive statistics on a univariate set of numeric samples.
pub trait Stats {
@ -239,13 +258,13 @@ impl<'a> Stats for &'a [f64] {
fn percentile(self, pct: f64) -> f64 {
let mut tmp = self.to_owned();
tmp.sort();
f64_sort(tmp);
percentile_of_sorted(tmp, pct)
}
fn quartiles(self) -> (f64,f64,f64) {
let mut tmp = self.to_owned();
tmp.sort();
f64_sort(tmp);
let a = percentile_of_sorted(tmp, 25.0);
let b = percentile_of_sorted(tmp, 50.0);
let c = percentile_of_sorted(tmp, 75.0);
@ -290,7 +309,7 @@ fn percentile_of_sorted(sorted_samples: &[f64],
/// See: http://en.wikipedia.org/wiki/Winsorising
pub fn winsorize(samples: &mut [f64], pct: f64) {
let mut tmp = samples.to_owned();
tmp.sort();
f64_sort(tmp);
let lo = percentile_of_sorted(tmp, pct);
let hi = percentile_of_sorted(tmp, 100.0-pct);
for samp in samples.mut_iter() {

View File

@ -837,10 +837,7 @@ pub fn filter_tests(
};
// Sort the tests alphabetically
fn lteq(t1: &TestDescAndFn, t2: &TestDescAndFn) -> bool {
t1.desc.name.to_str() <= t2.desc.name.to_str()
}
filtered.sort_by(lteq);
filtered.sort_by(|t1, t2| t1.desc.name.to_str().cmp(&t2.desc.name.to_str()));
// Shard the remaining tests, if sharding requested.
match opts.test_shard {

View File

@ -167,7 +167,7 @@ pub fn find_extern_mod_stmt_cnum(cstore: &CStore,
cstore.extern_mod_crate_map.find(&emod_id).map(|x| *x)
}
#[deriving(Clone)]
#[deriving(Clone, TotalEq, TotalOrd)]
struct crate_hash {
name: @str,
vers: @str,

View File

@ -1531,7 +1531,7 @@ fn encode_crate_deps(ecx: &EncodeContext,
});
// Sort by cnum
deps.sort_by(|kv1, kv2| kv1.cnum <= kv2.cnum);
deps.sort_by(|kv1, kv2| kv1.cnum.cmp(&kv2.cnum));
// Sanity-check the crate numbers
let mut expected_cnum = 1;

View File

@ -466,9 +466,9 @@ fn missing_ctor(cx: &MatchCheckCtxt,
// those with a destructured slice come first.
vec_pat_lens.sort_by(|&(len1, slice1), &(len2, slice2)| {
if len1 == len2 {
slice1 > slice2
slice2.cmp(&slice1)
} else {
len1 <= len2
len1.cmp(&len2)
}
});
vec_pat_lens.dedup();

View File

@ -63,7 +63,7 @@ use syntax::{ast, ast_util, visit};
use syntax::ast_util::IdVisitingOperation;
use syntax::visit::Visitor;
#[deriving(Clone, Eq)]
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
pub enum lint {
ctypes,
unused_imports,
@ -110,20 +110,16 @@ pub fn level_to_str(lv: level) -> &'static str {
}
}
#[deriving(Clone, Eq, Ord)]
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
pub enum level {
allow, warn, deny, forbid
}
#[deriving(Clone, Eq)]
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd)]
pub struct LintSpec {
default: level,
lint: lint,
desc: &'static str,
default: level
}
impl Ord for LintSpec {
fn lt(&self, other: &LintSpec) -> bool { self.default < other.default }
}
pub type LintDict = HashMap<&'static str, LintSpec>;

View File

@ -3163,7 +3163,7 @@ pub fn trans_crate(sess: session::Session,
println!("n_closures: {}", ccx.stats.n_closures);
println("fn stats:");
ccx.stats.fn_stats.sort_by(|&(_, _, insns_a), &(_, _, insns_b)| insns_a >= insns_b);
ccx.stats.fn_stats.sort_by(|&(_, _, insns_a), &(_, _, insns_b)| insns_b.cmp(&insns_a));
for tuple in ccx.stats.fn_stats.iter() {
match *tuple {

View File

@ -898,44 +898,44 @@ fn item_module(w: &mut Writer, cx: &Context,
debug!("{:?}", items);
let mut indices = vec::from_fn(items.len(), |i| i);
fn le(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> bool {
fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: uint, idx2: uint) -> Ordering {
if shortty(i1) == shortty(i2) {
return i1.name <= i2.name;
return i1.name.cmp(&i2.name);
}
match (&i1.inner, &i2.inner) {
(&clean::ViewItemItem(ref a), &clean::ViewItemItem(ref b)) => {
match (&a.inner, &b.inner) {
(&clean::ExternMod(..), _) => true,
(_, &clean::ExternMod(..)) => false,
_ => idx1 <= idx2,
(&clean::ExternMod(..), _) => Less,
(_, &clean::ExternMod(..)) => Greater,
_ => idx1.cmp(&idx2),
}
}
(&clean::ViewItemItem(..), _) => true,
(_, &clean::ViewItemItem(..)) => false,
(&clean::ModuleItem(..), _) => true,
(_, &clean::ModuleItem(..)) => false,
(&clean::StructItem(..), _) => true,
(_, &clean::StructItem(..)) => false,
(&clean::EnumItem(..), _) => true,
(_, &clean::EnumItem(..)) => false,
(&clean::StaticItem(..), _) => true,
(_, &clean::StaticItem(..)) => false,
(&clean::ForeignFunctionItem(..), _) => true,
(_, &clean::ForeignFunctionItem(..)) => false,
(&clean::ForeignStaticItem(..), _) => true,
(_, &clean::ForeignStaticItem(..)) => false,
(&clean::TraitItem(..), _) => true,
(_, &clean::TraitItem(..)) => false,
(&clean::FunctionItem(..), _) => true,
(_, &clean::FunctionItem(..)) => false,
(&clean::TypedefItem(..), _) => true,
(_, &clean::TypedefItem(..)) => false,
_ => idx1 <= idx2,
(&clean::ViewItemItem(..), _) => Less,
(_, &clean::ViewItemItem(..)) => Greater,
(&clean::ModuleItem(..), _) => Less,
(_, &clean::ModuleItem(..)) => Greater,
(&clean::StructItem(..), _) => Less,
(_, &clean::StructItem(..)) => Greater,
(&clean::EnumItem(..), _) => Less,
(_, &clean::EnumItem(..)) => Greater,
(&clean::StaticItem(..), _) => Less,
(_, &clean::StaticItem(..)) => Greater,
(&clean::ForeignFunctionItem(..), _) => Less,
(_, &clean::ForeignFunctionItem(..)) => Greater,
(&clean::ForeignStaticItem(..), _) => Less,
(_, &clean::ForeignStaticItem(..)) => Greater,
(&clean::TraitItem(..), _) => Less,
(_, &clean::TraitItem(..)) => Greater,
(&clean::FunctionItem(..), _) => Less,
(_, &clean::FunctionItem(..)) => Greater,
(&clean::TypedefItem(..), _) => Less,
(_, &clean::TypedefItem(..)) => Greater,
_ => idx1.cmp(&idx2),
}
}
debug!("{:?}", indices);
indices.sort_by(|&i1, &i2| le(&items[i1], &items[i2], i1, i2));
indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2));
debug!("{:?}", indices);
let mut curty = "";
@ -1530,7 +1530,7 @@ fn build_sidebar(m: &clean::Module) -> HashMap<~str, ~[~str]> {
}
for (_, items) in map.mut_iter() {
items.sort(|i1, i2| i1 <= i2);
items.sort();
}
return map;
}

View File

@ -79,7 +79,8 @@ pub use tuple::{Tuple1, Tuple2, Tuple3, Tuple4};
pub use tuple::{Tuple5, Tuple6, Tuple7, Tuple8};
pub use tuple::{Tuple9, Tuple10, Tuple11, Tuple12};
pub use vec::{ImmutableEqVector, ImmutableTotalOrdVector, ImmutableCopyableVector};
pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector, MutableVector, MutableOrdVector};
pub use vec::{OwnedVector, OwnedCopyableVector,OwnedEqVector};
pub use vec::{MutableVector, MutableTotalOrdVector};
pub use vec::{Vector, VectorVector, CopyableVector, ImmutableVector};
// Reexported runtime types

View File

@ -1921,7 +1921,7 @@ impl<T:Eq> OwnedEqVector<T> for ~[T] {
}
}
fn merge_sort<T>(v: &mut [T], less_eq: |&T, &T| -> bool) {
fn merge_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
// warning: this wildly uses unsafe.
static INSERTION: uint = 8;
@ -1930,7 +1930,7 @@ fn merge_sort<T>(v: &mut [T], less_eq: |&T, &T| -> bool) {
// allocate some memory to use as scratch memory, we keep the
// length 0 so we can keep shallow copies of the contents of `v`
// without risking the dtors running on an object twice if
// `less_eq` fails.
// `compare` fails.
let mut working_space = with_capacity(2 * len);
// these both are buffers of length `len`.
let mut buf_dat = working_space.as_mut_ptr();
@ -1960,7 +1960,8 @@ fn merge_sort<T>(v: &mut [T], less_eq: |&T, &T| -> bool) {
// start <= j - 1 < len, so .offset(j - 1) is in
// bounds.
while j > start as int && !less_eq(&*buf_dat.offset(j - 1), &*read_ptr) {
while j > start as int &&
compare(&*read_ptr, &*buf_dat.offset(j - 1)) == Less {
j -= 1;
}
@ -2034,10 +2035,10 @@ fn merge_sort<T>(v: &mut [T], less_eq: |&T, &T| -> bool) {
// `left < right_start` and `right < right_end`,
// so these are valid.
let to_copy = if less_eq(&*left, &*right) {
step(&mut left)
} else {
let to_copy = if compare(&*left, &*right) == Greater {
step(&mut right)
} else {
step(&mut left)
};
ptr::copy_nonoverlapping_memory(out, to_copy, 1);
step(&mut out);
@ -2164,8 +2165,8 @@ pub trait MutableVector<'a, T> {
/// Reverse the order of elements in a vector, in place
fn reverse(self);
/// Sort the vector, in place, using `less_eq` to compare `a <=
/// b`.
/// Sort the vector, in place, using `compare` to compare
/// elements.
///
/// This sort is `O(n log n)` worst-case and stable, but allocates
/// approximately `2 * n`, where `n` is the length of `self`.
@ -2174,14 +2175,14 @@ pub trait MutableVector<'a, T> {
///
/// ```rust
/// let mut v = [5, 4, 1, 3, 2];
/// v.sort(|a, b| *a <= *b);
/// v.sort(|a, b| a.cmp(b));
/// assert_eq!(v, [1, 2, 3, 4, 5]);
///
/// // reverse sorting
/// v.sort(|a, b| *b <= *a);
/// v.sort(|a, b| b.cmp(a));
/// assert_eq!(v, [5, 4, 3, 2, 1]);
/// ```
fn sort_by(self, less_eq: |&T, &T| -> bool);
fn sort_by(self, compare: |&T, &T| -> Ordering);
/**
* Consumes `src` and moves as many elements as it can into `self`
@ -2328,12 +2329,8 @@ impl<'a,T> MutableVector<'a, T> for &'a mut [T] {
}
#[inline]
<<<<<<< HEAD
fn sort(self, less_eq: |&T, &T| -> bool) {
=======
fn sort_by<Sort: SortComparator<T>>(self, less_eq: Sort) {
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
merge_sort(self, less_eq)
fn sort_by(self, compare: |&T, &T| -> Ordering) {
merge_sort(self, compare)
}
#[inline]
@ -2391,7 +2388,7 @@ impl<'a, T:Clone> MutableCloneableVector<T> for &'a mut [T] {
/// Methods for mutable vectors with orderable elements, such as
/// in-place sorting.
pub trait MutableOrdVector<T> {
pub trait MutableTotalOrdVector<T> {
/// Sort the vector, in place.
///
/// This is equivalent to `self.sort_by(std::vec::SortForward)`.
@ -2408,10 +2405,10 @@ pub trait MutableOrdVector<T> {
/// ```
fn sort(self);
}
impl<'a, T: Ord> MutableOrdVector<T> for &'a mut [T] {
impl<'a, T: TotalOrd> MutableTotalOrdVector<T> for &'a mut [T] {
#[inline]
fn sort(self) {
self.sort_by(SortForward)
self.sort_by(|a,b| a.cmp(b))
}
}
@ -3502,41 +3499,25 @@ mod tests {
for len in range(4u, 25) {
for _ in range(0, 100) {
let mut v = task_rng().gen_vec::<uint>(len);
v.sort(|a,b| a <= b);
<<<<<<< HEAD
assert!(v.windows(2).all(|w| w[0] <= w[1]));
=======
let mut v1 = v.clone();
let mut v2 = v.clone();
v.sort();
assert!(v.windows(2).all(|w| w[0] <= w[1]));
v1.sort_by(vec::SortForward);
v1.sort_by(|a, b| a.cmp(b));
assert!(v1.windows(2).all(|w| w[0] <= w[1]));
v1.sort_by(vec::SortReverse);
v1.sort_by(|a, b| b.cmp(a));
assert!(v1.windows(2).all(|w| w[0] >= w[1]));
v2.sort_by(|a: &uint, b: &uint| a <= b);
assert!(v2.windows(2).all(|w| w[0] <= w[1]));
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
}
}
// shouldn't fail/crash
let mut v: [uint, .. 0] = [];
<<<<<<< HEAD
v.sort(|a,b| a <= b);
v.sort();
let mut v = [0xDEADBEEF];
v.sort(|a,b| a <= b);
=======
v.sort_by(SortForward);
let mut v = [0xDEADBEEF];
v.sort_by(SortForward);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
v.sort();
assert_eq!(v, [0xDEADBEEF]);
}
@ -3559,11 +3540,7 @@ mod tests {
// only sort on the first element, so an unstable sort
// may mix up the counts.
<<<<<<< HEAD
v.sort(|&(a,_), &(b,_)| a <= b);
=======
v.sort_by(|&(a,_): &(uint, uint), &(b,_): &(uint, uint)| a <= b);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
v.sort_by(|&(a,_), &(b,_)| a.cmp(&b));
// this comparison includes the count (the second item
// of the tuple), so elements with equal first items
@ -4398,10 +4375,10 @@ mod bench {
use extra::test::BenchHarness;
use iter::range;
use vec;
use vec::{VectorVector, MutableOrdVector};
use vec::{VectorVector, MutableTotalOrdVector};
use option::*;
use ptr;
use rand::{weak_rng, task_rng, Rng};
use rand::{weak_rng, Rng};
use mem;
#[bench]
@ -4604,33 +4581,34 @@ mod bench {
})
}
#[bench]
fn sort_random_small(bh: &mut BenchHarness) {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(5);
let mut v: ~[u64] = rng.gen_vec(5);
v.sort();
});
bh.bytes = 5 * mem::size_of::<f64>() as u64;
bh.bytes = 5 * mem::size_of::<u64>() as u64;
}
#[bench]
fn sort_random_medium(bh: &mut BenchHarness) {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(100);
let mut v: ~[u64] = rng.gen_vec(100);
v.sort();
});
bh.bytes = 100 * mem::size_of::<f64>() as u64;
bh.bytes = 100 * mem::size_of::<u64>() as u64;
}
#[bench]
fn sort_random_large(bh: &mut BenchHarness) {
let mut rng = weak_rng();
bh.iter(|| {
let mut v: ~[f64] = rng.gen_vec(10000);
let mut v: ~[u64] = rng.gen_vec(10000);
v.sort();
});
bh.bytes = 10000 * mem::size_of::<f64>() as u64;
bh.bytes = 10000 * mem::size_of::<u64>() as u64;
}
#[bench]

View File

@ -203,11 +203,7 @@ pub fn sort_meta_items(items: &[@MetaItem]) -> ~[@MetaItem] {
.map(|&mi| (mi.name(), mi))
.collect::<~[(@str, @MetaItem)]>();
<<<<<<< HEAD
v.sort(|&(a, _), &(b, _)| a <= b);
=======
v.sort_by(|&(a, _): &(@str, @MetaItem), &(b, _): &(@str, @MetaItem)| a <= b);
>>>>>>> 9ceda35... std::vec: add a sugary .sort() method for plain Ord sorting.
v.sort_by(|&(a, _), &(b, _)| a.cmp(&b));
// There doesn't seem to be a more optimal way to do this
v.move_iter().map(|(_, m)| {

View File

@ -26,37 +26,32 @@ use std::task;
use std::util;
use std::vec;
fn f64_cmp(x: f64, y: f64) -> Ordering {
// arbitrarily decide that NaNs are larger than everything.
if y.is_nan() {
Less
} else if x.is_nan() {
Greater
} else if x < y {
Less
} else if x == y {
Equal
} else {
Greater
}
}
// given a map, print a sorted version of it
fn sort_and_fmt(mm: &HashMap<~[u8], uint>, total: uint) -> ~str {
fn pct(xx: uint, yy: uint) -> f64 {
return (xx as f64) * 100.0 / (yy as f64);
}
fn le_by_val<TT:Clone,
UU:Clone + Ord>(
kv0: &(TT,UU),
kv1: &(TT,UU))
-> bool {
let (_, v0) = (*kv0).clone();
let (_, v1) = (*kv1).clone();
return v0 >= v1;
}
fn le_by_key<TT:Clone + Ord,
UU:Clone>(
kv0: &(TT,UU),
kv1: &(TT,UU))
-> bool {
let (k0, _) = (*kv0).clone();
let (k1, _) = (*kv1).clone();
return k0 <= k1;
}
// sort by key, then by value
fn sortKV<TT:Clone + Ord, UU:Clone + Ord>(mut orig: ~[(TT,UU)]) -> ~[(TT,UU)] {
orig.sort_by(le_by_key);
orig.sort_by(le_by_val);
origin
fn sortKV(mut orig: ~[(~[u8],f64)]) -> ~[(~[u8],f64)] {
orig.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
orig.sort_by(|&(_, a), &(_, b)| f64_cmp(b, a));
orig
}
let mut pairs = ~[];

View File

@ -14,7 +14,7 @@ static MAX_LEN: uint = 20;
static mut drop_counts: [uint, .. MAX_LEN] = [0, .. MAX_LEN];
static mut clone_count: uint = 0;
#[deriving(Rand, Ord)]
#[deriving(Rand, Ord, TotalEq, TotalOrd)]
struct DropCounter { x: uint, clone_num: uint }
impl Clone for DropCounter {
@ -48,7 +48,7 @@ pub fn main() {
// work out the total number of comparisons required to sort
// this array...
let mut count = 0;
main.clone().sort_by(|a, b| { count += 1; a <= b });
main.clone().sort_by(|a, b| { count += 1; a.cmp(b) });
// ... and then fail on each and every single one.
for fail_countdown in range(0, count) {
@ -68,7 +68,7 @@ pub fn main() {
fail!()
}
fail_countdown -= 1;
a <= b
a.cmp(b)
})
});