use std::mem;
use crate::common::container::{Clusters, Run};
pub fn from_runs(runs: &[Run]) -> Vec<u64> {
let mut out = Vec::with_capacity(runs.len());
let mut value = false;
let mut length = 0;
for run in runs {
let this_value = run.value > 0;
if this_value ^ value {
out.push(mem::replace(&mut length, run.length));
value = this_value;
} else {
length += run.length;
}
}
(length > 0).then(|| out.push(length));
out
}
pub fn chunks(runs: &[u64], width: u64) -> Vec<Vec<u64>> {
let mut rows = Vec::new();
let mut row = Vec::new();
let mut row_length = 0;
for (i, mut run) in runs.iter().copied().enumerate() {
while run > 0 {
let clamped = run.min(width - row_length);
row.push(clamped);
row_length += clamped;
run -= clamped;
if row_length >= width {
rows.push(mem::take(&mut row));
row_length = 0;
((i % 2 == 0) ^ (run > 0)).then(|| row.push(0));
}
}
}
(!row.is_empty()).then(|| rows.push(row));
rows
}
#[derive(Default, Clone, Copy, Hash, PartialEq, Eq)]
pub struct ClusterRun {
pub row: usize,
pub index: usize,
pub position: u64,
pub size: u64,
}
pub fn cluster_row_adjacency(
clusters: &mut Clusters<ClusterRun>,
rows: &[Vec<u64>],
base_row: usize,
curr_row: usize,
) {
let (base, curr) = (&rows[base_row], &rows[curr_row]);
let mut b_pos = 0;
for (i, &b) in curr.iter().enumerate() {
if i % 2 != 0 {
let b_end = b_pos + b;
let cluster_b = ClusterRun {
row: curr_row,
index: i,
position: b_pos,
size: b,
};
clusters.insert(cluster_b);
let mut a_pos = 0;
for (j, &a) in base.iter().enumerate() {
let a_end = a_pos + a;
if a_pos > b_end {
break;
}
if j % 2 != 0 && b_pos <= a_end && b_end >= a_pos {
let cluster_a = ClusterRun {
row: base_row,
index: j,
position: a_pos,
size: a,
};
clusters.mark_adjacency(cluster_a, cluster_b);
}
a_pos += a;
}
}
b_pos += b;
}
}