use sux::prelude::*;
use sux::utils::FairChunks;
#[test]
fn test_fair_chunks_basic() {
let cwf = [0u64, 10, 30, 60, 100];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(50, &ef).collect();
assert!(!chunks.is_empty());
assert_eq!(chunks[0].start, 0);
assert_eq!(chunks.last().unwrap().end, 4);
}
#[test]
fn test_fair_chunks_new_with() {
let cwf = [0u64, 10, 30, 60, 100];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_dict();
let chunks: Vec<_> = FairChunks::new_with(50, &ef, 4, 100).collect();
assert!(!chunks.is_empty());
assert_eq!(chunks[0].start, 0);
assert_eq!(chunks.last().unwrap().end, 4);
}
#[test]
fn test_fair_chunks_single_element() {
let cwf = [0u64, 100];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(50, &ef).collect();
assert_eq!(chunks, vec![0..1, 1..1]);
}
#[test]
fn test_fair_chunks_large_target() {
let cwf = [0u64, 10, 20, 30];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(1000, &ef).collect();
assert_eq!(chunks, vec![0..3]);
}
#[test]
fn test_fair_chunks_small_target() {
let cwf = [0u64, 10, 20, 30, 40, 50];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(10, &ef).collect();
assert!(chunks.len() >= 2);
for i in 1..chunks.len() {
assert_eq!(chunks[i - 1].end, chunks[i].start);
}
}
#[test]
fn test_fair_chunks_fused_iterator() {
let cwf = [0u64, 10, 20, 30];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let mut chunks = FairChunks::new(100, &ef);
while chunks.next().is_some() {}
assert!(chunks.next().is_none());
assert!(chunks.next().is_none());
assert!(chunks.next().is_none());
}
#[test]
fn test_fair_chunks_example_from_docs() {
let weights = [
15u64, 27, 20, 26, 4, 22, 10, 25, 7, 13, 0, 11, 5, 28, 23, 1, 12, 24, 3, 30, 8, 29, 17, 2,
14, 9, 16, 18, 21, 19,
];
let mut cwf = vec![0u64];
cwf.extend(weights.iter().scan(0u64, |acc, x| {
*acc += x;
Some(*acc)
}));
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(50, &ef).collect();
assert_eq!(
chunks,
vec![
0..3, 3..6, 6..10, 10..15, 15..20, 20..23, 23..28, 28..30, ],
);
}
#[test]
fn test_fair_chunks_contiguous_ranges() {
let cwf = [0u64, 5, 15, 30, 50, 75, 100];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(25, &ef).collect();
assert_eq!(chunks[0].start, 0);
assert_eq!(chunks.last().unwrap().end, 6);
for i in 1..chunks.len() {
assert_eq!(
chunks[i - 1].end,
chunks[i].start,
"Ranges not contiguous at index {}",
i
);
}
}
#[test]
fn test_fair_chunks_uniform_weights() {
let cwf = vec![0u64, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100];
let mut efb = EliasFanoBuilder::new(cwf.len(), *cwf.last().unwrap());
efb.extend(cwf.iter().copied());
let ef = efb.build_with_seq_and_dict();
let chunks: Vec<_> = FairChunks::new(30, &ef).collect();
assert_eq!(chunks[0].start, 0);
assert_eq!(chunks.last().unwrap().end, 10);
}