use std::collections::BinaryHeap;
use std::collections::HashSet;
use nid::{NID, IDX};
use vid::VID;
pub type VHLHashMap<K,V> = hashbrown::hash_map::HashMap<K,V>;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct HiLo {pub hi:NID, pub lo:NID}
impl HiLo {
pub fn new(hi:NID, lo:NID)->HiLo { HiLo { hi, lo } }
#[inline] pub fn invert(self)-> HiLo { HiLo{ hi: !self.hi, lo: !self.lo }}
pub fn get_part(&self, which:HiLoPart)->NID {
if which == HiLoPart::HiPart { self.hi } else { self.lo }} }
impl std::ops::Not for HiLo {
type Output = HiLo;
fn not(self)-> HiLo {HiLo { hi:!self.hi, lo: !self.lo }}}
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct VHL {pub v:VID, pub hi:NID, pub lo:NID}
impl VHL {
pub fn new(v: VID, hi:NID, lo:NID)->VHL { VHL{ v, hi, lo } }
pub fn hilo(&self)->HiLo { HiLo{ hi:self.hi, lo: self.lo } }}
impl std::ops::Not for VHL {
type Output = VHL;
fn not(self)->VHL { VHL { v:self.v, hi:!self.hi, lo: !self.lo }}}
#[derive(PartialEq,Debug,Copy,Clone)]
pub enum HiLoPart { HiPart, LoPart }
#[derive(PartialEq,Debug,Copy,Clone)]
pub struct VHLParts{
pub v:VID,
pub hi:Option<NID>,
pub lo:Option<NID>,
pub invert:bool}
impl VHLParts {
pub fn hilo(&self)->Option<HiLo> {
if let (Some(hi), Some(lo)) = (self.hi, self.lo) { Some(HiLo{hi,lo}) }
else { None }}}
pub trait Walkable {
fn step<F>(&self, n:NID, f:&mut F, seen:&mut HashSet<NID>, topdown:bool)
where F: FnMut(NID,VID,NID,NID);
fn walk<F>(&self, n:NID, f:&mut F) where F: FnMut(NID,VID,NID,NID) {
let mut seen = HashSet::new();
self.step(n, f, &mut seen, true)}
fn walk_up<F>(&self, n:NID, f:&mut F) where F: FnMut(NID,VID,NID,NID) {
let mut seen = HashSet::new();
self.step(n, f, &mut seen, false)}
#[deprecated]
fn as_heap(&self, n:NID)->BinaryHeap<(VHL, NID)> {
let mut result = BinaryHeap::new();
self.walk_up(n, &mut |nid, v, hi, lo| result.push((VHL{ v, hi, lo }, nid)));
result }}
pub trait HiLoBase {
fn get_hilo(&self, n:NID)->Option<HiLo>;
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct HiLoCache {
hilos: Vec<HiLo>,
index: VHLHashMap<HiLo, IDX>,
vindex: VHLHashMap<(VID,HiLo), IDX>}
impl HiLoCache {
pub fn new()->Self {
HiLoCache {
hilos: vec![],
index: VHLHashMap::default(),
vindex: VHLHashMap::default()}}
#[inline] pub fn get_hilo(&self, n:NID)->HiLo {
assert!(!n.is_lit());
let res = self.hilos[n.idx()];
if n.is_inv() { res.invert() } else { res }}
#[inline] pub fn get_node(&self, v:VID, hl0:HiLo)-> Option<NID> {
let inv = hl0.lo.is_inv();
let hl1 = if inv { hl0.invert() } else { hl0 };
let to_nid = |&ix| NID::from_vid_idx(v, ix);
let res = self.vindex.get(&(v, hl1)).map(to_nid);
if inv { res.map(|nid| !nid ) } else { res }}
#[inline] pub fn insert(&mut self, v:VID, hl0:HiLo)->NID {
let inv = hl0.lo.is_inv();
let hilo = if inv { hl0.invert() } else { hl0 };
let ix:IDX =
if let Some(&ix) = self.index.get(&hilo) { ix }
else {
let ix = self.hilos.len() as IDX;
self.hilos.push(hilo);
self.index.insert(hilo, ix);
self.vindex.insert((v,hilo), ix);
ix };
let res = NID::from_vid_idx(v, ix);
if inv { !res } else { res } }}
impl Default for HiLoCache {
fn default() -> Self { Self::new() }}