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 {
let run = find_run(arr);
build_run(arr, run, &mut buf);
return;
}
let min_run = min_run_length(len);
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 + min_run);
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 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],
}
struct Buffer<T> {
stack: StackBuffer<T>,
heap: Vec<T>,
len: usize,
}
impl<T> Buffer<T> {
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>()
}
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
}
fn power_scale(len: usize) -> u64 {
(1u64 << 62).div_ceil(len as u64)
}
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
}
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 {
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;
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
}
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 mut a = buf.cast_const();
let mut a_end = a.add(mid);
let mut b = a_end;
let mut b_end = a.add(len);
let mut out = dst;
let mut out_end = dst.add(len);
ptr::copy_nonoverlapping(b, out, 1);
b = b.add(1);
out = out.add(1);
a_end = a_end.sub(1);
out_end = out_end.sub(1);
ptr::copy_nonoverlapping(a_end, out_end, 1);
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 a_end.offset_from_unsigned(a) < 2 || b_end.offset_from_unsigned(b) < 2 {
break 'merge;
}
let take_b = *b < *a;
ptr::copy_nonoverlapping(hint::select_unpredictable(take_b, b, a), out, 1);
out = out.add(1);
b = b.add(usize::from(take_b));
a = a.add(usize::from(!take_b));
let (last_a, last_b) = (a_end.sub(1), b_end.sub(1));
let take_a = *last_b < *last_a;
out_end = out_end.sub(1);
let src = hint::select_unpredictable(take_a, last_a, last_b);
ptr::copy_nonoverlapping(src, out_end, 1);
a_end = a_end.sub(usize::from(take_a));
b_end = b_end.sub(usize::from(!take_a));
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);
let galloping = (front_a | front_b | back_a | back_b) >= gallop;
if galloping && (a == a_end || b == b_end) {
break 'merge;
}
if (front_a | front_b) >= gallop {
break;
}
if (back_a | back_b) >= gallop {
loop {
gallop -= usize::from(gallop > 1);
let last_b = b_end.sub(1);
let rest = slice::from_raw_parts(a, a_end.offset_from_unsigned(a));
let count_a = rest.len() - gallop_from_end(rest, |x| x <= &*last_b);
a_end = a_end.sub(count_a);
out_end = out_end.sub(count_a);
ptr::copy_nonoverlapping(a_end, out_end, count_a);
if a == a_end {
break 'merge;
}
b_end = b_end.sub(1);
out_end = out_end.sub(1);
ptr::copy_nonoverlapping(b_end, out_end, 1);
if b == b_end {
break 'merge;
}
let last_a = a_end.sub(1);
let rest = slice::from_raw_parts(b, b_end.offset_from_unsigned(b));
let count_b = rest.len() - gallop_from_end(rest, |x| x < &*last_a);
b_end = b_end.sub(count_b);
out_end = out_end.sub(count_b);
ptr::copy_nonoverlapping(b_end, out_end, count_b);
if b == b_end {
break 'merge;
}
a_end = a_end.sub(1);
out_end = out_end.sub(1);
ptr::copy_nonoverlapping(a_end, out_end, 1);
if a == 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 = b;
let rest = slice::from_raw_parts(a, a_end.offset_from_unsigned(a));
let count_a = gallop_from_start(rest, |x| x <= &*first_b);
ptr::copy_nonoverlapping(a, out, count_a);
a = a.add(count_a);
out = out.add(count_a);
if a == a_end {
break 'merge;
}
ptr::copy_nonoverlapping(b, out, 1);
b = b.add(1);
out = out.add(1);
if b == b_end {
break 'merge;
}
let first_a = a;
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_nonoverlapping(b, out, count_b);
b = b.add(count_b);
out = out.add(count_b);
if b == b_end {
break 'merge;
}
ptr::copy_nonoverlapping(a, out, 1);
a = a.add(1);
out = out.add(1);
if a == a_end {
break 'merge;
}
if count_a < MIN_GALLOP && count_b < MIN_GALLOP {
break;
}
}
gallop += 2;
}
*min_gallop = gallop;
let rest_a = a_end.offset_from_unsigned(a);
let rest_b = b_end.offset_from_unsigned(b);
if rest_a == 1 && rest_b > 0 {
let rest = slice::from_raw_parts(b, rest_b);
let k = binary_search(rest, |x| x < &*a, 0, rest_b);
ptr::copy_nonoverlapping(b, out, k);
ptr::copy_nonoverlapping(a, out.add(k), 1);
ptr::copy_nonoverlapping(b.add(k), out.add(k + 1), rest_b - k);
} else if rest_b == 1 && rest_a > 0 {
let rest = slice::from_raw_parts(a, rest_a);
let k = binary_search(rest, |x| x <= &*b, 0, rest_a);
ptr::copy_nonoverlapping(a, out, k);
ptr::copy_nonoverlapping(b, out.add(k), 1);
ptr::copy_nonoverlapping(a.add(k), out.add(k + 1), rest_a - k);
} else {
ptr::copy_nonoverlapping(a, out, rest_a);
ptr::copy_nonoverlapping(b, out.add(rest_a), rest_b);
}
mem::forget(restore);
}
}
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 = b.add(usize::from(take_b));
gap.src = gap.src.add(usize::from(!take_b));
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 = gap.dst.sub(usize::from(take_a));
gap.end = gap.end.sub(usize::from(!take_a));
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) }
}
}