pub trait InverseBwt: Default + Send {
fn invert(&mut self, ll: &[u8], counts: &[u32; 256], orig_ptr: u32, out: &mut Vec<u8>);
}
#[derive(Default)]
pub struct Plain {
tt: TVector,
}
impl InverseBwt for Plain {
fn invert(&mut self, ll: &[u8], counts: &[u32; 256], orig_ptr: u32, out: &mut Vec<u8>) {
build(ll, counts, &mut self.tt);
walk(&self.tt, orig_ptr, out);
}
}
#[derive(Default)]
pub struct Segmented {
tt: TVector,
seg: SegScratch,
}
impl InverseBwt for Segmented {
fn invert(&mut self, ll: &[u8], counts: &[u32; 256], orig_ptr: u32, out: &mut Vec<u8>) {
build(ll, counts, &mut self.tt);
walk_fast(&self.tt, orig_ptr, out, &mut self.seg);
}
}
#[derive(Default)]
pub struct TVector(Vec<u32>);
impl TVector {
pub fn new() -> Self {
TVector(Vec::new())
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
}
pub fn build(ll: &[u8], counts: &[u32; 256], tt: &mut TVector) {
let tt = &mut tt.0;
tt.clear();
tt.extend(ll.iter().map(|&c| c as u32));
let mut ftab = [0u32; 256];
let mut cum = 0u32;
for i in 0..256 {
ftab[i] = cum;
cum += counts[i];
}
for (i, &c) in ll.iter().enumerate() {
let k = ftab[c as usize] as usize;
tt[k] = (tt[k] & 0xff) | (i as u32) << 8;
ftab[c as usize] += 1;
}
}
pub fn walk(tt: &TVector, orig_ptr: u32, out: &mut Vec<u8>) {
let t = &tt.0;
let n = t.len();
out.clear();
out.reserve(n);
let mut p = t[orig_ptr as usize];
for _ in 0..n {
p = unsafe { *t.get_unchecked((p >> 8) as usize) };
out.push(p as u8);
}
}
const LANES: usize = 12;
const SEGMENTS: usize = 256;
const MIN_SEGMENTED: usize = 1 << 16;
#[derive(Default)]
pub struct SegScratch {
starts: Vec<u32>,
bitmap: Vec<u64>,
bufs: Vec<Vec<u8>>,
next: Vec<usize>,
}
pub fn walk_fast(tt: &TVector, orig_ptr: u32, out: &mut Vec<u8>, s: &mut SegScratch) {
if tt.len() < MIN_SEGMENTED {
walk(tt, orig_ptr, out)
} else {
walk_segments(tt, orig_ptr, out, s)
}
}
pub fn walk_segments(tt: &TVector, orig_ptr: u32, out: &mut Vec<u8>, s: &mut SegScratch) {
let t = &tt.0;
let n = t.len();
out.clear();
let r0 = t[orig_ptr as usize] >> 8;
random_rows(n, SEGMENTS - 1, &mut s.starts);
s.starts.push(r0);
s.starts.sort_unstable();
s.starts.dedup();
let starts = &s.starts;
let ns = starts.len();
s.bitmap.clear();
s.bitmap.resize(n.div_ceil(64), 0);
for &r in starts {
s.bitmap[(r >> 6) as usize] |= 1 << (r & 63);
}
let cap = 2 * n / ns + 64;
s.bufs.resize_with(ns.max(s.bufs.len()), Vec::new);
for b in &mut s.bufs[..ns] {
b.clear();
b.reserve(cap);
}
s.next.clear();
s.next.resize(ns, usize::MAX);
let seg_of = |row: u32| starts.binary_search(&row).unwrap_or(usize::MAX);
let mut lane_seg = [usize::MAX; LANES];
let mut lane_row = [0u32; LANES];
let mut queued = 0;
for k in 0..LANES {
if queued < ns {
lane_seg[k] = queued;
lane_row[k] = starts[queued];
queued += 1;
}
}
let mut active = lane_seg.iter().filter(|&&x| x != usize::MAX).count();
let bm = &s.bitmap;
let bufs = &mut s.bufs;
while active > 0 {
for k in 0..LANES {
let seg = lane_seg[k];
if seg == usize::MAX {
continue;
}
let q = unsafe { *t.get_unchecked(lane_row[k] as usize) };
let row = q >> 8;
bufs[seg].push(q as u8);
lane_row[k] = row;
if unsafe { *bm.get_unchecked((row >> 6) as usize) } >> (row & 63) & 1 != 0 {
s.next[seg] = seg_of(row);
if queued < ns {
lane_seg[k] = queued;
lane_row[k] = starts[queued];
queued += 1;
} else {
lane_seg[k] = usize::MAX;
active -= 1;
}
}
}
}
out.reserve(n);
let mut seg = seg_of(r0);
while out.len() < n {
let b = &bufs[seg];
out.extend_from_slice(&b[..b.len().min(n - out.len())]);
seg = s.next[seg];
}
}
fn random_rows(n: usize, m: usize, rows: &mut Vec<u32>) {
rows.clear();
let mut x = 0x2545_f491_4f6c_dd1du64 ^ n as u64;
rows.extend((0..m).map(|_| {
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
(x % n as u64) as u32
}));
}