-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathslice_utils.rs
54 lines (49 loc) · 1.56 KB
/
slice_utils.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use std::mem;
// NOTE: copy from https://doc.rust-lang.org/std/primitive.slice.html#method.sort_by_cached_key
pub(crate) fn sort_by_cached_key<T, K, F>(list: &mut Vec<T>, desc: bool, f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
macro_rules! sort_by_key {
($t:ty, $slice:ident, $f:ident) => {{
let mut indices: Vec<_> = $slice
.iter()
.map($f)
.enumerate()
.map(|(i, k)| (k, i as $t))
.collect();
if desc {
indices.sort_unstable_by(|a, b| b.cmp(a));
} else {
indices.sort_unstable_by(|a, b| a.cmp(b));
}
for i in 0..$slice.len() {
let mut index = indices[i].1;
while (index as usize) < i {
index = indices[index as usize].1;
}
indices[i].1 = index;
$slice.swap(i, index as usize);
}
}};
}
let sz_u8 = mem::size_of::<(K, u8)>();
let sz_u16 = mem::size_of::<(K, u16)>();
let sz_u32 = mem::size_of::<(K, u32)>();
let sz_usize = mem::size_of::<(K, usize)>();
let len = list.len();
if len < 2 {
return;
}
if sz_u8 < sz_u16 && len <= (u8::MAX as usize) {
return sort_by_key!(u8, list, f);
}
if sz_u16 < sz_u32 && len <= (u16::MAX as usize) {
return sort_by_key!(u16, list, f);
}
if sz_u32 < sz_usize && len <= (u32::MAX as usize) {
return sort_by_key!(u32, list, f);
}
sort_by_key!(usize, list, f)
}