From cef77636497fad5f3e07c5089ef8ed68fa739689 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Tue, 25 Sep 2012 17:53:24 -0500 Subject: [PATCH 01/28] Add timsort to std/sort --- src/libstd/sort.rs | 594 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 594 insertions(+) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 46f79c0194862..8cd98f8ab0ba9 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -4,6 +4,7 @@ use vec::{len, push}; use core::cmp::{Eq, Ord}; +use dvec::DVec; export le; export merge_sort; @@ -168,6 +169,599 @@ impl &[mut T] : Sort { fn qsort(self) { quick_sort3(self); } } +const MIN_MERGE: uint = 64; +const MIN_GALLOP: uint = 7; +const INITIAL_TMP_STORAGE: uint = 128; + +fn timsort(array: &[mut T]) { + let size = array.len(); + if size < 2 { + return; + } + + if size < MIN_MERGE { + let initRunLen = countRunAndMakeAscending(array); + binarysort(array, initRunLen); + return; + } + + let ms = &MergeState(); + let minRun = minRunLength(size); + + let mut idx = 0; + let mut remaining = size; + loop { + let arr = vec::mut_view(array, idx, size); + let mut runLen: uint = countRunAndMakeAscending(arr); + + if runLen < minRun { + let force = if remaining <= minRun {remaining} else {minRun}; + let slice = vec::mut_view(arr, 0, force); + binarysort(slice, runLen); + runLen = force; + } + + ms.pushRun(idx, runLen); + ms.mergeCollapse(array); + + idx += runLen; + remaining -= runLen; + if remaining == 0 { break; } + } + + ms.mergeForceCollapse(array); +} + +fn binarysort(array: &[mut T], start: uint) { + let size = array.len(); + let mut start = start; + assert start <= size; + + if start == 0 { start += 1; } + + let mut pivot = ~[mut]; + vec::reserve(pivot, 1); + unsafe { vec::raw::set_len(pivot, 1); }; + + while start < size { + unsafe { + let tmpView = vec::mut_view(array, start, start+1); + vec::raw::memmove(pivot, tmpView, 1); + } + let mut left = 0; + let mut right = start; + assert left <= right; + + while left < right { + let mid = (left + right) >> 1; + if pivot[0] < array[mid] { + right = mid; + } else { + left = mid+1; + } + } + assert left == right; + let mut n = start-left; + + unsafe { + moveVec(array, left+1, array, left, n); + } + array[left] <-> pivot[0]; + start += 1; + } + unsafe { vec::raw::set_len(pivot, 0); } // Forget the boxed element +} + +/// Reverse the order of elements in a slice, in place +fn reverseSlice(v: &[mut T], start: uint, end:uint) { + let mut i = start; + while i < end / 2 { + v[i] <-> v[end - i - 1]; + i += 1; + } +} + +pure fn minRunLength(n: uint) -> uint { + let mut n = n; + let mut r = 0; // becomes 1 if any 1 bits are shifted off + + while n >= MIN_MERGE { + r |= n & 1; + n >>= 1; + } + return n + r; +} + +fn countRunAndMakeAscending(array: &[mut T]) -> uint { + let size = array.len(); + assert size > 0; + if size == 1 { return 1; } + + let mut run = 2; + if array[1] < array[0] { + while run < size && array[run] < array[run-1] { + run += 1; + } + reverseSlice(array, 0, run); + } else { + while run < size && array[run] >= array[run-1] { + run += 1; + } + } + + return run; +} + +pure fn gallopLeft(key: &const T, array: &[const T], hint: uint) -> uint { + let size = array.len(); + assert size != 0 && hint < size; + + let mut lastOfs = 0; + let mut ofs = 1; + + if *key > array[hint] { + // Gallop right until array[hint+lastOfs] < key <= array[hint+ofs] + let maxOfs = size - hint; + while ofs < maxOfs && *key > array[hint+ofs] { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if ofs < lastOfs { ofs = maxOfs; } // uint overflow guard + } + if ofs > maxOfs { ofs = maxOfs; } + + lastOfs += hint; + ofs += hint; + } else { + let maxOfs = hint + 1; + while ofs < maxOfs && *key <= array[hint-ofs] { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if ofs < lastOfs { ofs = maxOfs; } // uint overflow guard + } + + if ofs > maxOfs { ofs = maxOfs; } + + let tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + assert (lastOfs < ofs || lastOfs+1 < ofs+1) && ofs <= size; + + lastOfs += 1; + while lastOfs < ofs { + let m = lastOfs + ((ofs - lastOfs) >> 1); + if *key > array[m] { + lastOfs = m+1; + } else { + ofs = m; + } + } + assert lastOfs == ofs; + return ofs; +} + +pure fn gallopRight(key: &const T, array: &[const T], hint: uint) -> uint { + let size = array.len(); + assert size != 0 && hint < size; + + let mut lastOfs = 0; + let mut ofs = 1; + + if *key >= array[hint] { + // Gallop right until array[hint+lastOfs] <= key < array[hint+ofs] + let maxOfs = size - hint; + while ofs < maxOfs && *key >= array[hint+ofs] { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if ofs < lastOfs { ofs = maxOfs; } + } + if ofs > maxOfs { ofs = maxOfs; } + + lastOfs += hint; + ofs += hint; + } else { + // Gallop left until array[hint-ofs] <= key < array[hint-lastOfs] + let maxOfs = hint + 1; + while ofs < maxOfs && *key < array[hint-ofs] { + lastOfs = ofs; + ofs = (ofs << 1) + 1; + if ofs < lastOfs { ofs = maxOfs; } + } + if ofs > maxOfs { ofs = maxOfs; } + + let tmp = lastOfs; + lastOfs = hint - ofs; + ofs = hint - tmp; + } + + assert (lastOfs < ofs || lastOfs+1 < ofs+1) && ofs <= size; + + lastOfs += 1; + while lastOfs < ofs { + let m = lastOfs + ((ofs - lastOfs) >> 1); + + if *key >= array[m] { + lastOfs = m + 1; + } else { + ofs = m; + } + } + assert lastOfs == ofs; + return ofs; +} + +struct RunState { + base: uint, + len: uint, +} + +struct MergeState { + mut minGallop: uint, + mut tmp: ~[T], + runs: DVec, + + drop { + unsafe { + vec::raw::set_len(self.tmp, 0); + } + } +} + +fn MergeState() -> MergeState { + let mut tmp = ~[]; + vec::reserve(tmp, INITIAL_TMP_STORAGE); + MergeState { + minGallop: MIN_GALLOP, + tmp: tmp, + runs: DVec(), + } +} + +impl &MergeState { + fn pushRun(runBase: uint, runLen: uint) { + let tmp = RunState{base: runBase, len: runLen}; + self.runs.push(tmp); + } + + fn mergeAt(n: uint, array: &[mut T]) { + let mut size = self.runs.len(); + assert size >= 2; + assert n == size-2 || n == size-3; + + do self.runs.borrow_mut |arr| { + + let mut b1 = arr[n].base; + let mut l1 = arr[n].len; + let b2 = arr[n+1].base; + let l2 = arr[n+1].len; + + assert l1 > 0 && l2 > 0; + assert b1 + l1 == b2; + + arr[n].len = l1 + l2; + if n == size-3 { + arr[n+1].base = arr[n+2].base; + arr[n+1].len = arr[n+2].len; + } + + let slice = vec::mut_view(array, b1, b1+l1); + let k = gallopRight(&const array[b2], slice, 0); + b1 += k; + l1 -= k; + if l1 != 0 { + let slice = vec::mut_view(array, b2, b2+l2); + let l2 = gallopLeft( + &const array[b1+l1-1],slice,l2-1); + if l2 > 0 { + if l1 <= l2 { + self.mergeLo(array, b1, l1, b2, l2); + } else { + self.mergeHi(array, b1, l1, b2, l2); + } + } + } + } + self.runs.pop(); + } + + fn mergeLo(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { + assert len1 != 0 && len2 != 0 && base1+len1 == base2; + + vec::reserve(self.tmp, len1); + + unsafe { + vec::raw::set_len(self.tmp, len1); + moveVec(self.tmp, 0, array, base1, len1); + } + + let mut c1 = 0; + let mut c2 = base2; + let mut dest = base1; + let mut len1 = len1; + let mut len2 = len2; + + array[dest] <-> array[c2]; + dest += 1; c2 += 1; len2 -= 1; + + if len2 == 0 { + unsafe { + moveVec(array, dest, self.tmp, 0, len1); + vec::raw::set_len(self.tmp, 0); // Forget the elements + } + return; + } + if len1 == 1 { + unsafe { + moveVec(array, dest, array, c2, len2); + array[dest+len2] <-> self.tmp[c1]; + vec::raw::set_len(self.tmp, 0); // Forget the element + } + return; + } + + let mut minGallop = self.minGallop; + loop { + let mut count1 = 0; + let mut count2 = 0; + let mut breakOuter = false; + + loop { + assert len1 > 1 && len2 != 0; + if array[c2] < self.tmp[c1] { + array[dest] <-> array[c2]; + dest += 1; c2 += 1; len2 -= 1; + count2 += 1; count1 = 0; + if len2 == 0 { + breakOuter = true; + } + } else { + array[dest] <-> self.tmp[c1]; + dest += 1; c1 += 1; len1 -= 1; + count1 += 1; count2 = 0; + if len1 == 1 { + breakOuter = true; + } + } + if breakOuter || ((count1 | count2) >= minGallop) { + break; + } + } + if breakOuter { break; } + + // Start to gallop + loop { + assert len1 > 1 && len2 != 0; + + let tmpView = vec::mut_view(self.tmp, c1, c1+len1); + count1 = gallopRight(&const array[c2], tmpView, 0); + if count1 != 0 { + unsafe { + moveVec(array, dest, self.tmp, c1, count1); + } + dest += count1; c1 += count1; len1 -= count1; + if len1 <= 1 { breakOuter = true; break; } + } + array[dest] <-> array[c2]; + dest += 1; c2 += 1; len2 -= 1; + if len2 == 0 { breakOuter = true; break; } + + let tmpView = vec::mut_view(array, c2, c2+len2); + count2 = gallopLeft(&const self.tmp[c1], tmpView, 0); + if count2 != 0 { + unsafe { + moveVec(array, dest, array, c2, count2); + } + dest += count2; c2 += count2; len2 -= count2; + if len2 == 0 { breakOuter = true; break; } + } + array[dest] <-> self.tmp[c1]; + dest += 1; c1 += 1; len1 -= 1; + if len1 == 1 { breakOuter = true; break; } + minGallop -= 1; + if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } + } + if breakOuter { break; } + if minGallop < 0 { minGallop = 0; } + minGallop += 2; // Penalize for leaving gallop + } + self.minGallop = if minGallop < 1 { 1 } else { minGallop }; + + if len1 == 1 { + assert len2 > 0; + unsafe { + moveVec(array, dest, array, c2, len2); + } + array[dest+len2] <-> self.tmp[c1]; + } else if len1 == 0 { + fail fmt!("Method mergeLo violates its contract! %?", len1); + } else { + assert len2 == 0; + assert len1 > 1; + unsafe { + moveVec(array, dest, self.tmp, c1, len1); + } + } + unsafe { vec::raw::set_len(self.tmp, 0); } + } + + fn mergeHi(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { + assert len1 != 1 && len2 != 0 && base1 + len1 == base2; + + vec::reserve(self.tmp, len2); + + unsafe { + vec::raw::set_len(self.tmp, len2); + moveVec(self.tmp, 0, array, base2, len2); + } + + let mut c1 = base1 + len1 - 1; + let mut c2 = len2 - 1; + let mut dest = base2 + len2 - 1; + let mut len1 = len1; + let mut len2 = len2; + + array[dest] <-> array[c1]; + dest -= 1; c1 -= 1; len1 -= 1; + + if len1 == 0 { + unsafe { + moveVec(array, dest-(len2-1), self.tmp, 0, len2); + vec::raw::set_len(self.tmp, 0); // Forget the elements + } + return; + } + if len2 == 1 { + dest -= len1; + c1 -= len1; + unsafe { + moveVec(array, dest+1, array, c1+1, len1); + array[dest] <-> self.tmp[c2]; + vec::raw::set_len(self.tmp, 0); // Forget the element + } + return; + } + + let mut minGallop = self.minGallop; + loop { + let mut count1 = 0; + let mut count2 = 0; + let mut breakOuter = false; + + loop { + assert len1 != 0 && len2 > 1; + if self.tmp[c2] < array[c1] { + array[dest] <-> array[c1]; + dest -= 1; c1 -= 1; len1 -= 1; + count1 += 1; count2 = 0; + if len1 == 0 { + breakOuter = true; + } + } else { + array[dest] <-> self.tmp[c2]; + dest -= 1; c2 -= 1; len2 -= 1; + count2 += 1; count1 = 0; + if len2 == 1 { + breakOuter = true; + } + } + if breakOuter || ((count1 | count2) >= minGallop) { + break; + } + } + if breakOuter { break; } + + // Start to gallop + loop { + assert len2 > 1 && len1 != 0; + + let tmpView = vec::mut_view(array, base1, base1+len1); + count1 = len1-gallopRight(&const self.tmp[c2], tmpView, len1-1); + + if count1 != 0 { + dest -= count1; c1 -= count1; len1 -= count1; + unsafe { + moveVec(array, dest+1, array, c1+1, count1); + } + if len1 == 0 { breakOuter = true; break; } + } + + array[dest] <-> self.tmp[c2]; + dest -= 1; c2 -= 1; len2 -= 1; + if len2 == 1 { breakOuter = true; break; } + + let tmpView = vec::mut_view(self.tmp, 0, len2); + let gL = gallopLeft(&const array[c1], tmpView, len2-1); + count2 = len2 - gL; + if count2 != 0 { + dest -= count2; c2 -= count2; len2 -= count2; + unsafe { + moveVec(array, dest+1, self.tmp, c2+1, count2); + } + if len2 <= 1 { breakOuter = true; break; } + } + array[dest] <-> array[c1]; + dest -= 1; c1 -= 1; len1 -= 1; + if len1 == 0 { breakOuter = true; break; } + minGallop -= 1; + if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } + } + + if breakOuter { break; } + if minGallop < 0 { minGallop = 0; } + minGallop += 2; // Penalize for leaving gallop + } + self.minGallop = if minGallop < 1 { 1 } else { minGallop }; + + if len2 == 1 { + assert len1 > 0; + dest -= len1; + c1 -= len1; + unsafe { + moveVec(array, dest+1, array, c1+1, len1); + } + array[dest] <-> self.tmp[c2]; + } else if len2 == 0 { + fail fmt!("Method mergeHi violates its contract! %?", len2); + } else { + assert len1 == 0; + assert len2 != 0; + unsafe { + moveVec(array, dest-(len2-1), self.tmp, 0, len2); + } + } + unsafe { vec::raw::set_len(self.tmp, 0); } + } + + fn mergeCollapse(array: &[mut T]) { + while self.runs.len() > 1 { + let mut n = self.runs.len()-2; + let chk = do self.runs.borrow |arr| { + if n > 0 && arr[n-1].len <= arr[n].len + arr[n+1].len { + if arr[n-1].len < arr[n+1].len { n -= 1; } + true + } else if arr[n].len <= arr[n+1].len { + true + } else { + false + } + }; + if !chk { break; } + self.mergeAt(n, array); + } + } + + fn mergeForceCollapse(array: &[mut T]) { + while self.runs.len() > 1 { + let mut n = self.runs.len()-2; + if n > 0 { + do self.runs.borrow |arr| { + if arr[n-1].len < arr[n+1].len { + n -= 1; + } + } + } + self.mergeAt(n, array); + } + } +} + +// Moves elements to from dest to from +// Unsafe as it makes the from parameter invalid between s2 and s2+len +#[inline(always)] +unsafe fn moveVec(dest: &[mut T], s1: uint, from: &[const T], s2: uint, len: uint) { + assert s1+len <= dest.len() && s2+len <= from.len(); + + do vec::as_mut_buf(dest) |p, _len| { + let destPtr = ptr::mut_offset(p, s1); + + do vec::as_const_buf(from) |p, _len| { + let fromPtr = ptr::const_offset(p, s2); + + ptr::memmove(destPtr, fromPtr, len); + } + } +} + #[cfg(test)] mod test_qsort3 { #[legacy_exports]; From f98f00f7f6afac993fd2a08e7135bfdb8e70dec6 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 18:15:57 -0500 Subject: [PATCH 02/28] Fix timsort to use updated vec::reserve --- src/libstd/sort.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 8cd98f8ab0ba9..4f8102515ce86 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -219,8 +219,8 @@ fn binarysort(array: &[mut T], start: uint) { if start == 0 { start += 1; } - let mut pivot = ~[mut]; - vec::reserve(pivot, 1); + let mut pivot = ~[]; + vec::reserve(&mut pivot, 1); unsafe { vec::raw::set_len(pivot, 1); }; while start < size { @@ -409,7 +409,7 @@ struct MergeState { fn MergeState() -> MergeState { let mut tmp = ~[]; - vec::reserve(tmp, INITIAL_TMP_STORAGE); + vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { minGallop: MIN_GALLOP, tmp: tmp, @@ -467,7 +467,7 @@ impl &MergeState { fn mergeLo(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; - vec::reserve(self.tmp, len1); + vec::reserve(&mut self.tmp, len1); unsafe { vec::raw::set_len(self.tmp, len1); @@ -587,7 +587,7 @@ impl &MergeState { fn mergeHi(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; - vec::reserve(self.tmp, len2); + vec::reserve(&mut self.tmp, len2); unsafe { vec::raw::set_len(self.tmp, len2); From 868d10160f81c9d836202ed1c0683b75730fe73d Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 19:05:13 -0500 Subject: [PATCH 03/28] Put function argument last in sort function. Fixes #3265. --- src/cargo/cargo.rs | 2 +- src/libstd/json.rs | 2 +- src/libstd/sort.rs | 56 +++++++++++++++++++++-------------- src/libstd/test.rs | 4 +-- src/libsyntax/attr.rs | 2 +- src/libsyntax/ext/qquote.rs | 2 +- src/rustc/metadata/cstore.rs | 2 +- src/rustc/metadata/encoder.rs | 2 +- src/rustdoc/sort_pass.rs | 2 +- 9 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/cargo/cargo.rs b/src/cargo/cargo.rs index 4dcfc608e0ea3..a9fa6ca899c6b 100644 --- a/src/cargo/cargo.rs +++ b/src/cargo/cargo.rs @@ -1498,7 +1498,7 @@ fn print_pkg(s: source, p: package) { fn print_source(s: source) { info(s.name + ~" (" + s.url + ~")"); - let pks = sort::merge_sort(sys::shape_lt, s.packages.get()); + let pks = sort::merge_sort(s.packages.get(), sys::shape_lt); let l = vec::len(pks); print(io::with_str_writer(|writer| { diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 0f7bec6344a63..0094b5a92773b 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -145,7 +145,7 @@ fn to_writer_pretty(wr: io::Writer, j: Json, indent: uint) { } // sort by key strings - let sorted_pairs = sort::merge_sort(|a,b| *a <= *b, pairs); + let sorted_pairs = do sort::merge_sort(pairs) |a,b| { *a <= *b }; // { wr.write_str(~"{\n"); diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 4f8102515ce86..e0e35f68da268 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -20,12 +20,12 @@ type Le = pure fn(v1: &T, v2: &T) -> bool; * Has worst case O(n log n) performance, best case O(n), but * is not space efficient. This is a stable sort. */ -fn merge_sort(le: Le, v: &[const T]) -> ~[T] { +fn merge_sort(v: &[const T], le: Le) -> ~[T] { type Slice = (uint, uint); - return merge_sort_(le, v, (0u, len(v))); + return merge_sort_(v, (0u, len(v)), le); - fn merge_sort_(le: Le, v: &[const T], slice: Slice) + fn merge_sort_(v: &[const T], slice: Slice, le: Le) -> ~[T] { let begin = slice.first(); let end = slice.second(); @@ -37,7 +37,7 @@ fn merge_sort(le: Le, v: &[const T]) -> ~[T] { let mid = v_len / 2u + begin; let a = (begin, mid); let b = (mid, end); - return merge(le, merge_sort_(le, v, a), merge_sort_(le, v, b)); + return merge(le, merge_sort_(v, a, le), merge_sort_(v, b, le)); } fn merge(le: Le, a: &[T], b: &[T]) -> ~[T] { @@ -58,8 +58,8 @@ fn merge_sort(le: Le, v: &[const T]) -> ~[T] { } } -fn part(compare_func: Le, arr: &[mut T], left: uint, - right: uint, pivot: uint) -> uint { +fn part(arr: &[mut T], left: uint, + right: uint, pivot: uint, compare_func: Le) -> uint { let pivot_value = arr[pivot]; arr[pivot] <-> arr[right]; let mut storage_index: uint = left; @@ -75,16 +75,16 @@ fn part(compare_func: Le, arr: &[mut T], left: uint, return storage_index; } -fn qsort(compare_func: Le, arr: &[mut T], left: uint, - right: uint) { +fn qsort(arr: &[mut T], left: uint, + right: uint, compare_func: Le) { if right > left { let pivot = (left + right) / 2u; - let new_pivot = part::(compare_func, arr, left, right, pivot); + let new_pivot = part::(arr, left, right, pivot, compare_func); if new_pivot != 0u { // Need to do this check before recursing due to overflow - qsort::(compare_func, arr, left, new_pivot - 1u); + qsort::(arr, left, new_pivot - 1u, compare_func); } - qsort::(compare_func, arr, new_pivot + 1u, right); + qsort::(arr, new_pivot + 1u, right, compare_func); } } @@ -94,9 +94,9 @@ fn qsort(compare_func: Le, arr: &[mut T], left: uint, * Has worst case O(n^2) performance, average case O(n log n). * This is an unstable sort. */ -fn quick_sort(compare_func: Le, arr: &[mut T]) { +fn quick_sort(arr: &[mut T], compare_func: Le) { if len::(arr) == 0u { return; } - qsort::(compare_func, arr, 0u, len::(arr) - 1u); + qsort::(arr, 0u, len::(arr) - 1u, compare_func); } fn qsort3(arr: &[mut T], left: int, right: int) { @@ -292,7 +292,8 @@ fn countRunAndMakeAscending(array: &[mut T]) -> uint { return run; } -pure fn gallopLeft(key: &const T, array: &[const T], hint: uint) -> uint { +pure fn gallopLeft(key: &const T, array: &[const T], + hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; @@ -340,7 +341,8 @@ pure fn gallopLeft(key: &const T, array: &[const T], hint: uint) -> uint return ofs; } -pure fn gallopRight(key: &const T, array: &[const T], hint: uint) -> uint { +pure fn gallopRight(key: &const T, array: &[const T], + hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; @@ -464,7 +466,8 @@ impl &MergeState { self.runs.pop(); } - fn mergeLo(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { + fn mergeLo(array: &[mut T], base1: uint, len1: uint, + base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; vec::reserve(&mut self.tmp, len1); @@ -558,7 +561,9 @@ impl &MergeState { dest += 1; c1 += 1; len1 -= 1; if len1 == 1 { breakOuter = true; break; } minGallop -= 1; - if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } + if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { + break; + } } if breakOuter { break; } if minGallop < 0 { minGallop = 0; } @@ -584,7 +589,8 @@ impl &MergeState { unsafe { vec::raw::set_len(self.tmp, 0); } } - fn mergeHi(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { + fn mergeHi(array: &[mut T], base1: uint, len1: uint, + base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; vec::reserve(&mut self.tmp, len2); @@ -655,7 +661,8 @@ impl &MergeState { assert len2 > 1 && len1 != 0; let tmpView = vec::mut_view(array, base1, base1+len1); - count1 = len1-gallopRight(&const self.tmp[c2], tmpView, len1-1); + count1 = len1 - gallopRight( + &const self.tmp[c2], tmpView, len1-1); if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; @@ -670,8 +677,8 @@ impl &MergeState { if len2 == 1 { breakOuter = true; break; } let tmpView = vec::mut_view(self.tmp, 0, len2); - let gL = gallopLeft(&const array[c1], tmpView, len2-1); - count2 = len2 - gL; + let count2 = len2 - gallopLeft( + &const array[c1], tmpView, len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; unsafe { @@ -683,7 +690,9 @@ impl &MergeState { dest -= 1; c1 -= 1; len1 -= 1; if len1 == 0 { breakOuter = true; break; } minGallop -= 1; - if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } + if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { + break; + } } if breakOuter { break; } @@ -748,7 +757,8 @@ impl &MergeState { // Moves elements to from dest to from // Unsafe as it makes the from parameter invalid between s2 and s2+len #[inline(always)] -unsafe fn moveVec(dest: &[mut T], s1: uint, from: &[const T], s2: uint, len: uint) { +unsafe fn moveVec(dest: &[mut T], s1: uint, + from: &[const T], s2: uint, len: uint) { assert s1+len <= dest.len() && s2+len <= from.len(); do vec::as_mut_buf(dest) |p, _len| { diff --git a/src/libstd/test.rs b/src/libstd/test.rs index 51c0ad385ce16..faa22ae096718 100644 --- a/src/libstd/test.rs +++ b/src/libstd/test.rs @@ -229,7 +229,7 @@ fn print_failures(st: ConsoleTestState) { st.out.write_line(~"\nfailures:"); let failures = copy st.failures; let failures = vec::map(failures, |test| test.name); - let failures = sort::merge_sort(|x, y| str::le(*x, *y), failures); + let failures = do sort::merge_sort(failures) |x, y| { str::le(*x, *y) }; for vec::each(failures) |name| { st.out.write_line(fmt!(" %s", *name)); } @@ -382,7 +382,7 @@ fn filter_tests(opts: &TestOpts, pure fn lteq(t1: &TestDesc, t2: &TestDesc) -> bool { str::le(t1.name, t2.name) } - sort::merge_sort(lteq, filtered) + sort::merge_sort(filtered, lteq) }; move filtered diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index eb4ffb26fb157..a291501ef5fd6 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -281,7 +281,7 @@ fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] { // This is sort of stupid here, converting to a vec of mutables and back let v: ~[mut @ast::meta_item] = vec::to_mut(items); - std::sort::quick_sort(lteq, v); + std::sort::quick_sort(v, lteq); vec::from_mut(move v) } diff --git a/src/libsyntax/ext/qquote.rs b/src/libsyntax/ext/qquote.rs index ee9602598d1ed..342743d8c4601 100644 --- a/src/libsyntax/ext/qquote.rs +++ b/src/libsyntax/ext/qquote.rs @@ -127,7 +127,7 @@ fn gather_anti_quotes(lo: uint, node: N) -> aq_ctxt pure fn by_lo(a: &gather_item, b: &gather_item) -> bool { a.lo < b.lo } - std::sort::merge_sort(by_lo, v) + std::sort::merge_sort(v, by_lo) }; return cx; } diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs index cb304c419e563..c5686153c000e 100644 --- a/src/rustc/metadata/cstore.rs +++ b/src/rustc/metadata/cstore.rs @@ -166,7 +166,7 @@ fn get_dep_hashes(cstore: cstore) -> ~[~str] { vec::push(result, {name: cdata.name, hash: hash}); }; pure fn lteq(a: &crate_hash, b: &crate_hash) -> bool {a.name <= b.name} - let sorted = std::sort::merge_sort(lteq, result); + let sorted = std::sort::merge_sort(result, lteq); debug!("sorted:"); for sorted.each |x| { debug!(" hash[%s]: %s", x.name, x.hash); diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs index 3424ea8dd576d..8da5fa0aee204 100644 --- a/src/rustc/metadata/encoder.rs +++ b/src/rustc/metadata/encoder.rs @@ -1038,7 +1038,7 @@ fn encode_crate_deps(ecx: @encode_ctxt, ebml_w: ebml::Writer, pure fn lteq(kv1: &numdep, kv2: &numdep) -> bool { kv1.cnum <= kv2.cnum } - std::sort::quick_sort(lteq, deps); + std::sort::quick_sort(deps, lteq); // Sanity-check the crate numbers let mut expected_cnum = 1; diff --git a/src/rustdoc/sort_pass.rs b/src/rustdoc/sort_pass.rs index 497c076d3ab6c..da3cf2395384e 100644 --- a/src/rustdoc/sort_pass.rs +++ b/src/rustdoc/sort_pass.rs @@ -36,7 +36,7 @@ fn fold_mod( ) -> doc::ModDoc { let doc = fold::default_any_fold_mod(fold, doc); doc::ModDoc_({ - items: sort::merge_sort(fold.ctxt, doc.items), + items: sort::merge_sort(doc.items, fold.ctxt), .. *doc }) } From f34c4f4b040c1a7b086f1551141ee65f4af0dd48 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 20:44:14 -0500 Subject: [PATCH 04/28] Remove trailing whitespace --- src/libstd/sort.rs | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index e0e35f68da268..47b66fc17b281 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -206,9 +206,9 @@ fn timsort(array: &[mut T]) { idx += runLen; remaining -= runLen; - if remaining == 0 { break; } + if remaining == 0 { break; } } - + ms.mergeForceCollapse(array); } @@ -288,18 +288,18 @@ fn countRunAndMakeAscending(array: &[mut T]) -> uint { run += 1; } } - + return run; } pure fn gallopLeft(key: &const T, array: &[const T], - hint: uint) -> uint { + hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; let mut lastOfs = 0; let mut ofs = 1; - + if *key > array[hint] { // Gallop right until array[hint+lastOfs] < key <= array[hint+ofs] let maxOfs = size - hint; @@ -319,7 +319,7 @@ pure fn gallopLeft(key: &const T, array: &[const T], ofs = (ofs << 1) + 1; if ofs < lastOfs { ofs = maxOfs; } // uint overflow guard } - + if ofs > maxOfs { ofs = maxOfs; } let tmp = lastOfs; @@ -348,7 +348,7 @@ pure fn gallopRight(key: &const T, array: &[const T], let mut lastOfs = 0; let mut ofs = 1; - + if *key >= array[hint] { // Gallop right until array[hint+lastOfs] <= key < array[hint+ofs] let maxOfs = size - hint; @@ -360,7 +360,7 @@ pure fn gallopRight(key: &const T, array: &[const T], if ofs > maxOfs { ofs = maxOfs; } lastOfs += hint; - ofs += hint; + ofs += hint; } else { // Gallop left until array[hint-ofs] <= key < array[hint-lastOfs] let maxOfs = hint + 1; @@ -411,7 +411,7 @@ struct MergeState { fn MergeState() -> MergeState { let mut tmp = ~[]; - vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); + vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { minGallop: MIN_GALLOP, tmp: tmp, @@ -469,7 +469,7 @@ impl &MergeState { fn mergeLo(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; - + vec::reserve(&mut self.tmp, len1); unsafe { @@ -563,7 +563,7 @@ impl &MergeState { minGallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; - } + } } if breakOuter { break; } if minGallop < 0 { minGallop = 0; } @@ -655,7 +655,7 @@ impl &MergeState { } } if breakOuter { break; } - + // Start to gallop loop { assert len2 > 1 && len1 != 0; @@ -692,15 +692,15 @@ impl &MergeState { minGallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; - } + } } - + if breakOuter { break; } if minGallop < 0 { minGallop = 0; } minGallop += 2; // Penalize for leaving gallop } self.minGallop = if minGallop < 1 { 1 } else { minGallop }; - + if len2 == 1 { assert len1 > 0; dest -= len1; @@ -757,8 +757,8 @@ impl &MergeState { // Moves elements to from dest to from // Unsafe as it makes the from parameter invalid between s2 and s2+len #[inline(always)] -unsafe fn moveVec(dest: &[mut T], s1: uint, - from: &[const T], s2: uint, len: uint) { +unsafe fn moveVec(dest: &[mut T], s1: uint, + from: &[const T], s2: uint, len: uint) { assert s1+len <= dest.len() && s2+len <= from.len(); do vec::as_mut_buf(dest) |p, _len| { @@ -818,7 +818,7 @@ mod test_qsort { fn check_sort(v1: &[mut int], v2: &[mut int]) { let len = vec::len::(v1); pure fn leual(a: &int, b: &int) -> bool { *a <= *b } - quick_sort::(leual, v1); + quick_sort::(v1, leual); let mut i = 0u; while i < len { log(debug, v2[i]); @@ -859,7 +859,7 @@ mod test_qsort { let expected = ~[1, 2, 3]; - sort::quick_sort(|x, y| { int::le(*x, *y) }, names); + do sort::quick_sort(names) |x, y| { int::le(*x, *y) }; let immut_names = vec::from_mut(names); @@ -880,7 +880,7 @@ mod tests { let len = vec::len::(v1); pure fn le(a: &int, b: &int) -> bool { *a <= *b } let f = le; - let v3 = merge_sort::(f, v1); + let v3 = merge_sort::(v1, f); let mut i = 0u; while i < len { log(debug, v3[i]); @@ -910,7 +910,7 @@ mod tests { fn test_merge_sort_mutable() { pure fn le(a: &int, b: &int) -> bool { *a <= *b } let v1 = ~[mut 3, 2, 1]; - let v2 = merge_sort(le, v1); + let v2 = merge_sort(v1, le); assert v2 == ~[1, 2, 3]; } @@ -932,7 +932,7 @@ mod tests { "Sally Mae", "JOE BOB", "Alex Andy"]; let names2 = ~["Alex Andy", "Jack Brown", "joe bob", "Joe Bob", "JOE Bob", "JOE BOB", "Sally Mae"]; - let names3 = merge_sort(ile, names1); + let names3 = merge_sort(names1, ile); assert names3 == names2; } } From 4f9f1c5f9a1c3570d73171b2a2e9e83e471688da Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 20:44:31 -0500 Subject: [PATCH 05/28] Switch order of merge_sort arguments in some benchmarks --- src/test/bench/shootout-k-nucleotide-pipes.rs | 2 +- src/test/bench/shootout-k-nucleotide.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/bench/shootout-k-nucleotide-pipes.rs b/src/test/bench/shootout-k-nucleotide-pipes.rs index dbdcf15db8a75..21bed9f8790b4 100644 --- a/src/test/bench/shootout-k-nucleotide-pipes.rs +++ b/src/test/bench/shootout-k-nucleotide-pipes.rs @@ -34,7 +34,7 @@ fn sort_and_fmt(mm: HashMap<~[u8], uint>, total: uint) -> ~str { // sort by key, then by value fn sortKV(orig: ~[(TT,UU)]) -> ~[(TT,UU)] { - return sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig)); + return sort::merge_sort(sort::merge_sort(orig, le_by_key), le_by_val); } let mut pairs = ~[]; diff --git a/src/test/bench/shootout-k-nucleotide.rs b/src/test/bench/shootout-k-nucleotide.rs index d9d5827c56d41..d107db7e6b082 100644 --- a/src/test/bench/shootout-k-nucleotide.rs +++ b/src/test/bench/shootout-k-nucleotide.rs @@ -31,7 +31,7 @@ fn sort_and_fmt(mm: HashMap<~[u8], uint>, total: uint) -> ~str { // sort by key, then by value fn sortKV(orig: ~[(TT,UU)]) -> ~[(TT,UU)] { - return sort::merge_sort(le_by_val, sort::merge_sort(le_by_key, orig)); + return sort::merge_sort(sort::merge_sort(orig, le_by_key), le_by_val); } let mut pairs = ~[]; From f7be2d92a4e01d4dbe57934b2cc8e3935e336c8a Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 20:56:13 -0500 Subject: [PATCH 06/28] Export timsort --- src/libstd/sort.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 47b66fc17b281..449e249dfa7ec 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -10,6 +10,7 @@ export le; export merge_sort; export quick_sort; export quick_sort3; +export timsort; export Sort; type Le = pure fn(v1: &T, v2: &T) -> bool; From 4d30d7ff04b2ec0d9013582ac9d79fdbd64cf7d6 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 27 Sep 2012 21:01:43 -0500 Subject: [PATCH 07/28] Add a simple testsuite for timsort --- src/libstd/sort.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 449e249dfa7ec..4bc42e44d92aa 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -938,6 +938,46 @@ mod tests { } } +#[cfg(test)] +mod test_timsort { + #[legacy_exports]; + fn check_sort(v1: &[mut int], v2: &[mut int]) { + let len = vec::len::(v1); + timsort::(v1); + let mut i = 0u; + while i < len { + log(debug, v2[i]); + assert (v2[i] == v1[i]); + i += 1u; + } + } + + #[test] + fn test() { + { + let v1 = ~[mut 3, 7, 4, 5, 2, 9, 5, 8]; + let v2 = ~[mut 2, 3, 4, 5, 5, 7, 8, 9]; + check_sort(v1, v2); + } + { + let v1 = ~[mut 1, 1, 1]; + let v2 = ~[mut 1, 1, 1]; + check_sort(v1, v2); + } + { + let v1: ~[mut int] = ~[mut]; + let v2: ~[mut int] = ~[mut]; + check_sort(v1, v2); + } + { let v1 = ~[mut 9]; let v2 = ~[mut 9]; check_sort(v1, v2); } + { + let v1 = ~[mut 9, 3, 3, 3, 9]; + let v2 = ~[mut 3, 3, 3, 9, 9]; + check_sort(v1, v2); + } + } +} + // Local Variables: // mode: rust; // fill-column: 78; From 579c7e3ef18089825edc52316745c71b2664217a Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 1 Oct 2012 11:34:04 -0500 Subject: [PATCH 08/28] Make local variables and methods use underscores not camel case --- src/libstd/sort.rs | 276 ++++++++++++++++++++++----------------------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 4bc42e44d92aa..1f446b51fe8ed 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -174,43 +174,43 @@ const MIN_MERGE: uint = 64; const MIN_GALLOP: uint = 7; const INITIAL_TMP_STORAGE: uint = 128; -fn timsort(array: &[mut T]) { +fn tim_sort(array: &[mut T]) { let size = array.len(); if size < 2 { return; } if size < MIN_MERGE { - let initRunLen = countRunAndMakeAscending(array); - binarysort(array, initRunLen); + let init_run_len = count_run_ascending(array); + binarysort(array, init_run_len); return; } let ms = &MergeState(); - let minRun = minRunLength(size); + let min_run = min_run_length(size); let mut idx = 0; let mut remaining = size; loop { let arr = vec::mut_view(array, idx, size); - let mut runLen: uint = countRunAndMakeAscending(arr); + let mut run_len: uint = count_run_ascending(arr); - if runLen < minRun { - let force = if remaining <= minRun {remaining} else {minRun}; + if run_len < min_run { + let force = if remaining <= min_run {remaining} else {min_run}; let slice = vec::mut_view(arr, 0, force); - binarysort(slice, runLen); - runLen = force; + binarysort(slice, run_len); + run_len = force; } - ms.pushRun(idx, runLen); - ms.mergeCollapse(array); + ms.push_run(idx, run_len); + ms.merge_collapse(array); - idx += runLen; - remaining -= runLen; + idx += run_len; + remaining -= run_len; if remaining == 0 { break; } } - ms.mergeForceCollapse(array); + ms.merge_force_collapse(array); } fn binarysort(array: &[mut T], start: uint) { @@ -226,8 +226,8 @@ fn binarysort(array: &[mut T], start: uint) { while start < size { unsafe { - let tmpView = vec::mut_view(array, start, start+1); - vec::raw::memmove(pivot, tmpView, 1); + let tmp_view = vec::mut_view(array, start, start+1); + vec::raw::memmove(pivot, tmp_view, 1); } let mut left = 0; let mut right = start; @@ -245,7 +245,7 @@ fn binarysort(array: &[mut T], start: uint) { let mut n = start-left; unsafe { - moveVec(array, left+1, array, left, n); + move_vec(array, left+1, array, left, n); } array[left] <-> pivot[0]; start += 1; @@ -254,7 +254,7 @@ fn binarysort(array: &[mut T], start: uint) { } /// Reverse the order of elements in a slice, in place -fn reverseSlice(v: &[mut T], start: uint, end:uint) { +fn reverse_slice(v: &[mut T], start: uint, end:uint) { let mut i = start; while i < end / 2 { v[i] <-> v[end - i - 1]; @@ -262,7 +262,7 @@ fn reverseSlice(v: &[mut T], start: uint, end:uint) { } } -pure fn minRunLength(n: uint) -> uint { +pure fn min_run_length(n: uint) -> uint { let mut n = n; let mut r = 0; // becomes 1 if any 1 bits are shifted off @@ -273,7 +273,7 @@ pure fn minRunLength(n: uint) -> uint { return n + r; } -fn countRunAndMakeAscending(array: &[mut T]) -> uint { +fn count_run_ascending(array: &[mut T]) -> uint { let size = array.len(); assert size > 0; if size == 1 { return 1; } @@ -283,7 +283,7 @@ fn countRunAndMakeAscending(array: &[mut T]) -> uint { while run < size && array[run] < array[run-1] { run += 1; } - reverseSlice(array, 0, run); + reverse_slice(array, 0, run); } else { while run < size && array[run] >= array[run-1] { run += 1; @@ -293,103 +293,103 @@ fn countRunAndMakeAscending(array: &[mut T]) -> uint { return run; } -pure fn gallopLeft(key: &const T, array: &[const T], +pure fn gallop_left(key: &const T, array: &[const T], hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; - let mut lastOfs = 0; + let mut last_ofs = 0; let mut ofs = 1; if *key > array[hint] { - // Gallop right until array[hint+lastOfs] < key <= array[hint+ofs] - let maxOfs = size - hint; - while ofs < maxOfs && *key > array[hint+ofs] { - lastOfs = ofs; + // Gallop right until array[hint+last_ofs] < key <= array[hint+ofs] + let max_ofs = size - hint; + while ofs < max_ofs && *key > array[hint+ofs] { + last_ofs = ofs; ofs = (ofs << 1) + 1; - if ofs < lastOfs { ofs = maxOfs; } // uint overflow guard + if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard } - if ofs > maxOfs { ofs = maxOfs; } + if ofs > max_ofs { ofs = max_ofs; } - lastOfs += hint; + last_ofs += hint; ofs += hint; } else { - let maxOfs = hint + 1; - while ofs < maxOfs && *key <= array[hint-ofs] { - lastOfs = ofs; + let max_ofs = hint + 1; + while ofs < max_ofs && *key <= array[hint-ofs] { + last_ofs = ofs; ofs = (ofs << 1) + 1; - if ofs < lastOfs { ofs = maxOfs; } // uint overflow guard + if ofs < last_ofs { ofs = max_ofs; } // uint overflow guard } - if ofs > maxOfs { ofs = maxOfs; } + if ofs > max_ofs { ofs = max_ofs; } - let tmp = lastOfs; - lastOfs = hint - ofs; + let tmp = last_ofs; + last_ofs = hint - ofs; ofs = hint - tmp; } - assert (lastOfs < ofs || lastOfs+1 < ofs+1) && ofs <= size; + assert (last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size; - lastOfs += 1; - while lastOfs < ofs { - let m = lastOfs + ((ofs - lastOfs) >> 1); + last_ofs += 1; + while last_ofs < ofs { + let m = last_ofs + ((ofs - last_ofs) >> 1); if *key > array[m] { - lastOfs = m+1; + last_ofs = m+1; } else { ofs = m; } } - assert lastOfs == ofs; + assert last_ofs == ofs; return ofs; } -pure fn gallopRight(key: &const T, array: &[const T], +pure fn gallop_right(key: &const T, array: &[const T], hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; - let mut lastOfs = 0; + let mut last_ofs = 0; let mut ofs = 1; if *key >= array[hint] { - // Gallop right until array[hint+lastOfs] <= key < array[hint+ofs] - let maxOfs = size - hint; - while ofs < maxOfs && *key >= array[hint+ofs] { - lastOfs = ofs; + // Gallop right until array[hint+last_ofs] <= key < array[hint+ofs] + let max_ofs = size - hint; + while ofs < max_ofs && *key >= array[hint+ofs] { + last_ofs = ofs; ofs = (ofs << 1) + 1; - if ofs < lastOfs { ofs = maxOfs; } + if ofs < last_ofs { ofs = max_ofs; } } - if ofs > maxOfs { ofs = maxOfs; } + if ofs > max_ofs { ofs = max_ofs; } - lastOfs += hint; + last_ofs += hint; ofs += hint; } else { - // Gallop left until array[hint-ofs] <= key < array[hint-lastOfs] - let maxOfs = hint + 1; - while ofs < maxOfs && *key < array[hint-ofs] { - lastOfs = ofs; + // Gallop left until array[hint-ofs] <= key < array[hint-last_ofs] + let max_ofs = hint + 1; + while ofs < max_ofs && *key < array[hint-ofs] { + last_ofs = ofs; ofs = (ofs << 1) + 1; - if ofs < lastOfs { ofs = maxOfs; } + if ofs < last_ofs { ofs = max_ofs; } } - if ofs > maxOfs { ofs = maxOfs; } + if ofs > max_ofs { ofs = max_ofs; } - let tmp = lastOfs; - lastOfs = hint - ofs; + let tmp = last_ofs; + last_ofs = hint - ofs; ofs = hint - tmp; } - assert (lastOfs < ofs || lastOfs+1 < ofs+1) && ofs <= size; + assert (last_ofs < ofs || last_ofs+1 < ofs+1) && ofs <= size; - lastOfs += 1; - while lastOfs < ofs { - let m = lastOfs + ((ofs - lastOfs) >> 1); + last_ofs += 1; + while last_ofs < ofs { + let m = last_ofs + ((ofs - last_ofs) >> 1); if *key >= array[m] { - lastOfs = m + 1; + last_ofs = m + 1; } else { ofs = m; } } - assert lastOfs == ofs; + assert last_ofs == ofs; return ofs; } @@ -399,7 +399,7 @@ struct RunState { } struct MergeState { - mut minGallop: uint, + mut min_gallop: uint, mut tmp: ~[T], runs: DVec, @@ -414,19 +414,19 @@ fn MergeState() -> MergeState { let mut tmp = ~[]; vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { - minGallop: MIN_GALLOP, + min_gallop: MIN_GALLOP, tmp: tmp, runs: DVec(), } } impl &MergeState { - fn pushRun(runBase: uint, runLen: uint) { - let tmp = RunState{base: runBase, len: runLen}; + fn push_run(run_base: uint, run_len: uint) { + let tmp = RunState{base: run_base, len: run_len}; self.runs.push(tmp); } - fn mergeAt(n: uint, array: &[mut T]) { + fn merge_at(n: uint, array: &[mut T]) { let mut size = self.runs.len(); assert size >= 2; assert n == size-2 || n == size-3; @@ -448,18 +448,18 @@ impl &MergeState { } let slice = vec::mut_view(array, b1, b1+l1); - let k = gallopRight(&const array[b2], slice, 0); + let k = gallop_right(&const array[b2], slice, 0); b1 += k; l1 -= k; if l1 != 0 { let slice = vec::mut_view(array, b2, b2+l2); - let l2 = gallopLeft( + let l2 = gallop_left( &const array[b1+l1-1],slice,l2-1); if l2 > 0 { if l1 <= l2 { - self.mergeLo(array, b1, l1, b2, l2); + self.merge_lo(array, b1, l1, b2, l2); } else { - self.mergeHi(array, b1, l1, b2, l2); + self.merge_hi(array, b1, l1, b2, l2); } } } @@ -467,7 +467,7 @@ impl &MergeState { self.runs.pop(); } - fn mergeLo(array: &[mut T], base1: uint, len1: uint, + fn merge_lo(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; @@ -475,7 +475,7 @@ impl &MergeState { unsafe { vec::raw::set_len(self.tmp, len1); - moveVec(self.tmp, 0, array, base1, len1); + move_vec(self.tmp, 0, array, base1, len1); } let mut c1 = 0; @@ -489,25 +489,25 @@ impl &MergeState { if len2 == 0 { unsafe { - moveVec(array, dest, self.tmp, 0, len1); + move_vec(array, dest, self.tmp, 0, len1); vec::raw::set_len(self.tmp, 0); // Forget the elements } return; } if len1 == 1 { unsafe { - moveVec(array, dest, array, c2, len2); + move_vec(array, dest, array, c2, len2); array[dest+len2] <-> self.tmp[c1]; vec::raw::set_len(self.tmp, 0); // Forget the element } return; } - let mut minGallop = self.minGallop; + let mut min_gallop = self.min_gallop; loop { let mut count1 = 0; let mut count2 = 0; - let mut breakOuter = false; + let mut break_outer = false; loop { assert len1 > 1 && len2 != 0; @@ -516,81 +516,81 @@ impl &MergeState { dest += 1; c2 += 1; len2 -= 1; count2 += 1; count1 = 0; if len2 == 0 { - breakOuter = true; + break_outer = true; } } else { array[dest] <-> self.tmp[c1]; dest += 1; c1 += 1; len1 -= 1; count1 += 1; count2 = 0; if len1 == 1 { - breakOuter = true; + break_outer = true; } } - if breakOuter || ((count1 | count2) >= minGallop) { + if break_outer || ((count1 | count2) >= min_gallop) { break; } } - if breakOuter { break; } + if break_outer { break; } // Start to gallop loop { assert len1 > 1 && len2 != 0; - let tmpView = vec::mut_view(self.tmp, c1, c1+len1); - count1 = gallopRight(&const array[c2], tmpView, 0); + let tmp_view = vec::mut_view(self.tmp, c1, c1+len1); + count1 = gallop_right(&const array[c2], tmp_view, 0); if count1 != 0 { unsafe { - moveVec(array, dest, self.tmp, c1, count1); + move_vec(array, dest, self.tmp, c1, count1); } dest += count1; c1 += count1; len1 -= count1; - if len1 <= 1 { breakOuter = true; break; } + if len1 <= 1 { break_outer = true; break; } } array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - if len2 == 0 { breakOuter = true; break; } + if len2 == 0 { break_outer = true; break; } - let tmpView = vec::mut_view(array, c2, c2+len2); - count2 = gallopLeft(&const self.tmp[c1], tmpView, 0); + let tmp_view = vec::mut_view(array, c2, c2+len2); + count2 = gallop_left(&const self.tmp[c1], tmp_view, 0); if count2 != 0 { unsafe { - moveVec(array, dest, array, c2, count2); + move_vec(array, dest, array, c2, count2); } dest += count2; c2 += count2; len2 -= count2; - if len2 == 0 { breakOuter = true; break; } + if len2 == 0 { break_outer = true; break; } } array[dest] <-> self.tmp[c1]; dest += 1; c1 += 1; len1 -= 1; - if len1 == 1 { breakOuter = true; break; } - minGallop -= 1; + if len1 == 1 { break_outer = true; break; } + min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } } - if breakOuter { break; } - if minGallop < 0 { minGallop = 0; } - minGallop += 2; // Penalize for leaving gallop + if break_outer { break; } + if min_gallop < 0 { min_gallop = 0; } + min_gallop += 2; // Penalize for leaving gallop } - self.minGallop = if minGallop < 1 { 1 } else { minGallop }; + self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop }; if len1 == 1 { assert len2 > 0; unsafe { - moveVec(array, dest, array, c2, len2); + move_vec(array, dest, array, c2, len2); } array[dest+len2] <-> self.tmp[c1]; } else if len1 == 0 { - fail fmt!("Method mergeLo violates its contract! %?", len1); + fail fmt!("Method merge_lo violates its contract! %?", len1); } else { assert len2 == 0; assert len1 > 1; unsafe { - moveVec(array, dest, self.tmp, c1, len1); + move_vec(array, dest, self.tmp, c1, len1); } } unsafe { vec::raw::set_len(self.tmp, 0); } } - fn mergeHi(array: &[mut T], base1: uint, len1: uint, + fn merge_hi(array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; @@ -598,7 +598,7 @@ impl &MergeState { unsafe { vec::raw::set_len(self.tmp, len2); - moveVec(self.tmp, 0, array, base2, len2); + move_vec(self.tmp, 0, array, base2, len2); } let mut c1 = base1 + len1 - 1; @@ -612,7 +612,7 @@ impl &MergeState { if len1 == 0 { unsafe { - moveVec(array, dest-(len2-1), self.tmp, 0, len2); + move_vec(array, dest-(len2-1), self.tmp, 0, len2); vec::raw::set_len(self.tmp, 0); // Forget the elements } return; @@ -621,18 +621,18 @@ impl &MergeState { dest -= len1; c1 -= len1; unsafe { - moveVec(array, dest+1, array, c1+1, len1); + move_vec(array, dest+1, array, c1+1, len1); array[dest] <-> self.tmp[c2]; vec::raw::set_len(self.tmp, 0); // Forget the element } return; } - let mut minGallop = self.minGallop; + let mut min_gallop = self.min_gallop; loop { let mut count1 = 0; let mut count2 = 0; - let mut breakOuter = false; + let mut break_outer = false; loop { assert len1 != 0 && len2 > 1; @@ -641,88 +641,88 @@ impl &MergeState { dest -= 1; c1 -= 1; len1 -= 1; count1 += 1; count2 = 0; if len1 == 0 { - breakOuter = true; + break_outer = true; } } else { array[dest] <-> self.tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; count2 += 1; count1 = 0; if len2 == 1 { - breakOuter = true; + break_outer = true; } } - if breakOuter || ((count1 | count2) >= minGallop) { + if break_outer || ((count1 | count2) >= min_gallop) { break; } } - if breakOuter { break; } + if break_outer { break; } // Start to gallop loop { assert len2 > 1 && len1 != 0; - let tmpView = vec::mut_view(array, base1, base1+len1); - count1 = len1 - gallopRight( - &const self.tmp[c2], tmpView, len1-1); + let tmp_view = vec::mut_view(array, base1, base1+len1); + count1 = len1 - gallop_right( + &const self.tmp[c2], tmp_view, len1-1); if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; unsafe { - moveVec(array, dest+1, array, c1+1, count1); + move_vec(array, dest+1, array, c1+1, count1); } - if len1 == 0 { breakOuter = true; break; } + if len1 == 0 { break_outer = true; break; } } array[dest] <-> self.tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; - if len2 == 1 { breakOuter = true; break; } + if len2 == 1 { break_outer = true; break; } - let tmpView = vec::mut_view(self.tmp, 0, len2); - let count2 = len2 - gallopLeft( - &const array[c1], tmpView, len2-1); + let tmp_view = vec::mut_view(self.tmp, 0, len2); + let count2 = len2 - gallop_left( + &const array[c1], tmp_view, len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; unsafe { - moveVec(array, dest+1, self.tmp, c2+1, count2); + move_vec(array, dest+1, self.tmp, c2+1, count2); } - if len2 <= 1 { breakOuter = true; break; } + if len2 <= 1 { break_outer = true; break; } } array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; - if len1 == 0 { breakOuter = true; break; } - minGallop -= 1; + if len1 == 0 { break_outer = true; break; } + min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { break; } } - if breakOuter { break; } - if minGallop < 0 { minGallop = 0; } - minGallop += 2; // Penalize for leaving gallop + if break_outer { break; } + if min_gallop < 0 { min_gallop = 0; } + min_gallop += 2; // Penalize for leaving gallop } - self.minGallop = if minGallop < 1 { 1 } else { minGallop }; + self.min_gallop = if min_gallop < 1 { 1 } else { min_gallop }; if len2 == 1 { assert len1 > 0; dest -= len1; c1 -= len1; unsafe { - moveVec(array, dest+1, array, c1+1, len1); + move_vec(array, dest+1, array, c1+1, len1); } array[dest] <-> self.tmp[c2]; } else if len2 == 0 { - fail fmt!("Method mergeHi violates its contract! %?", len2); + fail fmt!("Method merge_hi violates its contract! %?", len2); } else { assert len1 == 0; assert len2 != 0; unsafe { - moveVec(array, dest-(len2-1), self.tmp, 0, len2); + move_vec(array, dest-(len2-1), self.tmp, 0, len2); } } unsafe { vec::raw::set_len(self.tmp, 0); } } - fn mergeCollapse(array: &[mut T]) { + fn merge_collapse(array: &[mut T]) { while self.runs.len() > 1 { let mut n = self.runs.len()-2; let chk = do self.runs.borrow |arr| { @@ -736,11 +736,11 @@ impl &MergeState { } }; if !chk { break; } - self.mergeAt(n, array); + self.merge_at(n, array); } } - fn mergeForceCollapse(array: &[mut T]) { + fn merge_force_collapse(array: &[mut T]) { while self.runs.len() > 1 { let mut n = self.runs.len()-2; if n > 0 { @@ -750,7 +750,7 @@ impl &MergeState { } } } - self.mergeAt(n, array); + self.merge_at(n, array); } } } @@ -758,7 +758,7 @@ impl &MergeState { // Moves elements to from dest to from // Unsafe as it makes the from parameter invalid between s2 and s2+len #[inline(always)] -unsafe fn moveVec(dest: &[mut T], s1: uint, +unsafe fn move_vec(dest: &[mut T], s1: uint, from: &[const T], s2: uint, len: uint) { assert s1+len <= dest.len() && s2+len <= from.len(); From 0ec5c9af9bef2969203eaba02b168603620cc0c6 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 3 Oct 2012 09:51:05 -0500 Subject: [PATCH 09/28] Add cleanup code so the the array remains in a valid state if a comparison fails --- src/libstd/sort.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 1f446b51fe8ed..75331d5a4c446 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -187,6 +187,7 @@ fn tim_sort(array: &[mut T]) { } let ms = &MergeState(); + ms.array = array; let min_run = min_run_length(size); let mut idx = 0; @@ -401,10 +402,23 @@ struct RunState { struct MergeState { mut min_gallop: uint, mut tmp: ~[T], + mut last_hi: bool, + mut mergePt: uint, + mut tmpPt: uint, + mut array: &[mut T], runs: DVec, drop { unsafe { + let size = self.tmp.len(); + // Move tmp back into invalid part of array + if self.last_hi && size > 0 { + self.mergePt -= self.tmpPt; + move_vec(self.array, self.mergePt, self.tmp, 0, self.tmpPt); + } else if !self.last_hi && size > 0 { + move_vec(self.array, self.mergePt, + self.tmp, self.tmpPt, size-self.tmpPt); + } vec::raw::set_len(self.tmp, 0); } } @@ -416,6 +430,10 @@ fn MergeState() -> MergeState { MergeState { min_gallop: MIN_GALLOP, tmp: tmp, + last_hi: false, + mergePt: 0, + tmpPt: 0, + array: &[mut], runs: DVec(), } } @@ -448,11 +466,13 @@ impl &MergeState { } let slice = vec::mut_view(array, b1, b1+l1); + self.mergePt = b1; let k = gallop_right(&const array[b2], slice, 0); b1 += k; l1 -= k; if l1 != 0 { let slice = vec::mut_view(array, b2, b2+l2); + self.mergePt = b2; let l2 = gallop_left( &const array[b1+l1-1],slice,l2-1); if l2 > 0 { @@ -465,6 +485,7 @@ impl &MergeState { } } self.runs.pop(); + self.mergePt = 0; } fn merge_lo(array: &[mut T], base1: uint, len1: uint, @@ -472,11 +493,14 @@ impl &MergeState { assert len1 != 0 && len2 != 0 && base1+len1 == base2; vec::reserve(&mut self.tmp, len1); + self.last_hi = false; unsafe { vec::raw::set_len(self.tmp, len1); move_vec(self.tmp, 0, array, base1, len1); } + self.tmpPt = 0; + self.mergePt = base1; let mut c1 = 0; let mut c2 = base2; @@ -486,6 +510,7 @@ impl &MergeState { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; + self.mergePt += 1; if len2 == 0 { unsafe { @@ -514,6 +539,7 @@ impl &MergeState { if array[c2] < self.tmp[c1] { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; + self.mergePt += 1; count2 += 1; count1 = 0; if len2 == 0 { break_outer = true; @@ -521,6 +547,8 @@ impl &MergeState { } else { array[dest] <-> self.tmp[c1]; dest += 1; c1 += 1; len1 -= 1; + self.mergePt += 1; + self.tmpPt += 1; count1 += 1; count2 = 0; if len1 == 1 { break_outer = true; @@ -536,17 +564,19 @@ impl &MergeState { loop { assert len1 > 1 && len2 != 0; - let tmp_view = vec::mut_view(self.tmp, c1, c1+len1); + let tmp_view = vec::const_view(self.tmp, c1, c1+len1); count1 = gallop_right(&const array[c2], tmp_view, 0); if count1 != 0 { unsafe { move_vec(array, dest, self.tmp, c1, count1); } dest += count1; c1 += count1; len1 -= count1; + self.mergePt += count1; self.tmpPt += count1; if len1 <= 1 { break_outer = true; break; } } array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; + self.mergePt += 1; if len2 == 0 { break_outer = true; break; } let tmp_view = vec::mut_view(array, c2, c2+len2); @@ -556,10 +586,12 @@ impl &MergeState { move_vec(array, dest, array, c2, count2); } dest += count2; c2 += count2; len2 -= count2; + self.mergePt += count2; if len2 == 0 { break_outer = true; break; } } array[dest] <-> self.tmp[c1]; dest += 1; c1 += 1; len1 -= 1; + self.mergePt += 1; self.tmpPt += 1; if len1 == 1 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -587,6 +619,7 @@ impl &MergeState { move_vec(array, dest, self.tmp, c1, len1); } } + self.tmpPt = 0; unsafe { vec::raw::set_len(self.tmp, 0); } } @@ -595,6 +628,7 @@ impl &MergeState { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; vec::reserve(&mut self.tmp, len2); + self.last_hi = true; unsafe { vec::raw::set_len(self.tmp, len2); @@ -607,6 +641,9 @@ impl &MergeState { let mut len1 = len1; let mut len2 = len2; + self.mergePt = dest; + self.tmpPt = len2 - 1; + array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; @@ -639,6 +676,7 @@ impl &MergeState { if self.tmp[c2] < array[c1] { array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; + self.mergePt -= 1; count1 += 1; count2 = 0; if len1 == 0 { break_outer = true; @@ -646,6 +684,7 @@ impl &MergeState { } else { array[dest] <-> self.tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; + self.mergePt -= 1; self.tmpPt -= 1; count2 += 1; count1 = 0; if len2 == 1 { break_outer = true; @@ -667,6 +706,7 @@ impl &MergeState { if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; + self.mergePt -= count1; unsafe { move_vec(array, dest+1, array, c1+1, count1); } @@ -675,6 +715,7 @@ impl &MergeState { array[dest] <-> self.tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; + self.mergePt -= 1; self.tmpPt -= 1; if len2 == 1 { break_outer = true; break; } let tmp_view = vec::mut_view(self.tmp, 0, len2); @@ -682,6 +723,7 @@ impl &MergeState { &const array[c1], tmp_view, len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; + self.mergePt -= count2; self.tmpPt -= count2; unsafe { move_vec(array, dest+1, self.tmp, c2+1, count2); } @@ -689,6 +731,7 @@ impl &MergeState { } array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; + self.mergePt -= 1; if len1 == 0 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -719,6 +762,7 @@ impl &MergeState { move_vec(array, dest-(len2-1), self.tmp, 0, len2); } } + self.tmpPt = 0; unsafe { vec::raw::set_len(self.tmp, 0); } } @@ -941,6 +985,23 @@ mod tests { #[cfg(test)] mod test_timsort { #[legacy_exports]; + struct CVal { + val: ~float, + } + + impl CVal: Ord { + pure fn lt(other: &CVal) -> bool { + unsafe { + let rng = rand::Rng(); + if rng.gen_float() > 0.995 { fail ~"It's happening!!!"; } + } + self.val < other.val + } + pure fn le(other: &CVal) -> bool { self.val <= other.val } + pure fn gt(other: &CVal) -> bool { self.val > other.val } + pure fn ge(other: &CVal) -> bool { self.val >= other.val } + } + fn check_sort(v1: &[mut int], v2: &[mut int]) { let len = vec::len::(v1); timsort::(v1); @@ -976,6 +1037,18 @@ mod test_timsort { check_sort(v1, v2); } } + + #[test] + #[should_fail] + fn crash_test() { + let arr = do vec::from_fn |_i| { + let randVal = rng.gen_float(); + CVal { val: ~randVal } + }; + + tim_sort(arr); + fail ~"Guarantee the fail"; + } } // Local Variables: From 44f8a4401ab37a45ba49db56611d77807bcbce35 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 3 Oct 2012 21:41:53 -0500 Subject: [PATCH 10/28] Backup changes before pull from incoming --- src/libstd/sort.rs | 142 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 11 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 75331d5a4c446..ed7e3f0f6d9e4 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -10,7 +10,7 @@ export le; export merge_sort; export quick_sort; export quick_sort3; -export timsort; +export tim_sort; export Sort; type Le = pure fn(v1: &T, v2: &T) -> bool; @@ -415,7 +415,7 @@ struct MergeState { if self.last_hi && size > 0 { self.mergePt -= self.tmpPt; move_vec(self.array, self.mergePt, self.tmp, 0, self.tmpPt); - } else if !self.last_hi && size > 0 { + } else if !self.last_hi && size-self.tmpPt > 0 { move_vec(self.array, self.mergePt, self.tmp, self.tmpPt, size-self.tmpPt); } @@ -982,9 +982,9 @@ mod tests { } } -#[cfg(test)] -mod test_timsort { - #[legacy_exports]; +//#[cfg(test)] +//mod test_tim_sort { +// #[legacy_exports]; struct CVal { val: ~float, } @@ -1004,7 +1004,7 @@ mod test_timsort { fn check_sort(v1: &[mut int], v2: &[mut int]) { let len = vec::len::(v1); - timsort::(v1); + tim_sort::(v1); let mut i = 0u; while i < len { log(debug, v2[i]); @@ -1037,11 +1037,12 @@ mod test_timsort { check_sort(v1, v2); } } - - #[test] - #[should_fail] +//} + //#[test] + //#[should_fail] fn crash_test() { - let arr = do vec::from_fn |_i| { + let rng = rand::Rng(); + let mut arr = do vec::from_fn(1000) |_i| { let randVal = rng.gen_float(); CVal { val: ~randVal } }; @@ -1049,7 +1050,126 @@ mod test_timsort { tim_sort(arr); fail ~"Guarantee the fail"; } -} +//} + +//#[cfg(test)] +/*mod big_tests { + + #[test] + fn sorts_test() { + let low = 5; + let high = 10; + + //pure fn le(a: &~float, b: &~float) -> bool { *a <= *b } + + //let sorts = ~[ + //let s1 = fn(arr: &[mut ~float]) { tim_sort(arr); }; + //let s2 = fn(arr: &[mut ~float]) { quick_sort(arr, le); }; + //let s3 = fn(arr: &[mut ~float]) { quick_sort3(arr); }; + //let s4 = fn(arr: &[mut ~float]) { let rs = merge_sort(arr, le); + // for rs.eachi |i, v| {arr[i] = *v}}; + //]; + + tabulate_unique(low, high); + //tabulate_managed(low, high, tim_sort); + //tabulate_linear(low, high, tim_sort); + } + + fn multiplyVec(arr: &[const T], num: uint) -> ~[mut T] { + let size = arr.len(); + let res = do vec::from_fn(num) |i| { + arr[i % size] + }; + vec::to_mut(res) + } + + fn makeRange(n: uint) -> ~[uint] { + let one = do vec::from_fn(n) |i| { i }; + let mut two = copy one; + vec::reverse(two); + vec::append(two, one) + } + + fn tabulate_unique(lo: uint, hi: uint) { + fn isSorted(arr: &[const T]) { + for uint::range(0, arr.len()-1) |i| { + if arr[i] > arr[i+1] { + fail ~"Array not sorted"; + } + } + } + + let rng = rand::Rng(); + + for uint::range(lo, hi) |i| { + let n = 1 << i; + let arr = do vec::from_fn(n) |_i| { + ~rng.gen_float() + }; + let arr = vec::to_mut(arr); + + tim_sort(arr); // *sort + isSorted(arr); + + vec::reverse(arr); + tim_sort(arr); // \sort + isSorted(arr); + + tim_sort(arr); // /sort + isSorted(arr); + + for 3.times { + let i1 = rng.gen_uint_range(0, n); + let i2 = rng.gen_uint_range(0, n); + arr[i1] <-> arr[i2]; + } + tim_sort(arr); // 3sort + isSorted(arr); + + if n >= 10 { + let size = arr.len(); + let mut idx = 1; + while idx <= 10 { + arr[size-idx] = ~rng.gen_float(); + idx += 1; + } + } + tim_sort(arr); // +sort + isSorted(arr); + + for (n/100).times { + let idx = rng.gen_uint_range(0, n); + arr[idx] = ~rng.gen_float(); + } + tim_sort(arr); + isSorted(arr); + + let arr = if n > 4 { + let part = vec::view(arr, 0, 4); + multiplyVec(part, n) + } else { arr }; + tim_sort(arr); // ~sort + isSorted(arr); + + let mut arr = vec::from_elem(n, ~(-0.5)); + tim_sort(arr); // =sort + isSorted(arr); + + let half = n / 2; + let mut arr = makeRange(half).map(|i| ~(*i as float)); + tim_sort(arr); // !sort + isSorted(arr); + } + } + + fn tabulate_managed(lo: uint, hi: uint, sort: fn(x: &[mut ~float])) { + + } + + fn tabulate_linear(lo: uint, hi: uint, sort: fn(x: &[mut ~float])) { + + } +}*/ // Local Variables: // mode: rust; From 455591d026546c78b5f03a4d013470685bcc2813 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 4 Oct 2012 11:24:38 -0500 Subject: [PATCH 11/28] Fix my merge --- src/libstd/json.rs | 130 --------------------------------------------- 1 file changed, 130 deletions(-) diff --git a/src/libstd/json.rs b/src/libstd/json.rs index 2d78ef066cc86..f244f2869a60e 100644 --- a/src/libstd/json.rs +++ b/src/libstd/json.rs @@ -27,136 +27,6 @@ pub struct Error { line: uint, col: uint, msg: @~str, -}; - -/// Serializes a json value into a io::writer -fn to_writer(wr: io::Writer, j: Json) { - match j { - Num(n) => wr.write_str(float::to_str(n, 6u)), - String(s) => wr.write_str(escape_str(*s)), - Boolean(b) => wr.write_str(if b { ~"true" } else { ~"false" }), - List(v) => { - wr.write_char('['); - let mut first = true; - for (*v).each |item| { - if !first { - wr.write_str(~", "); - } - first = false; - to_writer(wr, *item); - }; - wr.write_char(']'); - } - Dict(d) => { - if d.size() == 0u { - wr.write_str(~"{}"); - return; - } - - wr.write_str(~"{ "); - let mut first = true; - for d.each |key, value| { - if !first { - wr.write_str(~", "); - } - first = false; - wr.write_str(escape_str(key)); - wr.write_str(~": "); - to_writer(wr, value); - }; - wr.write_str(~" }"); - } - Null => wr.write_str(~"null") - } -} - -/// Serializes a json value into a io::writer -fn to_writer_pretty(wr: io::Writer, j: Json, indent: uint) { - fn spaces(n: uint) -> ~str { - let mut ss = ~""; - for n.times { str::push_str(&mut ss, " "); } - return ss; - } - - match j { - Num(n) => wr.write_str(float::to_str(n, 6u)), - String(s) => wr.write_str(escape_str(*s)), - Boolean(b) => wr.write_str(if b { ~"true" } else { ~"false" }), - List(vv) => { - if vv.len() == 0u { - wr.write_str(~"[]"); - return; - } - - let inner_indent = indent + 2; - - // [ - wr.write_str("[\n"); - wr.write_str(spaces(inner_indent)); - - // [ elem, - // elem, - // elem ] - let mut first = true; - for (*vv).each |item| { - if !first { - wr.write_str(~",\n"); - wr.write_str(spaces(inner_indent)); - } - first = false; - to_writer_pretty(wr, *item, inner_indent); - }; - - // ] - wr.write_str("\n"); - wr.write_str(spaces(indent)); - wr.write_str(~"]"); - } - Dict(dd) => { - if dd.size() == 0u { - wr.write_str(~"{}"); - return; - } - - let inner_indent = indent + 2; - - // convert from a dictionary - let mut pairs = ~[]; - for dd.each |key, value| { - vec::push(pairs, (key, value)); - } - - // sort by key strings - let sorted_pairs = do sort::merge_sort(pairs) |a,b| { *a <= *b }; - - // { - wr.write_str(~"{\n"); - wr.write_str(spaces(inner_indent)); - - // { k: v, - // k: v, - // k: v } - let mut first = true; - for sorted_pairs.each |kv| { - let (key, value) = *kv; - if !first { - wr.write_str(~",\n"); - wr.write_str(spaces(inner_indent)); - } - first = false; - let key = str::append(escape_str(key), ~": "); - let key_indent = inner_indent + str::len(key); - wr.write_str(key); - to_writer_pretty(wr, value, key_indent); - }; - - // } - wr.write_str(~"\n"); - wr.write_str(spaces(indent)); - wr.write_str(~"}"); - } - Null => wr.write_str(~"null") - } } fn escape_str(s: &str) -> ~str { From 7bd48b92d951a72c40e472a14c6c83d733be1282 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 4 Oct 2012 11:24:55 -0500 Subject: [PATCH 12/28] Get tim_sort working, add test for double-freeing elements in tmp --- src/libstd/sort.rs | 49 +++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 6a292402dac34..6f3628f4fc722 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -215,7 +215,7 @@ fn binarysort(array: &[mut T], start: uint) { let mut pivot = ~[]; vec::reserve(&mut pivot, 1); - unsafe { vec::raw::set_len(pivot, 1); }; + unsafe { vec::raw::set_len(&mut pivot, 1); }; while start < size { unsafe { @@ -243,7 +243,7 @@ fn binarysort(array: &[mut T], start: uint) { array[left] <-> pivot[0]; start += 1; } - unsafe { vec::raw::set_len(pivot, 0); } // Forget the boxed element + unsafe { vec::raw::set_len(&mut pivot, 0); } // Forget the boxed element } /// Reverse the order of elements in a slice, in place @@ -411,7 +411,7 @@ struct MergeState { move_vec(self.array, self.mergePt, self.tmp, self.tmpPt, size-self.tmpPt); } - vec::raw::set_len(self.tmp, 0); + vec::raw::set_len(&mut self.tmp, 0); } } } @@ -488,7 +488,7 @@ impl &MergeState { self.last_hi = false; unsafe { - vec::raw::set_len(self.tmp, len1); + vec::raw::set_len(&mut self.tmp, len1); move_vec(self.tmp, 0, array, base1, len1); } self.tmpPt = 0; @@ -507,7 +507,7 @@ impl &MergeState { if len2 == 0 { unsafe { move_vec(array, dest, self.tmp, 0, len1); - vec::raw::set_len(self.tmp, 0); // Forget the elements + vec::raw::set_len(&mut self.tmp, 0); // Forget the elements } return; } @@ -515,7 +515,7 @@ impl &MergeState { unsafe { move_vec(array, dest, array, c2, len2); array[dest+len2] <-> self.tmp[c1]; - vec::raw::set_len(self.tmp, 0); // Forget the element + vec::raw::set_len(&mut self.tmp, 0); // Forget the element } return; } @@ -556,8 +556,9 @@ impl &MergeState { loop { assert len1 > 1 && len2 != 0; - let tmp_view = vec::const_view(self.tmp, c1, c1+len1); - count1 = gallop_right(&const array[c2], tmp_view, 0); + //let tmp_view = vec::const_view(self.tmp, c1, c1+len1); + count1 = gallop_right(&const array[c2], + vec::const_view(self.tmp, c1, c1+len1), 0); if count1 != 0 { unsafe { move_vec(array, dest, self.tmp, c1, count1); @@ -571,7 +572,7 @@ impl &MergeState { self.mergePt += 1; if len2 == 0 { break_outer = true; break; } - let tmp_view = vec::mut_view(array, c2, c2+len2); + let tmp_view = vec::const_view(array, c2, c2+len2); count2 = gallop_left(&const self.tmp[c1], tmp_view, 0); if count2 != 0 { unsafe { @@ -612,7 +613,7 @@ impl &MergeState { } } self.tmpPt = 0; - unsafe { vec::raw::set_len(self.tmp, 0); } + unsafe { vec::raw::set_len(&mut self.tmp, 0); } } fn merge_hi(array: &[mut T], base1: uint, len1: uint, @@ -623,7 +624,7 @@ impl &MergeState { self.last_hi = true; unsafe { - vec::raw::set_len(self.tmp, len2); + vec::raw::set_len(&mut self.tmp, len2); move_vec(self.tmp, 0, array, base2, len2); } @@ -642,7 +643,7 @@ impl &MergeState { if len1 == 0 { unsafe { move_vec(array, dest-(len2-1), self.tmp, 0, len2); - vec::raw::set_len(self.tmp, 0); // Forget the elements + vec::raw::set_len(&mut self.tmp, 0); // Forget the elements } return; } @@ -652,7 +653,7 @@ impl &MergeState { unsafe { move_vec(array, dest+1, array, c1+1, len1); array[dest] <-> self.tmp[c2]; - vec::raw::set_len(self.tmp, 0); // Forget the element + vec::raw::set_len(&mut self.tmp, 0); // Forget the element } return; } @@ -710,9 +711,9 @@ impl &MergeState { self.mergePt -= 1; self.tmpPt -= 1; if len2 == 1 { break_outer = true; break; } - let tmp_view = vec::mut_view(self.tmp, 0, len2); - let count2 = len2 - gallop_left( - &const array[c1], tmp_view, len2-1); + //let tmp_view = vec::mut_view(self.tmp, 0, len2); + let count2 = len2 - gallop_left(&const array[c1], + vec::mut_view(self.tmp, 0, len2), len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; self.mergePt -= count2; self.tmpPt -= count2; @@ -755,7 +756,7 @@ impl &MergeState { } } self.tmpPt = 0; - unsafe { vec::raw::set_len(self.tmp, 0); } + unsafe { vec::raw::set_len(&mut self.tmp, 0); } } fn merge_collapse(array: &[mut T]) { @@ -974,9 +975,9 @@ mod tests { } } -//#[cfg(test)] -//mod test_tim_sort { -// #[legacy_exports]; +#[cfg(test)] +mod test_tim_sort { + #[legacy_exports]; struct CVal { val: ~float, } @@ -1029,9 +1030,9 @@ mod tests { check_sort(v1, v2); } } -//} - //#[test] - //#[should_fail] + + #[test] + #[should_fail] fn crash_test() { let rng = rand::Rng(); let mut arr = do vec::from_fn(1000) |_i| { @@ -1042,7 +1043,7 @@ mod tests { tim_sort(arr); fail ~"Guarantee the fail"; } -//} +} //#[cfg(test)] /*mod big_tests { From 74246d47fd505c260242f65a70e8f64865885431 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 4 Oct 2012 21:35:03 -0500 Subject: [PATCH 13/28] Finish up tests, uncomment when ICE is fixed. --- src/libstd/sort.rs | 164 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 146 insertions(+), 18 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 6f3628f4fc722..a8fe79161019c 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1045,27 +1045,34 @@ mod test_tim_sort { } } +/*fn f(array: &[mut T]) { array[0] <-> array[0] } + +fn ice_test() { + let _s1 = &fn(arr: &[mut ~float]) { tim_sort(arr); }; +}*/ + //#[cfg(test)] -/*mod big_tests { +mod big_tests { - #[test] + //#[test] fn sorts_test() { let low = 5; let high = 10; //pure fn le(a: &~float, b: &~float) -> bool { *a <= *b } - //let sorts = ~[ - //let s1 = fn(arr: &[mut ~float]) { tim_sort(arr); }; - //let s2 = fn(arr: &[mut ~float]) { quick_sort(arr, le); }; - //let s3 = fn(arr: &[mut ~float]) { quick_sort3(arr); }; - //let s4 = fn(arr: &[mut ~float]) { let rs = merge_sort(arr, le); - // for rs.eachi |i, v| {arr[i] = *v}}; - //]; - - tabulate_unique(low, high); - //tabulate_managed(low, high, tim_sort); - //tabulate_linear(low, high, tim_sort); + //let s1 = fn(arr: &[mut ~float]) { tim_sort(arr); }; + //let s2 = fn(arr: &[mut ~float]) { quick_sort(arr, le); }; + //let s3 = fn(arr: &[mut ~float]) { quick_sort3(arr); }; + //let s4 = fn(arr: &[mut ~float]) { let rs = merge_sort(arr, le); + // for rs.eachi |i, v| {arr[i] = *v}}; + + + // Run tabulate_unique and tabulate_managed + // with the other sorts at some point + //tabulate_unique(low, high); + //tabulate_managed(low, high); + //tabulate_linear(low, high); } fn multiplyVec(arr: &[const T], num: uint) -> ~[mut T] { @@ -1083,7 +1090,7 @@ mod test_tim_sort { vec::append(two, one) } - fn tabulate_unique(lo: uint, hi: uint) { + /*fn tabulate_unique(lo: uint, hi: uint) { fn isSorted(arr: &[const T]) { for uint::range(0, arr.len()-1) |i| { if arr[i] > arr[i+1] { @@ -1153,16 +1160,137 @@ mod test_tim_sort { tim_sort(arr); // !sort isSorted(arr); } - } + }*/ + + /*fn tabulate_managed(lo: uint, hi: uint) { + fn isSorted(arr: &[const @T], expected_refcount: uint) { + for uint::range(0, arr.len()-1) |i| { + if arr[i] > arr[i+1] { + fail ~"Array not sorted"; + } + assert sys::refcount(arr[i]) == expected_refcount; + } + } + + let rng = rand::Rng(); + + for uint::range(lo, hi) |i| { + let n = 1 << i; + let arr = do vec::from_fn(n) |_i| { + @rng.gen_float() + }; + let arr = vec::to_mut(arr); - fn tabulate_managed(lo: uint, hi: uint, sort: fn(x: &[mut ~float])) { + tim_sort(arr); // *sort + isSorted(arr, 1); + + vec::reverse(arr); + tim_sort(arr); // \sort + isSorted(arr, 1); + + tim_sort(arr); // /sort + isSorted(arr, 1); + + for 3.times { + let i1 = rng.gen_uint_range(0, n); + let i2 = rng.gen_uint_range(0, n); + arr[i1] <-> arr[i2]; + } + tim_sort(arr); // 3sort + isSorted(arr, 1); + + if n >= 10 { + let size = arr.len(); + let mut idx = 1; + while idx <= 10 { + arr[size-idx] = @rng.gen_float(); + idx += 1; + } + } + tim_sort(arr); // +sort + isSorted(arr, 1); + for (n/100).times { + let idx = rng.gen_uint_range(0, n); + arr[idx] = @rng.gen_float(); + } + tim_sort(arr); + isSorted(arr, 1); + + let arr = if n > 4 { + let part = vec::view(arr, 0, 4); + multiplyVec(part, n) + } else { arr }; + tim_sort(arr); // ~sort + isSorted(arr, n/4+1); + + let mut arr = vec::from_elem(n, @(-0.5)); + tim_sort(arr); // =sort + isSorted(arr, n); + + let half = n / 2; + let mut arr = makeRange(half).map(|i| @(*i as float)); + tim_sort(arr); // !sort + isSorted(arr, 2); + } + } +*/ +/* + struct LVal { + val: uint, + key: fn(@uint), + + drop { + let x = unsafe { task::local_data::local_data_get(self.key) }; + match x { + Some(@y) => { + unsafe { + task::local_data::local_data_set(self.key, @(y+1)); + } + } + _ => fail ~"Expected key to work", + } + } } - fn tabulate_linear(lo: uint, hi: uint, sort: fn(x: &[mut ~float])) { + impl LVal: Ord { + pure fn lt(other: &LVal) -> bool { self.val < other.val } + pure fn le(other: &LVal) -> bool { self.val <= other.val } + pure fn gt(other: &LVal) -> bool { self.val > other.val } + pure fn ge(other: &LVal) -> bool { self.val >= other.val } + } + fn tabulate_linear(lo: uint, hi: uint) { + fn key(+_x: @uint) { } + fn isSorted(arr: &[const T]) { + for uint::range(0, arr.len()-1) |i| { + if arr[i] > arr[i+1] { + fail ~"Array not sorted"; + } + } + } + + let n = 1000; + unsafe { + task::local_data::local_data_set(key, @0u); + } + + { + let mut arr = do vec::from_fn(n) |i| { + LVal { val: i, key: key } + }; + //tim_sort(arr); + isSorted(arr); + } + + let @dropped = unsafe { + task::local_data::local_data_get(key).get() + }; + + assert n == dropped; } -}*/ + */ +} // Local Variables: // mode: rust; From eee86d4340668037c12cd4c69cc40daa6564f2fb Mon Sep 17 00:00:00 2001 From: Simon BD Date: Sat, 6 Oct 2012 12:44:56 -0500 Subject: [PATCH 14/28] Remove debug info --- src/libstd/sort.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index a8fe79161019c..f3c2f5ff44660 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -604,7 +604,7 @@ impl &MergeState { } array[dest+len2] <-> self.tmp[c1]; } else if len1 == 0 { - fail fmt!("Method merge_lo violates its contract! %?", len1); + fail ~"Comparison violates its contract!"; } else { assert len2 == 0; assert len1 > 1; @@ -747,7 +747,7 @@ impl &MergeState { } array[dest] <-> self.tmp[c2]; } else if len2 == 0 { - fail fmt!("Method merge_hi violates its contract! %?", len2); + fail ~"Coparison violates its contract!"; } else { assert len1 == 0; assert len2 != 0; From d4a54837d4ab28219727e1f1e0c131ba6033ba94 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Sat, 6 Oct 2012 13:07:29 -0500 Subject: [PATCH 15/28] Add a test to check that badly written Ord impl do not cause double frees --- src/libstd/sort.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index f3c2f5ff44660..7bafb324dad04 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1043,6 +1043,27 @@ mod test_tim_sort { tim_sort(arr); fail ~"Guarantee the fail"; } + + struct DVal { val: ~uint } + impl DVal: Ord { + pure fn lt(other: &DVal) -> bool { true } + pure fn le(other: &DVal) -> bool { true } + pure fn gt(other: &DVal) -> bool { true } + pure fn ge(other: &DVal) -> bool { true } + } + + #[test] + #[should_fail] + fn test_bad_Ord_impl() { + let rng = rand::Rng(); + let mut arr = do vec::from_fn(500) |_i| { + let randVal = rng.gen_uint(); + DVal { val: ~randVal } + }; + + tim_sort(arr); + fail ~"Guarantee the fail"; + } } /*fn f(array: &[mut T]) { array[0] <-> array[0] } From 9aec7a3e85c5b07923eab05d3ebe9d031bf258f3 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 18:33:28 -0500 Subject: [PATCH 16/28] Fix up tests, export tim_sort --- src/libstd/sort.rs | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 7bafb324dad04..98f98fe7fce6f 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -166,7 +166,7 @@ const MIN_MERGE: uint = 64; const MIN_GALLOP: uint = 7; const INITIAL_TMP_STORAGE: uint = 128; -fn tim_sort(array: &[mut T]) { +pub fn tim_sort(array: &[mut T]) { let size = array.len(); if size < 2 { return; @@ -977,7 +977,7 @@ mod tests { #[cfg(test)] mod test_tim_sort { - #[legacy_exports]; + // #[legacy_exports]; struct CVal { val: ~float, } @@ -1046,10 +1046,10 @@ mod test_tim_sort { struct DVal { val: ~uint } impl DVal: Ord { - pure fn lt(other: &DVal) -> bool { true } - pure fn le(other: &DVal) -> bool { true } - pure fn gt(other: &DVal) -> bool { true } - pure fn ge(other: &DVal) -> bool { true } + pure fn lt(_x: &DVal) -> bool { true } + pure fn le(_x: &DVal) -> bool { true } + pure fn gt(_x: &DVal) -> bool { true } + pure fn ge(_x: &DVal) -> bool { true } } #[test] @@ -1066,16 +1066,11 @@ mod test_tim_sort { } } -/*fn f(array: &[mut T]) { array[0] <-> array[0] } - -fn ice_test() { - let _s1 = &fn(arr: &[mut ~float]) { tim_sort(arr); }; -}*/ - -//#[cfg(test)] +/* +#[cfg(test)] mod big_tests { - //#[test] + #[test] fn sorts_test() { let low = 5; let high = 10; @@ -1091,9 +1086,9 @@ mod big_tests { // Run tabulate_unique and tabulate_managed // with the other sorts at some point - //tabulate_unique(low, high); - //tabulate_managed(low, high); - //tabulate_linear(low, high); + tabulate_unique(low, high); + tabulate_managed(low, high); + tabulate_linear(); } fn multiplyVec(arr: &[const T], num: uint) -> ~[mut T] { @@ -1111,7 +1106,7 @@ mod big_tests { vec::append(two, one) } - /*fn tabulate_unique(lo: uint, hi: uint) { + fn tabulate_unique(lo: uint, hi: uint) { fn isSorted(arr: &[const T]) { for uint::range(0, arr.len()-1) |i| { if arr[i] > arr[i+1] { @@ -1181,9 +1176,9 @@ mod big_tests { tim_sort(arr); // !sort isSorted(arr); } - }*/ + } - /*fn tabulate_managed(lo: uint, hi: uint) { + fn tabulate_managed(lo: uint, hi: uint) { fn isSorted(arr: &[const @T], expected_refcount: uint) { for uint::range(0, arr.len()-1) |i| { if arr[i] > arr[i+1] { @@ -1255,8 +1250,7 @@ mod big_tests { isSorted(arr, 2); } } -*/ -/* + struct LVal { val: uint, key: fn(@uint), @@ -1281,8 +1275,8 @@ mod big_tests { pure fn ge(other: &LVal) -> bool { self.val >= other.val } } - fn tabulate_linear(lo: uint, hi: uint) { - fn key(+_x: @uint) { } + fn tabulate_linear() { + fn key(_x: @uint) { } fn isSorted(arr: &[const T]) { for uint::range(0, arr.len()-1) |i| { if arr[i] > arr[i+1] { @@ -1310,8 +1304,8 @@ mod big_tests { assert n == dropped; } - */ } +*/ // Local Variables: // mode: rust; From 71c311cec5fa4a71e5349ed2df962a7adfd336bd Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 21:42:09 -0500 Subject: [PATCH 17/28] Uncomment tests and fix binarysort segmentation fault --- src/libstd/sort.rs | 167 +++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 95 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 946a3e1155dd5..97ae0054cce32 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -172,16 +172,16 @@ pub fn tim_sort(array: &[mut T]) { return; } + let ms = &MergeState(); + ms.array = array; + let min_run = min_run_length(size); + if size < MIN_MERGE { let init_run_len = count_run_ascending(array); - binarysort(array, init_run_len); + ms.binarysort(array, init_run_len); return; } - let ms = &MergeState(); - ms.array = array; - let min_run = min_run_length(size); - let mut idx = 0; let mut remaining = size; loop { @@ -191,7 +191,7 @@ pub fn tim_sort(array: &[mut T]) { if run_len < min_run { let force = if remaining <= min_run {remaining} else {min_run}; let slice = vec::mut_view(arr, 0, force); - binarysort(slice, run_len); + ms.binarysort(slice, run_len); run_len = force; } @@ -206,47 +206,7 @@ pub fn tim_sort(array: &[mut T]) { ms.merge_force_collapse(array); } -fn binarysort(array: &[mut T], start: uint) { - let size = array.len(); - let mut start = start; - assert start <= size; - - if start == 0 { start += 1; } - - let mut pivot = ~[]; - vec::reserve(&mut pivot, 1); - unsafe { vec::raw::set_len(&mut pivot, 1); }; - - while start < size { - unsafe { - let tmp_view = vec::mut_view(array, start, start+1); - vec::raw::memmove(pivot, tmp_view, 1); - } - let mut left = 0; - let mut right = start; - assert left <= right; - - while left < right { - let mid = (left + right) >> 1; - if pivot[0] < array[mid] { - right = mid; - } else { - left = mid+1; - } - } - assert left == right; - let mut n = start-left; - - unsafe { - move_vec(array, left+1, array, left, n); - } - array[left] <-> pivot[0]; - start += 1; - } - unsafe { vec::raw::set_len(&mut pivot, 0); } // Forget the boxed element -} - -/// Reverse the order of elements in a slice, in place +// Reverse the order of elements in a slice, in place fn reverse_slice(v: &[mut T], start: uint, end:uint) { let mut i = start; while i < end / 2 { @@ -395,6 +355,7 @@ struct MergeState { mut min_gallop: uint, mut tmp: ~[T], mut last_hi: bool, + mut last_bsort: bool, mut mergePt: uint, mut tmpPt: uint, mut array: &[mut T], @@ -404,7 +365,9 @@ struct MergeState { unsafe { let size = self.tmp.len(); // Move tmp back into invalid part of array - if self.last_hi && size > 0 { + if self.last_bsort { + + } else if self.last_hi && size > 0 { self.mergePt -= self.tmpPt; move_vec(self.array, self.mergePt, self.tmp, 0, self.tmpPt); } else if !self.last_hi && size-self.tmpPt > 0 { @@ -421,8 +384,9 @@ fn MergeState() -> MergeState { vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { min_gallop: MIN_GALLOP, - tmp: tmp, + tmp: move tmp, last_hi: false, + last_bsort: false, mergePt: 0, tmpPt: 0, array: &[mut], @@ -431,6 +395,45 @@ fn MergeState() -> MergeState { } impl &MergeState { + fn binarysort(array: &[mut T], start: uint) { + let size = array.len(); + let mut start = start; + assert start <= size; + + if start == 0 { start += 1; } + + self.last_bsort = true; + unsafe { vec::raw::set_len(&mut self.tmp, 1); }; + + while start < size { + unsafe { + move_vec(self.tmp, 0, array, start, 1); + } + let mut left = 0; + let mut right = start; + assert left <= right; + + while left < right { + let mid = (left + right) >> 1; + if self.tmp[0] < array[mid] { + right = mid; + } else { + left = mid+1; + } + } + assert left == right; + let mut n = start-left; + + unsafe { + move_vec(array, left+1, array, left, n); + } + array[left] <-> self.tmp[0]; + start += 1; + } + unsafe { vec::raw::set_len(&mut self.tmp, 0); } // Forget the boxed element + self.last_bsort = false; + } + fn push_run(run_base: uint, run_len: uint) { let tmp = RunState{base: run_base, len: run_len}; self.runs.push(tmp); @@ -958,7 +961,7 @@ mod tests { // tjc: funny that we have to use parens pure fn ile(x: &(&static/str), y: &(&static/str)) -> bool { - unsafe // to_lower is not pure... + unsafe // to_lower is not pure... { let x = x.to_lower(); let y = y.to_lower(); @@ -977,7 +980,6 @@ mod tests { #[cfg(test)] mod test_tim_sort { - // #[legacy_exports]; struct CVal { val: ~float, } @@ -1043,51 +1045,27 @@ mod test_tim_sort { tim_sort(arr); fail ~"Guarantee the fail"; } - - struct DVal { val: ~uint } - impl DVal: Ord { - pure fn lt(_x: &DVal) -> bool { true } - pure fn le(_x: &DVal) -> bool { true } - pure fn gt(_x: &DVal) -> bool { true } - pure fn ge(_x: &DVal) -> bool { true } - } - - #[test] - #[should_fail] - fn test_bad_Ord_impl() { - let rng = rand::Rng(); - let mut arr = do vec::from_fn(500) |_i| { - let randVal = rng.gen_uint(); - DVal { val: ~randVal } - }; - - tim_sort(arr); - fail ~"Guarantee the fail"; - } } -/* #[cfg(test)] mod big_tests { #[test] - fn sorts_test() { + fn test_unique() { let low = 5; let high = 10; - - //pure fn le(a: &~float, b: &~float) -> bool { *a <= *b } - - //let s1 = fn(arr: &[mut ~float]) { tim_sort(arr); }; - //let s2 = fn(arr: &[mut ~float]) { quick_sort(arr, le); }; - //let s3 = fn(arr: &[mut ~float]) { quick_sort3(arr); }; - //let s4 = fn(arr: &[mut ~float]) { let rs = merge_sort(arr, le); - // for rs.eachi |i, v| {arr[i] = *v}}; - - - // Run tabulate_unique and tabulate_managed - // with the other sorts at some point tabulate_unique(low, high); + } + + #[test] + fn test_managed() { + let low = 5; + let high = 10; tabulate_managed(low, high); + } + + #[test] + fn test_linear() { tabulate_linear(); } @@ -1096,14 +1074,14 @@ mod big_tests { let res = do vec::from_fn(num) |i| { arr[i % size] }; - vec::to_mut(res) + vec::to_mut(move res) } fn makeRange(n: uint) -> ~[uint] { let one = do vec::from_fn(n) |i| { i }; let mut two = copy one; vec::reverse(two); - vec::append(two, one) + vec::append(move two, one) } fn tabulate_unique(lo: uint, hi: uint) { @@ -1122,7 +1100,7 @@ mod big_tests { let arr = do vec::from_fn(n) |_i| { ~rng.gen_float() }; - let arr = vec::to_mut(arr); + let arr = vec::to_mut(move arr); tim_sort(arr); // *sort isSorted(arr); @@ -1163,7 +1141,7 @@ mod big_tests { let arr = if n > 4 { let part = vec::view(arr, 0, 4); multiplyVec(part, n) - } else { arr }; + } else { move arr }; tim_sort(arr); // ~sort isSorted(arr); @@ -1195,7 +1173,7 @@ mod big_tests { let arr = do vec::from_fn(n) |_i| { @rng.gen_float() }; - let arr = vec::to_mut(arr); + let arr = vec::to_mut(move arr); tim_sort(arr); // *sort isSorted(arr, 1); @@ -1236,7 +1214,7 @@ mod big_tests { let arr = if n > 4 { let part = vec::view(arr, 0, 4); multiplyVec(part, n) - } else { arr }; + } else { move arr }; tim_sort(arr); // ~sort isSorted(arr, n/4+1); @@ -1247,7 +1225,7 @@ mod big_tests { let half = n / 2; let mut arr = makeRange(half).map(|i| @(*i as float)); tim_sort(arr); // !sort - isSorted(arr, 2); + isSorted(arr, 1); } } @@ -1294,7 +1272,7 @@ mod big_tests { let mut arr = do vec::from_fn(n) |i| { LVal { val: i, key: key } }; - //tim_sort(arr); + tim_sort(arr); isSorted(arr); } @@ -1305,7 +1283,6 @@ mod big_tests { assert n == dropped; } } -*/ // Local Variables: // mode: rust; From 1380776d36ca269a7c0c7684568e6ae2d395107f Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 21:44:43 -0500 Subject: [PATCH 18/28] Use explicit self --- src/libstd/sort.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 97ae0054cce32..032b2ec312900 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -394,8 +394,8 @@ fn MergeState() -> MergeState { } } -impl &MergeState { - fn binarysort(array: &[mut T], start: uint) { +impl MergeState { + fn binarysort(&self, array: &[mut T], start: uint) { let size = array.len(); let mut start = start; assert start <= size; @@ -434,12 +434,12 @@ impl &MergeState { self.last_bsort = false; } - fn push_run(run_base: uint, run_len: uint) { + fn push_run(&self, run_base: uint, run_len: uint) { let tmp = RunState{base: run_base, len: run_len}; self.runs.push(tmp); } - fn merge_at(n: uint, array: &[mut T]) { + fn merge_at(&self, n: uint, array: &[mut T]) { let mut size = self.runs.len(); assert size >= 2; assert n == size-2 || n == size-3; @@ -483,7 +483,7 @@ impl &MergeState { self.mergePt = 0; } - fn merge_lo(array: &[mut T], base1: uint, len1: uint, + fn merge_lo(&self, array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; @@ -619,7 +619,7 @@ impl &MergeState { unsafe { vec::raw::set_len(&mut self.tmp, 0); } } - fn merge_hi(array: &[mut T], base1: uint, len1: uint, + fn merge_hi(&self, array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; @@ -762,7 +762,7 @@ impl &MergeState { unsafe { vec::raw::set_len(&mut self.tmp, 0); } } - fn merge_collapse(array: &[mut T]) { + fn merge_collapse(&self, array: &[mut T]) { while self.runs.len() > 1 { let mut n = self.runs.len()-2; let chk = do self.runs.borrow |arr| { @@ -780,7 +780,7 @@ impl &MergeState { } } - fn merge_force_collapse(array: &[mut T]) { + fn merge_force_collapse(&self, array: &[mut T]) { while self.runs.len() > 1 { let mut n = self.runs.len()-2; if n > 0 { From 781e446e2675c397d9be8a70f5e3e8c4fae0695c Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 21:49:47 -0500 Subject: [PATCH 19/28] Fix long line --- src/libstd/sort.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 032b2ec312900..c8744f01662c2 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -430,7 +430,8 @@ impl MergeState { array[left] <-> self.tmp[0]; start += 1; } - unsafe { vec::raw::set_len(&mut self.tmp, 0); } // Forget the boxed element + // Forget the boxed element + unsafe { vec::raw::set_len(&mut self.tmp, 0); } self.last_bsort = false; } From 254a86e49edb0fbf38d335a50b1ab535fa7fd757 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 21:53:37 -0500 Subject: [PATCH 20/28] Fix typo --- src/libstd/sort.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index c8744f01662c2..92389ca03e4f5 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -751,7 +751,7 @@ impl MergeState { } array[dest] <-> self.tmp[c2]; } else if len2 == 0 { - fail ~"Coparison violates its contract!"; + fail ~"Comparison violates its contract!"; } else { assert len1 == 0; assert len2 != 0; From e0a9d41b04f16b7771315dcbfcb4e1fa4c347c33 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Mon, 22 Oct 2012 22:04:14 -0500 Subject: [PATCH 21/28] Re-add bad Ord impl test --- src/libstd/sort.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 92389ca03e4f5..a42d6be51fb5c 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1046,6 +1046,25 @@ mod test_tim_sort { tim_sort(arr); fail ~"Guarantee the fail"; } + + struct DVal { val: ~uint } + impl DVal: Ord { + pure fn lt(_x: &DVal) -> bool { true } + pure fn le(_x: &DVal) -> bool { true } + pure fn gt(_x: &DVal) -> bool { true } + pure fn ge(_x: &DVal) -> bool { true } + } + + #[test] + fn test_bad_Ord_impl() { + let rng = rand::Rng(); + let mut arr = do vec::from_fn(500) |_i| { + let randVal = rng.gen_uint(); + DVal { val: ~randVal } + }; + + tim_sort(arr); + } } #[cfg(test)] From fb61f915db842ec06e6531237f5c73112dd1c7a0 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 19:15:11 -0500 Subject: [PATCH 22/28] Add copy bound to sort --- src/libstd/sort.rs | 156 +++++++++++++++------------------------------ 1 file changed, 52 insertions(+), 104 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index a42d6be51fb5c..2408605739307 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -166,7 +166,7 @@ const MIN_MERGE: uint = 64; const MIN_GALLOP: uint = 7; const INITIAL_TMP_STORAGE: uint = 128; -pub fn tim_sort(array: &[mut T]) { +pub fn tim_sort(array: &[mut T]) { let size = array.len(); if size < 2 { return; @@ -210,7 +210,7 @@ pub fn tim_sort(array: &[mut T]) { fn reverse_slice(v: &[mut T], start: uint, end:uint) { let mut i = start; while i < end / 2 { - v[i] <-> v[end - i - 1]; + util::swap(&mut v[i], &mut v[end - i - 1]); i += 1; } } @@ -226,7 +226,7 @@ pure fn min_run_length(n: uint) -> uint { return n + r; } -fn count_run_ascending(array: &[mut T]) -> uint { +fn count_run_ascending(array: &[mut T]) -> uint { let size = array.len(); assert size > 0; if size == 1 { return 1; } @@ -246,7 +246,7 @@ fn count_run_ascending(array: &[mut T]) -> uint { return run; } -pure fn gallop_left(key: &const T, array: &[const T], +pure fn gallop_left(key: &const T, array: &[const T], hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; @@ -295,7 +295,7 @@ pure fn gallop_left(key: &const T, array: &[const T], return ofs; } -pure fn gallop_right(key: &const T, array: &[const T], +pure fn gallop_right(key: &const T, array: &[const T], hint: uint) -> uint { let size = array.len(); assert size != 0 && hint < size; @@ -353,7 +353,7 @@ struct RunState { struct MergeState { mut min_gallop: uint, - mut tmp: ~[T], + //mut tmp: ~[T], mut last_hi: bool, mut last_bsort: bool, mut mergePt: uint, @@ -361,7 +361,7 @@ struct MergeState { mut array: &[mut T], runs: DVec, - drop { + /*drop { unsafe { let size = self.tmp.len(); // Move tmp back into invalid part of array @@ -376,15 +376,15 @@ struct MergeState { } vec::raw::set_len(&mut self.tmp, 0); } - } + }*/ } fn MergeState() -> MergeState { - let mut tmp = ~[]; - vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); + //let mut tmp = ~[]; + //vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { min_gallop: MIN_GALLOP, - tmp: move tmp, + //tmp: move tmp, last_hi: false, last_bsort: false, mergePt: 0, @@ -394,7 +394,7 @@ fn MergeState() -> MergeState { } } -impl MergeState { +impl MergeState { fn binarysort(&self, array: &[mut T], start: uint) { let size = array.len(); let mut start = start; @@ -403,19 +403,16 @@ impl MergeState { if start == 0 { start += 1; } self.last_bsort = true; - unsafe { vec::raw::set_len(&mut self.tmp, 1); }; while start < size { - unsafe { - move_vec(self.tmp, 0, array, start, 1); - } + let pivot = array[start]; let mut left = 0; let mut right = start; assert left <= right; while left < right { let mid = (left + right) >> 1; - if self.tmp[0] < array[mid] { + if pivot < array[mid] { right = mid; } else { left = mid+1; @@ -424,14 +421,10 @@ impl MergeState { assert left == right; let mut n = start-left; - unsafe { - move_vec(array, left+1, array, left, n); - } - array[left] <-> self.tmp[0]; + copy_vec(array, left+1, array, left, n); + array[left] = move pivot; start += 1; } - // Forget the boxed element - unsafe { vec::raw::set_len(&mut self.tmp, 0); } self.last_bsort = false; } @@ -488,13 +481,9 @@ impl MergeState { base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; - vec::reserve(&mut self.tmp, len1); + //vec::reserve(&mut self.tmp, len1); self.last_hi = false; - - unsafe { - vec::raw::set_len(&mut self.tmp, len1); - move_vec(self.tmp, 0, array, base1, len1); - } + let tmp = vec::to_mut(vec::slice(array, base1, base1+len1)); self.tmpPt = 0; self.mergePt = base1; @@ -509,18 +498,12 @@ impl MergeState { self.mergePt += 1; if len2 == 0 { - unsafe { - move_vec(array, dest, self.tmp, 0, len1); - vec::raw::set_len(&mut self.tmp, 0); // Forget the elements - } + copy_vec(array, dest, tmp, 0, len1); return; } if len1 == 1 { - unsafe { - move_vec(array, dest, array, c2, len2); - array[dest+len2] <-> self.tmp[c1]; - vec::raw::set_len(&mut self.tmp, 0); // Forget the element - } + copy_vec(array, dest, array, c2, len2); + array[dest+len2] <-> tmp[c1]; return; } @@ -532,7 +515,7 @@ impl MergeState { loop { assert len1 > 1 && len2 != 0; - if array[c2] < self.tmp[c1] { + if array[c2] < tmp[c1] { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; self.mergePt += 1; @@ -541,7 +524,7 @@ impl MergeState { break_outer = true; } } else { - array[dest] <-> self.tmp[c1]; + array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; self.mergePt += 1; self.tmpPt += 1; @@ -560,13 +543,11 @@ impl MergeState { loop { assert len1 > 1 && len2 != 0; - //let tmp_view = vec::const_view(self.tmp, c1, c1+len1); + //let tmp_view = vec::const_view(tmp, c1, c1+len1); count1 = gallop_right(&const array[c2], - vec::const_view(self.tmp, c1, c1+len1), 0); + vec::const_view(tmp, c1, c1+len1), 0); if count1 != 0 { - unsafe { - move_vec(array, dest, self.tmp, c1, count1); - } + copy_vec(array, dest, tmp, c1, count1); dest += count1; c1 += count1; len1 -= count1; self.mergePt += count1; self.tmpPt += count1; if len1 <= 1 { break_outer = true; break; } @@ -577,16 +558,14 @@ impl MergeState { if len2 == 0 { break_outer = true; break; } let tmp_view = vec::const_view(array, c2, c2+len2); - count2 = gallop_left(&const self.tmp[c1], tmp_view, 0); + count2 = gallop_left(&const tmp[c1], tmp_view, 0); if count2 != 0 { - unsafe { - move_vec(array, dest, array, c2, count2); - } + copy_vec(array, dest, array, c2, count2); dest += count2; c2 += count2; len2 -= count2; self.mergePt += count2; if len2 == 0 { break_outer = true; break; } } - array[dest] <-> self.tmp[c1]; + array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; self.mergePt += 1; self.tmpPt += 1; if len1 == 1 { break_outer = true; break; } @@ -603,34 +582,25 @@ impl MergeState { if len1 == 1 { assert len2 > 0; - unsafe { - move_vec(array, dest, array, c2, len2); - } - array[dest+len2] <-> self.tmp[c1]; + copy_vec(array, dest, array, c2, len2); + array[dest+len2] <-> tmp[c1]; } else if len1 == 0 { fail ~"Comparison violates its contract!"; } else { assert len2 == 0; assert len1 > 1; - unsafe { - move_vec(array, dest, self.tmp, c1, len1); - } + copy_vec(array, dest, tmp, c1, len1); } self.tmpPt = 0; - unsafe { vec::raw::set_len(&mut self.tmp, 0); } } fn merge_hi(&self, array: &[mut T], base1: uint, len1: uint, base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; - vec::reserve(&mut self.tmp, len2); self.last_hi = true; - unsafe { - vec::raw::set_len(&mut self.tmp, len2); - move_vec(self.tmp, 0, array, base2, len2); - } + let tmp = vec::to_mut(vec::slice(array, base2, base2+len2)); let mut c1 = base1 + len1 - 1; let mut c2 = len2 - 1; @@ -645,20 +615,14 @@ impl MergeState { dest -= 1; c1 -= 1; len1 -= 1; if len1 == 0 { - unsafe { - move_vec(array, dest-(len2-1), self.tmp, 0, len2); - vec::raw::set_len(&mut self.tmp, 0); // Forget the elements - } + copy_vec(array, dest-(len2-1), tmp, 0, len2); return; } if len2 == 1 { dest -= len1; c1 -= len1; - unsafe { - move_vec(array, dest+1, array, c1+1, len1); - array[dest] <-> self.tmp[c2]; - vec::raw::set_len(&mut self.tmp, 0); // Forget the element - } + copy_vec(array, dest+1, array, c1+1, len1); + array[dest] <-> tmp[c2]; return; } @@ -670,7 +634,7 @@ impl MergeState { loop { assert len1 != 0 && len2 > 1; - if self.tmp[c2] < array[c1] { + if tmp[c2] < array[c1] { array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; self.mergePt -= 1; @@ -679,7 +643,7 @@ impl MergeState { break_outer = true; } } else { - array[dest] <-> self.tmp[c2]; + array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; self.mergePt -= 1; self.tmpPt -= 1; count2 += 1; count1 = 0; @@ -699,31 +663,27 @@ impl MergeState { let tmp_view = vec::mut_view(array, base1, base1+len1); count1 = len1 - gallop_right( - &const self.tmp[c2], tmp_view, len1-1); + &const tmp[c2], tmp_view, len1-1); if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; self.mergePt -= count1; - unsafe { - move_vec(array, dest+1, array, c1+1, count1); - } + copy_vec(array, dest+1, array, c1+1, count1); if len1 == 0 { break_outer = true; break; } } - array[dest] <-> self.tmp[c2]; + array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; self.mergePt -= 1; self.tmpPt -= 1; if len2 == 1 { break_outer = true; break; } - //let tmp_view = vec::mut_view(self.tmp, 0, len2); + //let tmp_view = vec::mut_view(tmp, 0, len2); let count2 = len2 - gallop_left(&const array[c1], - vec::mut_view(self.tmp, 0, len2), len2-1); + vec::mut_view(tmp, 0, len2), len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; self.mergePt -= count2; self.tmpPt -= count2; - unsafe { - move_vec(array, dest+1, self.tmp, c2+1, count2); - } + copy_vec(array, dest+1, tmp, c2+1, count2); if len2 <= 1 { break_outer = true; break; } } array[dest] <-> array[c1]; @@ -746,21 +706,16 @@ impl MergeState { assert len1 > 0; dest -= len1; c1 -= len1; - unsafe { - move_vec(array, dest+1, array, c1+1, len1); - } - array[dest] <-> self.tmp[c2]; + copy_vec(array, dest+1, array, c1+1, len1); + array[dest] <-> tmp[c2]; } else if len2 == 0 { fail ~"Comparison violates its contract!"; } else { assert len1 == 0; assert len2 != 0; - unsafe { - move_vec(array, dest-(len2-1), self.tmp, 0, len2); - } + copy_vec(array, dest-(len2-1), tmp, 0, len2); } self.tmpPt = 0; - unsafe { vec::raw::set_len(&mut self.tmp, 0); } } fn merge_collapse(&self, array: &[mut T]) { @@ -796,21 +751,14 @@ impl MergeState { } } -// Moves elements to from dest to from -// Unsafe as it makes the from parameter invalid between s2 and s2+len #[inline(always)] -unsafe fn move_vec(dest: &[mut T], s1: uint, +fn copy_vec(dest: &[mut T], s1: uint, from: &[const T], s2: uint, len: uint) { assert s1+len <= dest.len() && s2+len <= from.len(); - - do vec::as_mut_buf(dest) |p, _len| { - let destPtr = ptr::mut_offset(p, s1); - - do vec::as_const_buf(from) |p, _len| { - let fromPtr = ptr::const_offset(p, s2); - - ptr::memmove(destPtr, fromPtr, len); - } + + let slice = vec::slice(from, s2, s2+len); + for slice.eachi |i, v| { + dest[s1+i] = *v; } } From 19a59cb748b6715cd940eb6fa5ae4e1841dcfcf4 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 19:17:24 -0500 Subject: [PATCH 23/28] Fix tests for Copy bound --- src/libstd/sort.rs | 54 ++++++++-------------------------------------- 1 file changed, 9 insertions(+), 45 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 2408605739307..161d7fab81dda 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -1032,11 +1032,6 @@ mod big_tests { tabulate_managed(low, high); } - #[test] - fn test_linear() { - tabulate_linear(); - } - fn multiplyVec(arr: &[const T], num: uint) -> ~[mut T] { let size = arr.len(); let res = do vec::from_fn(num) |i| { @@ -1125,12 +1120,11 @@ mod big_tests { } fn tabulate_managed(lo: uint, hi: uint) { - fn isSorted(arr: &[const @T], expected_refcount: uint) { + fn isSorted(arr: &[const @T]) { for uint::range(0, arr.len()-1) |i| { if arr[i] > arr[i+1] { fail ~"Array not sorted"; } - assert sys::refcount(arr[i]) == expected_refcount; } } @@ -1144,14 +1138,14 @@ mod big_tests { let arr = vec::to_mut(move arr); tim_sort(arr); // *sort - isSorted(arr, 1); + isSorted(arr); vec::reverse(arr); tim_sort(arr); // \sort - isSorted(arr, 1); + isSorted(arr); tim_sort(arr); // /sort - isSorted(arr, 1); + isSorted(arr); for 3.times { let i1 = rng.gen_uint_range(0, n); @@ -1159,7 +1153,7 @@ mod big_tests { arr[i1] <-> arr[i2]; } tim_sort(arr); // 3sort - isSorted(arr, 1); + isSorted(arr); if n >= 10 { let size = arr.len(); @@ -1170,7 +1164,7 @@ mod big_tests { } } tim_sort(arr); // +sort - isSorted(arr, 1); + isSorted(arr); for (n/100).times { let idx = rng.gen_uint_range(0, n); @@ -1184,16 +1178,16 @@ mod big_tests { multiplyVec(part, n) } else { move arr }; tim_sort(arr); // ~sort - isSorted(arr, n/4+1); + isSorted(arr); let mut arr = vec::from_elem(n, @(-0.5)); tim_sort(arr); // =sort - isSorted(arr, n); + isSorted(arr); let half = n / 2; let mut arr = makeRange(half).map(|i| @(*i as float)); tim_sort(arr); // !sort - isSorted(arr, 1); + isSorted(arr); } } @@ -1220,36 +1214,6 @@ mod big_tests { pure fn gt(other: &LVal) -> bool { self.val > other.val } pure fn ge(other: &LVal) -> bool { self.val >= other.val } } - - fn tabulate_linear() { - fn key(_x: @uint) { } - fn isSorted(arr: &[const T]) { - for uint::range(0, arr.len()-1) |i| { - if arr[i] > arr[i+1] { - fail ~"Array not sorted"; - } - } - } - - let n = 1000; - unsafe { - task::local_data::local_data_set(key, @0u); - } - - { - let mut arr = do vec::from_fn(n) |i| { - LVal { val: i, key: key } - }; - tim_sort(arr); - isSorted(arr); - } - - let @dropped = unsafe { - task::local_data::local_data_get(key).get() - }; - - assert n == dropped; - } } // Local Variables: From 046460c7f6ff9d196b0d4c9757bce15cf99e1070 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 19:21:39 -0500 Subject: [PATCH 24/28] Remove some code that MergeState used to prevent double frees --- src/libstd/sort.rs | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 161d7fab81dda..05d8533a3533e 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -353,40 +353,15 @@ struct RunState { struct MergeState { mut min_gallop: uint, - //mut tmp: ~[T], - mut last_hi: bool, - mut last_bsort: bool, mut mergePt: uint, mut tmpPt: uint, mut array: &[mut T], runs: DVec, - - /*drop { - unsafe { - let size = self.tmp.len(); - // Move tmp back into invalid part of array - if self.last_bsort { - - } else if self.last_hi && size > 0 { - self.mergePt -= self.tmpPt; - move_vec(self.array, self.mergePt, self.tmp, 0, self.tmpPt); - } else if !self.last_hi && size-self.tmpPt > 0 { - move_vec(self.array, self.mergePt, - self.tmp, self.tmpPt, size-self.tmpPt); - } - vec::raw::set_len(&mut self.tmp, 0); - } - }*/ } fn MergeState() -> MergeState { - //let mut tmp = ~[]; - //vec::reserve(&mut tmp, INITIAL_TMP_STORAGE); MergeState { min_gallop: MIN_GALLOP, - //tmp: move tmp, - last_hi: false, - last_bsort: false, mergePt: 0, tmpPt: 0, array: &[mut], @@ -402,8 +377,6 @@ impl MergeState { if start == 0 { start += 1; } - self.last_bsort = true; - while start < size { let pivot = array[start]; let mut left = 0; @@ -425,7 +398,6 @@ impl MergeState { array[left] = move pivot; start += 1; } - self.last_bsort = false; } fn push_run(&self, run_base: uint, run_len: uint) { @@ -481,8 +453,6 @@ impl MergeState { base2: uint, len2: uint) { assert len1 != 0 && len2 != 0 && base1+len1 == base2; - //vec::reserve(&mut self.tmp, len1); - self.last_hi = false; let tmp = vec::to_mut(vec::slice(array, base1, base1+len1)); self.tmpPt = 0; self.mergePt = base1; @@ -598,8 +568,6 @@ impl MergeState { base2: uint, len2: uint) { assert len1 != 1 && len2 != 0 && base1 + len1 == base2; - self.last_hi = true; - let tmp = vec::to_mut(vec::slice(array, base2, base2+len2)); let mut c1 = base1 + len1 - 1; @@ -755,7 +723,7 @@ impl MergeState { fn copy_vec(dest: &[mut T], s1: uint, from: &[const T], s2: uint, len: uint) { assert s1+len <= dest.len() && s2+len <= from.len(); - + let slice = vec::slice(from, s2, s2+len); for slice.eachi |i, v| { dest[s1+i] = *v; From 8e6d2099145ee3d6bd349865e712b1a13e70115f Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 20:36:10 -0500 Subject: [PATCH 25/28] Remove and comment out more MergeState code --- src/libstd/sort.rs | 56 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 05d8533a3533e..498959982a9d3 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -353,8 +353,8 @@ struct RunState { struct MergeState { mut min_gallop: uint, - mut mergePt: uint, - mut tmpPt: uint, + //mut mergePt: uint, + //mut tmpPt: uint, mut array: &[mut T], runs: DVec, } @@ -362,8 +362,8 @@ struct MergeState { fn MergeState() -> MergeState { MergeState { min_gallop: MIN_GALLOP, - mergePt: 0, - tmpPt: 0, + //mergePt: 0, + //tmpPt: 0, array: &[mut], runs: DVec(), } @@ -427,13 +427,13 @@ impl MergeState { } let slice = vec::mut_view(array, b1, b1+l1); - self.mergePt = b1; + //self.mergePt = b1; let k = gallop_right(&const array[b2], slice, 0); b1 += k; l1 -= k; if l1 != 0 { let slice = vec::mut_view(array, b2, b2+l2); - self.mergePt = b2; + //self.mergePt = b2; let l2 = gallop_left( &const array[b1+l1-1],slice,l2-1); if l2 > 0 { @@ -446,7 +446,7 @@ impl MergeState { } } self.runs.pop(); - self.mergePt = 0; + //self.mergePt = 0; } fn merge_lo(&self, array: &[mut T], base1: uint, len1: uint, @@ -454,8 +454,8 @@ impl MergeState { assert len1 != 0 && len2 != 0 && base1+len1 == base2; let tmp = vec::to_mut(vec::slice(array, base1, base1+len1)); - self.tmpPt = 0; - self.mergePt = base1; + //self.tmpPt = 0; + //self.mergePt = base1; let mut c1 = 0; let mut c2 = base2; @@ -465,7 +465,7 @@ impl MergeState { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - self.mergePt += 1; + //self.mergePt += 1; if len2 == 0 { copy_vec(array, dest, tmp, 0, len1); @@ -488,7 +488,7 @@ impl MergeState { if array[c2] < tmp[c1] { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - self.mergePt += 1; + //self.mergePt += 1; count2 += 1; count1 = 0; if len2 == 0 { break_outer = true; @@ -496,8 +496,8 @@ impl MergeState { } else { array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; - self.mergePt += 1; - self.tmpPt += 1; + //self.mergePt += 1; + //self.tmpPt += 1; count1 += 1; count2 = 0; if len1 == 1 { break_outer = true; @@ -519,12 +519,12 @@ impl MergeState { if count1 != 0 { copy_vec(array, dest, tmp, c1, count1); dest += count1; c1 += count1; len1 -= count1; - self.mergePt += count1; self.tmpPt += count1; + //self.mergePt += count1; self.tmpPt += count1; if len1 <= 1 { break_outer = true; break; } } array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - self.mergePt += 1; + //self.mergePt += 1; if len2 == 0 { break_outer = true; break; } let tmp_view = vec::const_view(array, c2, c2+len2); @@ -532,12 +532,12 @@ impl MergeState { if count2 != 0 { copy_vec(array, dest, array, c2, count2); dest += count2; c2 += count2; len2 -= count2; - self.mergePt += count2; + //self.mergePt += count2; if len2 == 0 { break_outer = true; break; } } array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; - self.mergePt += 1; self.tmpPt += 1; + //self.mergePt += 1; self.tmpPt += 1; if len1 == 1 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -561,7 +561,7 @@ impl MergeState { assert len1 > 1; copy_vec(array, dest, tmp, c1, len1); } - self.tmpPt = 0; + //self.tmpPt = 0; } fn merge_hi(&self, array: &[mut T], base1: uint, len1: uint, @@ -576,8 +576,8 @@ impl MergeState { let mut len1 = len1; let mut len2 = len2; - self.mergePt = dest; - self.tmpPt = len2 - 1; + //self.mergePt = dest; + //self.tmpPt = len2 - 1; array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; @@ -605,7 +605,7 @@ impl MergeState { if tmp[c2] < array[c1] { array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; - self.mergePt -= 1; + //self.mergePt -= 1; count1 += 1; count2 = 0; if len1 == 0 { break_outer = true; @@ -613,7 +613,7 @@ impl MergeState { } else { array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; - self.mergePt -= 1; self.tmpPt -= 1; + //self.mergePt -= 1; self.tmpPt -= 1; count2 += 1; count1 = 0; if len2 == 1 { break_outer = true; @@ -635,14 +635,14 @@ impl MergeState { if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; - self.mergePt -= count1; + //self.mergePt -= count1; copy_vec(array, dest+1, array, c1+1, count1); if len1 == 0 { break_outer = true; break; } } array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; - self.mergePt -= 1; self.tmpPt -= 1; + //self.mergePt -= 1; self.tmpPt -= 1; if len2 == 1 { break_outer = true; break; } //let tmp_view = vec::mut_view(tmp, 0, len2); @@ -650,13 +650,13 @@ impl MergeState { vec::mut_view(tmp, 0, len2), len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; - self.mergePt -= count2; self.tmpPt -= count2; + //self.mergePt -= count2; self.tmpPt -= count2; copy_vec(array, dest+1, tmp, c2+1, count2); if len2 <= 1 { break_outer = true; break; } } array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; - self.mergePt -= 1; + //self.mergePt -= 1; if len1 == 0 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -683,7 +683,7 @@ impl MergeState { assert len2 != 0; copy_vec(array, dest-(len2-1), tmp, 0, len2); } - self.tmpPt = 0; + //self.tmpPt = 0; } fn merge_collapse(&self, array: &[mut T]) { @@ -1139,7 +1139,7 @@ mod big_tests { arr[idx] = @rng.gen_float(); } tim_sort(arr); - isSorted(arr, 1); + isSorted(arr); let arr = if n > 4 { let part = vec::view(arr, 0, 4); From 98c8a40828d5f86890439eccb9199236ae9e60d9 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 20:38:34 -0500 Subject: [PATCH 26/28] Remove commented out code --- src/libstd/sort.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 498959982a9d3..890e3cf884e31 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -353,8 +353,6 @@ struct RunState { struct MergeState { mut min_gallop: uint, - //mut mergePt: uint, - //mut tmpPt: uint, mut array: &[mut T], runs: DVec, } @@ -362,8 +360,6 @@ struct MergeState { fn MergeState() -> MergeState { MergeState { min_gallop: MIN_GALLOP, - //mergePt: 0, - //tmpPt: 0, array: &[mut], runs: DVec(), } @@ -427,13 +423,11 @@ impl MergeState { } let slice = vec::mut_view(array, b1, b1+l1); - //self.mergePt = b1; let k = gallop_right(&const array[b2], slice, 0); b1 += k; l1 -= k; if l1 != 0 { let slice = vec::mut_view(array, b2, b2+l2); - //self.mergePt = b2; let l2 = gallop_left( &const array[b1+l1-1],slice,l2-1); if l2 > 0 { @@ -446,7 +440,6 @@ impl MergeState { } } self.runs.pop(); - //self.mergePt = 0; } fn merge_lo(&self, array: &[mut T], base1: uint, len1: uint, @@ -454,8 +447,6 @@ impl MergeState { assert len1 != 0 && len2 != 0 && base1+len1 == base2; let tmp = vec::to_mut(vec::slice(array, base1, base1+len1)); - //self.tmpPt = 0; - //self.mergePt = base1; let mut c1 = 0; let mut c2 = base2; @@ -465,7 +456,6 @@ impl MergeState { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - //self.mergePt += 1; if len2 == 0 { copy_vec(array, dest, tmp, 0, len1); @@ -488,7 +478,6 @@ impl MergeState { if array[c2] < tmp[c1] { array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - //self.mergePt += 1; count2 += 1; count1 = 0; if len2 == 0 { break_outer = true; @@ -496,8 +485,6 @@ impl MergeState { } else { array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; - //self.mergePt += 1; - //self.tmpPt += 1; count1 += 1; count2 = 0; if len1 == 1 { break_outer = true; @@ -519,12 +506,10 @@ impl MergeState { if count1 != 0 { copy_vec(array, dest, tmp, c1, count1); dest += count1; c1 += count1; len1 -= count1; - //self.mergePt += count1; self.tmpPt += count1; if len1 <= 1 { break_outer = true; break; } } array[dest] <-> array[c2]; dest += 1; c2 += 1; len2 -= 1; - //self.mergePt += 1; if len2 == 0 { break_outer = true; break; } let tmp_view = vec::const_view(array, c2, c2+len2); @@ -532,12 +517,10 @@ impl MergeState { if count2 != 0 { copy_vec(array, dest, array, c2, count2); dest += count2; c2 += count2; len2 -= count2; - //self.mergePt += count2; if len2 == 0 { break_outer = true; break; } } array[dest] <-> tmp[c1]; dest += 1; c1 += 1; len1 -= 1; - //self.mergePt += 1; self.tmpPt += 1; if len1 == 1 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -561,7 +544,6 @@ impl MergeState { assert len1 > 1; copy_vec(array, dest, tmp, c1, len1); } - //self.tmpPt = 0; } fn merge_hi(&self, array: &[mut T], base1: uint, len1: uint, @@ -576,9 +558,6 @@ impl MergeState { let mut len1 = len1; let mut len2 = len2; - //self.mergePt = dest; - //self.tmpPt = len2 - 1; - array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; @@ -605,7 +584,6 @@ impl MergeState { if tmp[c2] < array[c1] { array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; - //self.mergePt -= 1; count1 += 1; count2 = 0; if len1 == 0 { break_outer = true; @@ -613,7 +591,6 @@ impl MergeState { } else { array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; - //self.mergePt -= 1; self.tmpPt -= 1; count2 += 1; count1 = 0; if len2 == 1 { break_outer = true; @@ -635,14 +612,12 @@ impl MergeState { if count1 != 0 { dest -= count1; c1 -= count1; len1 -= count1; - //self.mergePt -= count1; copy_vec(array, dest+1, array, c1+1, count1); if len1 == 0 { break_outer = true; break; } } array[dest] <-> tmp[c2]; dest -= 1; c2 -= 1; len2 -= 1; - //self.mergePt -= 1; self.tmpPt -= 1; if len2 == 1 { break_outer = true; break; } //let tmp_view = vec::mut_view(tmp, 0, len2); @@ -650,13 +625,11 @@ impl MergeState { vec::mut_view(tmp, 0, len2), len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; - //self.mergePt -= count2; self.tmpPt -= count2; copy_vec(array, dest+1, tmp, c2+1, count2); if len2 <= 1 { break_outer = true; break; } } array[dest] <-> array[c1]; dest -= 1; c1 -= 1; len1 -= 1; - //self.mergePt -= 1; if len1 == 0 { break_outer = true; break; } min_gallop -= 1; if !(count1 >= MIN_GALLOP || count2 >= MIN_GALLOP) { @@ -683,7 +656,6 @@ impl MergeState { assert len2 != 0; copy_vec(array, dest-(len2-1), tmp, 0, len2); } - //self.tmpPt = 0; } fn merge_collapse(&self, array: &[mut T]) { From f2216ec9d069a2fc332750a37c08bab522a41df7 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Wed, 24 Oct 2012 20:42:41 -0500 Subject: [PATCH 27/28] Move binarysort out of MergeState --- src/libstd/sort.rs | 72 +++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 890e3cf884e31..14af2ead61b0f 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -172,16 +172,16 @@ pub fn tim_sort(array: &[mut T]) { return; } - let ms = &MergeState(); - ms.array = array; - let min_run = min_run_length(size); - if size < MIN_MERGE { let init_run_len = count_run_ascending(array); - ms.binarysort(array, init_run_len); + binarysort(array, init_run_len); return; } + let ms = &MergeState(); + ms.array = array; + let min_run = min_run_length(size); + let mut idx = 0; let mut remaining = size; loop { @@ -191,7 +191,7 @@ pub fn tim_sort(array: &[mut T]) { if run_len < min_run { let force = if remaining <= min_run {remaining} else {min_run}; let slice = vec::mut_view(arr, 0, force); - ms.binarysort(slice, run_len); + binarysort(slice, run_len); run_len = force; } @@ -206,6 +206,36 @@ pub fn tim_sort(array: &[mut T]) { ms.merge_force_collapse(array); } +fn binarysort(array: &[mut T], start: uint) { + let size = array.len(); + let mut start = start; + assert start <= size; + + if start == 0 { start += 1; } + + while start < size { + let pivot = array[start]; + let mut left = 0; + let mut right = start; + assert left <= right; + + while left < right { + let mid = (left + right) >> 1; + if pivot < array[mid] { + right = mid; + } else { + left = mid+1; + } + } + assert left == right; + let mut n = start-left; + + copy_vec(array, left+1, array, left, n); + array[left] = move pivot; + start += 1; + } +} + // Reverse the order of elements in a slice, in place fn reverse_slice(v: &[mut T], start: uint, end:uint) { let mut i = start; @@ -366,36 +396,6 @@ fn MergeState() -> MergeState { } impl MergeState { - fn binarysort(&self, array: &[mut T], start: uint) { - let size = array.len(); - let mut start = start; - assert start <= size; - - if start == 0 { start += 1; } - - while start < size { - let pivot = array[start]; - let mut left = 0; - let mut right = start; - assert left <= right; - - while left < right { - let mid = (left + right) >> 1; - if pivot < array[mid] { - right = mid; - } else { - left = mid+1; - } - } - assert left == right; - let mut n = start-left; - - copy_vec(array, left+1, array, left, n); - array[left] = move pivot; - start += 1; - } - } - fn push_run(&self, run_base: uint, run_len: uint) { let tmp = RunState{base: run_base, len: run_len}; self.runs.push(tmp); From d4432a797450594ff78457fe3e516bb0aeaedfe0 Mon Sep 17 00:00:00 2001 From: Simon BD Date: Thu, 25 Oct 2012 11:30:41 -0500 Subject: [PATCH 28/28] Remove some unused MergeState code, add a Fixme and remove a workaround involving pure code not being considered pure --- src/libstd/sort.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/libstd/sort.rs b/src/libstd/sort.rs index 14af2ead61b0f..52ef271fd5606 100644 --- a/src/libstd/sort.rs +++ b/src/libstd/sort.rs @@ -179,7 +179,6 @@ pub fn tim_sort(array: &[mut T]) { } let ms = &MergeState(); - ms.array = array; let min_run = min_run_length(size); let mut idx = 0; @@ -383,14 +382,13 @@ struct RunState { struct MergeState { mut min_gallop: uint, - mut array: &[mut T], runs: DVec, } +// Fixme (#3853) Move into MergeState fn MergeState() -> MergeState { MergeState { min_gallop: MIN_GALLOP, - array: &[mut], runs: DVec(), } } @@ -500,9 +498,8 @@ impl MergeState { loop { assert len1 > 1 && len2 != 0; - //let tmp_view = vec::const_view(tmp, c1, c1+len1); - count1 = gallop_right(&const array[c2], - vec::const_view(tmp, c1, c1+len1), 0); + let tmp_view = vec::const_view(tmp, c1, c1+len1); + count1 = gallop_right(&const array[c2], tmp_view, 0); if count1 != 0 { copy_vec(array, dest, tmp, c1, count1); dest += count1; c1 += count1; len1 -= count1; @@ -620,9 +617,9 @@ impl MergeState { dest -= 1; c2 -= 1; len2 -= 1; if len2 == 1 { break_outer = true; break; } - //let tmp_view = vec::mut_view(tmp, 0, len2); + let tmp_view = vec::mut_view(tmp, 0, len2); let count2 = len2 - gallop_left(&const array[c1], - vec::mut_view(tmp, 0, len2), len2-1); + tmp_view, len2-1); if count2 != 0 { dest -= count2; c2 -= count2; len2 -= count2; copy_vec(array, dest+1, tmp, c2+1, count2);