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.
		
		
		
		
		
			
		
			
				
					
					
						
							639 lines
						
					
					
						
							17 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							639 lines
						
					
					
						
							17 KiB
						
					
					
				
								/**CFile***********************************************************************
							 | 
						|
								
							 | 
						|
								  FileName    [cuddAddIte.c]
							 | 
						|
								
							 | 
						|
								  PackageName [cudd]
							 | 
						|
								
							 | 
						|
								  Synopsis    [ADD ITE function and satellites.]
							 | 
						|
								
							 | 
						|
								  Description [External procedures included in this module:
							 | 
						|
										<ul>
							 | 
						|
										<li> Cudd_addIte()
							 | 
						|
										<li> Cudd_addIteConstant()
							 | 
						|
										<li> Cudd_addEvalConst()
							 | 
						|
										<li> Cudd_addCmpl()
							 | 
						|
										<li> Cudd_addLeq()
							 | 
						|
										</ul>
							 | 
						|
									Internal procedures included in this module:
							 | 
						|
										<ul>
							 | 
						|
										<li> cuddAddIteRecur()
							 | 
						|
										<li> cuddAddCmplRecur()
							 | 
						|
										</ul>
							 | 
						|
									Static procedures included in this module:
							 | 
						|
										<ul>
							 | 
						|
										<li> addVarToConst()
							 | 
						|
										</ul>]
							 | 
						|
								
							 | 
						|
								  Author      [Fabio Somenzi]
							 | 
						|
								
							 | 
						|
								  Copyright   [Copyright (c) 1995-2012, 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.]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								
							 | 
						|
								#include "util.h"
							 | 
						|
								#include "cuddInt.h"
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Constant declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Stucture declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Type declarations                                                         */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Variable declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#ifndef lint
							 | 
						|
								static char rcsid[] DD_UNUSED = "$Id: cuddAddIte.c,v 1.16 2012/02/05 01:07:18 fabio Exp $";
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**AutomaticStart*************************************************************/
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								static void addVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *one, DdNode *zero);
							 | 
						|
								
							 | 
						|
								/**AutomaticEnd***************************************************************/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of exported functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Implements ITE(f,g,h).]
							 | 
						|
								
							 | 
						|
								  Description [Implements ITE(f,g,h). This procedure assumes that f is
							 | 
						|
								  a 0-1 ADD.  Returns a pointer to the resulting ADD if successful; NULL
							 | 
						|
								  otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [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);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addIte */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Implements ITEconstant for ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [Implements ITEconstant for ADDs.  f must be a 0-1 ADD.
							 | 
						|
								  Returns a pointer to the resulting ADD (which may or may not be
							 | 
						|
								  constant) or DD_NON_CONSTANT. 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.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [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;
							 | 
						|
								    unsigned 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 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Checks whether ADD g is constant whenever ADD f is 1.]
							 | 
						|
								
							 | 
						|
								  Description [Checks whether ADD g is constant whenever ADD f is 1.  f
							 | 
						|
								  must be a 0-1 ADD.  Returns a pointer to the resulting ADD (which may
							 | 
						|
								  or may not be constant) or DD_NON_CONSTANT. If f is identically 0,
							 | 
						|
								  the check is assumed to be successful, and the background value is
							 | 
						|
								  returned. No new nodes are created.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addIteConstant Cudd_addLeq]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addEvalConst(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g)
							 | 
						|
								{
							 | 
						|
								    DdNode *zero;
							 | 
						|
								    DdNode *Fv,*Fnv,*Gv,*Gnv,*r,*t,*e;
							 | 
						|
								    unsigned 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 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Computes the complement of an ADD a la C language.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the complement of an ADD a la C language: The
							 | 
						|
								  complement of 0 is 1 and the complement of everything else is 0.
							 | 
						|
								  Returns a pointer to the resulting ADD if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addNegate]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addCmpl(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddCmplRecur(dd,f);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addCmpl */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**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 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Implements the recursive step of Cudd_addIte(f,g,h).]
							 | 
						|
								
							 | 
						|
								  Description [Implements the recursive step of Cudd_addIte(f,g,h).
							 | 
						|
								  Returns a pointer to the resulting ADD if successful; NULL
							 | 
						|
								  otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [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;
							 | 
						|
								    unsigned int topf,topg,toph,v;
							 | 
						|
								    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);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute cofactors. */
							 | 
						|
								    if (topf <= v) {
							 | 
						|
									v = ddMin(topf,v);	/* v = top_var(F,G,H) */
							 | 
						|
									index = f->index;
							 | 
						|
								        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 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_addCmpl.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_addCmpl. Returns a
							 | 
						|
								  pointer to the resulting ADD if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [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);
							 | 
						|
								    }
							 | 
						|
								    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                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Replaces variables with constants if possible (part of
							 | 
						|
								  canonical form).]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [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 */
							 |