diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 53cbdd84c3a8d..6f8b199f886b7 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -2253,6 +2253,15 @@ pub unsafe fn from_raw_parts_mut<'a, T>(p: *mut T, len: usize) -> &'a mut [T] { mem::transmute(Repr { data: p, len: len }) } +// This function is public only because there is no other way to unit test heapsort. +#[unstable(feature = "sort_internals", reason = "internal to sort module", issue = "0")] +#[doc(hidden)] +pub fn heapsort(v: &mut [T], mut is_less: F) + where F: FnMut(&T, &T) -> bool +{ + sort::heapsort(v, &mut is_less); +} + // // Comparison traits // diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs index a015c8fc120e0..fdfba33f8a9d9 100644 --- a/src/libcore/slice/sort.rs +++ b/src/libcore/slice/sort.rs @@ -57,7 +57,7 @@ fn shift_head(v: &mut [T], is_less: &mut F) ptr::copy_nonoverlapping(v.get_unchecked(1), v.get_unchecked_mut(0), 1); for i in 2..len { - if !is_less(&v[i], &tmp.value) { + if !is_less(v.get_unchecked(i), &tmp.value) { break; } @@ -159,7 +159,7 @@ fn insertion_sort(v: &mut [T], is_less: &mut F) /// Sorts `v` using heapsort, which guarantees `O(n log n)` worst-case. #[cold] -fn heapsort(v: &mut [T], is_less: &mut F) +pub fn heapsort(v: &mut [T], is_less: &mut F) where F: FnMut(&T, &T) -> bool { // This binary heap respects the invariant `parent >= child`. diff --git a/src/libcoretest/lib.rs b/src/libcoretest/lib.rs index 4f3b775ceb2e0..d92c378160d2e 100644 --- a/src/libcoretest/lib.rs +++ b/src/libcoretest/lib.rs @@ -26,6 +26,7 @@ #![feature(raw)] #![feature(sip_hash_13)] #![feature(slice_patterns)] +#![feature(sort_internals)] #![feature(sort_unstable)] #![feature(step_by)] #![feature(test)] diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs index b51bae4db2251..89bd3be08519c 100644 --- a/src/libcoretest/slice.rs +++ b/src/libcoretest/slice.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use core::slice::heapsort; use core::result::Result::{Ok, Err}; use rand::{Rng, XorShiftRng}; @@ -226,26 +227,43 @@ fn get_unchecked_mut_range() { #[test] fn sort_unstable() { let mut v = [0; 600]; - let mut v1 = [0; 600]; + let mut tmp = [0; 600]; let mut rng = XorShiftRng::new_unseeded(); for len in (2..25).chain(500..510) { - for &modulus in &[10, 1000] { + let v = &mut v[0..len]; + let tmp = &mut tmp[0..len]; + + for &modulus in &[5, 10, 100, 1000] { for _ in 0..100 { for i in 0..len { - let num = rng.gen::() % modulus; - v[i] = num; - v1[i] = num; + v[i] = rng.gen::() % modulus; } - v.sort_unstable(); - assert!(v.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_unstable_by(|a, b| a.cmp(b)); - assert!(v1.windows(2).all(|w| w[0] <= w[1])); - - v1.sort_unstable_by(|a, b| b.cmp(a)); - assert!(v1.windows(2).all(|w| w[0] >= w[1])); + // Sort in default order. + tmp.copy_from_slice(v); + tmp.sort_unstable(); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in ascending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| a.cmp(b)); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Sort in descending order. + tmp.copy_from_slice(v); + tmp.sort_unstable_by(|a, b| b.cmp(a)); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); + + // Test heapsort using `<` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a < b); + assert!(tmp.windows(2).all(|w| w[0] <= w[1])); + + // Test heapsort using `>` operator. + tmp.copy_from_slice(v); + heapsort(tmp, |a, b| a > b); + assert!(tmp.windows(2).all(|w| w[0] >= w[1])); } } }