use super::Scratch;
use super::scout::ScoutResult;
use crate::view::{AllocError, Arr, copy_forward, reverse_range};
pub fn merge_with_buffer<V: Arr>(a: V, buf: V, lo: usize, mid: usize, hi: usize) {
let (len1, len2) = (mid - lo, hi - mid);
if len1 == 0 || len2 == 0 {
return;
}
if len1 <= len2 {
copy_forward(a, lo, buf, 0, len1);
let (mut i, mut j, mut o) = (0usize, mid, lo);
let (mut x, mut y) = (buf.get(0), a.get(j));
loop {
if a.less(y, x) {
a.set(o, y);
o += 1;
j += 1;
if j == hi {
break;
}
y = a.get(j);
} else {
a.set(o, x);
o += 1;
i += 1;
if i == len1 {
break;
}
x = buf.get(i);
}
}
while i < len1 {
a.set(o, buf.get(i));
o += 1;
i += 1;
}
} else {
copy_forward(a, mid, buf, 0, len2);
let (mut i, mut j, mut o) = (mid, len2, hi);
let (mut x, mut y) = (a.get(i - 1), buf.get(j - 1));
loop {
if a.less(y, x) {
o -= 1;
a.set(o, x);
i -= 1;
if i == lo {
break;
}
x = a.get(i - 1);
} else {
o -= 1;
a.set(o, y);
j -= 1;
if j == 0 {
break;
}
y = buf.get(j - 1);
}
}
while j > 0 {
o -= 1;
j -= 1;
a.set(o, buf.get(j));
}
}
}
pub fn sort_few_runs<V: Arr>(a: V, scratch: &mut Scratch<V>, n: usize, s: &ScoutResult) -> Result<(), AllocError> {
let buf = scratch.ensure(a, n / 2 + 1)?;
let bounds = &s.bound;
let runs = s.runs;
for j in 0..runs {
if s.dir[j] < 0 {
reverse_range(a, bounds[j], bounds[j + 1]);
}
}
if runs >= 2 {
merge_with_buffer(a, buf, bounds[0], bounds[1], bounds[2]);
}
if runs == 3 {
merge_with_buffer(a, buf, bounds[0], bounds[2], bounds[3]);
}
if runs == 4 {
merge_with_buffer(a, buf, bounds[2], bounds[3], bounds[4]);
merge_with_buffer(a, buf, bounds[0], bounds[2], bounds[4]);
}
Ok(())
}