1#![allow(missing_docs)]
8#![cfg_attr(not(test), no_std)]
9extern crate alloc;
10
11use core::mem::size_of;
12
13pub const MAX_VERTICES_PER_CORE: usize = 256;
15
16pub const MAX_EDGES_PER_CORE: usize = 384;
24
25pub type CompactVertexId = u16;
27
28pub type CompactEdgeId = u16;
30
31#[derive(Clone, Copy, Default)]
34#[repr(C, align(32))]
35pub struct BitSet256 {
36 pub bits: [u64; 4], }
39
40impl BitSet256 {
41 pub const fn new() -> Self {
42 Self { bits: [0; 4] }
43 }
44
45 #[inline(always)]
46 pub fn insert(&mut self, v: CompactVertexId) {
47 let idx = (v / 64) as usize;
48 let bit = v % 64;
49 if idx < 4 {
50 self.bits[idx] |= 1u64 << bit;
51 }
52 }
53
54 #[inline(always)]
55 pub fn contains(&self, v: CompactVertexId) -> bool {
56 let idx = (v / 64) as usize;
57 let bit = v % 64;
58 idx < 4 && (self.bits[idx] & (1u64 << bit)) != 0
59 }
60
61 #[inline(always)]
62 pub fn remove(&mut self, v: CompactVertexId) {
63 let idx = (v / 64) as usize;
64 let bit = v % 64;
65 if idx < 4 {
66 self.bits[idx] &= !(1u64 << bit);
67 }
68 }
69
70 #[inline(always)]
71 pub fn count(&self) -> u32 {
72 self.bits.iter().map(|b| b.count_ones()).sum()
73 }
74
75 #[inline(always)]
76 pub fn union(&self, other: &Self) -> Self {
77 Self {
78 bits: [
79 self.bits[0] | other.bits[0],
80 self.bits[1] | other.bits[1],
81 self.bits[2] | other.bits[2],
82 self.bits[3] | other.bits[3],
83 ],
84 }
85 }
86
87 #[inline(always)]
88 pub fn intersection(&self, other: &Self) -> Self {
89 Self {
90 bits: [
91 self.bits[0] & other.bits[0],
92 self.bits[1] & other.bits[1],
93 self.bits[2] & other.bits[2],
94 self.bits[3] & other.bits[3],
95 ],
96 }
97 }
98
99 #[inline(always)]
100 pub fn xor(&self, other: &Self) -> Self {
101 Self {
102 bits: [
103 self.bits[0] ^ other.bits[0],
104 self.bits[1] ^ other.bits[1],
105 self.bits[2] ^ other.bits[2],
106 self.bits[3] ^ other.bits[3],
107 ],
108 }
109 }
110
111 pub fn iter(&self) -> BitSet256Iter {
112 BitSet256Iter {
114 set: self,
115 current: self.bits[0],
116 word_idx: 0,
117 }
118 }
119}
120
121pub struct BitSet256Iter<'a> {
122 set: &'a BitSet256,
123 current: u64,
124 word_idx: usize,
125}
126
127impl<'a> Iterator for BitSet256Iter<'a> {
128 type Item = CompactVertexId;
129
130 fn next(&mut self) -> Option<Self::Item> {
131 loop {
132 if self.current != 0 {
133 let bit = self.current.trailing_zeros();
134 self.current &= self.current - 1; return Some((self.word_idx as u16 * 64) + bit as u16);
136 }
137 self.word_idx += 1;
138 if self.word_idx >= 4 {
139 return None;
140 }
141 self.current = self.set.bits[self.word_idx];
142 }
143 }
144}
145
146#[derive(Clone, Copy, Default)]
148#[repr(C, packed)]
149pub struct CompactEdge {
150 pub source: CompactVertexId, pub target: CompactVertexId, pub weight: u16, pub flags: u16, }
155
156impl CompactEdge {
157 pub const FLAG_ACTIVE: u16 = 0x0001;
158 pub const FLAG_IN_CUT: u16 = 0x0002;
159 pub const FLAG_TREE_EDGE: u16 = 0x0004;
160
161 #[inline(always)]
162 pub fn is_active(&self) -> bool {
163 self.flags & Self::FLAG_ACTIVE != 0
164 }
165
166 #[inline(always)]
167 pub fn is_in_cut(&self) -> bool {
168 self.flags & Self::FLAG_IN_CUT != 0
169 }
170}
171
172#[derive(Clone, Copy, Default)]
174#[repr(C)]
175pub struct CompactWitness {
176 pub membership: BitSet256, pub seed: CompactVertexId, pub boundary_size: u16, pub cardinality: u16, pub hash: u16, }
182
183impl CompactWitness {
184 pub fn new(seed: CompactVertexId, membership: BitSet256, boundary: u16) -> Self {
185 let cardinality = membership.count() as u16;
186 let hash = Self::compute_hash(seed, &membership);
187 Self {
188 membership,
189 seed,
190 boundary_size: boundary,
191 cardinality,
192 hash,
193 }
194 }
195
196 fn compute_hash(seed: CompactVertexId, membership: &BitSet256) -> u16 {
197 let mut h = seed as u32;
198 for &word in &membership.bits {
199 h = h.wrapping_mul(31).wrapping_add(word as u32);
200 }
201 (h & 0xFFFF) as u16
202 }
203
204 #[inline(always)]
205 pub fn contains(&self, v: CompactVertexId) -> bool {
206 self.membership.contains(v)
207 }
208}
209
210#[derive(Clone)]
212#[repr(C)]
213pub struct CompactAdjacency {
214 pub offsets: [u16; MAX_VERTICES_PER_CORE + 1], pub neighbors: [(CompactVertexId, CompactEdgeId); MAX_EDGES_PER_CORE * 2], }
219
220impl Default for CompactAdjacency {
221 fn default() -> Self {
222 Self {
223 offsets: [0; MAX_VERTICES_PER_CORE + 1],
224 neighbors: [(0, 0); MAX_EDGES_PER_CORE * 2],
225 }
226 }
227}
228
229impl CompactAdjacency {
230 pub fn neighbors(&self, v: CompactVertexId) -> &[(CompactVertexId, CompactEdgeId)] {
231 let start = self.offsets[v as usize] as usize;
232 let end = self.offsets[v as usize + 1] as usize;
233 &self.neighbors[start..end]
234 }
235
236 pub fn degree(&self, v: CompactVertexId) -> u16 {
237 self.offsets[v as usize + 1] - self.offsets[v as usize]
238 }
239}
240
241#[repr(C)]
251pub struct CompactCoreState {
252 pub adjacency: CompactAdjacency,
254 pub edges: [CompactEdge; MAX_EDGES_PER_CORE],
256 pub num_vertices: u16,
258 pub num_edges: u16,
260 pub min_cut: u16,
262 pub best_witness: CompactWitness,
264 pub lambda_min: u16,
266 pub lambda_max: u16,
267 pub core_id: u8,
269 pub status: u8,
271}
272
273impl CompactCoreState {
274 pub const STATUS_IDLE: u8 = 0;
275 pub const STATUS_PROCESSING: u8 = 1;
276 pub const STATUS_DONE: u8 = 2;
277 pub const STATUS_ERROR: u8 = 3;
278
279 pub const fn size() -> usize {
280 size_of::<Self>()
281 }
282}
283
284const _: () = assert!(
286 CompactCoreState::size() <= 8192,
287 "CompactCoreState exceeds 8KB"
288);
289
290#[derive(Clone, Copy, Default)]
292#[repr(C)]
293pub struct CoreResult {
294 pub core_id: u8,
295 pub status: u8,
296 pub min_cut: u16,
297 pub witness_hash: u16,
298 pub witness_seed: CompactVertexId,
299 pub witness_cardinality: u16,
300 pub witness_boundary: u16,
301 pub padding: [u8; 4],
302}
303
304#[cfg(test)]
305mod tests {
306 use super::*;
307
308 #[test]
309 fn test_bitset256_basic() {
310 let mut bs = BitSet256::new();
311 assert!(!bs.contains(0));
312
313 bs.insert(0);
314 bs.insert(100);
315 bs.insert(255);
316
317 assert!(bs.contains(0));
318 assert!(bs.contains(100));
319 assert!(bs.contains(255));
320 assert!(!bs.contains(50));
321
322 assert_eq!(bs.count(), 3);
323 }
324
325 #[test]
326 fn test_bitset256_iter() {
327 let mut bs = BitSet256::new();
328 bs.insert(1);
329 bs.insert(64);
330 bs.insert(200);
331
332 let collected: alloc::vec::Vec<_> = bs.iter().collect();
333 assert_eq!(collected, alloc::vec![1, 64, 200]);
334 }
335
336 #[test]
337 fn test_compact_witness_size() {
338 assert_eq!(size_of::<CompactWitness>(), 64);
340 }
341
342 #[test]
343 fn test_compact_edge_size() {
344 assert_eq!(size_of::<CompactEdge>(), 8);
345 }
346
347 #[test]
348 fn test_core_state_fits_8kb() {
349 assert!(CompactCoreState::size() <= 8192);
350 }
353
354 #[test]
355 fn test_bitset_operations() {
356 let mut a = BitSet256::new();
357 let mut b = BitSet256::new();
358
359 a.insert(1);
360 a.insert(2);
361 b.insert(2);
362 b.insert(3);
363
364 let union = a.union(&b);
365 assert!(union.contains(1));
366 assert!(union.contains(2));
367 assert!(union.contains(3));
368
369 let inter = a.intersection(&b);
370 assert!(!inter.contains(1));
371 assert!(inter.contains(2));
372 assert!(!inter.contains(3));
373 }
374}