/**Function******************************************************************** Synopsis [Integer and floating point max.] Description [Integer and floating point max for Cudd_addApply. Returns NULL if not a terminal case; max(f,g) otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addMaximum( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(F); if (F == DD_MINUS_INFINITY(dd)) return(G); if (G == DD_MINUS_INFINITY(dd)) return(F); #if 0 /* These special cases probably do not pay off. */ if (F == DD_PLUS_INFINITY(dd)) return(F); if (G == DD_PLUS_INFINITY(dd)) return(G); #endif if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) >= cuddV(G)) { return(F); } else { return(G); } } if (F > G) { /* swap f and g */ *f = G; *g = F; } return(NULL); } /* end of Cudd_addMaximum */
/**Function******************************************************************** Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.] Description [Returns NULL if not a terminal case; f op g otherwise, where f op g is plusinfinity if f=g; min(f,g) if f!=g.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addDiff( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G) return(DD_PLUS_INFINITY(dd)); if (F == DD_PLUS_INFINITY(dd)) return(G); if (G == DD_PLUS_INFINITY(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) != cuddV(G)) { if (cuddV(F) < cuddV(G)) { return(F); } else { return(G); } } else { return(DD_PLUS_INFINITY(dd)); } } return(NULL); } /* end of Cudd_addDiff */
/**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 */
/**Function******************************************************************** Synopsis [Finds the maximum discriminant of f.] Description [Returns a pointer to a constant ADD.] SideEffects [None] ******************************************************************************/ DdNode * Cudd_addFindMax( DdManager * dd, DdNode * f) { DdNode *t, *e, *res; statLine(dd); if (cuddIsConstant(f)) { return(f); } res = cuddCacheLookup1(dd,Cudd_addFindMax,f); if (res != NULL) { return(res); } t = Cudd_addFindMax(dd,cuddT(f)); if (t == DD_PLUS_INFINITY(dd)) return(t); e = Cudd_addFindMax(dd,cuddE(f)); res = (cuddV(t) >= cuddV(e)) ? t : e; cuddCacheInsert1(dd,Cudd_addFindMax,f,res); return(res); } /* end of Cudd_addFindMax */
/**Function******************************************************************** Synopsis [f if f>=g; 0 if f<g.] Description [Threshold operator for Apply (f if f >=g; 0 if f<g). Returns NULL if not a terminal case; f op g otherwise.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addThreshold( DdManager * dd, DdNode ** f, DdNode ** g) { DdNode *F, *G; F = *f; G = *g; if (F == G || F == DD_PLUS_INFINITY(dd)) return(F); if (cuddIsConstant(F) && cuddIsConstant(G)) { if (cuddV(F) >= cuddV(G)) { return(F); } else { return(DD_ZERO(dd)); } } return(NULL); } /* end of Cudd_addThreshold */
/**Function******************************************************************** Synopsis [Returns 1 if f > g and 0 otherwise.] Description [Returns 1 if f > g (both should be terminal cases) and 0 otherwise. Used in conjunction with Cudd_addApply. Returns NULL if not a terminal case.] SideEffects [None] SeeAlso [Cudd_addApply] ******************************************************************************/ DdNode * Cudd_addOneZeroMaximum( DdManager * dd, DdNode ** f, DdNode ** g) { if (*g == DD_PLUS_INFINITY(dd)) return DD_ZERO(dd); if (cuddIsConstant(*f) && cuddIsConstant(*g)) { if (cuddV(*f) > cuddV(*g)) { return(DD_ONE(dd)); } else { return(DD_ZERO(dd)); } } return(NULL); } /* end of Cudd_addOneZeroMaximum */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addOuterSum.] Description [Performs the recursive step of Cudd_addOuterSum. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] SeeAlso [] ******************************************************************************/ static DdNode * cuddAddOuterSumRecur( DdManager *dd, DdNode *M, DdNode *r, DdNode *c) { DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re; int topM, topc, topr; int v, index; statLine(dd); /* Check special cases. */ if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); if (cuddIsConstant(c) && cuddIsConstant(r)) { R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r)); cuddRef(R); if (cuddIsConstant(M)) { if (cuddV(R) <= cuddV(M)) { cuddDeref(R); return(R); } else { Cudd_RecursiveDeref(dd,R); return(M); } } else { P = Cudd_addApply(dd,Cudd_addMinimum,R,M); cuddRef(P); Cudd_RecursiveDeref(dd,R); cuddDeref(P); return(P); } } /* Check the cache. */ R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c); if (R != NULL) return(R); topM = cuddI(dd,M->index); topr = cuddI(dd,r->index); topc = cuddI(dd,c->index); v = ddMin(topM,ddMin(topr,topc)); /* Compute cofactors. */ if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; } if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; } if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; } /* Recursively solve. */ Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct); if (Rt == NULL) return(NULL); cuddRef(Rt); Re = cuddAddOuterSumRecur(dd,Me,re,ce); if (Re == NULL) { Cudd_RecursiveDeref(dd, Rt); return(NULL); } cuddRef(Re); index = dd->invperm[v]; R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re); if (R == NULL) { Cudd_RecursiveDeref(dd, Rt); Cudd_RecursiveDeref(dd, Re); return(NULL); } cuddDeref(Rt); cuddDeref(Re); /* Store the result in the cache. */ cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R); return(R); } /* end of cuddAddOuterSumRecur */
/**Function******************************************************************** Synopsis [Performs the recursive step of Cudd_addTriangle.] Description [Performs the recursive step of Cudd_addTriangle. Returns a pointer to the result if successful; NULL otherwise.] SideEffects [None] ******************************************************************************/ static DdNode * addTriangleRecur( DdManager * dd, DdNode * f, DdNode * g, int * vars, DdNode *cube) { DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res; CUDD_VALUE_TYPE value; int top, topf, topg, index; statLine(dd); if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) { return(DD_PLUS_INFINITY(dd)); } if (cuddIsConstant(f) && cuddIsConstant(g)) { value = cuddV(f) + cuddV(g); res = cuddUniqueConst(dd, value); return(res); } if (f < g) { DdNode *tmp = f; f = g; g = tmp; } if (f->ref != 1 || g->ref != 1) { res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube); if (res != NULL) { return(res); } } topf = cuddI(dd,f->index); topg = cuddI(dd,g->index); top = ddMin(topf,topg); if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;} if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;} t = addTriangleRecur(dd, fv, gv, vars, cube); if (t == NULL) return(NULL); cuddRef(t); e = addTriangleRecur(dd, fvn, gvn, vars, cube); if (e == NULL) { Cudd_RecursiveDeref(dd, t); return(NULL); } cuddRef(e); index = dd->invperm[top]; if (vars[index] < 0) { res = (t == e) ? t : cuddUniqueInter(dd,index,t,e); if (res == NULL) { Cudd_RecursiveDeref(dd, t); Cudd_RecursiveDeref(dd, e); return(NULL); } cuddDeref(t); cuddDeref(e); } else { res = cuddAddApplyRecur(dd,Cudd_addMinimum,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); cuddDeref(res); } if (f->ref != 1 || g->ref != 1) { cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res); } return(res); } /* end of addTriangleRecur */