diff options
| author | varkor <github@varkor.com> | 2018-03-02 16:28:55 +0000 |
|---|---|---|
| committer | varkor <github@varkor.com> | 2018-03-16 13:57:08 +0000 |
| commit | bdcc6f939a10bc23a434b2ef301238650841dec9 (patch) | |
| tree | ed3c7a9f50dd05496bdea2894b65d6f7c58800bd /src/liballoc | |
| parent | 7dcfc07d2c441e6e18c34dfe844c7bdc1c0137fe (diff) | |
| download | rust-bdcc6f939a10bc23a434b2ef301238650841dec9.tar.gz rust-bdcc6f939a10bc23a434b2ef301238650841dec9.zip | |
Index enumeration by minimally sized type
Diffstat (limited to 'src/liballoc')
| -rw-r--r-- | src/liballoc/slice.rs | 37 |
1 files changed, 25 insertions, 12 deletions
diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 3fa5e78c04f..fbd8d879308 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -102,6 +102,7 @@ use core::mem::size_of; use core::mem; use core::ptr; use core::slice as core_slice; +use core::{u8, u16, u32}; use borrow::{Borrow, BorrowMut, ToOwned}; use boxed::Box; @@ -1329,19 +1330,31 @@ impl<T> [T] { pub fn sort_by_key<K, F>(&mut self, f: F) where F: FnMut(&T) -> K, K: Ord { - let mut indices: Vec<_> = self.iter().map(f).enumerate().map(|(i, k)| (k, i)).collect(); - // The elements of `indices` are unique, as they are indexed, so any sort will be stable - // with respect to the original slice. We use `sort_unstable` here because it requires less - // memory allocation. - indices.sort_unstable(); - for i in 0..self.len() { - let mut index = indices[i].1; - while index < i { - index = indices[index].1; - } - indices[i].1 = index; - self.swap(i, index); + // Helper macro for indexing our vector by the smallest possible type, to reduce allocation. + 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(); + // The elements of `indices` are unique, as they are indexed, so any sort will be + // stable with respect to the original slice. We use `sort_unstable` here because it + // requires less memory allocation. + indices.sort_unstable(); + 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 len = self.len(); + if len <= ( u8::MAX as usize) { return sort_by_key!( u8, self, f) } + if len <= (u16::MAX as usize) { return sort_by_key!(u16, self, f) } + if len <= (u32::MAX as usize) { return sort_by_key!(u32, self, f) } + sort_by_key!(usize, self, f) } /// Sorts the slice, but may not preserve the order of equal elements. |
