use crate::{
db::{atom::AtomDB, keys::ClauseKey},
structures::{atom::Atom, clause::ClauseKind, literal::abLiteral},
types::err::{self},
};
pub enum WatchTag {
Binary(abLiteral, ClauseKey),
Clause(ClauseKey),
}
#[derive(Clone, Copy, PartialEq)]
pub enum WatchStatus {
Witness,
None,
Conflict,
}
pub struct WatchDB {
positive_binary: Vec<WatchTag>,
positive_long: Vec<WatchTag>,
negative_binary: Vec<WatchTag>,
negative_long: Vec<WatchTag>,
}
impl Default for WatchDB {
fn default() -> Self {
Self {
positive_binary: Vec::default(),
positive_long: Vec::default(),
negative_binary: Vec::default(),
negative_long: Vec::default(),
}
}
}
impl WatchDB {
fn occurrences_binary(&mut self, value: bool) -> &mut Vec<WatchTag> {
match value {
true => &mut self.positive_binary,
false => &mut self.negative_binary,
}
}
fn occurrences_long(&mut self, value: bool) -> &mut Vec<WatchTag> {
match value {
true => &mut self.positive_long,
false => &mut self.negative_long,
}
}
}
impl AtomDB {
pub unsafe fn add_watch_unchecked(&mut self, atom: Atom, value: bool, watcher: WatchTag) {
match watcher {
WatchTag::Binary(_, _) => match value {
true => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.positive_binary
.push(watcher),
false => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.negative_binary
.push(watcher),
},
WatchTag::Clause(_) => match value {
true => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.positive_long
.push(watcher),
false => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.negative_long
.push(watcher),
},
}
}
pub unsafe fn unwatch_unchecked(
&mut self,
atom: Atom,
value: bool,
key: &ClauseKey,
) -> Result<(), err::Watch> {
match key {
ClauseKey::Original(_) | ClauseKey::Addition(_, _) => {
let list = match value {
true => {
&mut self
.watch_dbs
.get_unchecked_mut(atom as usize)
.positive_long
}
false => {
&mut self
.watch_dbs
.get_unchecked_mut(atom as usize)
.negative_long
}
};
let mut index = 0;
let mut limit = list.len();
while index < limit {
let WatchTag::Clause(list_key) = list.get_unchecked(index) else {
return Err(err::Watch::NotLongInLong);
};
if list_key == key {
list.swap_remove(index);
limit -= 1;
} else {
index += 1;
}
}
Ok(())
}
ClauseKey::Unit(_) | ClauseKey::Binary(_) => Err(err::Watch::NotLongInLong),
}
}
pub unsafe fn get_watch_list_unchecked(
&mut self,
atom: Atom,
kind: ClauseKind,
value: bool,
) -> *mut Vec<WatchTag> {
match kind {
ClauseKind::Empty => panic!("!"),
ClauseKind::Unit => panic!("!"),
ClauseKind::Binary => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.occurrences_binary(value),
ClauseKind::Long => self
.watch_dbs
.get_unchecked_mut(atom as usize)
.occurrences_long(value),
}
}
}