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 { set: self, current: self.bits[0], word_idx: 0 }
114 }
115}
116
117pub struct BitSet256Iter<'a> {
118 set: &'a BitSet256,
119 current: u64,
120 word_idx: usize,
121}
122
123impl<'a> Iterator for BitSet256Iter<'a> {
124 type Item = CompactVertexId;
125
126 fn next(&mut self) -> Option<Self::Item> {
127 loop {
128 if self.current != 0 {
129 let bit = self.current.trailing_zeros();
130 self.current &= self.current - 1; return Some((self.word_idx as u16 * 64) + bit as u16);
132 }
133 self.word_idx += 1;
134 if self.word_idx >= 4 {
135 return None;
136 }
137 self.current = self.set.bits[self.word_idx];
138 }
139 }
140}
141
142#[derive(Clone, Copy, Default)]
144#[repr(C, packed)]
145pub struct CompactEdge {
146 pub source: CompactVertexId, pub target: CompactVertexId, pub weight: u16, pub flags: u16, }
151
152impl CompactEdge {
153 pub const FLAG_ACTIVE: u16 = 0x0001;
154 pub const FLAG_IN_CUT: u16 = 0x0002;
155 pub const FLAG_TREE_EDGE: u16 = 0x0004;
156
157 #[inline(always)]
158 pub fn is_active(&self) -> bool {
159 self.flags & Self::FLAG_ACTIVE != 0
160 }
161
162 #[inline(always)]
163 pub fn is_in_cut(&self) -> bool {
164 self.flags & Self::FLAG_IN_CUT != 0
165 }
166}
167
168#[derive(Clone, Copy, Default)]
170#[repr(C)]
171pub struct CompactWitness {
172 pub membership: BitSet256, pub seed: CompactVertexId, pub boundary_size: u16, pub cardinality: u16, pub hash: u16, }
178
179impl CompactWitness {
180 pub fn new(seed: CompactVertexId, membership: BitSet256, boundary: u16) -> Self {
181 let cardinality = membership.count() as u16;
182 let hash = Self::compute_hash(seed, &membership);
183 Self {
184 membership,
185 seed,
186 boundary_size: boundary,
187 cardinality,
188 hash,
189 }
190 }
191
192 fn compute_hash(seed: CompactVertexId, membership: &BitSet256) -> u16 {
193 let mut h = seed as u32;
194 for &word in &membership.bits {
195 h = h.wrapping_mul(31).wrapping_add(word as u32);
196 }
197 (h & 0xFFFF) as u16
198 }
199
200 #[inline(always)]
201 pub fn contains(&self, v: CompactVertexId) -> bool {
202 self.membership.contains(v)
203 }
204}
205
206#[derive(Clone)]
208#[repr(C)]
209pub struct CompactAdjacency {
210 pub offsets: [u16; MAX_VERTICES_PER_CORE + 1], pub neighbors: [(CompactVertexId, CompactEdgeId); MAX_EDGES_PER_CORE * 2], }
215
216impl Default for CompactAdjacency {
217 fn default() -> Self {
218 Self {
219 offsets: [0; MAX_VERTICES_PER_CORE + 1],
220 neighbors: [(0, 0); MAX_EDGES_PER_CORE * 2],
221 }
222 }
223}
224
225impl CompactAdjacency {
226 pub fn neighbors(&self, v: CompactVertexId) -> &[(CompactVertexId, CompactEdgeId)] {
227 let start = self.offsets[v as usize] as usize;
228 let end = self.offsets[v as usize + 1] as usize;
229 &self.neighbors[start..end]
230 }
231
232 pub fn degree(&self, v: CompactVertexId) -> u16 {
233 self.offsets[v as usize + 1] - self.offsets[v as usize]
234 }
235}
236
237#[repr(C)]
247pub struct CompactCoreState {
248 pub adjacency: CompactAdjacency,
250 pub edges: [CompactEdge; MAX_EDGES_PER_CORE],
252 pub num_vertices: u16,
254 pub num_edges: u16,
256 pub min_cut: u16,
258 pub best_witness: CompactWitness,
260 pub lambda_min: u16,
262 pub lambda_max: u16,
263 pub core_id: u8,
265 pub status: u8,
267}
268
269impl CompactCoreState {
270 pub const STATUS_IDLE: u8 = 0;
271 pub const STATUS_PROCESSING: u8 = 1;
272 pub const STATUS_DONE: u8 = 2;
273 pub const STATUS_ERROR: u8 = 3;
274
275 pub const fn size() -> usize {
276 size_of::<Self>()
277 }
278}
279
280const _: () = assert!(CompactCoreState::size() <= 8192, "CompactCoreState exceeds 8KB");
282
283#[derive(Clone, Copy, Default)]
285#[repr(C)]
286pub struct CoreResult {
287 pub core_id: u8,
288 pub status: u8,
289 pub min_cut: u16,
290 pub witness_hash: u16,
291 pub witness_seed: CompactVertexId,
292 pub witness_cardinality: u16,
293 pub witness_boundary: u16,
294 pub padding: [u8; 4],
295}
296
297#[cfg(test)]
298mod tests {
299 use super::*;
300
301 #[test]
302 fn test_bitset256_basic() {
303 let mut bs = BitSet256::new();
304 assert!(!bs.contains(0));
305
306 bs.insert(0);
307 bs.insert(100);
308 bs.insert(255);
309
310 assert!(bs.contains(0));
311 assert!(bs.contains(100));
312 assert!(bs.contains(255));
313 assert!(!bs.contains(50));
314
315 assert_eq!(bs.count(), 3);
316 }
317
318 #[test]
319 fn test_bitset256_iter() {
320 let mut bs = BitSet256::new();
321 bs.insert(1);
322 bs.insert(64);
323 bs.insert(200);
324
325 let collected: alloc::vec::Vec<_> = bs.iter().collect();
326 assert_eq!(collected, alloc::vec![1, 64, 200]);
327 }
328
329 #[test]
330 fn test_compact_witness_size() {
331 assert_eq!(size_of::<CompactWitness>(), 64);
333 }
334
335 #[test]
336 fn test_compact_edge_size() {
337 assert_eq!(size_of::<CompactEdge>(), 8);
338 }
339
340 #[test]
341 fn test_core_state_fits_8kb() {
342 assert!(CompactCoreState::size() <= 8192);
343 }
346
347 #[test]
348 fn test_bitset_operations() {
349 let mut a = BitSet256::new();
350 let mut b = BitSet256::new();
351
352 a.insert(1);
353 a.insert(2);
354 b.insert(2);
355 b.insert(3);
356
357 let union = a.union(&b);
358 assert!(union.contains(1));
359 assert!(union.contains(2));
360 assert!(union.contains(3));
361
362 let inter = a.intersection(&b);
363 assert!(!inter.contains(1));
364 assert!(inter.contains(2));
365 assert!(!inter.contains(3));
366 }
367}