use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::Hash;
use std::marker::PhantomData;
use super::points_to::PointsToSet;
use crate::util::bit_vec::Idx;
pub struct BasePTData<K, KS, D, DS> {
pts_map: HashMap<K, DS>,
rev_pts_map: HashMap<D, KS>,
}
impl<K, KS, D, DS> fmt::Debug for BasePTData<K, KS, D, DS> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"BasePTData".fmt(f)
}
}
impl<K, D, DS> BasePTData<K, HashSet<K>, D, DS>
where
K: Hash + Eq + Copy,
D: Idx,
DS: PointsToSet<D>,
{
pub fn new() -> BasePTData<K, HashSet<K>, D, DS> {
BasePTData {
pts_map: HashMap::new(),
rev_pts_map: HashMap::new(),
}
}
#[inline]
pub fn get_pts_map(&self) -> &HashMap<K, DS> {
&self.pts_map
}
#[inline]
pub fn clear(&mut self) {
self.pts_map.clear();
self.rev_pts_map.clear();
}
#[inline]
pub fn get_pts(&self, var: K) -> Option<&DS> {
self.pts_map.get(&var)
}
#[inline]
pub fn get_mut_pts(&mut self, var: K) -> Option<&mut DS> {
self.pts_map.get_mut(&var)
}
#[inline]
pub fn get_rev_pts(&self, elem: D) -> Option<&HashSet<K>> {
self.rev_pts_map.get(&elem)
}
pub fn add_pts(&mut self, var: K, elem: D) -> bool {
self.rev_pts_map.entry(elem).or_default().insert(var);
self.pts_map.entry(var).or_insert(DS::new()).insert(elem)
}
pub fn union_pts(&mut self, dst_var: K, src_var: K) -> bool {
if self.get_pts(src_var).is_some() {
let dst_ds = unsafe { &mut *(self.pts_map.entry(dst_var).or_insert(DS::new()) as *mut DS) };
let src_ds = unsafe { &*(self.pts_map.get(&src_var).unwrap() as *const DS) };
self.add_rev_pts(src_ds, dst_var);
dst_ds.union(src_ds)
} else {
false
}
}
pub fn union_pts_to(&mut self, dst_var: K, src_ds: &DS) -> bool {
self.add_rev_pts(src_ds, dst_var);
let dst_ds = self.pts_map.entry(dst_var).or_insert(DS::new());
dst_ds.union(src_ds)
}
pub fn remove_pts_elem(&mut self, var: K, elem: D) -> bool {
if let Some(vars) = self.rev_pts_map.get_mut(&elem) {
vars.remove(&var);
}
if let Some(pts) = self.pts_map.get_mut(&var) {
pts.remove(elem)
} else {
false
}
}
pub fn clear_pts(&mut self, var: K) {
if let Some(pts) = self.pts_map.get_mut(&var) {
for elem in pts.iter() {
self.rev_pts_map.get_mut(&elem).unwrap().remove(&var);
}
pts.clear();
}
}
pub fn dump_pt_data(&self) {
unimplemented!("implement if/when necessary");
}
#[inline]
fn add_rev_pts(&mut self, data_set: &DS, var: K) {
for elem in data_set.iter() {
self.rev_pts_map.entry(elem).or_default().insert(var);
}
}
}
pub struct DiffPTData<K, D, DS> {
pub(crate) diff_pts_map: HashMap<K, DS>,
pub(crate) propa_pts_map: HashMap<K, DS>,
marker: PhantomData<D>,
}
impl<K, D, DS> fmt::Debug for DiffPTData<K, D, DS> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"DiffPTData".fmt(f)
}
}
impl<K, D, DS> DiffPTData<K, D, DS>
where
K: Hash + Eq + Copy,
D: Idx,
DS: PointsToSet<D> + Clone + fmt::Debug,
for<'a> &'a DS: IntoIterator<Item = D>,
{
pub fn new() -> DiffPTData<K, D, DS> {
DiffPTData {
diff_pts_map: HashMap::new(),
propa_pts_map: HashMap::new(),
marker: PhantomData,
}
}
#[inline]
pub fn clear(&mut self) {
self.diff_pts_map.clear();
self.propa_pts_map.clear();
}
#[inline]
pub fn add_pts(&mut self, var: K, elem: D) -> bool {
if let Some(propa) = self.propa_pts_map.get(&var) {
if propa.contains(elem) {
return false;
}
}
let diff = self.diff_pts_map.entry(var).or_insert(DS::new());
diff.insert(elem)
}
pub fn union_diff_pts(&mut self, dst_var: K, src_var: K) -> bool {
if dst_var == src_var {
return false;
}
let mut changed = false;
if let Some(diff) = self.diff_pts_map.get(&src_var) {
let src_ds = diff.clone();
changed |= self.union_pts_to(dst_var, &src_ds);
}
changed
}
#[inline]
pub fn union_pts(&mut self, dst_var: K, src_var: K) -> bool {
if dst_var == src_var {
return false;
}
let mut changed = false;
if let Some(diff) = self.diff_pts_map.get(&src_var) {
let src_ds = diff.clone();
changed |= self.union_pts_to(dst_var, &src_ds);
}
if let Some(propa) = self.propa_pts_map.get(&src_var) {
let src_ds = propa.clone();
changed |= self.union_pts_to(dst_var, &src_ds);
}
changed
}
#[inline]
pub fn union_pts_to(&mut self, dst_var: K, src_ds: &DS) -> bool {
let diff = self.diff_pts_map.entry(dst_var).or_insert(DS::new());
let propa = self.propa_pts_map.entry(dst_var).or_insert(DS::new());
let mut new = src_ds.clone();
new.subtract(propa);
diff.union(&new)
}
#[inline]
pub fn remove_pts_elem(&mut self, var: K, elem: D) -> bool {
let diff = self.diff_pts_map.entry(var).or_insert(DS::new());
let propa = self.propa_pts_map.entry(var).or_insert(DS::new());
diff.remove(elem) | propa.remove(elem)
}
#[inline]
pub fn get_diff_pts(&self, var: K) -> Option<&DS> {
self.diff_pts_map.get(&var)
}
#[inline]
pub fn get_mut_diff_pts(&mut self, var: K) -> Option<&mut DS> {
self.diff_pts_map.get_mut(&var)
}
#[inline]
pub fn get_propa_pts(&self, var: K) -> Option<&DS> {
self.propa_pts_map.get(&var)
}
#[inline]
pub fn get_mut_propa_pts(&mut self, var: K) -> Option<&mut DS> {
self.propa_pts_map.get_mut(&var)
}
pub fn flush(&mut self, var: K) {
if !self.diff_pts_map.contains_key(&var) {
return;
}
let diff = self.diff_pts_map.get_mut(&var).unwrap();
let propa = self.propa_pts_map.entry(var).or_insert(DS::new());
propa.union(diff);
diff.clear();
}
#[inline]
pub fn clear_pts(&mut self, var: K) {
if let Some(diff) = self.diff_pts_map.get_mut(&var) {
diff.clear();
}
if let Some(propa) = self.propa_pts_map.get_mut(&var) {
propa.clear();
}
}
pub fn clear_diff_pts(&mut self, var: K) {
if let Some(diff) = self.diff_pts_map.get_mut(&var) {
diff.clear()
}
}
pub fn clear_propa_pts(&mut self, var: K) {
if let Some(propa) = self.propa_pts_map.get_mut(&var) {
propa.clear()
}
}
#[inline]
pub fn dump_pt_data(&self) {
unimplemented!("implement if/when necessary");
}
}