}
let ms = &MergeState();
+ ms.array = array;
let min_run = min_run_length(size);
let mut idx = 0;
struct MergeState<T> {
mut min_gallop: uint,
mut tmp: ~[T],
+ mut last_hi: bool,
+ mut mergePt: uint,
+ mut tmpPt: uint,
+ mut array: &[mut T],
runs: DVec<RunState>,
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);
}
}
MergeState {
min_gallop: MIN_GALLOP,
tmp: tmp,
+ last_hi: false,
+ mergePt: 0,
+ tmpPt: 0,
+ array: &[mut],
runs: DVec(),
}
}
}
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 {
}
}
self.runs.pop();
+ self.mergePt = 0;
}
fn merge_lo(array: &[mut T], base1: uint, len1: uint,
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;
array[dest] <-> array[c2];
dest += 1; c2 += 1; len2 -= 1;
+ self.mergePt += 1;
if len2 == 0 {
unsafe {
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;
} 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;
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);
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) {
move_vec(array, dest, self.tmp, c1, len1);
}
}
+ self.tmpPt = 0;
unsafe { vec::raw::set_len(self.tmp, 0); }
}
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);
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;
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;
} 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;
if count1 != 0 {
dest -= count1; c1 -= count1; len1 -= count1;
+ self.mergePt -= count1;
unsafe {
move_vec(array, dest+1, array, c1+1, count1);
}
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);
&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);
}
}
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) {
move_vec(array, dest-(len2-1), self.tmp, 0, len2);
}
}
+ self.tmpPt = 0;
unsafe { vec::raw::set_len(self.tmp, 0); }
}
#[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::<int>(v1);
timsort::<int>(v1);
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: