use core::mem::{self, ManuallyDrop, MaybeUninit};
use core::{hint, ptr, slice};
pub fn tim<T: Ord>(arr: &mut [T]) {
let len = arr.len();
if len < 2 || mem::size_of::<T>() == 0 {
return;
}
let mut buf = Buffer::<T>::new(len);
if len < MIN_MERGE * build_factor::<T>() {
let run = find_run(arr);
build_run(arr, run, &mut buf);
return;
}
let min_run = min_run_length(len);
let build_len = min_run * build_factor::<T>();
let scale = power_scale(len);
let mut min_gallop = MIN_GALLOP;
let mut runs = RunStack::new();
let mut start = 0;
while start < len {
let mut run = find_run(&mut arr[start..]);
if run < min_run {
let end = len.min(start + build_len);
build_run(&mut arr[start..end], run, &mut buf);
run = end - start;
}
let power = match runs.top(0) {
Some(top) => node_power(scale, top.start, start, start + run),
None => 0,
};
while runs.len > 1 && runs.top(0).is_some_and(|top| top.power >= power) {
merge_top(arr, &mut runs, &mut buf, &mut min_gallop);
}
runs.push(Run {
start,
len: run,
power,
});
start += run;
}
while runs.len > 1 {
merge_top(arr, &mut runs, &mut buf, &mut min_gallop);
}
}
const MIN_MERGE: usize = 32;
const fn build_factor<T>() -> usize {
if mem::size_of::<T>() <= SMALL_SORT_MAX_SIZE {
2
} else {
1
}
}
pub(super) const MIN_GALLOP: usize = 7;
const LOPSIDED: usize = 4;
const STACK_BYTES: usize = 4096;
const MAX_RUNS: usize = 65;
#[derive(Clone, Copy)]
struct Run {
start: usize,
len: usize,
power: u32,
}
struct RunStack {
runs: [MaybeUninit<Run>; MAX_RUNS],
len: usize,
}
impl RunStack {
fn new() -> Self {
Self {
runs: [MaybeUninit::uninit(); MAX_RUNS],
len: 0,
}
}
fn top(&self, depth: usize) -> Option<Run> {
let i = self.len.checked_sub(depth + 1)?;
Some(unsafe { self.runs[i].assume_init() })
}
fn push(&mut self, run: Run) {
self.runs[self.len].write(run);
self.len += 1;
}
}
#[repr(C)]
struct StackBuffer<T> {
_align: [T; 0],
bytes: [MaybeUninit<u8>; STACK_BYTES],
}
pub(super) struct Buffer<T> {
stack: StackBuffer<T>,
heap: Vec<T>,
len: usize,
}
impl<T> Buffer<T> {
pub(super) fn new(len: usize) -> Self {
Self {
stack: StackBuffer {
_align: [],
bytes: [MaybeUninit::uninit(); STACK_BYTES],
},
heap: Vec::new(),
len,
}
}
fn on_stack(&mut self) -> *mut T {
self.stack.bytes.as_mut_ptr().cast::<T>()
}
pub(super) fn get(&mut self) -> *mut T {
if self.len <= STACK_BYTES / mem::size_of::<T>() {
return self.on_stack();
}
if self.heap.capacity() == 0 {
self.heap = Vec::with_capacity(self.len);
}
self.heap.as_mut_ptr()
}
}
fn min_run_length(mut n: usize) -> usize {
let mut rest = 0;
while n >= MIN_MERGE {
rest |= n & 1;
n >>= 1;
}
n + rest
}
pub(super) fn power_scale(len: usize) -> u64 {
(1u64 << 62).div_ceil(len as u64)
}
pub(super) fn node_power(scale: u64, start: usize, mid: usize, end: usize) -> u32 {
let left = (start + mid) as u64 * scale;
let right = (mid + end) as u64 * scale;
(left ^ right).leading_zeros()
}
fn merge_top<T: Ord>(
arr: &mut [T],
runs: &mut RunStack,
buf: &mut Buffer<T>,
min_gallop: &mut usize,
) {
let (Some(left), Some(right)) = (runs.top(1), runs.top(0)) else {
return;
};
let v = &mut arr[left.start..right.start + right.len];
merge(v, left.len, buf, min_gallop);
runs.len -= 1;
runs.runs[runs.len - 1].write(Run {
len: left.len + right.len,
..left
});
}
fn find_run<T: Ord>(v: &mut [T]) -> usize {
let len = v.len();
if len < 2 {
return len;
}
let mut end = 2;
if v[1] < v[0] {
while end < len && v[end] < v[end - 1] {
end += 1;
}
v[..end].reverse();
} else {
while end < len && v[end] >= v[end - 1] {
end += 1;
}
}
end
}
pub(super) fn build_run<T: Ord>(v: &mut [T], sorted: usize, buf: &mut Buffer<T>) {
if mem::size_of::<T>() <= SMALL_SORT_MAX_SIZE
&& (sorted < SMALL_SORT_RUN || (sorted + 2 < v.len() && v[sorted + 2] < v[sorted - 2]))
{
super::merge::sort(v, buf.on_stack());
} else {
extend_run(v, sorted);
}
}
const SMALL_SORT_MAX_SIZE: usize = 8;
const SMALL_SORT_RUN: usize = 4;
pub(super) fn extend_run<T: Ord>(v: &mut [T], sorted: usize) {
let len = v.len();
let mut i = sorted.max(1);
while i + 1 < len {
insert_pair(&mut v[..i + 2]);
i += 2;
}
if i < len {
insert_last(v);
}
}
fn insert_pair<T: Ord>(v: &mut [T]) {
let i = v.len() - 2;
let swapped = v[i + 1] < v[i];
let (s, l) = if swapped { (i + 1, i) } else { (i, i + 1) };
if v[s] >= v[i - 1] {
if swapped {
v.swap(i, i + 1);
}
return;
}
let base = v.as_mut_ptr();
unsafe {
let large = ManuallyDrop::new(ptr::read(base.add(l)));
let small = ManuallyDrop::new(ptr::read(base.add(s)));
let mut hole = PairHole {
small: &*small,
large: &*large,
slot: base.add(i),
large_out: true,
};
let mut j = i;
while j > 0 && *large < *base.add(j - 1) {
ptr::copy_nonoverlapping(base.add(j - 1), base.add(j + 1), 1);
j -= 1;
hole.slot = base.add(j);
}
ptr::copy_nonoverlapping(&*large, base.add(j + 1), 1);
hole.large_out = false;
if j == i {
ptr::copy_nonoverlapping(base.add(i - 1), base.add(i), 1);
j -= 1;
hole.slot = base.add(j);
}
while j > 0 && *small < *base.add(j - 1) {
ptr::copy_nonoverlapping(base.add(j - 1), base.add(j), 1);
j -= 1;
hole.slot = base.add(j);
}
}
}
fn insert_last<T: Ord>(v: &mut [T]) {
let i = v.len() - 1;
if i == 0 || v[i] >= v[i - 1] {
return;
}
let base = v.as_mut_ptr();
unsafe {
let last = ManuallyDrop::new(ptr::read(base.add(i)));
let mut hole = PairHole {
small: &*last,
large: &*last,
slot: base.add(i - 1),
large_out: false,
};
ptr::copy_nonoverlapping(base.add(i - 1), base.add(i), 1);
let mut j = i - 1;
while j > 0 && *last < *base.add(j - 1) {
ptr::copy_nonoverlapping(base.add(j - 1), base.add(j), 1);
j -= 1;
hole.slot = base.add(j);
}
}
}
struct PairHole<T> {
small: *const T,
large: *const T,
slot: *mut T,
large_out: bool,
}
impl<T> Drop for PairHole<T> {
fn drop(&mut self) {
unsafe {
ptr::copy_nonoverlapping(self.small, self.slot, 1);
if self.large_out {
ptr::copy_nonoverlapping(self.large, self.slot.add(1), 1);
}
}
}
}
#[inline]
fn gallop_from_start<T>(v: &[T], before: impl Fn(&T) -> bool) -> usize {
let n = v.len();
let (mut lo, mut hi) = (0, n);
let mut probe = 0;
while probe < n {
if before(&v[probe]) {
lo = probe + 1;
probe = 2 * probe + 1;
} else {
hi = probe;
break;
}
}
binary_search(v, before, lo, hi)
}
#[inline]
fn gallop_from_end<T>(v: &[T], before: impl Fn(&T) -> bool) -> usize {
let n = v.len();
let (mut lo, mut hi) = (0, n);
let mut step = 1;
while step <= n {
let probe = n - step;
if before(&v[probe]) {
lo = probe + 1;
break;
}
hi = probe;
step *= 2;
}
binary_search(v, before, lo, hi)
}
#[inline]
fn binary_search<T>(v: &[T], before: impl Fn(&T) -> bool, mut lo: usize, mut hi: usize) -> usize {
while lo < hi {
let mid = lo + (hi - lo) / 2;
if before(&v[mid]) {
lo = mid + 1;
} else {
hi = mid;
}
}
lo
}
const SELECT_ADVANCE_MAX_SIZE: usize = 8;
const BATCH_MAX_SIZE: usize = 8;
#[inline(always)]
unsafe fn advance<T>(p: *const T, cond: bool) -> *const T {
unsafe {
if mem::size_of::<T>() <= SELECT_ADVANCE_MAX_SIZE {
hint::select_unpredictable(cond, p.add(1), p)
} else {
p.add(usize::from(cond))
}
}
}
#[inline(always)]
unsafe fn retreat<T>(p: *const T, cond: bool) -> *const T {
unsafe {
if mem::size_of::<T>() <= SELECT_ADVANCE_MAX_SIZE {
hint::select_unpredictable(cond, p.sub(1), p)
} else {
p.sub(usize::from(cond))
}
}
}
pub(super) fn merge<T: Ord>(v: &mut [T], mid: usize, buf: &mut Buffer<T>, min_gallop: &mut usize) {
let first = &v[mid];
let skip = gallop_from_start(&v[..mid], |x| x <= first);
if skip == mid {
return;
}
let v = &mut v[skip..];
let mid = mid - skip;
let last = &v[mid - 1];
let keep = gallop_from_end(&v[mid..], |x| x < last);
if keep == 0 {
return;
}
let v = &mut v[..mid + keep];
let buf = buf.get();
unsafe {
if mid.min(keep) * LOPSIDED < mid.max(keep) {
if mid <= keep {
merge_low(v, mid, buf, min_gallop);
} else {
merge_high(v, mid, buf, min_gallop);
}
} else {
merge_through_buffer(v, mid, buf, min_gallop);
}
}
}
unsafe fn merge_through_buffer<T: Ord>(
v: &mut [T],
mid: usize,
buf: *mut T,
min_gallop: &mut usize,
) {
let len = v.len();
let dst = v.as_mut_ptr();
unsafe {
ptr::copy_nonoverlapping(dst, buf, len);
let restore = Restore { src: buf, dst, len };
let a = buf.cast_const();
let mut m = Merge {
a,
a_end: a.add(mid),
b: a.add(mid),
b_end: a.add(len),
out: dst,
out_end: dst.add(len),
};
ptr::copy_nonoverlapping(m.b, m.out, 1);
m.b = m.b.add(1);
m.out = m.out.add(1);
m.a_end = m.a_end.sub(1);
m.out_end = m.out_end.sub(1);
ptr::copy_nonoverlapping(m.a_end, m.out_end, 1);
let mut gallop = *min_gallop;
if gallop > MIN_GALLOP && m.rest_a() >= FOUR_CHAIN_MIN && m.rest_b() >= FOUR_CHAIN_MIN {
let (mut lower, mut upper) = m.split();
loop {
let n = lower.safe().min(upper.safe());
if n == 0 {
break;
}
let n = n.min(gallop);
let (mut lower_b, mut lower_a, mut upper_b, mut upper_a) = (0usize, 0, 0, 0);
for _ in 0..n {
let (take_b, take_a) = lower.step();
lower_b += usize::from(take_b);
lower_a += usize::from(take_a);
let (take_b, take_a) = upper.step();
upper_b += usize::from(take_b);
upper_a += usize::from(take_a);
}
if n == gallop
&& (streak(lower_b, n)
|| streak(lower_a, n)
|| streak(upper_b, n)
|| streak(upper_a, n))
{
break;
}
}
for half in [lower, upper] {
half.finish(&mut gallop);
}
} else {
m.finish(&mut gallop);
}
*min_gallop = gallop;
mem::forget(restore);
}
}
#[inline(always)]
fn streak(count: usize, n: usize) -> bool {
count == 0 || count == n
}
const FOUR_CHAIN_MIN: usize = 32;
struct Merge<T> {
a: *const T,
a_end: *const T,
b: *const T,
b_end: *const T,
out: *mut T,
out_end: *mut T,
}
impl<T: Ord> Merge<T> {
#[inline(always)]
unsafe fn rest_a(&self) -> usize {
unsafe { self.a_end.offset_from_unsigned(self.a) }
}
#[inline(always)]
unsafe fn rest_b(&self) -> usize {
unsafe { self.b_end.offset_from_unsigned(self.b) }
}
#[inline(always)]
unsafe fn safe(&self) -> usize {
unsafe { self.rest_a().min(self.rest_b()) / 2 }
}
#[inline(always)]
unsafe fn step(&mut self) -> (bool, bool) {
unsafe {
let take_b = *self.b < *self.a;
let src = hint::select_unpredictable(take_b, self.b, self.a);
ptr::copy_nonoverlapping(src, self.out, 1);
self.out = self.out.add(1);
self.b = advance(self.b, take_b);
self.a = advance(self.a, !take_b);
let (last_a, last_b) = (self.a_end.sub(1), self.b_end.sub(1));
let take_a = *last_b < *last_a;
self.out_end = self.out_end.sub(1);
let src = hint::select_unpredictable(take_a, last_a, last_b);
ptr::copy_nonoverlapping(src, self.out_end, 1);
self.a_end = retreat(self.a_end, take_a);
self.b_end = retreat(self.b_end, !take_a);
(take_b, take_a)
}
}
unsafe fn split(self) -> (Self, Self) {
unsafe {
let (rest_a, rest_b) = (self.rest_a(), self.rest_b());
let k = (rest_a + rest_b) / 2;
let (mut lo, mut hi) = (k.saturating_sub(rest_b), k.min(rest_a));
while lo < hi {
let m = lo + (hi - lo) / 2;
if *self.b.add(k - m - 1) >= *self.a.add(m) {
lo = m + 1;
} else {
hi = m;
}
}
let (i, j) = (lo, k - lo);
let lower = Merge {
a: self.a,
a_end: self.a.add(i),
b: self.b,
b_end: self.b.add(j),
out: self.out,
out_end: self.out.add(k),
};
let upper = Merge {
a: self.a.add(i),
a_end: self.a_end,
b: self.b.add(j),
b_end: self.b_end,
out: self.out.add(k),
out_end: self.out_end,
};
(lower, upper)
}
}
#[inline(never)]
unsafe fn finish(self, min_gallop: &mut usize) {
let mut m = self;
unsafe {
let mut gallop = *min_gallop;
'merge: loop {
let (mut front_a, mut front_b, mut back_a, mut back_b) = (0usize, 0, 0, 0);
loop {
if mem::size_of::<T>() <= BATCH_MAX_SIZE {
let safe = m.safe();
if safe == 0 {
break 'merge;
}
let batch_end = m.out.add(safe);
loop {
let (take_b, take_a) = m.step();
front_b = (front_b + 1) * usize::from(take_b);
front_a = (front_a + 1) * usize::from(!take_b);
back_a = (back_a + 1) * usize::from(take_a);
back_b = (back_b + 1) * usize::from(!take_a);
if (front_a | front_b | back_a | back_b) >= gallop || m.out == batch_end
{
break;
}
}
} else {
if m.rest_a() < 2 || m.rest_b() < 2 {
break 'merge;
}
let (take_b, take_a) = m.step();
front_b = (front_b + 1) * usize::from(take_b);
front_a = (front_a + 1) * usize::from(!take_b);
back_a = (back_a + 1) * usize::from(take_a);
back_b = (back_b + 1) * usize::from(!take_a);
}
if (front_a | front_b | back_a | back_b) < gallop {
continue;
}
if m.a == m.a_end || m.b == m.b_end {
break 'merge;
}
if (front_a | front_b) >= gallop {
break;
}
loop {
gallop -= usize::from(gallop > 1);
let last_b = m.b_end.sub(1);
let rest = slice::from_raw_parts(m.a, m.a_end.offset_from_unsigned(m.a));
let count_a = rest.len() - gallop_from_end(rest, |x| x <= &*last_b);
m.a_end = m.a_end.sub(count_a);
m.out_end = m.out_end.sub(count_a);
ptr::copy_nonoverlapping(m.a_end, m.out_end, count_a);
if m.a == m.a_end {
break 'merge;
}
m.b_end = m.b_end.sub(1);
m.out_end = m.out_end.sub(1);
ptr::copy_nonoverlapping(m.b_end, m.out_end, 1);
if m.b == m.b_end {
break 'merge;
}
let last_a = m.a_end.sub(1);
let rest = slice::from_raw_parts(m.b, m.b_end.offset_from_unsigned(m.b));
let count_b = rest.len() - gallop_from_end(rest, |x| x < &*last_a);
m.b_end = m.b_end.sub(count_b);
m.out_end = m.out_end.sub(count_b);
ptr::copy_nonoverlapping(m.b_end, m.out_end, count_b);
if m.b == m.b_end {
break 'merge;
}
m.a_end = m.a_end.sub(1);
m.out_end = m.out_end.sub(1);
ptr::copy_nonoverlapping(m.a_end, m.out_end, 1);
if m.a == m.a_end {
break 'merge;
}
if count_a < MIN_GALLOP && count_b < MIN_GALLOP {
break;
}
}
gallop += 2;
continue 'merge;
}
loop {
gallop -= usize::from(gallop > 1);
let first_b = m.b;
let rest = slice::from_raw_parts(m.a, m.a_end.offset_from_unsigned(m.a));
let count_a = gallop_from_start(rest, |x| x <= &*first_b);
ptr::copy_nonoverlapping(m.a, m.out, count_a);
m.a = m.a.add(count_a);
m.out = m.out.add(count_a);
if m.a == m.a_end {
break 'merge;
}
ptr::copy_nonoverlapping(m.b, m.out, 1);
m.b = m.b.add(1);
m.out = m.out.add(1);
if m.b == m.b_end {
break 'merge;
}
let first_a = m.a;
let rest = slice::from_raw_parts(m.b, m.b_end.offset_from_unsigned(m.b));
let count_b = gallop_from_start(rest, |x| x < &*first_a);
ptr::copy_nonoverlapping(m.b, m.out, count_b);
m.b = m.b.add(count_b);
m.out = m.out.add(count_b);
if m.b == m.b_end {
break 'merge;
}
ptr::copy_nonoverlapping(m.a, m.out, 1);
m.a = m.a.add(1);
m.out = m.out.add(1);
if m.a == m.a_end {
break 'merge;
}
if count_a < MIN_GALLOP && count_b < MIN_GALLOP {
break;
}
}
gallop += 2;
}
*min_gallop = gallop;
let rest_a = m.a_end.offset_from_unsigned(m.a);
let rest_b = m.b_end.offset_from_unsigned(m.b);
if rest_a == 1 && rest_b > 0 {
let rest = slice::from_raw_parts(m.b, rest_b);
let k = binary_search(rest, |x| x < &*m.a, 0, rest_b);
ptr::copy_nonoverlapping(m.b, m.out, k);
ptr::copy_nonoverlapping(m.a, m.out.add(k), 1);
ptr::copy_nonoverlapping(m.b.add(k), m.out.add(k + 1), rest_b - k);
} else if rest_b == 1 && rest_a > 0 {
let rest = slice::from_raw_parts(m.a, rest_a);
let k = binary_search(rest, |x| x <= &*m.b, 0, rest_a);
ptr::copy_nonoverlapping(m.a, m.out, k);
ptr::copy_nonoverlapping(m.b, m.out.add(k), 1);
ptr::copy_nonoverlapping(m.a.add(k), m.out.add(k + 1), rest_a - k);
} else {
ptr::copy_nonoverlapping(m.a, m.out, rest_a);
ptr::copy_nonoverlapping(m.b, m.out.add(rest_a), rest_b);
}
}
}
}
unsafe fn merge_low<T: Ord>(v: &mut [T], mid: usize, buf: *mut T, min_gallop: &mut usize) {
let len = v.len();
let base = v.as_mut_ptr();
unsafe {
ptr::copy_nonoverlapping(base, buf, mid);
let mut gap = Gap {
src: buf,
end: buf.add(mid),
dst: base,
};
let mut b = base.add(mid).cast_const();
let b_end = base.add(len).cast_const();
ptr::copy_nonoverlapping(b, gap.dst, 1);
b = b.add(1);
gap.dst = gap.dst.add(1);
if b == b_end {
return;
}
let mut gallop = *min_gallop;
'merge: loop {
let (mut wins_a, mut wins_b) = (0usize, 0);
loop {
let take_b = *b < *gap.src;
let src = hint::select_unpredictable(take_b, b, gap.src.cast_const());
ptr::copy_nonoverlapping(src, gap.dst, 1);
gap.dst = gap.dst.add(1);
b = advance(b, take_b);
gap.src = advance(gap.src, !take_b).cast_mut();
wins_b = (wins_b + 1) * usize::from(take_b);
wins_a = (wins_a + 1) * usize::from(!take_b);
if gap.src == gap.end || b == b_end {
break 'merge;
}
if (wins_a | wins_b) >= gallop {
break;
}
}
loop {
gallop -= usize::from(gallop > 1);
let rest = slice::from_raw_parts(gap.src, gap.end.offset_from_unsigned(gap.src));
let count_a = gallop_from_start(rest, |x| x <= &*b);
ptr::copy_nonoverlapping(gap.src, gap.dst, count_a);
gap.src = gap.src.add(count_a);
gap.dst = gap.dst.add(count_a);
if gap.src == gap.end {
break 'merge;
}
ptr::copy_nonoverlapping(b, gap.dst, 1);
b = b.add(1);
gap.dst = gap.dst.add(1);
if b == b_end {
break 'merge;
}
let first_a = gap.src;
let rest = slice::from_raw_parts(b, b_end.offset_from_unsigned(b));
let count_b = gallop_from_start(rest, |x| x < &*first_a);
ptr::copy(b, gap.dst, count_b);
b = b.add(count_b);
gap.dst = gap.dst.add(count_b);
if b == b_end {
break 'merge;
}
ptr::copy_nonoverlapping(gap.src, gap.dst, 1);
gap.src = gap.src.add(1);
gap.dst = gap.dst.add(1);
if gap.src == gap.end {
break 'merge;
}
if count_a < MIN_GALLOP && count_b < MIN_GALLOP {
break;
}
}
gallop += 2;
}
*min_gallop = gallop;
}
}
unsafe fn merge_high<T: Ord>(v: &mut [T], mid: usize, buf: *mut T, min_gallop: &mut usize) {
let len = v.len();
let base = v.as_mut_ptr();
unsafe {
ptr::copy_nonoverlapping(base.add(mid), buf, len - mid);
let mut gap = Gap {
src: buf,
end: buf.add(len - mid),
dst: base.add(mid),
};
let mut out = base.add(len);
gap.dst = gap.dst.sub(1);
out = out.sub(1);
ptr::copy_nonoverlapping(gap.dst, out, 1);
if gap.dst == base {
return;
}
let mut gallop = *min_gallop;
'merge: loop {
let (mut wins_a, mut wins_b) = (0usize, 0);
loop {
let (last_a, last_b) = (gap.dst.sub(1), gap.end.sub(1));
let take_a = *last_b < *last_a;
let src = hint::select_unpredictable(take_a, last_a, last_b);
out = out.sub(1);
ptr::copy_nonoverlapping(src, out, 1);
gap.dst = retreat(gap.dst, take_a).cast_mut();
gap.end = retreat(gap.end, !take_a).cast_mut();
wins_a = (wins_a + 1) * usize::from(take_a);
wins_b = (wins_b + 1) * usize::from(!take_a);
if gap.src == gap.end || gap.dst == base {
break 'merge;
}
if (wins_a | wins_b) >= gallop {
break;
}
}
loop {
gallop -= usize::from(gallop > 1);
let last_b = gap.end.sub(1);
let rest = slice::from_raw_parts(base, gap.dst.offset_from_unsigned(base));
let count_a = rest.len() - gallop_from_end(rest, |x| x <= &*last_b);
gap.dst = gap.dst.sub(count_a);
out = out.sub(count_a);
ptr::copy(gap.dst, out, count_a);
if gap.dst == base {
break 'merge;
}
gap.end = gap.end.sub(1);
out = out.sub(1);
ptr::copy_nonoverlapping(gap.end, out, 1);
if gap.src == gap.end {
break 'merge;
}
let last_a = gap.dst.sub(1);
let rest = slice::from_raw_parts(gap.src, gap.end.offset_from_unsigned(gap.src));
let count_b = rest.len() - gallop_from_end(rest, |x| x < &*last_a);
gap.end = gap.end.sub(count_b);
out = out.sub(count_b);
ptr::copy_nonoverlapping(gap.end, out, count_b);
if gap.src == gap.end {
break 'merge;
}
gap.dst = gap.dst.sub(1);
out = out.sub(1);
ptr::copy_nonoverlapping(gap.dst, out, 1);
if gap.dst == base {
break 'merge;
}
if count_a < MIN_GALLOP && count_b < MIN_GALLOP {
break;
}
}
gallop += 2;
}
*min_gallop = gallop;
}
}
struct Gap<T> {
src: *mut T,
end: *mut T,
dst: *mut T,
}
impl<T> Drop for Gap<T> {
fn drop(&mut self) {
unsafe {
let len = self.end.offset_from_unsigned(self.src);
ptr::copy_nonoverlapping(self.src, self.dst, len);
}
}
}
struct Restore<T> {
src: *const T,
dst: *mut T,
len: usize,
}
impl<T> Drop for Restore<T> {
fn drop(&mut self) {
unsafe { ptr::copy_nonoverlapping(self.src, self.dst, self.len) }
}
}