1use std::collections::BinaryHeap;
3use std::collections::HashSet;
4use dashmap::DashMap;
5use crate::nid::NID;
6use crate::vid::VID;
7
8type VhlHashMap<K,V> = DashMap<K,V,fxhash::FxBuildHasher>;
9
10#[derive(Debug,Default,Clone)]
11struct VhlVec<T>{ pub vec: boxcar::Vec<T> }
12
13
14#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Default)]
18pub struct HiLo {pub hi:NID, pub lo:NID}
19
20impl HiLo {
21 pub fn new(hi:NID, lo:NID)->HiLo { HiLo { hi, lo } }
23
24 #[inline] pub fn invert(self)-> HiLo { HiLo{ hi: !self.hi, lo: !self.lo }}
26
27 pub fn get_part(&self, which:HiLoPart)->NID {
28 if which == HiLoPart::HiPart { self.hi } else { self.lo }} }
29
30impl std::ops::Not for HiLo {
31 type Output = HiLo;
32 fn not(self)-> HiLo {HiLo { hi:!self.hi, lo: !self.lo }}}
33
34
35#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
37pub struct Vhl {pub v:VID, pub hi:NID, pub lo:NID}
38
39impl Vhl {
40 pub fn new(v: VID, hi:NID, lo:NID)->Vhl { Vhl{ v, hi, lo } }
41 pub fn hilo(&self)->HiLo { HiLo{ hi:self.hi, lo: self.lo } }}
42
43impl std::ops::Not for Vhl {
44 type Output = Vhl;
45 fn not(self)->Vhl { Vhl { v:self.v, hi:!self.hi, lo: !self.lo }}}
46
47
48#[derive(PartialEq,Debug,Copy,Clone)]
50pub enum HiLoPart { HiPart, LoPart }
51
52#[derive(Default,PartialEq,Debug,Copy,Clone)]
54pub struct VhlParts{
55 pub v:VID,
56 pub hi:Option<NID>,
57 pub lo:Option<NID>,
58 pub invert:bool}
59
60 impl VhlParts {
61 pub fn hilo(&self)->Option<HiLo> {
62 if let (Some(hi), Some(lo)) = (self.hi, self.lo) { Some(HiLo{hi,lo}) }
63 else { None }}
64 pub fn set_part(&mut self, part:HiLoPart, v:Option<NID>) {
65 if part == HiLoPart::HiPart { self.hi = v }
66 else { self.lo = v }}}
67
68
69pub trait Walkable {
70
71 fn step<F>(&self, n:NID, f:&mut F, seen:&mut HashSet<NID>, topdown:bool)
73 where F: FnMut(NID,VID,NID,NID);
74
75 fn walk_dn<F>(&self, n:NID, f:&mut F) where F: FnMut(NID,VID,NID,NID) {
78 let mut seen = HashSet::new();
79 self.step(n, f, &mut seen, true)}
80
81 fn walk_up<F>(&self, n:NID, f:&mut F) where F: FnMut(NID,VID,NID,NID) {
86 let mut seen = HashSet::new();
87 self.step(n, f, &mut seen, false)}
88
89 fn walk_up_each<F>(&self, nids:&[NID], f:&mut F) where F: FnMut(NID,VID,NID,NID) {
92 let mut seen = HashSet::new();
93 for &n in nids { self.step(n, f, &mut seen, false) }}
94
95 #[deprecated]
99 fn as_heap(&self, n:NID)->BinaryHeap<(Vhl, NID)> {
100 let mut result = BinaryHeap::new();
101 self.walk_up(n, &mut |nid, v, hi, lo| result.push((Vhl{ v, hi, lo }, nid)));
102 result }}
103
104
105pub trait HiLoBase {
106 fn get_hilo(&self, n:NID)->Option<HiLo>; }
107
108
109#[derive(Debug, Default, Clone)]
110pub struct HiLoCache {
111 hilos: VhlVec<HiLo>,
113 index: VhlHashMap<HiLo, usize>}
115
116
117impl HiLoCache {
118
119 pub fn new()->Self { Self::default() }
120
121 pub fn len(&self)->usize { self.hilos.vec.len() }
122 #[must_use] pub fn is_empty(&self) -> bool { self.len() == 0 }
123
124 #[inline] pub fn get_hilo(&self, n:NID)->HiLo {
126 assert!(!n.is_lit());
127 let res = self.hilos.vec[n.idx()];
128 if n.is_inv() { res.invert() } else { res }}
129
130 #[inline] pub fn get_node(&self, v:VID, hl0:HiLo)-> Option<NID> {
131 let inv = hl0.lo.is_inv();
132 let hl1 = if inv { hl0.invert() } else { hl0 };
133 if let Some(x) = self.index.get(&hl1) {
134 if hl1.hi.vid().is_below(&v) && hl1.lo.vid().is_below(&v) {
139 let nid = NID::from_vid_idx(v, *x);
140 return Some(if inv { !nid } else { nid }) }}
141 None }
142
143 #[inline] pub fn insert(&self, v:VID, hl0:HiLo)->NID {
144 let inv = hl0.lo.is_inv();
145 let hilo = if inv { hl0.invert() } else { hl0 };
146 let ix:usize =
147 if let Some(ix) = self.index.get(&hilo) { *ix }
148 else {
149 let ix = self.hilos.vec.push(hilo);
150 self.index.insert(hilo, ix);
151 ix };
152 let res = NID::from_vid_idx(v, ix);
153 if inv { !res } else { res } }}