use std::cmp::Ordering;
use std::cmp::Ordering::Greater;
use std::{ptr};
use std::mem::{ MaybeUninit};
use crate::datas::array::Array;
pub fn merge_sort<T>(l:&mut [T], a:usize, b:usize,cmp:fn(&T,&T)->Ordering)
where T:{
if(b-a<=1){
return;
}
let mut tmp=unsafe{Array::<MaybeUninit<T>>::with_uninit(b-a)};
merge_sort_recur(l,a,b,&mut tmp,cmp);
}
pub fn merge_sort_recur<T>(l:&mut [T], a:usize, b:usize, tmp:&mut [MaybeUninit<T>], cmp:fn(&T,&T)->Ordering)
where T:{
let len=b-a;
if(b-a<=1){
return;
}
if(len==2&&cmp(&l[a],&l[a+1])==Greater){
l.swap(a,a+1);
return;
}
let m:usize=a+len/2;
merge_sort_recur(l,a,m,tmp,cmp);
merge_sort_recur(l,m,b,tmp,cmp);
merge(l,a,m,b,tmp,cmp);
}
pub fn merge<T>(l:&mut[T],a:usize,m:usize,b:usize,tmp:&mut [MaybeUninit<T>],cmp:fn(&T,&T)->Ordering)
where T:
{
let mut i_left = a;
let mut i_right = m;
let mut i_tmp = 0;
unsafe {
while (i_left < m && i_right < b) {
if (cmp(&l[i_left], &l[i_right])!=Greater) {
set_uninit(&mut tmp[i_tmp], &mut l[i_left]);
i_left += 1;
i_tmp += 1;
} else {
set_uninit(&mut tmp[i_tmp], &mut l[i_right]);
i_right += 1;
i_tmp += 1;
}
}
while (i_left < m) {
set_uninit(&mut tmp[i_tmp], &mut l[i_left]);
i_left += 1;
i_tmp += 1;
}
while (i_right < b) {
set_uninit(&mut tmp[i_tmp], &mut l[i_right]);
i_right += 1;
i_tmp += 1;
}
i_tmp = a;
while (i_tmp < b) {
set_init_from_uninit(&mut l[i_tmp], &mut tmp[i_tmp]);
i_tmp = i_tmp + 1;
}
}
}
pub fn insertion_sort<T>(l:&mut [T],a:usize,b:usize,cmp:fn(&T,&T)->Ordering)where T:PartialOrd{
for i in a + 1..b {
let mut j = i;
while j > a && cmp(&l[j - 1], &l[j]) == Greater {
l.swap(j - 1, j);
j -= 1;
}
}
}
unsafe fn set_uninit<T>(dst: &mut MaybeUninit<T>,src: &mut T) {
unsafe{
let val = ptr::read(src); ptr::write(dst.as_mut_ptr(), val);
}
}
unsafe fn set_init_from_uninit<T>(dst: &mut T,src: &mut MaybeUninit<T>) {
unsafe{
let val = ptr::read(src.as_ptr()); ptr::write(dst, val);
}
}