use super::IFDS_REACH_MASK;
fn ifds_bit_is_set(words: &[u32], bit: usize) -> bool {
words
.get(bit / 32)
.is_some_and(|word| (word & (1u32 << (bit % 32))) != 0)
}
fn ifds_set_bit(words: &mut [u32], bit: usize) -> bool {
let Some(word) = words.get_mut(bit / 32) else {
return false;
};
let mask = 1u32 << (bit % 32);
let changed = (*word & mask) == 0;
*word |= mask;
changed
}
#[must_use]
#[deprecated(
note = "reference oracle only; production code must dispatch the Weir Program on a concrete GPU backend or use weir::oracle for parity evidence"
)]
pub(crate) fn ifds_reach_closure_cpu(
node_count: u32,
edge_offsets: &[u32],
edge_targets: &[u32],
edge_kind_mask: &[u32],
seed_bits: &[u32],
) -> Vec<u32> {
let nodes = node_count as usize;
let words = nodes.checked_add(31).unwrap_or_else(|| {
panic!(
"ifds_reach_closure_cpu node_count={node_count} overflows host bitset word calculation. Fix: shard the oracle graph."
)
}) / 32;
crate::dispatch_decode::require_bitset_words("ifds_reachability_cpu", seed_bits, words)
.expect("ifds_reachability CPU oracle received malformed seed bitset");
crate::dispatch_decode::require_csr_shape(
"ifds_reachability_cpu",
node_count,
edge_offsets,
edge_targets,
edge_kind_mask,
)
.expect("ifds_reachability CPU oracle received malformed CSR graph");
let mut reached = vec![0u32; words];
for (dst, src) in reached.iter_mut().zip(seed_bits.iter().copied()) {
*dst = src;
}
if words > 0 && nodes % 32 != 0 {
let keep = (1u32 << (nodes % 32)) - 1;
if let Some(last) = reached.last_mut() {
*last &= keep;
}
}
let mut changed = true;
while changed {
changed = false;
for node in 0..nodes {
if !ifds_bit_is_set(&reached, node) {
continue;
}
let start = edge_offsets[node] as usize;
let end = edge_offsets[node + 1] as usize;
for edge in start..end {
let kind = edge_kind_mask[edge];
if (kind & IFDS_REACH_MASK) == 0 {
continue;
}
let target = edge_targets[edge] as usize;
if target < nodes {
changed |= ifds_set_bit(&mut reached, target);
}
}
}
}
reached
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use super::ifds_reach_closure_cpu;
#[test]
#[should_panic(expected = "ifds_reachability CPU oracle received malformed seed bitset")]
fn ifds_reach_closure_rejects_bad_seed_len() {
let _ = ifds_reach_closure_cpu(2, &[0, 1, 1], &[1], &[0], &[0b1, 0b0]);
}
#[test]
#[should_panic(expected = "ifds_reachability CPU oracle received malformed CSR graph")]
fn ifds_reach_closure_rejects_malformed_csr() {
let _ = ifds_reach_closure_cpu(2, &[1, 1, 1], &[0], &[0], &[0b1]);
}
#[test]
#[should_panic(expected = "ifds_reachability CPU oracle received malformed CSR graph")]
fn ifds_reach_closure_rejects_oob_target() {
let _ = ifds_reach_closure_cpu(2, &[0, 1, 1], &[2], &[0], &[0b1]);
}
}