#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IfdsCsrLayout {
pub empty: bool,
pub num_procs: u32,
pub blocks_per_proc: u32,
pub facts_per_proc: u32,
pub intra_count: u32,
pub inter_count: u32,
pub gen_count: u32,
pub kill_count: u32,
pub intra_storage_words: usize,
pub inter_storage_words: usize,
pub gen_storage_words: usize,
pub kill_storage_words: usize,
pub slots_per_proc: u32,
pub total_nodes: u32,
pub row_words: usize,
pub row_cursor_words: usize,
pub killed_words: usize,
pub max_col_count: u32,
pub col_buffer_words: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IfdsCsrProgramCacheKey {
pub num_procs: u32,
pub blocks_per_proc: u32,
pub facts_per_proc: u32,
pub intra_count: u32,
pub inter_count: u32,
pub gen_count: u32,
pub kill_count: u32,
pub max_col_count: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IfdsCsrRuleInputFingerprint {
pub intra: u128,
pub inter: u128,
pub gen: u128,
pub kill: u128,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct IfdsCsrStaticInputKey {
pub program_key: IfdsCsrProgramCacheKey,
pub rule_fingerprint: IfdsCsrRuleInputFingerprint,
}
impl IfdsCsrRuleInputFingerprint {
#[must_use]
pub fn from_rules(
intra_edges: &[(u32, u32, u32)],
inter_edges: &[(u32, u32, u32, u32)],
flow_gen: &[(u32, u32, u32)],
flow_kill: &[(u32, u32, u32)],
) -> Self {
Self {
intra: fingerprint_rule_triples(intra_edges),
inter: fingerprint_rule_quads(inter_edges),
gen: fingerprint_rule_triples(flow_gen),
kill: fingerprint_rule_triples(flow_kill),
}
}
}
fn mix_rule_word(hash: &mut u128, value: u32) {
*hash ^= u128::from(value)
.wrapping_add(0x9E37_79B9_7F4A_7C15_6A09_E667_F3BC_C909)
.wrapping_add(*hash << 7)
.wrapping_add(*hash >> 3);
*hash = hash
.rotate_left(31)
.wrapping_mul(0xD6E8_FD9D_DA37_3C91_BB67_AE85_84CA_A73B);
}
fn fingerprint_rule_triples(rules: &[(u32, u32, u32)]) -> u128 {
let mut hash = 0x243F_6A88_85A3_08D3_1319_8A2E_0370_7344_u128 ^ rules.len() as u128;
for &(a, b, c) in rules {
mix_rule_word(&mut hash, a);
mix_rule_word(&mut hash, b);
mix_rule_word(&mut hash, c);
}
hash
}
fn fingerprint_rule_quads(rules: &[(u32, u32, u32, u32)]) -> u128 {
let mut hash = 0xA409_3822_299F_31D0_082E_FA98_EC4E_6C89_u128 ^ rules.len() as u128;
for &(a, b, c, d) in rules {
mix_rule_word(&mut hash, a);
mix_rule_word(&mut hash, b);
mix_rule_word(&mut hash, c);
mix_rule_word(&mut hash, d);
}
hash
}
impl IfdsCsrProgramCacheKey {
#[must_use]
pub const fn from_layout(layout: &IfdsCsrLayout) -> Self {
Self {
num_procs: layout.num_procs,
blocks_per_proc: layout.blocks_per_proc,
facts_per_proc: layout.facts_per_proc,
intra_count: layout.intra_count,
inter_count: layout.inter_count,
gen_count: layout.gen_count,
kill_count: layout.kill_count,
max_col_count: layout.max_col_count,
}
}
}