You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							620 lines
						
					
					
						
							15 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							620 lines
						
					
					
						
							15 KiB
						
					
					
				
								/**
							 | 
						|
								  @file 
							 | 
						|
								
							 | 
						|
								  @ingroup cudd
							 | 
						|
								
							 | 
						|
								  @brief %ADD ITE function and satellites.
							 | 
						|
								
							 | 
						|
								  @author Fabio Somenzi
							 | 
						|
								
							 | 
						|
								  @copyright@parblock
							 | 
						|
								  Copyright (c) 1995-2015, Regents of the University of Colorado
							 | 
						|
								
							 | 
						|
								  All rights reserved.
							 | 
						|
								
							 | 
						|
								  Redistribution and use in source and binary forms, with or without
							 | 
						|
								  modification, are permitted provided that the following conditions
							 | 
						|
								  are met:
							 | 
						|
								
							 | 
						|
								  Redistributions of source code must retain the above copyright
							 | 
						|
								  notice, this list of conditions and the following disclaimer.
							 | 
						|
								
							 | 
						|
								  Redistributions in binary form must reproduce the above copyright
							 | 
						|
								  notice, this list of conditions and the following disclaimer in the
							 | 
						|
								  documentation and/or other materials provided with the distribution.
							 | 
						|
								
							 | 
						|
								  Neither the name of the University of Colorado nor the names of its
							 | 
						|
								  contributors may be used to endorse or promote products derived from
							 | 
						|
								  this software without specific prior written permission.
							 | 
						|
								
							 | 
						|
								  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
							 | 
						|
								  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
							 | 
						|
								  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
							 | 
						|
								  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
							 | 
						|
								  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
							 | 
						|
								  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
							 | 
						|
								  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
							 | 
						|
								  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
							 | 
						|
								  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
							 | 
						|
								  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
							 | 
						|
								  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
							 | 
						|
								  POSSIBILITY OF SUCH DAMAGE.
							 | 
						|
								  @endparblock
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								#include "util.h"
							 | 
						|
								#include "cuddInt.h"
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Constant declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Stucture declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Type declarations                                                         */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Variable declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								/** \cond */
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
							 | 
						|
								
							 | 
						|
								/** \endcond */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of exported functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Implements ITE(f,g,h).
							 | 
						|
								
							 | 
						|
								  @details This procedure assumes that f is a 0-1 %ADD.
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD if successful; NULL
							 | 
						|
								  otherwise.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_bddIte Cudd_addIteConstant Cudd_addApply
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addIte(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g,
							 | 
						|
								  DdNode * h)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddIteRecur(dd,f,g,h);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
							 | 
						|
								        dd->timeoutHandler(dd, dd->tohArg);
							 | 
						|
								    }
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addIte */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Implements ITEconstant for %ADDs.
							 | 
						|
								
							 | 
						|
								  @details f must be a 0-1 %ADD.  No new nodes are created. This
							 | 
						|
								  function can be used, for instance, to check that g has a constant
							 | 
						|
								  value (specified by h) whenever f is 1. If the constant value is
							 | 
						|
								  unknown, then one should use Cudd_addEvalConst.
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD (which may or may not be
							 | 
						|
								  constant) or DD_NON_CONSTANT.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addIte Cudd_addEvalConst Cudd_bddIteConstant
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addIteConstant(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g,
							 | 
						|
								  DdNode * h)
							 | 
						|
								{
							 | 
						|
								    DdNode *one,*zero;
							 | 
						|
								    DdNode *Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*r,*t,*e;
							 | 
						|
								    int topf,topg,toph,v;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    /* Trivial cases. */
							 | 
						|
								    if (f == (one = DD_ONE(dd))) {	/* ITE(1,G,H) = G */
							 | 
						|
								        return(g);
							 | 
						|
								    }
							 | 
						|
								    if (f == (zero = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
							 | 
						|
								        return(h);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* From now on, f is known not to be a constant. */
							 | 
						|
								    addVarToConst(f,&g,&h,one,zero);
							 | 
						|
								
							 | 
						|
								    /* Check remaining one variable cases. */
							 | 
						|
								    if (g == h) { 			/* ITE(F,G,G) = G */
							 | 
						|
								        return(g);
							 | 
						|
								    }
							 | 
						|
								    if (cuddIsConstant(g) && cuddIsConstant(h)) {
							 | 
						|
								        return(DD_NON_CONSTANT);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    topf = cuddI(dd,f->index);
							 | 
						|
								    topg = cuddI(dd,g->index);
							 | 
						|
								    toph = cuddI(dd,h->index);
							 | 
						|
								    v = ddMin(topg,toph);
							 | 
						|
								
							 | 
						|
								    /* ITE(F,G,H) = (x,G,H) (non constant) if F = (x,1,0), x < top(G,H). */
							 | 
						|
								    if (topf < v && cuddIsConstant(cuddT(f)) && cuddIsConstant(cuddE(f))) {
							 | 
						|
									return(DD_NON_CONSTANT);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    r = cuddConstantLookup(dd,DD_ADD_ITE_CONSTANT_TAG,f,g,h);
							 | 
						|
								    if (r != NULL) {
							 | 
						|
								        return(r);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute cofactors. */
							 | 
						|
								    if (topf <= v) {
							 | 
						|
									v = ddMin(topf,v);	/* v = top_var(F,G,H) */
							 | 
						|
								        Fv = cuddT(f); Fnv = cuddE(f);
							 | 
						|
								    } else {
							 | 
						|
								        Fv = Fnv = f;
							 | 
						|
								    }
							 | 
						|
								    if (topg == v) {
							 | 
						|
								        Gv = cuddT(g); Gnv = cuddE(g);
							 | 
						|
								    } else {
							 | 
						|
								        Gv = Gnv = g;
							 | 
						|
								    }
							 | 
						|
								    if (toph == v) {
							 | 
						|
								        Hv = cuddT(h); Hnv = cuddE(h);
							 | 
						|
								    } else {
							 | 
						|
								        Hv = Hnv = h;
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    /* Recursive step. */
							 | 
						|
								    t = Cudd_addIteConstant(dd,Fv,Gv,Hv);
							 | 
						|
								    if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
							 | 
						|
									cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
							 | 
						|
									return(DD_NON_CONSTANT);
							 | 
						|
								    }
							 | 
						|
								    e = Cudd_addIteConstant(dd,Fnv,Gnv,Hnv);
							 | 
						|
								    if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
							 | 
						|
									cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, DD_NON_CONSTANT);
							 | 
						|
									return(DD_NON_CONSTANT);
							 | 
						|
								    }
							 | 
						|
								    cuddCacheInsert(dd, DD_ADD_ITE_CONSTANT_TAG, f, g, h, t);
							 | 
						|
								    return(t);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addIteConstant */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Checks whether %ADD g is constant whenever %ADD f is 1.
							 | 
						|
								
							 | 
						|
								  @details f must be a 0-1 %ADD.  If f is identically 0, the check is
							 | 
						|
								  assumed to be successful, and the background value is returned.  No
							 | 
						|
								  new nodes are created.
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD (which may or may not be
							 | 
						|
								  constant) or DD_NON_CONSTANT.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addIteConstant Cudd_addLeq
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addEvalConst(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g)
							 | 
						|
								{
							 | 
						|
								    DdNode *zero;
							 | 
						|
								    DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
							 | 
						|
								    int topf,topg;
							 | 
						|
								
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
								    assert(!Cudd_IsComplement(f));
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    /* Terminal cases. */
							 | 
						|
								    if (f == DD_ONE(dd) || cuddIsConstant(g)) {
							 | 
						|
								        return(g);
							 | 
						|
								    }
							 | 
						|
								    if (f == (zero = DD_ZERO(dd))) {
							 | 
						|
								        return(dd->background);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
								    assert(!cuddIsConstant(f));
							 | 
						|
								#endif
							 | 
						|
								    /* From now on, f and g are known not to be constants. */
							 | 
						|
								
							 | 
						|
								    topf = cuddI(dd,f->index);
							 | 
						|
								    topg = cuddI(dd,g->index);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    r = cuddConstantLookup(dd,DD_ADD_EVAL_CONST_TAG,f,g,g);
							 | 
						|
								    if (r != NULL) {
							 | 
						|
								        return(r);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute cofactors. */
							 | 
						|
								    if (topf <= topg) {
							 | 
						|
								        Fv = cuddT(f); Fnv = cuddE(f);
							 | 
						|
								    } else {
							 | 
						|
								        Fv = Fnv = f;
							 | 
						|
								    }
							 | 
						|
								    if (topg <= topf) {
							 | 
						|
								        Gv = cuddT(g); Gnv = cuddE(g);
							 | 
						|
								    } else {
							 | 
						|
								        Gv = Gnv = g;
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    /* Recursive step. */
							 | 
						|
								    if (Fv != zero) {
							 | 
						|
									t = Cudd_addEvalConst(dd,Fv,Gv);
							 | 
						|
									if (t == DD_NON_CONSTANT || !cuddIsConstant(t)) {
							 | 
						|
									    cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
							 | 
						|
									    return(DD_NON_CONSTANT);
							 | 
						|
									}
							 | 
						|
									if (Fnv != zero) {
							 | 
						|
									    e = Cudd_addEvalConst(dd,Fnv,Gnv);
							 | 
						|
									    if (e == DD_NON_CONSTANT || !cuddIsConstant(e) || t != e) {
							 | 
						|
										cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, DD_NON_CONSTANT);
							 | 
						|
										return(DD_NON_CONSTANT);
							 | 
						|
									    }
							 | 
						|
									}
							 | 
						|
									cuddCacheInsert2(dd,Cudd_addEvalConst,f,g,t);
							 | 
						|
									return(t);
							 | 
						|
								    } else { /* Fnv must be != zero */
							 | 
						|
									e = Cudd_addEvalConst(dd,Fnv,Gnv);
							 | 
						|
									cuddCacheInsert2(dd, Cudd_addEvalConst, f, g, e);
							 | 
						|
									return(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addEvalConst */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Computes the complement of an %ADD a la C language.
							 | 
						|
								
							 | 
						|
								  @details The complement of 0 is 1 and the complement of everything
							 | 
						|
								  else is 0.
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD if successful; NULL otherwise.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addNegate
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addCmpl(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddCmplRecur(dd,f);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
							 | 
						|
								        dd->timeoutHandler(dd, dd->tohArg);
							 | 
						|
								    }
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addCmpl */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Determines whether f is less than or equal to g.
							 | 
						|
								
							 | 
						|
								  @details No new nodes are created. This procedure works for arbitrary ADDs.
							 | 
						|
								  For 0-1 ADDs Cudd_addEvalConst is more efficient.
							 | 
						|
								
							 | 
						|
								  @return 1 if f is less than or equal to g; 0 otherwise.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addIteConstant Cudd_addEvalConst Cudd_bddLeq
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								int
							 | 
						|
								Cudd_addLeq(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g)
							 | 
						|
								{
							 | 
						|
								    DdNode *tmp, *fv, *fvn, *gv, *gvn;
							 | 
						|
								    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 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Implements the recursive step of Cudd_addIte(f,g,h).
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD if successful; NULL
							 | 
						|
								  otherwise.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addIte
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								cuddAddIteRecur(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g,
							 | 
						|
								  DdNode * h)
							 | 
						|
								{
							 | 
						|
								    DdNode *one,*zero;
							 | 
						|
								    DdNode *r,*Fv,*Fnv,*Gv,*Gnv,*Hv,*Hnv,*t,*e;
							 | 
						|
								    int topf,topg,toph,v;
							 | 
						|
								    unsigned int index;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    /* Trivial cases. */
							 | 
						|
								
							 | 
						|
								    /* One variable cases. */
							 | 
						|
								    if (f == (one = DD_ONE(dd))) {	/* ITE(1,G,H) = G */
							 | 
						|
								        return(g);
							 | 
						|
								    }
							 | 
						|
								    if (f == (zero = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
							 | 
						|
								        return(h);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* From now on, f is known to not be a constant. */
							 | 
						|
								    addVarToConst(f,&g,&h,one,zero);
							 | 
						|
								
							 | 
						|
								    /* Check remaining one variable cases. */
							 | 
						|
								    if (g == h) {			/* ITE(F,G,G) = G */
							 | 
						|
								        return(g);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (g == one) {			/* ITE(F,1,0) = F */
							 | 
						|
								        if (h == zero) return(f);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    topf = cuddI(dd,f->index);
							 | 
						|
								    topg = cuddI(dd,g->index);
							 | 
						|
								    toph = cuddI(dd,h->index);
							 | 
						|
								    v = ddMin(topg,toph);
							 | 
						|
								
							 | 
						|
								    /* A shortcut: ITE(F,G,H) = (x,G,H) if F=(x,1,0), x < top(G,H). */
							 | 
						|
								    if (topf < v && cuddT(f) == one && cuddE(f) == zero) {
							 | 
						|
									r = cuddUniqueInter(dd,(int)f->index,g,h);
							 | 
						|
									return(r);
							 | 
						|
								    }
							 | 
						|
								    if (topf < v && cuddT(f) == zero && cuddE(f) == one) {
							 | 
						|
									r = cuddUniqueInter(dd,(int)f->index,h,g);
							 | 
						|
									return(r);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    r = cuddCacheLookup(dd,DD_ADD_ITE_TAG,f,g,h);
							 | 
						|
								    if (r != NULL) {
							 | 
						|
								        return(r);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    checkWhetherToGiveUp(dd);
							 | 
						|
								
							 | 
						|
								    /* Compute cofactors. */
							 | 
						|
								    index = f->index;
							 | 
						|
								    if (topf <= v) {
							 | 
						|
									v = ddMin(topf,v);	/* v = top_var(F,G,H) */
							 | 
						|
								        Fv = cuddT(f); Fnv = cuddE(f);
							 | 
						|
								    } else {
							 | 
						|
								        Fv = Fnv = f;
							 | 
						|
								    }
							 | 
						|
								    if (topg == v) {
							 | 
						|
									index = g->index;
							 | 
						|
								        Gv = cuddT(g); Gnv = cuddE(g);
							 | 
						|
								    } else {
							 | 
						|
								        Gv = Gnv = g;
							 | 
						|
								    }
							 | 
						|
								    if (toph == v) {
							 | 
						|
									index = h->index;
							 | 
						|
								        Hv = cuddT(h); Hnv = cuddE(h);
							 | 
						|
								    } else {
							 | 
						|
								        Hv = Hnv = h;
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    /* Recursive step. */
							 | 
						|
								    t = cuddAddIteRecur(dd,Fv,Gv,Hv);
							 | 
						|
								    if (t == NULL) return(NULL);
							 | 
						|
								    cuddRef(t);
							 | 
						|
								
							 | 
						|
								    e = cuddAddIteRecur(dd,Fnv,Gnv,Hnv);
							 | 
						|
								    if (e == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,t);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(e);
							 | 
						|
								
							 | 
						|
								    r = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
							 | 
						|
								    if (r == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,t);
							 | 
						|
									Cudd_RecursiveDeref(dd,e);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(t);
							 | 
						|
								    cuddDeref(e);
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert(dd,DD_ADD_ITE_TAG,f,g,h,r);
							 | 
						|
								
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of cuddAddIteRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Performs the recursive step of Cudd_addCmpl.
							 | 
						|
								
							 | 
						|
								  @return a pointer to the resulting %ADD if successful; NULL
							 | 
						|
								  otherwise.
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								  @see Cudd_addCmpl
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								DdNode *
							 | 
						|
								cuddAddCmplRecur(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    DdNode *one,*zero;
							 | 
						|
								    DdNode *r,*Fv,*Fnv,*t,*e;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    one = DD_ONE(dd);
							 | 
						|
								    zero = DD_ZERO(dd); 
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(f)) {
							 | 
						|
								        if (f == zero) {
							 | 
						|
									    return(one);
							 | 
						|
									} else {
							 | 
						|
									    return(zero);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    r = cuddCacheLookup1(dd,Cudd_addCmpl,f);
							 | 
						|
								    if (r != NULL) {
							 | 
						|
									return(r);
							 | 
						|
								    }
							 | 
						|
								    checkWhetherToGiveUp(dd);
							 | 
						|
								    Fv = cuddT(f);
							 | 
						|
								    Fnv = cuddE(f);
							 | 
						|
								    t = cuddAddCmplRecur(dd,Fv);
							 | 
						|
								    if (t == NULL) return(NULL);
							 | 
						|
								    cuddRef(t);
							 | 
						|
								    e = cuddAddCmplRecur(dd,Fnv);
							 | 
						|
								    if (e == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,t);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(e);
							 | 
						|
								    r = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
							 | 
						|
								    if (r == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, t);
							 | 
						|
									Cudd_RecursiveDeref(dd, e);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(t);
							 | 
						|
								    cuddDeref(e);
							 | 
						|
								    cuddCacheInsert1(dd,Cudd_addCmpl,f,r);
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of cuddAddCmplRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of static functions                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								  @brief Replaces variables with constants if possible (part of
							 | 
						|
								  canonical form).
							 | 
						|
								
							 | 
						|
								  @sideeffect None
							 | 
						|
								
							 | 
						|
								*/
							 | 
						|
								static void
							 | 
						|
								addVarToConst(
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode ** gp,
							 | 
						|
								  DdNode ** hp,
							 | 
						|
								  DdNode * one,
							 | 
						|
								  DdNode * zero)
							 | 
						|
								{
							 | 
						|
								    DdNode *g = *gp;
							 | 
						|
								    DdNode *h = *hp;
							 | 
						|
								
							 | 
						|
								    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
							 | 
						|
									*gp = one;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
							 | 
						|
									*hp = zero;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								} /* end of addVarToConst */
							 |