vyre_libs/security/
sink_intersection.rs1use vyre_foundation::ir::Program;
6use vyre_primitives::bitset::and::bitset_and;
7use vyre_primitives::bitset::bitset_words;
8use vyre_primitives::reduce::count::reduce_count;
9
10use crate::security::flow_composition::fuse_security_flow;
11
12pub(crate) const OP_ID: &str = "vyre-libs::security::sink_intersection";
13
14#[must_use]
22pub fn sink_intersection(
23 node_count: u32,
24 query_set: &str,
25 sink_set: &str,
26 intersect_buf: &str,
27 out_scalar: &str,
28) -> Program {
29 let words = bitset_words(node_count);
30 fuse_security_flow(
31 OP_ID,
32 &[
33 bitset_and(query_set, sink_set, intersect_buf, words),
34 reduce_count(intersect_buf, out_scalar, words),
35 ],
36 out_scalar,
37 )
38}
39
40#[must_use]
42#[cfg(test)]
43pub(crate) fn cpu_ref(query_set: &[u32], sink_set: &[u32]) -> u32 {
44 vyre_primitives::reduce::count::cpu_ref(&vyre_primitives::bitset::and::cpu_ref(
45 query_set, sink_set,
46 ))
47}
48
49pub struct SinkIntersection;
51impl vyre_spec::soundness::SoundnessTagged for SinkIntersection {
52 fn soundness(&self) -> vyre_spec::soundness::Soundness {
53 vyre_spec::soundness::Soundness::Exact
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn full_overlap_counts_all_set_bits() {
63 assert_eq!(cpu_ref(&[0b1111], &[0b1111]), 4);
64 }
65
66 #[test]
67 fn no_overlap_returns_zero() {
68 assert_eq!(cpu_ref(&[0b1010], &[0b0101]), 0);
69 }
70
71 #[test]
72 fn partial_overlap_counts_intersection() {
73 assert_eq!(cpu_ref(&[0b1110], &[0b0111]), 2);
74 }
75
76 #[test]
77 fn distributes_across_words() {
78 assert_eq!(cpu_ref(&[0xFF00, 0x00FF], &[0xFFFF, 0xFFFF]), 16);
79 }
80}