/**Function******************************************************************** Synopsis [Performs the recursive step of Cuddaux_IsVarIn.] Description [Performs the recursive step of Cuddaux_IsVarIn. var is supposed to be a BDD projection function. Returns the logical one or zero.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode* cuddauxIsVarInRecur(DdManager* manager, DdNode* f, DdNode* Var) { DdNode *zero,*one, *F, *res; int topV,topF; one = DD_ONE(manager); zero = Cudd_Not(one); F = Cudd_Regular(f); if (cuddIsConstant(F)) return zero; if (Var==F) return(one); topV = Var->index; topF = F->index; if (topF == topV) return(one); if (cuddI(manager,topV) < cuddI(manager,topF)) return(zero); res = cuddCacheLookup2(manager,cuddauxIsVarInRecur, F, Var); if (res != NULL) return(res); res = cuddauxIsVarInRecur(manager,cuddT(F),Var); if (res==zero){ res = cuddauxIsVarInRecur(manager,cuddE(F),Var); } cuddCacheInsert2(manager,cuddauxIsVarInRecur,F,Var,res); return(res); }
DdNode* cuddauxAddGuardOfNodeRecur(DdManager* manager, DdNode* f, DdNode* h) { DdNode *one, *res, *T, *E; int topf, toph; /* Handle terminal cases */ one = DD_ONE(manager); if (f==h){ return(one); } topf = cuddI(manager,f->index); toph = cuddI(manager,h->index); if (topf >= toph){ return Cudd_Not(one); } /* Look in the cache */ res = cuddCacheLookup2(manager,Cuddaux_addGuardOfNode,f,h); if (res != NULL) return(res); T = cuddauxAddGuardOfNodeRecur(manager,cuddT(f),h); if (T == NULL) return(NULL); cuddRef(T); E = cuddauxAddGuardOfNodeRecur(manager,cuddE(f),h); if (E == NULL){ Cudd_IterDerefBdd(manager, T); return(NULL); } cuddRef(E); if (T == E){ res = T; } else { if (Cudd_IsComplement(T)){ res = cuddUniqueInter(manager,f->index,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); return(NULL); } res = Cudd_Not(res); } else { res = cuddUniqueInter(manager,f->index,T,E); if (res == NULL) { Cudd_IterDerefBdd(manager, T); Cudd_IterDerefBdd(manager, E); return(NULL); } } } cuddDeref(T); cuddDeref(E); cuddCacheInsert2(manager,Cuddaux_addGuardOfNode,f,h,res); return(res); }
/**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddStrictThreshold.] Description [Performs the recursive step for Cudd_addBddStrictThreshold. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [addBddDoThreshold] ******************************************************************************/ static DdNode * addBddDoStrictThreshold( DdManager * dd, DdNode * f, DdNode * val) { DdNode *res, *T, *E; DdNode *fv, *fvn; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { return(Cudd_NotCond(DD_TRUE(dd),cuddV(f) <= cuddV(val))); } /* Check cache. */ res = cuddCacheLookup2(dd,addBddDoStrictThreshold,f,val); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoStrictThreshold(dd,fv,val); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoStrictThreshold(dd,fvn,val); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addBddDoStrictThreshold,f,val,res); return(res); } /* end of addBddDoStrictThreshold */
/**Function******************************************************************** Synopsis [Performs the recursive steps of Cudd_bddBoleanDiff.] Description [Performs the recursive steps of Cudd_bddBoleanDiff. Returns the BDD obtained by XORing the cofactors of f with respect to var if successful; NULL otherwise. Exploits the fact that dF/dx = dF'/dx.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddBddBooleanDiffRecur( DdManager * manager, DdNode * f, DdNode * var) { DdNode *T, *E, *res, *res1, *res2; statLine(manager); if (cuddI(manager,f->index) > manager->perm[var->index]) { /* f does not depend on var. */ return(Cudd_Not(DD_ONE(manager))); } /* From now on, f is non-constant. */ /* If the two indices are the same, so are their levels. */ if (f->index == var->index) { res = cuddBddXorRecur(manager, cuddT(f), cuddE(f)); return(res); } /* From now on, cuddI(manager,f->index) < cuddI(manager,cube->index). */ /* Check the cache. */ res = cuddCacheLookup2(manager, cuddBddBooleanDiffRecur, f, var); if (res != NULL) { return(res); } /* Compute the cofactors of f. */ T = cuddT(f); E = cuddE(f); res1 = cuddBddBooleanDiffRecur(manager, T, var); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddBddBooleanDiffRecur(manager, Cudd_Regular(E), var); if (res2 == NULL) { Cudd_IterDerefBdd(manager, res1); return(NULL); } cuddRef(res2); /* ITE takes care of possible complementation of res1 and of the ** case in which res1 == res2. */ res = cuddBddIteRecur(manager, manager->vars[f->index], res1, res2); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, cuddBddBooleanDiffRecur, f, var, res); return(res); } /* end of cuddBddBooleanDiffRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addIthBit.] Description [Performs the recursive step for Cudd_addIthBit. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * addDoIthBit( DdManager * dd, DdNode * f, DdNode * index) { DdNode *res, *T, *E; DdNode *fv, *fvn; int mask, value; int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { mask = 1 << ((int) cuddV(index)); value = (int) cuddV(f); return((value & mask) == 0 ? DD_ZERO(dd) : DD_ONE(dd)); } /* Check cache. */ res = cuddCacheLookup2(dd,addDoIthBit,f,index); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addDoIthBit(dd,fv,index); if (T == NULL) return(NULL); cuddRef(T); E = addDoIthBit(dd,fvn,index); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addDoIthBit,f,index,res); return(res); } /* end of addDoIthBit */
/**Function******************************************************************** Synopsis [Checks whether a variable is dependent on others in a function.] Description [Checks whether a variable is dependent on others in a function. Returns 1 if the variable is dependent; 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [] ******************************************************************************/ int Cudd_bddVarIsDependent( DdManager *dd, /* manager */ DdNode *f, /* function */ DdNode *var /* variable */) { DdNode *F, *res, *zero, *ft, *fe; unsigned topf, level; DD_CTFP cacheOp; int retval; /* NuSMV: begin add */ abort(); /* NOT USED BY NUSMV */ /* NuSMV: begin end */ zero = Cudd_Not(DD_TRUE(dd)); if (Cudd_IsConstant(f)) return(f == zero); /* From now on f is not constant. */ F = Cudd_Regular(f); topf = (unsigned) dd->perm[F->index]; level = (unsigned) dd->perm[var->index]; /* Check terminal case. If topf > index of var, f does not depend on var. ** Therefore, var is not dependent in f. */ if (topf > level) { return(0); } cacheOp = (DD_CTFP) Cudd_bddVarIsDependent; res = cuddCacheLookup2(dd,cacheOp,f,var); if (res != NULL) { return(res != zero); } /* Compute cofactors. */ ft = Cudd_NotCond(cuddT(F), f != F); fe = Cudd_NotCond(cuddE(F), f != F); if (topf == level) { retval = Cudd_bddLeq(dd,ft,Cudd_Not(fe)); } else { retval = Cudd_bddVarIsDependent(dd,ft,var) && Cudd_bddVarIsDependent(dd,fe,var); } cuddCacheInsert2(dd,cacheOp,f,var,Cudd_NotCond(zero,retval)); return(retval); } /* Cudd_bddVarIsDependent */
/**Function******************************************************************** Synopsis [Determines whether f is less than or equal to g.] Description [Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created. This procedure works for arbitrary ADDs. For 0-1 ADDs Cudd_addEvalConst is more efficient.] SideEffects [None] SeeAlso [Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq] ******************************************************************************/ int Cudd_addLeq( DdManager * dd, DdNode * f, DdNode * g) { DdNode *tmp, *fv, *fvn, *gv, *gvn; unsigned int topf, topg, res; /* Terminal cases. */ if (f == g) return(1); statLine(dd); if (cuddIsConstant(f)) { if (cuddIsConstant(g)) return(cuddV(f) <= cuddV(g)); if (f == DD_MINUS_INFINITY(dd)) return(1); if (f == DD_PLUS_INFINITY(dd)) return(0); /* since f != g */ } if (g == DD_PLUS_INFINITY(dd)) return(1); if (g == DD_MINUS_INFINITY(dd)) return(0); /* since f != g */ /* Check cache. */ tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_addLeq,f,g); if (tmp != NULL) { return(tmp == DD_ONE(dd)); } /* Compute cofactors. One of f and g is not constant. */ topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); if (topf <= topg) { fv = cuddT(f); fvn = cuddE(f); } else { fv = fvn = f; } if (topg <= topf) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } res = Cudd_addLeq(dd,fvn,gvn) && Cudd_addLeq(dd,fv,gv); /* Store result in cache and return. */ cuddCacheInsert2(dd,(DD_CTFP) Cudd_addLeq,f,g, Cudd_NotCond(DD_ONE(dd),res==0)); return(res); } /* end of Cudd_addLeq */
/** @brief Performs the recursive step of addScalarInverse. @return a pointer to the resulting %ADD in case of success. Returns NULL if any discriminants smaller than epsilon is encountered. @sideeffect None */ DdNode * cuddAddScalarInverseRecur( DdManager * dd, DdNode * f, DdNode * epsilon) { DdNode *t, *e, *res; CUDD_VALUE_TYPE value; statLine(dd); if (cuddIsConstant(f)) { if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL); value = 1.0 / cuddV(f); res = cuddUniqueConst(dd,value); return(res); } res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon); if (res != NULL) return(res); checkWhetherToGiveUp(dd); t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon); if (t == NULL) return(NULL); cuddRef(t); e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res); return(res); } /* end of cuddAddScalarInverseRecur */
/** @brief Implements the recursive step of Cudd_bddClippingAnd. @details Takes the conjunction of two BDDs. @return a pointer to the result is successful; NULL otherwise. @sideeffect None @see cuddBddClippingAnd */ static DdNode * cuddBddClippingAndRecur( DdManager * manager, DdNode * f, DdNode * g, int distance, int direction) { DdNode *F, *ft, *fe, *G, *gt, *ge; DdNode *one, *zero, *r, *t, *e; int topf, topg; unsigned int index; DD_CTFP cacheOp; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == g || g == one) return(f); if (f == one) return(g); if (distance == 0) { /* One last attempt at returning the right result. We sort of ** cheat by calling Cudd_bddLeq. */ if (Cudd_bddLeq(manager,f,g)) return(f); if (Cudd_bddLeq(manager,g,f)) return(g); if (direction == 1) { if (Cudd_bddLeq(manager,f,Cudd_Not(g)) || Cudd_bddLeq(manager,g,Cudd_Not(f))) return(zero); } return(Cudd_NotCond(one,(direction == 0))); } /* At this point f and g are not constant. */ distance--; /* Check cache. Try to increase cache efficiency by sorting the ** pointers. */ if (f > g) { DdNode *tmp = f; f = g; g = tmp; } F = Cudd_Regular(f); G = Cudd_Regular(g); cacheOp = (DD_CTFP) (direction ? Cudd_bddClippingAnd : cuddBddClippingAnd); if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, cacheOp, f, g); if (r != NULL) return(r); } checkWhetherToGiveUp(manager); /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; ft = cuddT(F); fe = cuddE(F); if (Cudd_IsComplement(f)) { ft = Cudd_Not(ft); fe = Cudd_Not(fe); } } else { index = G->index; ft = fe = f; } if (topg <= topf) { gt = cuddT(G); ge = cuddE(G); if (Cudd_IsComplement(g)) { gt = Cudd_Not(gt); ge = Cudd_Not(ge); } } else { gt = ge = g; } t = cuddBddClippingAndRecur(manager, ft, gt, distance, direction); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddClippingAndRecur(manager, fe, ge, distance, direction); if (e == NULL) { Cudd_RecursiveDeref(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_RecursiveDeref(manager, t); Cudd_RecursiveDeref(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, cacheOp, f, g, r); return(r); } /* end of cuddBddClippingAndRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addUnivAbstract.] Description [Performs the recursive step of Cudd_addUnivAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddUnivAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one, *zero; statLine(manager); one = DD_ONE(manager); zero = DD_ZERO(manager); /* Cube is guaranteed to be a cube at this point. ** zero and one are the only constatnts c such that c*c=c. */ if (f == zero || f == one || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res1 = cuddAddUnivAbstractRecur(manager, f, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); /* Use the "internal" procedure to be alerted in case of ** dynamic reordering. If dynamic reordering occurs, we ** have to abort the entire abstraction. */ res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res1); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); cuddDeref(res); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addUnivAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddUnivAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addTimes, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddUnivAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddUnivAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addUnivAbstract, f, cube, res); return(res); } } /* end of cuddAddUnivAbstractRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOrAbstract.] Description [Performs the recursive step of Cudd_addOrAbstract. Returns the ADD obtained by abstracting the variables of cube from f, if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ DdNode * cuddAddOrAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *T, *E, *res, *res1, *res2, *one; statLine(manager); one = DD_ONE(manager); /* Cube is guaranteed to be a cube at this point. */ if (cuddIsConstant(f) || cube == one) { return(f); } /* Abstract a variable that does not appear in f. */ if (cuddI(manager,f->index) > cuddI(manager,cube->index)) { res = cuddAddOrAbstractRecur(manager, f, cuddT(cube)); return(res); } if ((res = cuddCacheLookup2(manager, Cudd_addOrAbstract, f, cube)) != NULL) { return(res); } T = cuddT(f); E = cuddE(f); /* If the two indices are the same, so are their levels. */ if (f->index == cube->index) { res1 = cuddAddOrAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); cuddRef(res1); if (res1 != one) { res2 = cuddAddOrAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = cuddAddApplyRecur(manager, Cudd_addOr, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); } else { res = res1; } cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,f->index) < cuddI(manager,cube->index)) */ res1 = cuddAddOrAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddAddOrAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_RecursiveDeref(manager,res1); return(NULL); } cuddRef(res2); res = (res1 == res2) ? res1 : cuddUniqueInter(manager, (int) f->index, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(manager,res1); Cudd_RecursiveDeref(manager,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); cuddCacheInsert2(manager, Cudd_addOrAbstract, f, cube, res); return(res); } } /* end of cuddAddOrAbstractRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step for Cudd_addBddIthBit.] Description [Performs the recursive step for Cudd_addBddIthBit. Returns a pointer to the BDD if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * addBddDoIthBit( DdManager * dd, DdNode * f, DdNode * index) { DdNode *res, *T, *E; DdNode *fv, *fvn; /* NuSMV: add begin */ ptrint mask, value; /* WAS: long mask, value; */ /* NuSMV: add end */ int v; statLine(dd); /* Check terminal case. */ if (cuddIsConstant(f)) { /* NuSMV: add begin */ mask = 1 << ((ptrint) cuddV(index)); value = (ptrint) cuddV(f); /* WAS: mask = 1 << ((long) cuddV(index)); value = (long) cuddV(f); */ /* NuSMV: add end */ return(Cudd_NotCond(DD_TRUE(dd),(value & mask) == 0)); } /* Check cache. */ res = cuddCacheLookup2(dd,addBddDoIthBit,f,index); if (res != NULL) return(res); /* Recursive step. */ v = f->index; fv = cuddT(f); fvn = cuddE(f); T = addBddDoIthBit(dd,fv,index); if (T == NULL) return(NULL); cuddRef(T); E = addBddDoIthBit(dd,fvn,index); if (E == NULL) { Cudd_RecursiveDeref(dd, T); return(NULL); } cuddRef(E); if (Cudd_IsComplement(T)) { res = (T == E) ? Cudd_Not(T) : cuddUniqueInter(dd,v,Cudd_Not(T),Cudd_Not(E)); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } res = Cudd_Not(res); } else { res = (T == E) ? T : cuddUniqueInter(dd,v,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,addBddDoIthBit,f,index,res); return(res); } /* end of addBddDoIthBit */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_Cofactor.] Description [Performs the recursive step of Cudd_Cofactor. Returns a pointer to the cofactor if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_Cofactor] ******************************************************************************/ DdNode * cuddCofactorRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *one,*zero,*F,*G,*g1,*g0,*f1,*f0,*t,*e,*r; unsigned int topf,topg; int comple; F = Cudd_Regular(f); if (cuddIsConstant(F)) return(f); one = DD_ONE(dd); /* The invariant g != 0 is true on entry to this procedure and is ** recursively maintained by it. Therefore it suffices to test g ** against one to make sure it is not constant. */ if (g == one) return(f); /* From now on, f and g are known not to be constants. */ comple = f != F; r = cuddCacheLookup2(dd,Cudd_Cofactor,F,g); if (r != NULL) { return(Cudd_NotCond(r,comple)); } topf = dd->perm[F->index]; G = Cudd_Regular(g); topg = dd->perm[G->index]; /* We take the cofactors of F because we are going to rely on ** the fact that the cofactors of the complement are the complements ** of the cofactors to better utilize the cache. Variable comple ** remembers whether we have to complement the result or not. */ if (topf <= topg) { f1 = cuddT(F); f0 = cuddE(F); } else { f1 = f0 = F; } if (topg <= topf) { g1 = cuddT(G); g0 = cuddE(G); if (g != G) { g1 = Cudd_Not(g1); g0 = Cudd_Not(g0); } } else { g1 = g0 = g; } zero = Cudd_Not(one); if (topf >= topg) { if (g0 == zero || g0 == DD_ZERO(dd)) { r = cuddCofactorRecur(dd, f1, g1); } else if (g1 == zero || g1 == DD_ZERO(dd)) { r = cuddCofactorRecur(dd, f0, g0); } else { (void) fprintf(stdout,"Cudd_Cofactor: Invalid restriction 2\n"); return(NULL); } if (r == NULL) return(NULL); } else /* if (topf < topg) */ { t = cuddCofactorRecur(dd, f1, g); if (t == NULL) return(NULL); cuddRef(t); e = cuddCofactorRecur(dd, f0, g); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else if (Cudd_IsComplement(t)) { r = cuddUniqueInter(dd,(int)F->index,Cudd_Not(t),Cudd_Not(e)); if (r != NULL) r = Cudd_Not(r); } else { r = cuddUniqueInter(dd,(int)F->index,t,e); } if (r == NULL) { Cudd_RecursiveDeref(dd ,e); Cudd_RecursiveDeref(dd ,t); return(NULL); } cuddDeref(t); cuddDeref(e); } cuddCacheInsert2(dd,Cudd_Cofactor,F,g,r); return(Cudd_NotCond(r,comple)); } /* end of cuddCofactorRecur */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddAnd.] Description [Implements the recursive step of Cudd_bddAnd by taking the conjunction of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddAnd] ******************************************************************************/ DdNode * cuddBddAndRecur( DdManager * manager, DdNode * f, DdNode * g) { DdNode *F, *fv, *fnv, *G, *gv, *gnv; DdNode *one, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); /* Terminal cases. */ F = Cudd_Regular(f); G = Cudd_Regular(g); if (F == G) { if (f == g) return(f); else return(Cudd_Not(one)); } if (F == one) { if (f == one) return(g); else return(f); } if (G == one) { if (g == one) return(f); else return(g); } /* At this point f and g are not constant. */ if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */ DdNode *tmp = f; f = g; g = tmp; F = Cudd_Regular(f); G = Cudd_Regular(g); } /* Check cache. */ if (F->ref != 1 || G->ref != 1) { r = cuddCacheLookup2(manager, Cudd_bddAnd, f, g); if (r != NULL) return(r); } if ( manager->TimeStop && Abc_Clock() > manager->TimeStop ) return NULL; /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[F->index]; topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } t = cuddBddAndRecur(manager, fv, gv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddAndRecur(manager, fnv, gnv); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); if (F->ref != 1 || G->ref != 1) cuddCacheInsert2(manager, Cudd_bddAnd, f, g, r); return(r); } /* end of cuddBddAndRecur */
/**Function******************************************************************** Synopsis [Performs the recursive steps of Cudd_bddExistAbstract.] Description [Performs the recursive steps of Cudd_bddExistAbstract. Returns the BDD obtained by abstracting the variables of cube from f if successful; NULL otherwise. It is also used by Cudd_bddUnivAbstract.] SideEffects [None] SeeAlso [Cudd_bddExistAbstract Cudd_bddUnivAbstract] ******************************************************************************/ DdNode * cuddBddExistAbstractRecur( DdManager * manager, DdNode * f, DdNode * cube) { DdNode *F, *T, *E, *res, *res1, *res2, *one; statLine(manager); one = DD_ONE(manager); F = Cudd_Regular(f); /* Cube is guaranteed to be a cube at this point. */ if (cube == one || F == one) { return(f); } /* From now on, f and cube are non-constant. */ /* Abstract a variable that does not appear in f. */ while (manager->perm[F->index] > manager->perm[cube->index]) { cube = cuddT(cube); if (cube == one) return(f); } /* Check the cache. */ if (F->ref != 1 && (res = cuddCacheLookup2(manager, Cudd_bddExistAbstract, f, cube)) != NULL) { return(res); } /* Compute the cofactors of f. */ T = cuddT(F); E = cuddE(F); if (f != F) { T = Cudd_Not(T); E = Cudd_Not(E); } /* If the two indices are the same, so are their levels. */ if (F->index == cube->index) { if (T == one || E == one || T == Cudd_Not(E)) { return(one); } res1 = cuddBddExistAbstractRecur(manager, T, cuddT(cube)); if (res1 == NULL) return(NULL); if (res1 == one) { if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, one); return(one); } cuddRef(res1); res2 = cuddBddExistAbstractRecur(manager, E, cuddT(cube)); if (res2 == NULL) { Cudd_IterDerefBdd(manager,res1); return(NULL); } cuddRef(res2); res = cuddBddAndRecur(manager, Cudd_Not(res1), Cudd_Not(res2)); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } res = Cudd_Not(res); cuddRef(res); Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); cuddDeref(res); return(res); } else { /* if (cuddI(manager,F->index) < cuddI(manager,cube->index)) */ res1 = cuddBddExistAbstractRecur(manager, T, cube); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddBddExistAbstractRecur(manager, E, cube); if (res2 == NULL) { Cudd_IterDerefBdd(manager, res1); return(NULL); } cuddRef(res2); /* ITE takes care of possible complementation of res1 and of the ** case in which res1 == res2. */ res = cuddBddIteRecur(manager, manager->vars[F->index], res1, res2); if (res == NULL) { Cudd_IterDerefBdd(manager, res1); Cudd_IterDerefBdd(manager, res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); if (F->ref != 1) cuddCacheInsert2(manager, Cudd_bddExistAbstract, f, cube, res); return(res); } } /* end of cuddBddExistAbstractRecur */
/**Function******************************************************************** Synopsis [Performs the recursive steps of Extra_bddSpaceFromFunction.] Description [] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddSpaceFromFunction( DdManager * dd, DdNode * bF, DdNode * bG ) { DdNode * bRes; DdNode * bFR, * bGR; bFR = Cudd_Regular( bF ); bGR = Cudd_Regular( bG ); if ( cuddIsConstant(bFR) ) { if ( bF == bG ) return b1; else return b0; } if ( cuddIsConstant(bGR) ) return b0; // both bFunc and bCore are not constants // the operation is commutative - normalize the problem if ( (unsigned)(ABC_PTRUINT_T)bF > (unsigned)(ABC_PTRUINT_T)bG ) return extraBddSpaceFromFunction(dd, bG, bF); if ( (bRes = cuddCacheLookup2(dd, extraBddSpaceFromFunction, bF, bG)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bG0, * bG1; DdNode * bTemp1, * bTemp2; DdNode * bRes0, * bRes1; int LevelF, LevelG; int index; LevelF = dd->perm[bFR->index]; LevelG = dd->perm[bGR->index]; if ( LevelF <= LevelG ) { index = dd->invperm[LevelF]; if ( bFR != bF ) { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else { index = dd->invperm[LevelG]; bF0 = bF1 = bF; } if ( LevelG <= LevelF ) { if ( bGR != bG ) { bG0 = Cudd_Not( cuddE(bGR) ); bG1 = Cudd_Not( cuddT(bGR) ); } else { bG0 = cuddE(bGR); bG1 = cuddT(bGR); } } else bG0 = bG1 = bG; bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG0 ); if ( bTemp1 == NULL ) return NULL; cuddRef( bTemp1 ); bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG1 ); if ( bTemp2 == NULL ) { Cudd_RecursiveDeref( dd, bTemp1 ); return NULL; } cuddRef( bTemp2 ); bRes0 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); if ( bRes0 == NULL ) { Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); return NULL; } cuddRef( bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); bTemp1 = extraBddSpaceFromFunction( dd, bF0, bG1 ); if ( bTemp1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); return NULL; } cuddRef( bTemp1 ); bTemp2 = extraBddSpaceFromFunction( dd, bF1, bG0 ); if ( bTemp2 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); return NULL; } cuddRef( bTemp2 ); bRes1 = cuddBddAndRecur( dd, bTemp1, bTemp2 ); if ( bRes1 == NULL ) { Cudd_RecursiveDeref( dd, bRes0 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); return NULL; } cuddRef( bRes1 ); Cudd_RecursiveDeref( dd, bTemp1 ); Cudd_RecursiveDeref( dd, bTemp2 ); // consider the case when Res0 and Res1 are the same node if ( bRes0 == bRes1 ) bRes = bRes1; // consider the case when Res1 is complemented else if ( Cudd_IsComplement(bRes1) ) { bRes = cuddUniqueInter(dd, index, Cudd_Not(bRes1), Cudd_Not(bRes0)); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } bRes = Cudd_Not(bRes); } else { bRes = cuddUniqueInter( dd, index, bRes1, bRes0 ); if ( bRes == NULL ) { Cudd_RecursiveDeref(dd,bRes0); Cudd_RecursiveDeref(dd,bRes1); return NULL; } } cuddDeref( bRes0 ); cuddDeref( bRes1 ); // insert the result into cache cuddCacheInsert2(dd, extraBddSpaceFromFunction, bF, bG, bRes); return bRes; } } /* end of extraBddSpaceFromFunction */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddIntersect.] Description [] SideEffects [None] SeeAlso [Cudd_bddIntersect] ******************************************************************************/ DdNode * cuddBddIntersectRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res; DdNode *F, *G, *t, *e; DdNode *fv, *fnv, *gv, *gnv; DdNode *one, *zero; unsigned int index, topf, topg; statLine(dd); one = DD_ONE(dd); zero = Cudd_Not(one); /* Terminal cases. */ if (f == zero || g == zero || f == Cudd_Not(g)) return(zero); if (f == g || g == one) return(f); if (f == one) return(g); /* At this point f and g are not constant. */ if (cuddF2L(f) > cuddF2L(g)) { DdNode *tmp = f; f = g; g = tmp; } res = cuddCacheLookup2(dd,Cudd_bddIntersect,f,g); if (res != NULL) return(res); /* Find splitting variable. Here we can skip the use of cuddI, ** because the operands are known to be non-constant. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; G = Cudd_Regular(g); topg = dd->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = F->index; fv = cuddT(F); fnv = cuddE(F); if (Cudd_IsComplement(f)) { fv = Cudd_Not(fv); fnv = Cudd_Not(fnv); } } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } /* Compute partial results. */ t = cuddBddIntersectRecur(dd,fv,gv); if (t == NULL) return(NULL); cuddRef(t); if (t != zero) { e = zero; } else { e = cuddBddIntersectRecur(dd,fnv,gnv); if (e == NULL) { Cudd_IterDerefBdd(dd, t); return(NULL); } } cuddRef(e); if (t == e) { /* both equal zero */ res = t; } else if (Cudd_IsComplement(t)) { res = cuddUniqueInter(dd,(int)index,Cudd_Not(t),Cudd_Not(e)); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } res = Cudd_Not(res); } else { res = cuddUniqueInter(dd,(int)index,t,e); if (res == NULL) { Cudd_IterDerefBdd(dd, t); Cudd_IterDerefBdd(dd, e); return(NULL); } } cuddDeref(e); cuddDeref(t); cuddCacheInsert2(dd,Cudd_bddIntersect,f,g,res); return(res); } /* end of cuddBddIntersectRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_CProjection.] Description [Performs the recursive step of Cudd_CProjection. Returns the projection if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_CProjection] ******************************************************************************/ DdNode * cuddCProjectionRecur( DdManager * dd, DdNode * R, DdNode * Y, DdNode * Ysupp) { DdNode *res, *res1, *res2, *resA; DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha; unsigned int topR, topY, top, index; DdNode *one = DD_ONE(dd); statLine(dd); if (Y == one) return(R); #ifdef DD_DEBUG assert(!Cudd_IsConstant(Y)); #endif if (R == Cudd_Not(one)) return(R); res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y); if (res != NULL) return(res); r = Cudd_Regular(R); topR = cuddI(dd,r->index); y = Cudd_Regular(Y); topY = cuddI(dd,y->index); top = ddMin(topR, topY); /* Compute the cofactors of R */ if (topR == top) { index = r->index; RT = cuddT(r); RE = cuddE(r); if (r != R) { RT = Cudd_Not(RT); RE = Cudd_Not(RE); } } else { RT = RE = R; } if (topY > top) { /* Y does not depend on the current top variable. ** We just need to compute the results on the two cofactors of R ** and make them the children of a node labeled r->index. */ res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp); if (res1 == NULL) return(NULL); cuddRef(res1); res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp); if (res2 == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddRef(res2); res = cuddBddIteRecur(dd, dd->vars[index], res1, res2); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(NULL); } /* If we have reached this point, res1 and res2 are now ** incorporated in res. cuddDeref is therefore sufficient. */ cuddDeref(res1); cuddDeref(res2); } else { /* Compute the cofactors of Y */ index = y->index; YT = cuddT(y); YE = cuddE(y); if (y != Y) { YT = Cudd_Not(YT); YE = Cudd_Not(YE); } if (YT == Cudd_Not(one)) { Alpha = Cudd_Not(dd->vars[index]); Yrest = YE; Ra = RE; Ran = RT; } else { Alpha = dd->vars[index]; Yrest = YT; Ra = RT; Ran = RE; } Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp)); if (Gamma == NULL) return(NULL); if (Gamma == one) { res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); if (res1 == NULL) return(NULL); cuddRef(res1); res = cuddBddAndRecur(dd, Alpha, res1); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddDeref(res1); } else if (Gamma == Cudd_Not(one)) { res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); if (res1 == NULL) return(NULL); cuddRef(res1); res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); return(NULL); } cuddDeref(res1); } else { cuddRef(Gamma); resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp)); if (resA == NULL) { Cudd_RecursiveDeref(dd,Gamma); return(NULL); } cuddRef(resA); res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA); if (res2 == NULL) { Cudd_RecursiveDeref(dd,Gamma); Cudd_RecursiveDeref(dd,resA); return(NULL); } cuddRef(res2); Cudd_RecursiveDeref(dd,Gamma); Cudd_RecursiveDeref(dd,resA); res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp)); if (res1 == NULL) { Cudd_RecursiveDeref(dd,res2); return(NULL); } cuddRef(res1); res = cuddBddIteRecur(dd, Alpha, res1, res2); if (res == NULL) { Cudd_RecursiveDeref(dd,res1); Cudd_RecursiveDeref(dd,res2); return(NULL); } cuddDeref(res1); cuddDeref(res2); } } cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res); return(res); } /* end of cuddCProjectionRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Extra_bddCheckVarsSymmetric().] Description [Returns b0 if the variables are not symmetric. Returns b1 if the variables can be symmetric. The variables are represented in the form of a two-variable cube. In case the cube contains one variable (below Var1 level), the cube's pointer is complemented if the variable Var1 occurred on the current path; otherwise, the cube's pointer is regular. Uses additional complemented bit (Hash_Not) to mark the result if in the BDD rooted that this node there is a branch passing though the node labeled with Var2.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddCheckVarsSymmetric( DdManager * dd, /* the DD manager */ DdNode * bF, DdNode * bVars) { DdNode * bRes; if ( bF == b0 ) return b1; assert( bVars != b1 ); if ( (bRes = cuddCacheLookup2(dd, extraBddCheckVarsSymmetric, bF, bVars)) ) return bRes; else { DdNode * bRes0, * bRes1; DdNode * bF0, * bF1; DdNode * bFR = Cudd_Regular(bF); int LevelF = cuddI(dd,bFR->index); DdNode * bVarsR = Cudd_Regular(bVars); int fVar1Pres; int iLev1; int iLev2; if ( bVarsR != bVars ) // cube's pointer is complemented { assert( cuddT(bVarsR) == b1 ); fVar1Pres = 1; // the first var is present on the path iLev1 = -1; // we are already below the first var level iLev2 = dd->perm[bVarsR->index]; // the level of the second var } else // cube's pointer is NOT complemented { fVar1Pres = 0; // the first var is absent on the path if ( cuddT(bVars) == b1 ) { iLev1 = -1; // we are already below the first var level iLev2 = dd->perm[bVars->index]; // the level of the second var } else { assert( cuddT(cuddT(bVars)) == b1 ); iLev1 = dd->perm[bVars->index]; // the level of the first var iLev2 = dd->perm[cuddT(bVars)->index]; // the level of the second var } } // cofactor the function // the cofactors are needed only if we are above the second level if ( LevelF < iLev2 ) { if ( bFR != bF ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } } else bF0 = bF1 = NULL; // consider five cases: // (1) F is above iLev1 // (2) F is on the level iLev1 // (3) F is between iLev1 and iLev2 // (4) F is on the level iLev2 // (5) F is below iLev2 // (1) F is above iLev1 if ( LevelF < iLev1 ) { // the returned result cannot have the hash attribute // because we still did not reach the level of Var1; // the attribute never travels above the level of Var1 bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); // assert( !Hash_IsComplement( bRes0 ) ); assert( bRes0 != z0 ); if ( bRes0 == b0 ) bRes = b0; else bRes = extraBddCheckVarsSymmetric( dd, bF1, bVars ); // assert( !Hash_IsComplement( bRes ) ); assert( bRes != z0 ); } // (2) F is on the level iLev1 else if ( LevelF == iLev1 ) { bRes0 = extraBddCheckVarsSymmetric( dd, bF0, Cudd_Not( cuddT(bVars) ) ); if ( bRes0 == b0 ) bRes = b0; else { bRes1 = extraBddCheckVarsSymmetric( dd, bF1, Cudd_Not( cuddT(bVars) ) ); if ( bRes1 == b0 ) bRes = b0; else { // if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) if ( bRes0 == z0 || bRes1 == z0 ) bRes = b1; else bRes = b0; } } } // (3) F is between iLev1 and iLev2 else if ( LevelF < iLev2 ) { bRes0 = extraBddCheckVarsSymmetric( dd, bF0, bVars ); if ( bRes0 == b0 ) bRes = b0; else { bRes1 = extraBddCheckVarsSymmetric( dd, bF1, bVars ); if ( bRes1 == b0 ) bRes = b0; else { // if ( Hash_IsComplement( bRes0 ) || Hash_IsComplement( bRes1 ) ) // bRes = Hash_Not( b1 ); if ( bRes0 == z0 || bRes1 == z0 ) bRes = z0; else bRes = b1; } } } // (4) F is on the level iLev2 else if ( LevelF == iLev2 ) { // this is the only place where the hash attribute (Hash_Not) can be added // to the result; it can be added only if the path came through the node // lebeled with Var1; therefore, the hash attribute cannot be returned // to the caller function if ( fVar1Pres ) // bRes = Hash_Not( b1 ); bRes = z0; else bRes = b0; } // (5) F is below iLev2 else // if ( LevelF > iLev2 ) { // it is possible that the path goes through the node labeled by Var1 // and still everything is okay; we do not label with Hash_Not here // because the path does not go through node labeled by Var2 bRes = b1; } cuddCacheInsert2(dd, extraBddCheckVarsSymmetric, bF, bVars, bRes); return bRes; } } /* end of extraBddCheckVarsSymmetric */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_zddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_zddIsop] ******************************************************************************/ DdNode * cuddZddIsop( DdManager * dd, DdNode * L, DdNode * U, DdNode ** zdd_I) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); DdNode *zdd_one = DD_ONE(dd); DdNode *zdd_zero = DD_ZERO(dd); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *zdd_Isub0, *zdd_Isub1, *zdd_Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r, *y, *z; int index; DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); statLine(dd); if (L == zero) { *zdd_I = zdd_zero; return(zero); } if (U == one) { *zdd_I = zdd_one; return(one); } if (U == zero || L == one) { printf("*** ERROR : illegal condition for ISOP (U < L).\n"); exit(1); } /* Check the cache. We store two results for each recursive call. ** One is the BDD, and the other is the ZDD. Both are needed. ** Hence we need a double hit in the cache to terminate the ** recursion. Clearly, collisions may evict only one of the two ** results. */ cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) cuddZddIsop; r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) { *zdd_I = cuddCacheLookup2Zdd(dd, cacheOp, L, U); if (*zdd_I) return(r); else { /* The BDD result may have been dead. In that case ** cuddCacheLookup2 would have called cuddReclaim, ** whose effects we now have to undo. */ cuddRef(r); Cudd_RecursiveDeref(dd, r); } } top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors. */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddZddIsop(dd, Lsub0, Usub0, &zdd_Isub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub0))) && (Cudd_Regular(Isub0)->index != zdd_Isub0->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub0->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub0); Cudd_Ref(zdd_Isub0); Isub1 = cuddZddIsop(dd, Lsub1, Usub1, &zdd_Isub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Isub1))) && (Cudd_Regular(Isub1)->index != zdd_Isub1->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Isub1->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Isub1); Cudd_Ref(zdd_Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Ld = Cudd_Not(Ld); Cudd_Ref(Ld); /* Ud = Usuper0 * Usuper1 */ Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddZddIsop(dd, Ld, Ud, &zdd_Id); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } /* if ((!cuddIsConstant(Cudd_Regular(Id))) && (Cudd_Regular(Id)->index != zdd_Id->index / 2 || dd->permZ[index * 2] > dd->permZ[zdd_Id->index])) { printf("*** ERROR : illegal permutation in ZDD. ***\n"); } */ Cudd_Ref(Id); Cudd_Ref(zdd_Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); return(NULL); } Cudd_Ref(x); /* term0 = x * Isub0 */ term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); /* term1 = x * Isub1 */ term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); if (sum == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } sum = Cudd_Not(sum); Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); if (zdd_Isub0 != zdd_zero) { z = cuddZddGetNodeIVO(dd, index * 2 + 1, zdd_Isub0, zdd_Id); if (z == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); return(NULL); } } else { z = zdd_Id; } Cudd_Ref(z); if (zdd_Isub1 != zdd_zero) { y = cuddZddGetNodeIVO(dd, index * 2, zdd_Isub1, z); if (y == NULL) { Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDeref(dd, r); Cudd_RecursiveDerefZdd(dd, z); return(NULL); } } else y = z; Cudd_Ref(y); Cudd_RecursiveDerefZdd(dd, zdd_Isub0); Cudd_RecursiveDerefZdd(dd, zdd_Isub1); Cudd_RecursiveDerefZdd(dd, zdd_Id); Cudd_RecursiveDerefZdd(dd, z); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); cuddCacheInsert2(dd, cacheOp, L, U, y); Cudd_Deref(r); Cudd_Deref(y); *zdd_I = y; /* if (Cudd_Regular(r)->index != y->index / 2) { printf("*** ERROR : mismatch in indices between BDD and ZDD. ***\n"); } */ return(r); } /* end of cuddZddIsop */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddLiteralSetIntersection.] Description [Performs the recursive step of Cudd_bddLiteralSetIntersection. Scans the cubes for common variables, and checks whether they agree in phase. Returns a pointer to the resulting cube if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ DdNode * cuddBddLiteralSetIntersectionRecur( DdManager * dd, DdNode * f, DdNode * g) { DdNode *res, *tmp; DdNode *F, *G; DdNode *fc, *gc; DdNode *one; DdNode *zero; unsigned int topf, topg, comple; int phasef, phaseg; statLine(dd); if (f == g) return(f); F = Cudd_Regular(f); G = Cudd_Regular(g); one = DD_ONE(dd); /* Here f != g. If F == G, then f and g are complementary. ** Since they are two cubes, this case only occurs when f == v, ** g == v', and v is a variable or its complement. */ if (F == G) return(one); zero = Cudd_Not(one); topf = cuddI(dd,F->index); topg = cuddI(dd,G->index); /* Look for a variable common to both cubes. If there are none, this ** loop will stop when the constant node is reached in both cubes. */ while (topf != topg) { if (topf < topg) { /* move down on f */ comple = f != F; f = cuddT(F); if (comple) f = Cudd_Not(f); if (f == zero) { f = cuddE(F); if (comple) f = Cudd_Not(f); } F = Cudd_Regular(f); topf = cuddI(dd,F->index); } else if (topg < topf) { comple = g != G; g = cuddT(G); if (comple) g = Cudd_Not(g); if (g == zero) { g = cuddE(G); if (comple) g = Cudd_Not(g); } G = Cudd_Regular(g); topg = cuddI(dd,G->index); } } /* At this point, f == one <=> g == 1. It suffices to test one of them. */ if (f == one) return(one); res = cuddCacheLookup2(dd,Cudd_bddLiteralSetIntersection,f,g); if (res != NULL) { return(res); } /* Here f and g are both non constant and have the same top variable. */ comple = f != F; fc = cuddT(F); phasef = 1; if (comple) fc = Cudd_Not(fc); if (fc == zero) { fc = cuddE(F); phasef = 0; if (comple) fc = Cudd_Not(fc); } comple = g != G; gc = cuddT(G); phaseg = 1; if (comple) gc = Cudd_Not(gc); if (gc == zero) { gc = cuddE(G); phaseg = 0; if (comple) gc = Cudd_Not(gc); } tmp = cuddBddLiteralSetIntersectionRecur(dd,fc,gc); if (tmp == NULL) { return(NULL); } if (phasef != phaseg) { res = tmp; } else { cuddRef(tmp); if (phasef == 0) { res = cuddBddAndRecur(dd,Cudd_Not(dd->vars[F->index]),tmp); } else { res = cuddBddAndRecur(dd,dd->vars[F->index],tmp); } if (res == NULL) { Cudd_RecursiveDeref(dd,tmp); return(NULL); } cuddDeref(tmp); /* Just cuddDeref, because it is included in result */ } cuddCacheInsert2(dd,Cudd_bddLiteralSetIntersection,f,g,res); return(res); } /* end of cuddBddLiteralSetIntersectionRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addMatrixMultiply.] Description [Performs the recursive step of Cudd_addMatrixMultiply. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * addMMRecur( DdManager * dd, DdNode * A, DdNode * B, int topP, int * vars) { DdNode *zero, *At, /* positive cofactor of first operand */ *Ae, /* negative cofactor of first operand */ *Bt, /* positive cofactor of second operand */ *Be, /* negative cofactor of second operand */ *t, /* positive cofactor of result */ *e, /* negative cofactor of result */ *scaled, /* scaled result */ *add_scale, /* ADD representing the scaling factor */ *res; int i; /* loop index */ double scale; /* scaling factor */ int index; /* index of the top variable */ CUDD_VALUE_TYPE value; unsigned int topA, topB, topV; DD_CTFP cacheOp; statLine(dd); zero = DD_ZERO(dd); if (A == zero || B == zero) { return(zero); } if (cuddIsConstant(A) && cuddIsConstant(B)) { /* Compute the scaling factor. It is 2^k, where k is the ** number of summation variables below the current variable. ** Indeed, these constants represent blocks of 2^k identical ** constant values in both A and B. */ value = cuddV(A) * cuddV(B); for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP) { value *= (CUDD_VALUE_TYPE) 2; } } } res = cuddUniqueConst(dd, value); return(res); } /* Standardize to increase cache efficiency. Clearly, A*B != B*A ** in matrix multiplication. However, which matrix is which is ** determined by the variables appearing in the ADDs and not by ** which one is passed as first argument. */ if (A > B) { DdNode *tmp = A; A = B; B = tmp; } topA = cuddI(dd,A->index); topB = cuddI(dd,B->index); topV = ddMin(topA,topB); cacheOp = (DD_CTFP) addMMRecur; res = cuddCacheLookup2(dd,cacheOp,A,B); if (res != NULL) { /* If the result is 0, there is no need to normalize. ** Otherwise we count the number of z variables between ** the current depth and the top of the ADDs. These are ** the missing variables that determine the size of the ** constant blocks. */ if (res == zero) return(res); scale = 1.0; for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { scale *= 2; } } } if (scale > 1.0) { cuddRef(res); add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); if (add_scale == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(add_scale); scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); if (scaled == NULL) { Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(scaled); Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); res = scaled; cuddDeref(res); } return(res); } /* compute the cofactors */ if (topV == topA) { At = cuddT(A); Ae = cuddE(A); } else { At = Ae = A; } if (topV == topB) { Bt = cuddT(B); Be = cuddE(B); } else { Bt = Be = B; } t = addMMRecur(dd, At, Bt, (int)topV, vars); if (t == NULL) return(NULL); cuddRef(t); e = addMMRecur(dd, Ae, Be, (int)topV, vars); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); index = dd->invperm[topV]; if (vars[index] == 0) { /* We have split on either the rows of A or the columns ** of B. We just need to connect the two subresults, ** which correspond to two submatrices of the result. */ res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddRef(res); cuddDeref(t); cuddDeref(e); } else { /* we have simultaneously split on the columns of A and ** the rows of B. The two subresults must be added. */ res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddRef(res); Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); } cuddCacheInsert2(dd,cacheOp,A,B,res); /* We have computed (and stored in the computed table) a minimal ** result; that is, a result that assumes no summation variables ** between the current depth of the recursion and its top ** variable. We now take into account the z variables by properly ** scaling the result. */ if (res != zero) { scale = 1.0; for (i = 0; i < dd->size; i++) { if (vars[i]) { if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) { scale *= 2; } } } if (scale > 1.0) { add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale); if (add_scale == NULL) { Cudd_RecursiveDeref(dd, res); return(NULL); } cuddRef(add_scale); scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale); if (scaled == NULL) { Cudd_RecursiveDeref(dd, res); Cudd_RecursiveDeref(dd, add_scale); return(NULL); } cuddRef(scaled); Cudd_RecursiveDeref(dd, add_scale); Cudd_RecursiveDeref(dd, res); res = scaled; } } cuddDeref(res); return(res); } /* end of addMMRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cuddaux_addConstrain.] Description [Performs the recursive step of Cuddaux_addConstrain. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [Cuddaux_addConstrain] ******************************************************************************/ DdNode * cuddauxAddConstrainRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *res; DdNode *one, *zero; unsigned int topf, topc; int index; one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases. */ if (c == one) return(f); if (c == zero){ fprintf(stderr,"CuddauxAddConstrainRecur: warning: false careset\n"); return(DD_BACKGROUND(dd)); } if (Cudd_IsConstant(f)) return(f); /* Now f and c are non-constant. */ /* Check the cache. */ res = cuddCacheLookup2(dd, Cuddaux_addConstrain, f, c); if (res != NULL) { return(res); } /* Recursive step. */ topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topf <= topc) { index = f->index; Fv = cuddT(f); Fnv = cuddE(f); } else { index = Cudd_Regular(c)->index; Fv = Fnv = f; } if (topc <= topf) { Cv = Cudd_T(c); Cnv = Cudd_E(c); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddauxAddConstrainRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return Fnv @ Cnv */ if (Cnv == one) { res = Fnv; } else { res = cuddauxAddConstrainRecur(dd, Fnv, Cnv); if (res == NULL) return(NULL); } return(res); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddauxAddConstrainRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return Fv @ Cv previously computed */ cuddDeref(t); return(t); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (res == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cuddaux_addConstrain, f, c, res); return(res); } /* end of cuddauxAddConstrainRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cuddaux_addRestrict.] Description [Performs the recursive step of Cuddaux_addRestrict. Returns the restricted ADD if successful; otherwise NULL.] SideEffects [None] SeeAlso [Cudd_addRestrict] ******************************************************************************/ DdNode * cuddauxAddRestrictRecur( DdManager * dd, DdNode * f, DdNode * c) { DdNode *Fv, *Fnv, *Cv, *Cnv, *t, *e, *res, *one, *zero; unsigned int topf, topc; int index; one = DD_ONE(dd); zero = Cudd_Not(one); /* Trivial cases */ if (c == one) return(f); if (c == zero){ fprintf(stderr,"CuddauxAddRestrictRecur: warning: false careset\n"); return(DD_BACKGROUND(dd)); } if (Cudd_IsConstant(f)) return(f); /* Now f and c are non-constant. */ /* Check the cache. */ res = cuddCacheLookup2(dd, Cuddaux_addRestrict, f, c); if (res != NULL) { return(res); } topf = dd->perm[f->index]; topc = dd->perm[Cudd_Regular(c)->index]; if (topc < topf) { /* abstract top variable from c */ DdNode *d, *s1, *s2; /* Take the OR by applying DeMorgan. */ /* Find complements of cofactors of c. */ if (Cudd_IsComplement(c)) { s1 = cuddT(Cudd_Regular(c)); s2 = cuddE(Cudd_Regular(c)); } else { s1 = Cudd_Not(cuddT(c)); s2 = Cudd_Not(cuddE(c)); } /* Take the AND and negate */ d = cuddBddAndRecur(dd, s1, s2); if (d == NULL) return(NULL); d = Cudd_Not(d); cuddRef(d); res = cuddauxAddRestrictRecur(dd, f, d); if (res == NULL) { Cudd_IterDerefBdd(dd, d); return(NULL); } cuddRef(res); Cudd_IterDerefBdd(dd, d); cuddDeref(res); cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res); return(res); } /* Recursive step. Here topf <= topc. */ index = f->index; Fv = cuddT(f); Fnv = cuddE(f); if (topc == topf) { Cv = Cudd_T(c); Cnv = Cudd_E(c); if (Cudd_IsComplement(c)) { Cv = Cudd_Not(Cv); Cnv = Cudd_Not(Cnv); } } else { Cv = Cnv = c; } if (!Cudd_IsConstant(Cv)) { t = cuddauxAddRestrictRecur(dd, Fv, Cv); if (t == NULL) return(NULL); } else if (Cv == one) { t = Fv; } else { /* Cv == zero: return(Fnv @ Cnv) */ if (Cnv == one) { res = Fnv; } else { res = cuddauxAddRestrictRecur(dd, Fnv, Cnv); if (res == NULL) return(NULL); } return(res); } cuddRef(t); if (!Cudd_IsConstant(Cnv)) { e = cuddauxAddRestrictRecur(dd, Fnv, Cnv); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } } else if (Cnv == one) { e = Fnv; } else { /* Cnv == zero: return (Fv @ Cv) previously computed */ cuddDeref(t); return(t); } cuddRef(e); res = (t == e) ? t : cuddUniqueInter(dd, index, t, e); if (res == NULL) { Cudd_RecursiveDeref(dd, e); Cudd_RecursiveDeref(dd, t); return(NULL); } cuddDeref(t); cuddDeref(e); cuddCacheInsert2(dd, Cuddaux_addRestrict, f, c, res); return(res); } /* end of cuddauxAddRestrictRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_bddIsop.] Description [] SideEffects [None] SeeAlso [Cudd_bddIsop] ******************************************************************************/ DdNode * cuddBddIsop( DdManager * dd, DdNode * L, DdNode * U) { DdNode *one = DD_ONE(dd); DdNode *zero = Cudd_Not(one); int v, top_l, top_u; DdNode *Lsub0, *Usub0, *Lsub1, *Usub1, *Ld, *Ud; DdNode *Lsuper0, *Usuper0, *Lsuper1, *Usuper1; DdNode *Isub0, *Isub1, *Id; DdNode *x; DdNode *term0, *term1, *sum; DdNode *Lv, *Uv, *Lnv, *Unv; DdNode *r; int index; statLine(dd); if (L == zero) return(zero); if (U == one) return(one); /* Check cache */ r = cuddCacheLookup2(dd, cuddBddIsop, L, U); if (r) return(r); top_l = dd->perm[Cudd_Regular(L)->index]; top_u = dd->perm[Cudd_Regular(U)->index]; v = ddMin(top_l, top_u); /* Compute cofactors */ if (top_l == v) { index = Cudd_Regular(L)->index; Lv = Cudd_T(L); Lnv = Cudd_E(L); if (Cudd_IsComplement(L)) { Lv = Cudd_Not(Lv); Lnv = Cudd_Not(Lnv); } } else { index = Cudd_Regular(U)->index; Lv = Lnv = L; } if (top_u == v) { Uv = Cudd_T(U); Unv = Cudd_E(U); if (Cudd_IsComplement(U)) { Uv = Cudd_Not(Uv); Unv = Cudd_Not(Unv); } } else { Uv = Unv = U; } Lsub0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Uv)); if (Lsub0 == NULL) return(NULL); Cudd_Ref(Lsub0); Usub0 = Unv; Lsub1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Unv)); if (Lsub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); return(NULL); } Cudd_Ref(Lsub1); Usub1 = Uv; Isub0 = cuddBddIsop(dd, Lsub0, Usub0); if (Isub0 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); return(NULL); } Cudd_Ref(Isub0); Isub1 = cuddBddIsop(dd, Lsub1, Usub1); if (Isub1 == NULL) { Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Cudd_RecursiveDeref(dd, Isub0); return(NULL); } Cudd_Ref(Isub1); Cudd_RecursiveDeref(dd, Lsub0); Cudd_RecursiveDeref(dd, Lsub1); Lsuper0 = cuddBddAndRecur(dd, Lnv, Cudd_Not(Isub0)); if (Lsuper0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); return(NULL); } Cudd_Ref(Lsuper0); Lsuper1 = cuddBddAndRecur(dd, Lv, Cudd_Not(Isub1)); if (Lsuper1 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); return(NULL); } Cudd_Ref(Lsuper1); Usuper0 = Unv; Usuper1 = Uv; /* Ld = Lsuper0 + Lsuper1 */ Ld = cuddBddAndRecur(dd, Cudd_Not(Lsuper0), Cudd_Not(Lsuper1)); Ld = Cudd_NotCond(Ld, Ld != NULL); if (Ld == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); return(NULL); } Cudd_Ref(Ld); Ud = cuddBddAndRecur(dd, Usuper0, Usuper1); if (Ud == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Cudd_RecursiveDeref(dd, Ld); return(NULL); } Cudd_Ref(Ud); Cudd_RecursiveDeref(dd, Lsuper0); Cudd_RecursiveDeref(dd, Lsuper1); Id = cuddBddIsop(dd, Ld, Ud); if (Id == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); return(NULL); } Cudd_Ref(Id); Cudd_RecursiveDeref(dd, Ld); Cudd_RecursiveDeref(dd, Ud); x = cuddUniqueInter(dd, index, one, zero); if (x == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); return(NULL); } Cudd_Ref(x); term0 = cuddBddAndRecur(dd, Cudd_Not(x), Isub0); if (term0 == NULL) { Cudd_RecursiveDeref(dd, Isub0); Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); return(NULL); } Cudd_Ref(term0); Cudd_RecursiveDeref(dd, Isub0); term1 = cuddBddAndRecur(dd, x, Isub1); if (term1 == NULL) { Cudd_RecursiveDeref(dd, Isub1); Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, term0); return(NULL); } Cudd_Ref(term1); Cudd_RecursiveDeref(dd, x); Cudd_RecursiveDeref(dd, Isub1); /* sum = term0 + term1 */ sum = cuddBddAndRecur(dd, Cudd_Not(term0), Cudd_Not(term1)); sum = Cudd_NotCond(sum, sum != NULL); if (sum == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); return(NULL); } Cudd_Ref(sum); Cudd_RecursiveDeref(dd, term0); Cudd_RecursiveDeref(dd, term1); /* r = sum + Id */ r = cuddBddAndRecur(dd, Cudd_Not(sum), Cudd_Not(Id)); r = Cudd_NotCond(r, r != NULL); if (r == NULL) { Cudd_RecursiveDeref(dd, Id); Cudd_RecursiveDeref(dd, sum); return(NULL); } Cudd_Ref(r); Cudd_RecursiveDeref(dd, sum); Cudd_RecursiveDeref(dd, Id); cuddCacheInsert2(dd, cuddBddIsop, L, U, r); Cudd_Deref(r); return(r); } /* end of cuddBddIsop */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addApply.] Description [Performs the recursive step of Cudd_addApply. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [cuddAddMonadicApplyRecur] ******************************************************************************/ DdNode * cuddAddApplyRecur( DdManager * dd, DdNode * (*op)(DdManager *, DdNode **, DdNode **), DdNode * f, DdNode * g) { DdNode *res, *fv, *fvn, *gv, *gvn, *T, *E; unsigned int ford, gord; unsigned int index; DdNode *(*cacheOp)(DdManager *, DdNode *, DdNode *); /* Check terminal cases. Op may swap f and g to increase the * cache hit rate. */ statLine(dd); res = (*op)(dd,&f,&g); if (res != NULL) return(res); /* Check cache. */ cacheOp = (DdNode *(*)(DdManager *, DdNode *, DdNode *)) op; res = cuddCacheLookup2(dd,cacheOp,f,g); if (res != NULL) return(res); /* Recursive step. */ ford = cuddI(dd,f->index); gord = cuddI(dd,g->index); if (ford <= gord) { index = f->index; fv = cuddT(f); fvn = cuddE(f); } else { index = g->index; fv = fvn = f; } if (gord <= ford) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } T = cuddAddApplyRecur(dd,op,fv,gv); if (T == NULL) return(NULL); cuddRef(T); E = cuddAddApplyRecur(dd,op,fvn,gvn); if (E == NULL) { Cudd_RecursiveDeref(dd,T); return(NULL); } cuddRef(E); res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E); if (res == NULL) { Cudd_RecursiveDeref(dd, T); Cudd_RecursiveDeref(dd, E); return(NULL); } cuddDeref(T); cuddDeref(E); /* Store result. */ cuddCacheInsert2(dd,cacheOp,f,g,res); return(res); } /* end of cuddAddApplyRecur */
/**Function******************************************************************** Synopsis [Performs a recursive step of Extra_bddReduceVarSet.] Description [Returns the set of all variables in the given set that are not in the support of the given function.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode * extraBddReduceVarSet( DdManager * dd, /* the DD manager */ DdNode * bVars, /* the set of variables to be reduced */ DdNode * bF) /* the function whose support is used for reduction */ { DdNode * bRes; DdNode * bFR = Cudd_Regular(bF); if ( cuddIsConstant(bFR) || bVars == b1 ) return bVars; if ( (bRes = cuddCacheLookup2(dd, extraBddReduceVarSet, bVars, bF)) ) return bRes; else { DdNode * bF0, * bF1; DdNode * bVarsThis, * bVarsLower, * bTemp; int LevelF; // if LevelF is below LevelV, scroll through the vars in bVars LevelF = dd->perm[bFR->index]; for ( bVarsThis = bVars; LevelF > cuddI(dd,bVarsThis->index); bVarsThis = cuddT(bVarsThis) ); // scroll also through the current var, because it should be not be added if ( LevelF == cuddI(dd,bVarsThis->index) ) bVarsLower = cuddT(bVarsThis); else bVarsLower = bVarsThis; // cofactor the function if ( bFR != bF ) // bFunc is complemented { bF0 = Cudd_Not( cuddE(bFR) ); bF1 = Cudd_Not( cuddT(bFR) ); } else { bF0 = cuddE(bFR); bF1 = cuddT(bFR); } // solve subproblems bRes = extraBddReduceVarSet( dd, bVarsLower, bF0 ); if ( bRes == NULL ) return NULL; cuddRef( bRes ); bRes = extraBddReduceVarSet( dd, bTemp = bRes, bF1 ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); return NULL; } cuddRef( bRes ); Cudd_RecursiveDeref( dd, bTemp ); // the current var should not be added // add the skipped vars if ( bVarsThis != bVars ) { DdNode * bVarsExtra; // extract the skipped variables bVarsExtra = cuddBddExistAbstractRecur( dd, bVars, bVarsThis ); if ( bVarsExtra == NULL ) { Cudd_RecursiveDeref( dd, bRes ); return NULL; } cuddRef( bVarsExtra ); // add these variables bRes = cuddBddAndRecur( dd, bTemp = bRes, bVarsExtra ); if ( bRes == NULL ) { Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bVarsExtra ); return NULL; } cuddRef( bRes ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bVarsExtra ); } cuddDeref( bRes ); cuddCacheInsert2( dd, extraBddReduceVarSet, bVars, bF, bRes ); return bRes; } } /* end of extraBddReduceVarSet */
/**Function******************************************************************** Synopsis [Implements the recursive step of Cudd_bddXor.] Description [Implements the recursive step of Cudd_bddXor by taking the exclusive OR of two BDDs. Returns a pointer to the result is successful; NULL otherwise.] SideEffects [None] SeeAlso [Cudd_bddXor] ******************************************************************************/ DdNode * cuddBddXorRecur( DdManager * manager, DdNode * f, DdNode * g) { DdNode *fv, *fnv, *G, *gv, *gnv; DdNode *one, *zero, *r, *t, *e; unsigned int topf, topg, index; statLine(manager); one = DD_ONE(manager); zero = Cudd_Not(one); /* Terminal cases. */ if (f == g) return(zero); if (f == Cudd_Not(g)) return(one); if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency and simplify tests. */ DdNode *tmp = f; f = g; g = tmp; } if (g == zero) return(f); if (g == one) return(Cudd_Not(f)); if (Cudd_IsComplement(f)) { f = Cudd_Not(f); g = Cudd_Not(g); } /* Now the first argument is regular. */ if (f == one) return(Cudd_Not(g)); /* At this point f and g are not constant. */ /* Check cache. */ r = cuddCacheLookup2(manager, Cudd_bddXor, f, g); if (r != NULL) return(r); /* Here we can skip the use of cuddI, because the operands are known ** to be non-constant. */ topf = manager->perm[f->index]; G = Cudd_Regular(g); topg = manager->perm[G->index]; /* Compute cofactors. */ if (topf <= topg) { index = f->index; fv = cuddT(f); fnv = cuddE(f); } else { index = G->index; fv = fnv = f; } if (topg <= topf) { gv = cuddT(G); gnv = cuddE(G); if (Cudd_IsComplement(g)) { gv = Cudd_Not(gv); gnv = Cudd_Not(gnv); } } else { gv = gnv = g; } t = cuddBddXorRecur(manager, fv, gv); if (t == NULL) return(NULL); cuddRef(t); e = cuddBddXorRecur(manager, fnv, gnv); if (e == NULL) { Cudd_IterDerefBdd(manager, t); return(NULL); } cuddRef(e); if (t == e) { r = t; } else { if (Cudd_IsComplement(t)) { r = cuddUniqueInter(manager,(int)index,Cudd_Not(t),Cudd_Not(e)); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } r = Cudd_Not(r); } else { r = cuddUniqueInter(manager,(int)index,t,e); if (r == NULL) { Cudd_IterDerefBdd(manager, t); Cudd_IterDerefBdd(manager, e); return(NULL); } } } cuddDeref(e); cuddDeref(t); cuddCacheInsert2(manager, Cudd_bddXor, f, g, r); return(r); } /* end of cuddBddXorRecur */
/**Function******************************************************************** Synopsis [Determines whether f is less than or equal to g.] Description [Returns 1 if f is less than or equal to g; 0 otherwise. No new nodes are created.] SideEffects [None] SeeAlso [Cudd_bddIteConstant Cudd_addEvalConst] ******************************************************************************/ int Cudd_bddLeq( DdManager * dd, DdNode * f, DdNode * g) { DdNode *one, *zero, *tmp, *F, *fv, *fvn, *gv, *gvn; unsigned int topf, topg, res; statLine(dd); /* Terminal cases and normalization. */ if (f == g) return(1); if (Cudd_IsComplement(g)) { /* Special case: if f is regular and g is complemented, ** f(1,...,1) = 1 > 0 = g(1,...,1). */ if (!Cudd_IsComplement(f)) return(0); /* Both are complemented: Swap and complement because ** f <= g <=> g' <= f' and we want the second argument to be regular. */ tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } else if (Cudd_IsComplement(f) && cuddF2L(g) < cuddF2L(f)) { tmp = g; g = Cudd_Not(f); f = Cudd_Not(tmp); } /* Now g is regular and, if f is not regular, f < g. */ one = DD_ONE(dd); if (g == one) return(1); /* no need to test against zero */ if (f == one) return(0); /* since at this point g != one */ if (Cudd_Not(f) == g) return(0); /* because neither is constant */ zero = Cudd_Not(one); if (f == zero) return(1); /* Here neither f nor g is constant. */ /* Check cache. */ tmp = cuddCacheLookup2(dd,(DD_CTFP)Cudd_bddLeq,f,g); if (tmp != NULL) { return(tmp == one); } /* Compute cofactors. */ F = Cudd_Regular(f); topf = dd->perm[F->index]; topg = dd->perm[g->index]; if (topf <= topg) { fv = cuddT(F); fvn = cuddE(F); if (f != F) { fv = Cudd_Not(fv); fvn = Cudd_Not(fvn); } } else { fv = fvn = f; } if (topg <= topf) { gv = cuddT(g); gvn = cuddE(g); } else { gv = gvn = g; } /* Recursive calls. Since we want to maximize the probability of ** the special case f(1,...,1) > g(1,...,1), we consider the negative ** cofactors first. Indeed, the complementation parity of the positive ** cofactors is the same as the one of the parent functions. */ res = Cudd_bddLeq(dd,fvn,gvn) && Cudd_bddLeq(dd,fv,gv); /* Store result in cache and return. */ cuddCacheInsert2(dd,(DD_CTFP)Cudd_bddLeq,f,g,(res ? one : zero)); return(res); } /* end of Cudd_bddLeq */
/**Function******************************************************************** Synopsis [Performs the reordering-sensitive step of Extra_bddHaar().] Description [Generates in a bottom-up fashion an ADD for all spectral coefficients of the functions represented by a BDD.] SideEffects [] SeeAlso [] ******************************************************************************/ DdNode* extraBddHaar( DdManager * dd, /* the manager */ DdNode * bFunc, /* the function whose spectrum is being computed */ DdNode * bVars) /* the variables on which the function depends */ { DdNode * aRes; statLine(dd); /* terminal cases */ if ( bVars == b1 ) { assert( Cudd_IsConstant(bFunc) ); if ( bFunc == b0 ) return a0; else return a1; } /* check cache */ // if ( bFunc->ref != 1 ) if ( aRes = cuddCacheLookup2(dd, extraBddHaar, bFunc, bVars) ) return aRes; else { DdNode * bFunc0, * bFunc1; /* cofactors of the function */ DdNode * aHaar0, * aHaar1; /* partial solutions of the problem */ DdNode * aNode0, * aNode1; /* the special terminal nodes */ DdNode * aRes0, * aRes1; /* partial results to be composed by ITE */ DdNode * bFuncR = Cudd_Regular(bFunc); /* the regular pointer to the function */ DdNode * aTemp; double dValue0, dValue1; /* bFunc cannot depend on a variable that is not in bVars */ assert( cuddI(dd,bFuncR->index) >= cuddI(dd,bVars->index) ); /* cofactor the BDD */ if ( bFuncR->index == bVars->index ) { if ( bFuncR != bFunc ) /* bFunc is complemented */ { bFunc0 = Cudd_Not( cuddE(bFuncR) ); bFunc1 = Cudd_Not( cuddT(bFuncR) ); } else { bFunc0 = cuddE(bFuncR); bFunc1 = cuddT(bFuncR); } } else /* bVars is higher in the variable order */ bFunc0 = bFunc1 = bFunc; /* solve subproblems */ aHaar0 = extraBddHaar( dd, bFunc0, cuddT(bVars) ); if ( aHaar0 == NULL ) return NULL; cuddRef( aHaar0 ); aHaar1 = extraBddHaar( dd, bFunc1, cuddT(bVars) ); if ( aHaar1 == NULL ) { Cudd_RecursiveDeref( dd, aHaar0 ); return NULL; } cuddRef( aHaar1 ); /* retrieve the terminal values in aHaar0 and aHaar1 */ for ( aTemp = aHaar0; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) ); dValue0 = cuddV( aTemp ); for ( aTemp = aHaar1; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) ); dValue1 = cuddV( aTemp ); /* get the new terminal nodes */ aNode0 = cuddUniqueConst( dd, dValue0 + dValue1 ); if ( aNode0 == NULL ) { Cudd_RecursiveDeref( dd, aHaar0 ); Cudd_RecursiveDeref( dd, aHaar1 ); return NULL; } cuddRef( aNode0 ); aNode1 = cuddUniqueConst( dd, dValue0 - dValue1 ); if ( aNode1 == NULL ) { Cudd_RecursiveDeref( dd, aHaar0 ); Cudd_RecursiveDeref( dd, aHaar1 ); Cudd_RecursiveDeref( dd, aNode0 ); return NULL; } cuddRef( aNode1 ); /* replace the terminal nodes in the cofactor ADDs */ aRes0 = extraAddUpdateZeroCubeValue( dd, aHaar0, cuddT(bVars), aNode0 ); if ( aRes0 == NULL ) { Cudd_RecursiveDeref( dd, aHaar0 ); Cudd_RecursiveDeref( dd, aHaar1 ); Cudd_RecursiveDeref( dd, aNode0 ); Cudd_RecursiveDeref( dd, aNode1 ); return NULL; } cuddRef( aRes0 ); aRes1 = extraAddUpdateZeroCubeValue( dd, aHaar1, cuddT(bVars), aNode1 ); if ( aRes1 == NULL ) { Cudd_RecursiveDeref( dd, aHaar0 ); Cudd_RecursiveDeref( dd, aHaar1 ); Cudd_RecursiveDeref( dd, aNode0 ); Cudd_RecursiveDeref( dd, aNode1 ); Cudd_RecursiveDeref( dd, aRes0 ); return NULL; } cuddRef( aRes1 ); Cudd_RecursiveDeref(dd, aHaar0); Cudd_RecursiveDeref(dd, aHaar1); Cudd_RecursiveDeref(dd, aNode0); Cudd_RecursiveDeref(dd, aNode1); /* only aRes0 and aRes1 are referenced at this point */ /* consider the case when Res0 and Res1 are the same node */ aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 ); if (aRes == NULL) { Cudd_RecursiveDeref(dd, aRes1); Cudd_RecursiveDeref(dd, aRes0); return NULL; } cuddDeref(aRes1); cuddDeref(aRes0); /* insert the result into cache */ // if ( bFunc->ref != 1 ) cuddCacheInsert2(dd, extraBddHaar, bFunc, bVars, aRes); return aRes; } } /* end of extraBddHaar */