diff --git a/buddy/ChangeLog b/buddy/ChangeLog index 0985d52bb..6bf505156 100644 --- a/buddy/ChangeLog +++ b/buddy/ChangeLog @@ -1,3 +1,8 @@ +2010-11-07 Alexandre Duret-Lutz + + * src/bddop.c (bdd_setxor): New function. + * src/bdd.h (bdd_setxor): New function. + 2010-01-22 Alexandre Duret-Lutz Get rid of some "deprecated conversion from string constant to diff --git a/buddy/src/bdd.h b/buddy/src/bdd.h index 53dc3a6e1..d9c12ded1 100644 --- a/buddy/src/bdd.h +++ b/buddy/src/bdd.h @@ -285,6 +285,7 @@ extern BDD bdd_or(BDD, BDD); extern BDD bdd_xor(BDD, BDD); extern BDD bdd_imp(BDD, BDD); extern BDD bdd_biimp(BDD, BDD); +extern BDD bdd_setxor(BDD, BDD); extern BDD bdd_ite(BDD, BDD, BDD); extern BDD bdd_restrict(BDD, BDD); extern BDD bdd_constrain(BDD, BDD); @@ -492,6 +493,7 @@ private: friend bdd bdd_xor(const bdd &, const bdd &); friend bdd bdd_imp(const bdd &, const bdd &); friend bdd bdd_biimp(const bdd &, const bdd &); + friend bdd bdd_setxor(const bdd &, const bdd &); friend bdd bdd_ite(const bdd &, const bdd &, const bdd &); friend bdd bdd_restrict(const bdd &, const bdd &); friend bdd bdd_constrain(const bdd &, const bdd &); @@ -649,6 +651,9 @@ inline bdd bdd_imp(const bdd &l, const bdd &r) inline bdd bdd_biimp(const bdd &l, const bdd &r) { return bdd_apply(l.root, r.root, bddop_biimp); } +inline bdd bdd_setxor(const bdd &l, const bdd &r) +{ return bdd_setxor(l.root, r.root); } + inline bdd bdd_ite(const bdd &f, const bdd &g, const bdd &h) { return bdd_ite(f.root, g.root, h.root); } diff --git a/buddy/src/bddop.c b/buddy/src/bddop.c index 420579295..b3a8b6404 100644 --- a/buddy/src/bddop.c +++ b/buddy/src/bddop.c @@ -49,6 +49,7 @@ #define CACHEID_SATCOU 0x2 #define CACHEID_SATCOULN 0x3 #define CACHEID_PATHCOU 0x4 +#define CACHEID_SETXOR 0x5 /* Hash value modifiers for replace/compose */ #define CACHEID_REPLACE 0x0 @@ -156,6 +157,7 @@ static int varset2svartable(BDD); #define NOTHASH(r) (r) #define APPLYHASH(l,r,op) (TRIPLE(l,r,op)) #define ITEHASH(f,g,h) (TRIPLE(f,g,h)) +#define SETXORHASH(l,r) (TRIPLE(l,r,CACHEID_SETXOR)) #define RESTRHASH(r,var) (PAIR(r,var)) #define CONSTRAINHASH(f,c) (PAIR(f,c)) #define QUANTHASH(r) (r) @@ -722,6 +724,111 @@ BDD bdd_biimp(BDD l, BDD r) return bdd_apply(l,r,bddop_biimp); } +/*=== bdd_setxor =========================================================*/ + +/* +NAME {* bdd\_setxor *} +SECTION {* operator *} +SHORT {* xor operator for variable sets *} +PROTO {* BDD bdd_setxor(BDD l, BDD r) *} +DESCR {* Given to set $l$ and $r$ represented as conjuctions of variables. + (positive variables are present in the set, negative or absent + variables are not in the set), this computes + $(l\setminus r)\cup(r\setminus l)$. The resulting set will be + represented as a conjunction in which all variables occur + (positive variables are present in the set, negative variables + are not in the set) *} +RETURN {* The BDD for $(l\setminus r)\cup(r\setminus l)$ *} +*/ +BDD bdd_setxor(BDD l, BDD r) +{ + BddCacheData *entry; + BDD res; + + if (ISONE(l)) + return r; + if (ISONE(r)) + return l; + + entry = BddCache_lookup(&misccache, SETXORHASH(l,r)); + if (entry->a == l && entry->b == r && entry->c == CACHEID_SETXOR) + { +#ifdef CACHESTATS + bddcachestats.opHit++; +#endif + return entry->r.res; + } +#ifdef CACHESTATS + bddcachestats.opMiss++; +#endif + + if (LEVEL(l) == LEVEL(r)) + { + if (ISZERO(LOW(l))) + { + if (ISZERO(LOW(r))) + { + PUSHREF(bdd_setxor(HIGH(l), HIGH(r))); + res = bdd_makenode(LEVEL(l), READREF(1), 0); + } + else + { + PUSHREF(bdd_setxor(HIGH(l), LOW(r))); + res = bdd_makenode(LEVEL(l), 0, READREF(1)); + } + } + else + { + if (ISZERO(LOW(r))) + { + PUSHREF(bdd_setxor(LOW(l), HIGH(r))); + res = bdd_makenode(LEVEL(l), 0, READREF(1)); + } + else + { + PUSHREF(bdd_setxor(LOW(l), LOW(r))); + res = bdd_makenode(LEVEL(l), READREF(1), 0); + } + } + } + else if (LEVEL(l) < LEVEL(r)) + { + if (ISZERO(LOW(l))) + { + PUSHREF(bdd_setxor(HIGH(l), r)); + res = bdd_makenode(LEVEL(l), 0, READREF(1)); + } + else + { + PUSHREF(bdd_setxor(LOW(l), r)); + res = bdd_makenode(LEVEL(l), READREF(1), 0); + } + } + else /* (LEVEL(l) > LEVEL(r)) */ + { + if (ISZERO(LOW(r))) + { + PUSHREF(bdd_setxor(l, HIGH(r))); + res = bdd_makenode(LEVEL(r), 0, READREF(1)); + } + else + { + PUSHREF(bdd_setxor(l, LOW(r))); + res = bdd_makenode(LEVEL(r), READREF(1), 0); + } + } + + POPREF(1); + + entry->a = l; + entry->b = r; + entry->c = CACHEID_SETXOR; + entry->r.res = res; + + return res; +} + + /*=== ITE ==============================================================*/