use crate::{
db::{
atom::{
watch_db::{WatchStatus, WatchTag},
AtomDB,
},
keys::ClauseKey,
},
structures::{
atom::Atom,
literal::{abLiteral, Literal},
},
};
use super::dbClause;
impl dbClause {
pub unsafe fn get_watch_a(&self) -> &abLiteral {
self.get_unchecked(0)
}
pub fn initialise_watches(&mut self, atoms: &mut AtomDB) {
let mut watch_a_set = false;
for (index, literal) in self.clause.iter().enumerate() {
let index_value = atoms.value_of(literal.atom());
match index_value {
None => {
self.note_watch(literal.atom(), literal.polarity(), atoms);
self.clause.swap(0, index);
watch_a_set = true;
break;
}
Some(value) if value == literal.polarity() => {
self.note_watch(literal.atom(), literal.polarity(), atoms);
self.clause.swap(0, index);
watch_a_set = true;
break;
}
Some(_) => {}
}
}
if !watch_a_set {
let zero_literal = unsafe { self.clause.get_unchecked(0) };
self.note_watch(zero_literal.atom(), zero_literal.polarity(), atoms);
}
let mut watch_b_set = false;
self.watch_ptr = 1;
for index in 1..self.clause.len() {
let literal = unsafe { self.clause.get_unchecked(index) };
match atoms.value_of(literal.atom()) {
None => {
self.watch_ptr = index;
self.note_watch(literal.atom(), literal.polarity(), atoms);
watch_b_set = true;
break;
}
Some(value) if value == literal.polarity() => {
self.watch_ptr = index;
self.note_watch(literal.atom(), literal.polarity(), atoms);
watch_b_set = true;
break;
}
Some(_) => {}
}
}
if !watch_b_set {
let ptr_literal = unsafe { self.clause.get_unchecked(self.watch_ptr) };
self.note_watch(ptr_literal.atom(), ptr_literal.polarity(), atoms);
}
}
pub fn note_watch(&self, atom: Atom, value: bool, atoms: &mut AtomDB) {
match self.key {
ClauseKey::Unit(_) => {
panic!("attempting to interact with watches on a unit clause")
}
ClauseKey::Binary(_) => unsafe {
let check_literal = if self.clause.get_unchecked(0).atom() == atom {
*self.clause.get_unchecked(1)
} else {
*self.clause.get_unchecked(0)
};
atoms.add_watch_unchecked(atom, value, WatchTag::Binary(check_literal, self.key()));
},
ClauseKey::Original(_) | ClauseKey::Addition(_, _) => unsafe {
atoms.add_watch_unchecked(atom, value, WatchTag::Clause(self.key()));
},
}
}
#[inline(always)]
#[allow(clippy::result_unit_err)]
pub unsafe fn update_watch(
&mut self,
atom: Atom,
atoms: &mut AtomDB,
) -> Result<WatchStatus, ()> {
if self.clause.get_unchecked(0).atom() == atom {
self.clause.swap(0, self.watch_ptr)
}
let watch_ptr_cache = self.watch_ptr;
let clause_length = self.clause.len();
loop {
self.watch_ptr += 1;
if self.watch_ptr == clause_length {
self.watch_ptr = 1 }
if self.watch_ptr == watch_ptr_cache {
break Err(());
}
let literal = unsafe { self.clause.get_unchecked(self.watch_ptr) };
match atoms.value_of(literal.atom()) {
None => {
self.note_watch(literal.atom(), literal.polarity(), atoms);
break Ok(WatchStatus::None);
}
Some(value) if value == literal.polarity() => {
self.note_watch(literal.atom(), literal.polarity(), atoms);
break Ok(WatchStatus::Witness);
}
Some(_) => {}
}
}
}
}