use std::collections::{BTreeSet, HashMap, HashSet};
use std::hash::BuildHasher;
use std::iter::FusedIterator;
use std::marker::PhantomData;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use crate::{Edge, LevelNo, Manager, NodeID};
mod on_drop;
mod substitution;
pub mod edge_hash_map;
pub use edge_hash_map::EdgeHashMap;
pub mod num;
pub use on_drop::*;
pub use substitution::*;
pub mod var_name_map;
pub use var_name_map::VarNameMap;
pub use nanorand::WyRand as Rng;
#[repr(transparent)]
#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub struct Borrowed<'a, H>(ManuallyDrop<H>, PhantomData<&'a H>);
impl<'a, H> Borrowed<'a, H> {
#[must_use]
#[inline]
pub fn new(handle: H) -> Self {
Self(ManuallyDrop::new(handle), PhantomData)
}
#[inline]
pub unsafe fn into_inner(this: Self) -> ManuallyDrop<H> {
this.0
}
}
impl<'a, H> Deref for Borrowed<'a, H> {
type Target = H;
#[inline]
fn deref(&self) -> &H {
self.0.deref()
}
}
impl<'a, E: Edge> Borrowed<'a, E> {
#[inline]
pub fn edge_with_tag(self, tag: E::Tag) -> Self {
let guard = AbortOnDrop("`Edge::with_tag_owned` panicked.");
let edge = ManuallyDrop::into_inner(self.0);
let res = Self(ManuallyDrop::new(edge.with_tag_owned(tag)), PhantomData);
guard.defuse();
res
}
}
pub trait DropWith<E: Edge>: Sized {
fn drop_with(self, drop_edge: impl Fn(E));
#[inline]
fn drop_with_manager<M: Manager<Edge = E>>(self, manager: &M) {
self.drop_with(|e| manager.drop_edge(e));
}
}
pub struct BorrowedEdgeIter<'a, E, I>(I, PhantomData<Borrowed<'a, E>>);
impl<'a, E: Edge, I: Iterator<Item = &'a E>> From<I> for BorrowedEdgeIter<'a, E, I> {
fn from(it: I) -> Self {
Self(it, PhantomData)
}
}
impl<'a, E: Edge, I: Iterator<Item = &'a E>> Iterator for BorrowedEdgeIter<'a, E, I> {
type Item = Borrowed<'a, E>;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
Some(self.0.next()?.borrowed())
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.0.size_hint()
}
}
impl<'a, E: Edge, I: FusedIterator<Item = &'a E>> FusedIterator for BorrowedEdgeIter<'a, E, I> {}
impl<'a, E: Edge, I: ExactSizeIterator<Item = &'a E>> ExactSizeIterator
for BorrowedEdgeIter<'a, E, I>
{
#[inline]
fn len(&self) -> usize {
self.0.len()
}
}
pub trait NodeSet<E>: Clone + Default + Eq {
#[must_use]
fn len(&self) -> usize;
#[must_use]
fn is_empty(&self) -> bool {
self.len() == 0
}
fn insert(&mut self, edge: &E) -> bool;
#[must_use]
fn contains(&self, edge: &E) -> bool;
fn remove(&mut self, edge: &E) -> bool;
}
impl<E: Edge, S: Clone + Default + BuildHasher> NodeSet<E> for HashSet<NodeID, S> {
#[inline]
fn len(&self) -> usize {
HashSet::len(self)
}
#[inline]
fn insert(&mut self, edge: &E) -> bool {
self.insert(edge.node_id())
}
#[inline]
fn contains(&self, edge: &E) -> bool {
self.contains(&edge.node_id())
}
#[inline]
fn remove(&mut self, edge: &E) -> bool {
self.remove(&edge.node_id())
}
}
impl<E: Edge> NodeSet<E> for BTreeSet<NodeID> {
#[inline]
fn len(&self) -> usize {
BTreeSet::len(self)
}
#[inline]
fn insert(&mut self, edge: &E) -> bool {
self.insert(edge.node_id())
}
#[inline]
fn contains(&self, edge: &E) -> bool {
self.contains(&edge.node_id())
}
#[inline]
fn remove(&mut self, edge: &E) -> bool {
self.remove(&edge.node_id())
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[repr(i8)]
pub enum OptBool {
None = -1,
#[allow(missing_docs)]
False = 0,
#[allow(missing_docs)]
True = 1,
}
impl From<bool> for OptBool {
fn from(value: bool) -> Self {
if value {
Self::True
} else {
Self::False
}
}
}
#[deprecated = "use oxidd_core::error::OutOfMemory instead"]
pub type OutOfMemory = crate::error::OutOfMemory;
pub type AllocResult<T> = Result<T, crate::error::OutOfMemory>;
pub trait IsFloatingPoint {
const FLOATING_POINT: bool;
const MIN_EXP: i32;
}
impl<T: std::ops::ShlAssign<i32>> IsFloatingPoint for T {
const FLOATING_POINT: bool = false;
const MIN_EXP: i32 = 0;
}
pub trait SatCountNumber:
Clone
+ From<u32>
+ for<'a> std::ops::AddAssign<&'a Self>
+ for<'a> std::ops::SubAssign<&'a Self>
+ std::ops::ShlAssign<u32>
+ std::ops::ShrAssign<u32>
+ IsFloatingPoint
{
}
impl<T> SatCountNumber for T where
T: Clone
+ From<u32>
+ for<'a> std::ops::AddAssign<&'a T>
+ for<'a> std::ops::SubAssign<&'a T>
+ std::ops::ShlAssign<u32>
+ std::ops::ShrAssign<u32>
+ IsFloatingPoint
{
}
pub struct SatCountCache<N: SatCountNumber, S: BuildHasher> {
pub map: HashMap<NodeID, N, S>,
vars: LevelNo,
epoch: u64,
}
impl<N: SatCountNumber, S: BuildHasher + Default> Default for SatCountCache<N, S> {
fn default() -> Self {
Self {
map: HashMap::default(),
vars: 0,
epoch: 0,
}
}
}
impl<N: SatCountNumber, S: BuildHasher> SatCountCache<N, S> {
pub fn with_hasher(hash_builder: S) -> Self {
Self {
map: HashMap::with_hasher(hash_builder),
vars: 0,
epoch: 0,
}
}
pub fn clear_if_invalid<M: Manager>(&mut self, manager: &M, vars: LevelNo) {
let epoch = manager.gc_count();
if epoch != self.epoch || vars != self.vars {
self.epoch = epoch;
self.vars = vars;
self.map.clear();
}
}
}