Skip to content

Add resort to slice/vec #16557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
110 changes: 109 additions & 1 deletion src/libcollections/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,6 @@ impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] {
fn insertion_sort<T>(v: &mut [T], compare: |&T, &T| -> Ordering) {
let len = v.len() as int;
let buf_v = v.as_mut_ptr();

// 1 <= i < len;
for i in range(1, len) {
// j satisfies: 0 <= j <= i;
Expand Down Expand Up @@ -579,6 +578,20 @@ pub trait MutableSliceAllocating<'a, T> {
/// ```
fn sort_by(self, compare: |&T, &T| -> Ordering);

/// Sort the vector, in place, using `compare` to compare the elements,
/// assuming that the vector is already mostly sorted, in terms of number
/// of inversions.
///
/// This sort is stable, and takes `O(n + i)` time,
/// where `i` is the number of element inversions.
/// As a consequence, this method is generally only appropriate for data
/// that is known to be almost completely sorted.
/// In the worst case (a reverse ordered list) this is <code>O(n<sup>2</sup>)</code>.
/// Further, <code>O(n<sup>2</sup>)</code> is also expected for a random permutation.
/// However, for highly sorted inputs, this can be as low as `O(n)`, in contrast to `sort`,
/// which always takes `O(n log n)`.
fn resort_by(self, compare: |&T, &T| -> Ordering);

/**
* Consumes `src` and moves as many elements as it can into `self`
* from the range [start,end).
Expand Down Expand Up @@ -611,6 +624,11 @@ impl<'a,T> MutableSliceAllocating<'a, T> for &'a mut [T] {
merge_sort(self, compare)
}

#[inline]
fn resort_by(self, compare: |&T, &T| -> Ordering) {
insertion_sort(self, compare)
}

#[inline]
fn move_from(self, mut src: Vec<T>, start: uint, end: uint) -> uint {
for (a, b) in self.mut_iter().zip(src.mut_slice(start, end).mut_iter()) {
Expand All @@ -637,6 +655,10 @@ pub trait MutableOrdSlice<T> {
/// ```
fn sort(self);

/// Sort the vector, in place, assuming that the vector is already mostly sorted,
/// in terms of number of inversions.
fn resort(self);

/// Mutates the slice to the next lexicographic permutation.
///
/// Returns `true` if successful, `false` if the slice is at the last-ordered permutation.
Expand Down Expand Up @@ -674,6 +696,11 @@ impl<'a, T: Ord> MutableOrdSlice<T> for &'a mut [T] {
self.sort_by(|a,b| a.cmp(b))
}

#[inline]
fn resort(self) {
self.resort_by(|a,b| a.cmp(b))
}

fn next_permutation(self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
Expand Down Expand Up @@ -2425,4 +2452,85 @@ mod bench {
});
b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
}

#[bench]
fn resort_random_small(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<u64>().take(5).collect::<Vec<u64>>();
v.as_mut_slice().resort();
});
b.bytes = 5 * mem::size_of::<u64>() as u64;
}

#[bench]
fn resort_random_medium(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<u64>().take(100).collect::<Vec<u64>>();
v.as_mut_slice().resort();
});
b.bytes = 100 * mem::size_of::<u64>() as u64;
}

#[bench]
fn resort_random_large(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<u64>().take(10000).collect::<Vec<u64>>();
v.as_mut_slice().resort();
});
b.bytes = 10000 * mem::size_of::<u64>() as u64;
}

#[bench]
fn resort_sorted(b: &mut Bencher) {
let mut v = Vec::from_fn(10000, |i| i);
b.iter(|| {
v.resort();
});
b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
}

#[bench]
fn resort_big_random_small(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>().take(5)
.collect::<Vec<BigSortable>>();
v.resort();
});
b.bytes = 5 * mem::size_of::<BigSortable>() as u64;
}

#[bench]
fn resort_big_random_medium(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>().take(100)
.collect::<Vec<BigSortable>>();
v.resort();
});
b.bytes = 100 * mem::size_of::<BigSortable>() as u64;
}

#[bench]
fn resort_big_random_large(b: &mut Bencher) {
let mut rng = weak_rng();
b.iter(|| {
let mut v = rng.gen_iter::<BigSortable>().take(10000)
.collect::<Vec<BigSortable>>();
v.resort();
});
b.bytes = 10000 * mem::size_of::<BigSortable>() as u64;
}

#[bench]
fn resort_big_sorted(b: &mut Bencher) {
let mut v = Vec::from_fn(10000u, |i| (i, i, i, i));
b.iter(|| {
v.resort();
});
b.bytes = (v.len() * mem::size_of_val(v.get(0))) as u64;
}
}
33 changes: 33 additions & 0 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,23 @@ impl<T> Vec<T> {
self.as_mut_slice().sort_by(compare)
}

/// Sort the vector, in place, using `compare` to compare the elements,
/// assuming that the vector is already mostly sorted, in terms of number
/// of inversions.
///
/// This sort is stable, and takes `O(n + i)` time,
/// where `i` is the number of element inversions.
/// As a consequence, this method is generally only appropriate for data
/// that is known to be almost completely sorted.
/// In the worst case (a reverse ordered list) this is <code>O(n<sup>2</sup>)</code>.
/// Further, <code>O(n<sup>2</sup>)</code> is also expected for a random permutation.
/// However, for highly sorted inputs, this can be as low as `O(n)`, in contrast to `sort`,
/// which always takes `O(n log n)`.
#[inline]
pub fn resort_by(&mut self, compare: |&T, &T| -> Ordering) {
self.as_mut_slice().resort_by(compare)
}

/// Returns a slice of self spanning the interval [`start`, `end`).
///
/// # Failure
Expand Down Expand Up @@ -1385,6 +1402,22 @@ impl<T:Ord> Vec<T> {
pub fn sort(&mut self) {
self.as_mut_slice().sort()
}

/// Sort the vector in place,
/// assuming that the vector is already mostly sorted, in terms of number
/// of inversions.
///
/// This sort is stable, and takes `O(n + i)` time,
/// where `i` is the number of element inversions.
/// As a consequence, this method is generally only appropriate for data
/// that is known to be almost completely sorted.
/// In the worst case (a reverse ordered list) this is <code>O(n<sup>2</sup>)</code>.
/// Further, <code>O(n<sup>2</sup>)</code> is also expected for a random permutation.
/// However, for highly sorted inputs, this can be as low as `O(n)`, in contrast to `sort`,
/// which always takes `O(n log n)`.
pub fn resort(&mut self) {
self.as_mut_slice().resort()
}
}

impl<T> Mutable for Vec<T> {
Expand Down