use std::cmp::Ordering;
pub use super::region_programs::{
cap_regions_per_pattern_flag_program, compact_first_per_region_pattern_flag_program,
dedup_regions_cluster_program, dedup_regions_flag_program, region_dedup_dispatch_grid,
region_sort_program, CAP_REGIONS_PER_PATTERN_OP_ID, COMPACT_FIRST_PER_REGION_PATTERN_OP_ID,
DEDUP_REGIONS_CLUSTER_OP_ID, DEDUP_REGIONS_FLAG_OP_ID, REGION_DEDUP_WORKGROUP_SIZE,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RegionTriple {
pub pid: u32,
pub start: u32,
pub end: u32,
}
impl RegionTriple {
#[must_use]
pub const fn new(pid: u32, start: u32, end: u32) -> Self {
Self { pid, start, end }
}
}
impl Ord for RegionTriple {
fn cmp(&self, other: &Self) -> Ordering {
self.pid
.cmp(&other.pid)
.then(self.start.cmp(&other.start))
.then(self.end.cmp(&other.end))
}
}
impl PartialOrd for RegionTriple {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[must_use]
#[cfg(any(test, feature = "cpu-parity"))]
pub fn dedup_regions_cpu(input: Vec<RegionTriple>) -> Vec<RegionTriple> {
let mut owned = input;
dedup_regions_inplace(&mut owned);
owned
}
#[cfg(any(test, feature = "cpu-parity"))]
pub fn sort_regions_cpu(input: &mut [RegionTriple]) {
input.sort();
}
#[cfg(any(test, feature = "cpu-parity"))]
pub fn dedup_regions_inplace(input: &mut Vec<RegionTriple>) {
if input.is_empty() {
return;
}
input.sort_unstable();
let mut write = 1usize;
for read in 1..input.len() {
let next = input[read];
let last = input[write - 1];
let same_pid = next.pid == last.pid;
let overlap_or_touch = next.start <= last.end;
if same_pid && overlap_or_touch {
if next.end > last.end {
input[write - 1].end = next.end;
}
} else {
input[write] = next;
write += 1;
}
}
input.truncate(write);
}
#[cfg(any(test, feature = "cpu-parity"))]
#[must_use]
pub fn cap_regions_per_pattern_survivors_cpu(pids: &[u32], k: u32) -> Vec<u32> {
use std::collections::HashMap;
let mut seen: HashMap<u32, u32> = HashMap::new();
pids.iter()
.map(|&pid| {
let count = seen.entry(pid).or_insert(0);
let survivor = u32::from(*count < k);
*count += 1;
survivor
})
.collect()
}
#[cfg(any(test, feature = "cpu-parity"))]
#[must_use]
pub fn compact_first_per_region_pattern_survivors_cpu(regions: &[u32], pids: &[u32]) -> Vec<u32> {
use std::collections::HashSet;
assert_eq!(
regions.len(),
pids.len(),
"regions and pids columns must be parallel"
);
let mut seen: HashSet<(u32, u32)> = HashSet::new();
regions
.iter()
.zip(pids.iter())
.map(|(®ion, &pid)| u32::from(seen.insert((region, pid))))
.collect()
}