diff --git a/libbz2-rs-sys/src/blocksort.rs b/libbz2-rs-sys/src/blocksort.rs index 58db62213..a4804fc55 100644 --- a/libbz2-rs-sys/src/blocksort.rs +++ b/libbz2-rs-sys/src/blocksort.rs @@ -9,182 +9,6 @@ use crate::{ }; use crate::{debug_log, debug_logln}; -/// Fallback O(N log(N)^2) sorting algorithm, for repetitive blocks -#[inline] -fn fallbackSimpleSort(fmap: &mut [u32], eclass: &[u32], lo: i32, hi: i32) { - let mut j: i32; - let mut tmp: i32; - let mut ec_tmp: u32; - - if lo == hi { - return; - } - - if hi - lo > 3 { - for i in (lo..=hi - 4).rev() { - tmp = fmap[i as usize] as i32; - ec_tmp = eclass[tmp as usize]; - j = i + 4; - while j <= hi && ec_tmp > eclass[fmap[j as usize] as usize] { - fmap[(j - 4) as usize] = fmap[j as usize]; - j += 4; - } - fmap[(j - 4) as usize] = tmp as u32; - } - } - - for i in (lo..=hi - 1).rev() { - tmp = fmap[i as usize] as i32; - ec_tmp = eclass[tmp as usize]; - j = i + 1; - while j <= hi && ec_tmp > eclass[fmap[j as usize] as usize] { - fmap[(j - 1) as usize] = fmap[j as usize]; - j += 1; - } - fmap[(j - 1) as usize] = tmp as u32; - } -} - -const FALLBACK_QSORT_SMALL_THRESH: i32 = 10; -const FALLBACK_QSORT_STACK_SIZE: usize = 100; - -fn fallbackQSort3(fmap: &mut [u32], eclass: &[u32], loSt: i32, hiSt: i32) { - let mut unLo: i32; - let mut unHi: i32; - let mut ltLo: i32; - let mut gtHi: i32; - let mut n: i32; - let mut m: i32; - let mut sp: usize; - let mut lo: i32; - let mut hi: i32; - let mut stackLo: [i32; FALLBACK_QSORT_STACK_SIZE] = [0; FALLBACK_QSORT_STACK_SIZE]; - let mut stackHi: [i32; FALLBACK_QSORT_STACK_SIZE] = [0; FALLBACK_QSORT_STACK_SIZE]; - - macro_rules! fpush { - ($lz:expr, $hz:expr) => { - stackLo[sp] = $lz; - stackHi[sp] = $hz; - sp += 1; - }; - } - - macro_rules! fvswap { - ($zzp1:expr, $zzp2:expr, $zzn:expr) => { - let mut yyp1: i32 = $zzp1; - let mut yyp2: i32 = $zzp2; - let mut yyn: i32 = $zzn; - - while (yyn > 0) { - fmap.swap(yyp1 as usize, yyp2 as usize); - yyp1 += 1; - yyp2 += 1; - yyn -= 1; - } - }; - } - - let mut r = 0u32; - - sp = 0; - fpush!(loSt, hiSt); - - while sp > 0 { - assert_h!(sp < FALLBACK_QSORT_STACK_SIZE - 1, 1004); - - // the `fpop` macro has one occurence, so it was inlined here - sp -= 1; - lo = stackLo[sp]; - hi = stackHi[sp]; - - if hi - lo < FALLBACK_QSORT_SMALL_THRESH { - fallbackSimpleSort(fmap, eclass, lo, hi); - continue; - } - - /* Random partitioning. Median of 3 sometimes fails to - avoid bad cases. Median of 9 seems to help but - looks rather expensive. This too seems to work but - is cheaper. Guidance for the magic constants - 7621 and 32768 is taken from Sedgewick's algorithms - book, chapter 35. - */ - r = r.wrapping_mul(7621).wrapping_add(1).wrapping_rem(32768); - let index = match r.wrapping_rem(3) { - 0 => fmap[lo as usize], - 1 => fmap[((lo + hi) >> 1) as usize], - _ => fmap[hi as usize], - }; - let med = eclass[index as usize]; - - ltLo = lo; - unLo = lo; - - gtHi = hi; - unHi = hi; - - loop { - while unLo <= unHi { - match eclass[fmap[unLo as usize] as usize].cmp(&med) { - Ordering::Greater => break, - Ordering::Equal => { - fmap.swap(unLo as usize, ltLo as usize); - ltLo += 1; - unLo += 1; - } - Ordering::Less => { - unLo += 1; - } - } - } - - while unLo <= unHi { - match eclass[fmap[unHi as usize] as usize].cmp(&med) { - Ordering::Less => break, - Ordering::Equal => { - fmap.swap(unHi as usize, gtHi as usize); - gtHi -= 1; - unHi -= 1; - } - Ordering::Greater => { - unHi -= 1; - } - } - } - - if unLo > unHi { - break; - } - - fmap.swap(unLo as usize, unHi as usize); - unLo += 1; - unHi -= 1; - } - - debug_assert_eq!(unHi, unLo - 1, "fallbackQSort3(2)"); - - if gtHi < ltLo { - continue; - } - - n = Ord::min(ltLo - lo, unLo - ltLo); - fvswap!(lo, unLo - n, n); - m = Ord::min(hi - gtHi, gtHi - unHi); - fvswap!(unLo, hi - m + 1, m); - - n = lo + unLo - ltLo - 1; - m = hi - (gtHi - unHi) + 1; - - if n - lo > hi - m { - fpush!(lo, n); - fpush!(m, hi); - } else { - fpush!(m, hi); - fpush!(lo, n); - } - } -} - fn fallbackSort( fmap: &mut [u32], arr2: &mut Arr2, @@ -339,7 +163,10 @@ fn fallbackSort( /*-- now [l, r] bracket current bucket --*/ if r > l { nNotDone += r - l + 1; - fallbackQSort3(fmap, arr2.eclass(), l, r); + + if let Some(slice) = fmap.get_mut(l as usize..=r as usize) { + slice.sort_unstable_by_key(|v| arr2.eclass()[*v as usize]); + } /*-- scan bucket and generate header bits-- */ cc = -1;