logicng 0.1.0-alpha.3

A Library for Creating, Manipulating, and Solving Boolean Formulas
Documentation
use num_bigint::{BigUint, ToBigUint};

use super::bdd_prime::prime_gte;

struct BddCacheEntry {
    a: Option<usize>,
    b: usize,
    c: usize,
    bdres: BigUint,
    res: usize,
}

impl BddCacheEntry {
    fn reset(&mut self) {
        self.a = None;
        self.b = 0;
        self.c = 0;
        self.res = 0;
    }
}

pub struct BddCache {
    table: Vec<BddCacheEntry>,
}

impl BddCache {
    pub fn new(cs: usize) -> Self {
        let size = prime_gte(cs);
        let mut table = Vec::new();
        (0..size).for_each(|_x| table.push(BddCacheEntry { a: None, b: 0, c: 0, bdres: 0.to_biguint().unwrap(), res: 0 }));
        Self { table }
    }

    pub fn reset(&mut self) {
        for entry in &mut self.table {
            entry.reset();
        }
    }

    pub fn lookup_bdres(&self, hash: usize) -> BigUint {
        self.table[hash % self.table.len()].bdres.clone()
    }

    pub fn lookup_res(&self, hash: usize) -> usize {
        self.table[hash % self.table.len()].res
    }

    pub fn lookup(&self, hash: usize) -> (Option<usize>, usize, usize) {
        let entry = &self.table[hash % self.table.len()];
        (entry.a, entry.b, entry.c)
    }

    pub fn set_with_res(&mut self, hash: usize, tuple: (usize, usize, usize), res: usize) {
        let len = self.table.len();
        let entry = self.table.get_mut(hash % len).unwrap();
        entry.a = Some(tuple.0);
        entry.b = tuple.1;
        entry.c = tuple.2;
        entry.res = res;
    }

    pub fn set_with_bdres(&mut self, hash: usize, tuple: (usize, usize, usize), bdres: BigUint) {
        let len = self.table.len();
        let entry = self.table.get_mut(hash % len).unwrap();
        entry.a = Some(tuple.0);
        entry.b = tuple.1;
        entry.c = tuple.2;
        entry.bdres = bdres;
    }
}

#[cfg(test)]
mod tests {
    use num_bigint::{BigUint, ToBigUint};

    use super::BddCache;

    #[test]
    fn test_cache() {
        let mut cache = BddCache::new(10);
        let entry = cache.lookup(7);
        assert_eq!(entry, (None, 0, 0));
        assert_eq!(lookup_a(&cache, 7), None);
        assert_eq!(lookup_b(&cache, 7), 0);
        assert_eq!(lookup_c(&cache, 7), 0);
        assert_eq!(cache.lookup_bdres(7), 0.to_biguint().unwrap());
        assert_eq!(cache.lookup_res(7), 0);

        set_a(&mut cache, 5, 41);
        set_b(&mut cache, 5, 42);
        set_c(&mut cache, 5, 43);
        set_bdres(&mut cache, 5, 44.to_biguint().unwrap());
        set_res(&mut cache, 5, 45);

        assert_eq!(lookup_a(&cache, 5), Some(41));
        assert_eq!(lookup_b(&cache, 5), 42);
        assert_eq!(lookup_c(&cache, 5), 43);
        assert_eq!(cache.lookup_bdres(5), 44.to_biguint().unwrap());
        assert_eq!(cache.lookup_res(5), 45);

        set(&mut cache, 3, (1, 2, 3));
        assert_eq!(lookup_a(&cache, 3), Some(1));
        assert_eq!(lookup_b(&cache, 3), 2);
        assert_eq!(lookup_c(&cache, 3), 3);

        cache.reset();
        assert_eq!(lookup_a(&cache, 7), None);
        assert_eq!(lookup_b(&cache, 7), 0);
        assert_eq!(lookup_c(&cache, 7), 0);
        assert_eq!(cache.lookup_bdres(7), 0.to_biguint().unwrap());
        assert_eq!(cache.lookup_res(7), 0);
    }

    fn lookup_a(cache: &BddCache, hash: usize) -> Option<usize> {
        cache.table[hash % cache.table.len()].a
    }

    fn lookup_b(cache: &BddCache, hash: usize) -> usize {
        cache.table[hash % cache.table.len()].b
    }

    fn lookup_c(cache: &BddCache, hash: usize) -> usize {
        cache.table[hash % cache.table.len()].c
    }

    fn set_a(cache: &mut BddCache, hash: usize, a: usize) {
        let len = cache.table.len();
        cache.table.get_mut(hash % len).unwrap().a = Some(a);
    }

    fn set_b(cache: &mut BddCache, hash: usize, b: usize) {
        let len = cache.table.len();
        cache.table.get_mut(hash % len).unwrap().b = b;
    }

    fn set_c(cache: &mut BddCache, hash: usize, c: usize) {
        let len = cache.table.len();
        cache.table.get_mut(hash % len).unwrap().c = c;
    }

    fn set_bdres(cache: &mut BddCache, hash: usize, bdres: BigUint) {
        let len = cache.table.len();
        cache.table.get_mut(hash % len).unwrap().bdres = bdres;
    }

    fn set_res(cache: &mut BddCache, hash: usize, res: usize) {
        let len = cache.table.len();
        cache.table.get_mut(hash % len).unwrap().res = res;
    }

    fn set(cache: &mut BddCache, hash: usize, tuple: (usize, usize, usize)) {
        let len = cache.table.len();
        let entry = cache.table.get_mut(hash % len).unwrap();
        entry.a = Some(tuple.0);
        entry.b = tuple.1;
        entry.c = tuple.2;
    }
}