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.
		
		
		
		
		
			
		
			
				
					
					
						
							1166 lines
						
					
					
						
							28 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1166 lines
						
					
					
						
							28 KiB
						
					
					
				
								/**CFile***********************************************************************
							 | 
						|
								
							 | 
						|
								  FileName    [cuddZddSetop.c]
							 | 
						|
								
							 | 
						|
								  PackageName [cudd]
							 | 
						|
								
							 | 
						|
								  Synopsis    [Set operations on ZDDs.]
							 | 
						|
								
							 | 
						|
								  Description [External procedures included in this module:
							 | 
						|
										    <ul>
							 | 
						|
										    <li> Cudd_zddIte()
							 | 
						|
										    <li> Cudd_zddUnion()
							 | 
						|
										    <li> Cudd_zddIntersect()
							 | 
						|
										    <li> Cudd_zddDiff()
							 | 
						|
										    <li> Cudd_zddDiffConst()
							 | 
						|
										    <li> Cudd_zddSubset1()
							 | 
						|
										    <li> Cudd_zddSubset0()
							 | 
						|
										    <li> Cudd_zddChange()
							 | 
						|
										    </ul>
							 | 
						|
									       Internal procedures included in this module:
							 | 
						|
										    <ul>
							 | 
						|
										    <li> cuddZddIte()
							 | 
						|
										    <li> cuddZddUnion()
							 | 
						|
										    <li> cuddZddIntersect()
							 | 
						|
										    <li> cuddZddDiff()
							 | 
						|
										    <li> cuddZddChangeAux()
							 | 
						|
										    <li> cuddZddSubset1()
							 | 
						|
										    <li> cuddZddSubset0()
							 | 
						|
										    </ul>
							 | 
						|
									       Static procedures included in this module:
							 | 
						|
										    <ul>
							 | 
						|
										    <li> zdd_subset1_aux()
							 | 
						|
										    <li> zdd_subset0_aux()
							 | 
						|
										    <li> zddVarToConst()
							 | 
						|
										    </ul>
							 | 
						|
									      ]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								  Author      [Hyong-Kyoon Shin, In-Ho Moon]
							 | 
						|
								
							 | 
						|
								  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: cuddZddSetop.c,v 1.26 2012/02/05 01:07:19 fabio Exp $";
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#ifdef __cplusplus
							 | 
						|
								extern "C" {
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/**AutomaticStart*************************************************************/
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								static DdNode * zdd_subset1_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
							 | 
						|
								static DdNode * zdd_subset0_aux (DdManager *zdd, DdNode *P, DdNode *zvar);
							 | 
						|
								static void zddVarToConst (DdNode *f, DdNode **gp, DdNode **hp, DdNode *base, DdNode *empty);
							 | 
						|
								
							 | 
						|
								/**AutomaticEnd***************************************************************/
							 | 
						|
								
							 | 
						|
								#ifdef __cplusplus
							 | 
						|
								}
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of exported functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the ITE of three ZDDs.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the ITE of three ZDDs. Returns a pointer to the
							 | 
						|
								  result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddIte(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g,
							 | 
						|
								  DdNode * h)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddZddIte(dd, f, g, h);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddIte */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the union of two ZDDs.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the union of two ZDDs. Returns a pointer to the
							 | 
						|
								  result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddUnion(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddZddUnion(dd, P, Q);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddUnion */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the intersection of two ZDDs.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the intersection of two ZDDs. Returns a pointer to
							 | 
						|
								  the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddIntersect(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddZddIntersect(dd, P, Q);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddIntersect */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the difference of two ZDDs.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the difference of two ZDDs. Returns a pointer to the
							 | 
						|
								  result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddDiffConst]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddDiff(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddZddDiff(dd, P, Q);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddDiff */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the inclusion test for ZDDs (P implies Q).]
							 | 
						|
								
							 | 
						|
								  Description [Inclusion test for ZDDs (P implies Q). No new nodes are
							 | 
						|
								  generated by this procedure. Returns empty if true;
							 | 
						|
								  a valid pointer different from empty or DD_NON_CONSTANT otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddDiff]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddDiffConst(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    int		p_top, q_top;
							 | 
						|
								    DdNode	*empty = DD_ZERO(zdd), *t, *res;
							 | 
						|
								    DdManager	*table = zdd;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    if (P == empty)
							 | 
						|
									return(empty);
							 | 
						|
								    if (Q == empty)
							 | 
						|
									return(P);
							 | 
						|
								    if (P == Q)
							 | 
						|
									return(empty);
							 | 
						|
								
							 | 
						|
								    /* Check cache.  The cache is shared by cuddZddDiff(). */
							 | 
						|
								    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P))
							 | 
						|
									p_top = P->index;
							 | 
						|
								    else
							 | 
						|
									p_top = zdd->permZ[P->index];
							 | 
						|
								    if (cuddIsConstant(Q))
							 | 
						|
									q_top = Q->index;
							 | 
						|
								    else
							 | 
						|
									q_top = zdd->permZ[Q->index];
							 | 
						|
								    if (p_top < q_top) {
							 | 
						|
									res = DD_NON_CONSTANT;
							 | 
						|
								    } else if (p_top > q_top) {
							 | 
						|
									res = Cudd_zddDiffConst(zdd, P, cuddE(Q));
							 | 
						|
								    } else {
							 | 
						|
									t = Cudd_zddDiffConst(zdd, cuddT(P), cuddT(Q));
							 | 
						|
									if (t != empty)
							 | 
						|
									    res = DD_NON_CONSTANT;
							 | 
						|
									else
							 | 
						|
									    res = Cudd_zddDiffConst(zdd, cuddE(P), cuddE(Q));
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddDiffConst */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the positive cofactor of a ZDD w.r.t. a
							 | 
						|
								  variable. In terms of combinations, the result is the set of all
							 | 
						|
								  combinations in which the variable is asserted. Returns a pointer to
							 | 
						|
								  the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddSubset0]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddSubset1(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*r;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									r = cuddZddSubset1(dd, P, var);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddSubset1 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the negative cofactor of a ZDD w.r.t. a
							 | 
						|
								  variable. In terms of combinations, the result is the set of all
							 | 
						|
								  combinations in which the variable is negated. Returns a pointer to
							 | 
						|
								  the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddSubset1]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddSubset0(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*r;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									r = cuddZddSubset0(dd, P, var);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddSubset0 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Substitutes a variable with its complement in a ZDD.]
							 | 
						|
								
							 | 
						|
								  Description [Substitutes a variable with its complement in a ZDD.
							 | 
						|
								  returns a pointer to the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_zddChange(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*res;
							 | 
						|
								
							 | 
						|
								    if ((unsigned int) var >= CUDD_MAXINDEX - 1) return(NULL);
							 | 
						|
								    
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddZddChange(dd, P, var);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_zddChange */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_zddIte.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddIte(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g,
							 | 
						|
								  DdNode * h)
							 | 
						|
								{
							 | 
						|
								    DdNode *tautology, *empty;
							 | 
						|
								    DdNode *r,*Gv,*Gvn,*Hv,*Hvn,*t,*e;
							 | 
						|
								    unsigned int topf,topg,toph,v,top;
							 | 
						|
								    int index;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    /* Trivial cases. */
							 | 
						|
								    /* One variable cases. */
							 | 
						|
								    if (f == (empty = DD_ZERO(dd))) {	/* ITE(0,G,H) = H */
							 | 
						|
									return(h);
							 | 
						|
								    }
							 | 
						|
								    topf = cuddIZ(dd,f->index);
							 | 
						|
								    topg = cuddIZ(dd,g->index);
							 | 
						|
								    toph = cuddIZ(dd,h->index);
							 | 
						|
								    v = ddMin(topg,toph);
							 | 
						|
								    top  = ddMin(topf,v);
							 | 
						|
								
							 | 
						|
								    tautology = (top == CUDD_MAXINDEX) ? DD_ONE(dd) : dd->univ[top];
							 | 
						|
								    if (f == tautology) {			/* ITE(1,G,H) = G */
							 | 
						|
								    	return(g);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* From now on, f is known to not be a constant. */
							 | 
						|
								    zddVarToConst(f,&g,&h,tautology,empty);
							 | 
						|
								
							 | 
						|
								    /* Check remaining one variable cases. */
							 | 
						|
								    if (g == h) {			/* ITE(F,G,G) = G */
							 | 
						|
									return(g);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (g == tautology) {			/* ITE(F,1,0) = F */
							 | 
						|
									if (h == empty) return(f);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    r = cuddCacheLookupZdd(dd,DD_ZDD_ITE_TAG,f,g,h);
							 | 
						|
								    if (r != NULL) {
							 | 
						|
									return(r);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Recompute these because they may have changed in zddVarToConst. */
							 | 
						|
								    topg = cuddIZ(dd,g->index);
							 | 
						|
								    toph = cuddIZ(dd,h->index);
							 | 
						|
								    v = ddMin(topg,toph);
							 | 
						|
								
							 | 
						|
								    if (topf < v) {
							 | 
						|
									r = cuddZddIte(dd,cuddE(f),g,h);
							 | 
						|
									if (r == NULL) return(NULL);
							 | 
						|
								    } else if (topf > v) {
							 | 
						|
									if (topg > v) {
							 | 
						|
									    Gvn = g;
							 | 
						|
									    index = h->index;
							 | 
						|
									} else {
							 | 
						|
									    Gvn = cuddE(g);
							 | 
						|
									    index = g->index;
							 | 
						|
									}
							 | 
						|
									if (toph > v) {
							 | 
						|
									    Hv = empty; Hvn = h;
							 | 
						|
									} else {
							 | 
						|
									    Hv = cuddT(h); Hvn = cuddE(h);
							 | 
						|
									}
							 | 
						|
									e = cuddZddIte(dd,f,Gvn,Hvn);
							 | 
						|
									if (e == NULL) return(NULL);
							 | 
						|
									cuddRef(e);
							 | 
						|
									r = cuddZddGetNode(dd,index,Hv,e);
							 | 
						|
									if (r == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd,e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    } else {
							 | 
						|
									index = f->index;
							 | 
						|
									if (topg > v) {
							 | 
						|
									    Gv = empty; Gvn = g;
							 | 
						|
									} else {
							 | 
						|
									    Gv = cuddT(g); Gvn = cuddE(g);
							 | 
						|
									}
							 | 
						|
									if (toph > v) {
							 | 
						|
									    Hv = empty; Hvn = h;
							 | 
						|
									} else {
							 | 
						|
									    Hv = cuddT(h); Hvn = cuddE(h);
							 | 
						|
									}
							 | 
						|
									e = cuddZddIte(dd,cuddE(f),Gvn,Hvn);
							 | 
						|
									if (e == NULL) return(NULL);
							 | 
						|
									cuddRef(e);
							 | 
						|
									t = cuddZddIte(dd,cuddT(f),Gv,Hv);
							 | 
						|
									if (t == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd,e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(t);
							 | 
						|
									r = cuddZddGetNode(dd,index,t,e);
							 | 
						|
									if (r == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd,e);
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd,t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert(dd,DD_ZDD_ITE_TAG,f,g,h,r);
							 | 
						|
								
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddIte */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddUnion.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddUnion(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    int		p_top, q_top;
							 | 
						|
								    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
							 | 
						|
								    DdManager	*table = zdd;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    if (P == empty)
							 | 
						|
									return(Q);
							 | 
						|
								    if (Q == empty)
							 | 
						|
									return(P);
							 | 
						|
								    if (P == Q)
							 | 
						|
									return(P);
							 | 
						|
								
							 | 
						|
								    /* Check cache */
							 | 
						|
								    res = cuddCacheLookup2Zdd(table, cuddZddUnion, P, Q);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P))
							 | 
						|
									p_top = P->index;
							 | 
						|
								    else
							 | 
						|
									p_top = zdd->permZ[P->index];
							 | 
						|
								    if (cuddIsConstant(Q))
							 | 
						|
									q_top = Q->index;
							 | 
						|
								    else
							 | 
						|
									q_top = zdd->permZ[Q->index];
							 | 
						|
								    if (p_top < q_top) {
							 | 
						|
									e = cuddZddUnion(zdd, cuddE(P), Q);
							 | 
						|
									if (e == NULL) return (NULL);
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    } else if (p_top > q_top) {
							 | 
						|
									e = cuddZddUnion(zdd, P, cuddE(Q));
							 | 
						|
									if (e == NULL) return(NULL);
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, Q->index, cuddT(Q), e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    } else {
							 | 
						|
									t = cuddZddUnion(zdd, cuddT(P), cuddT(Q));
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
									e = cuddZddUnion(zdd, cuddE(P), cuddE(Q));
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(table, cuddZddUnion, P, Q, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddUnion */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddIntersect.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddIntersect(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    int		p_top, q_top;
							 | 
						|
								    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
							 | 
						|
								    DdManager	*table = zdd;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    if (P == empty)
							 | 
						|
									return(empty);
							 | 
						|
								    if (Q == empty)
							 | 
						|
									return(empty);
							 | 
						|
								    if (P == Q)
							 | 
						|
									return(P);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    res = cuddCacheLookup2Zdd(table, cuddZddIntersect, P, Q);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P))
							 | 
						|
									p_top = P->index;
							 | 
						|
								    else
							 | 
						|
									p_top = zdd->permZ[P->index];
							 | 
						|
								    if (cuddIsConstant(Q))
							 | 
						|
									q_top = Q->index;
							 | 
						|
								    else
							 | 
						|
									q_top = zdd->permZ[Q->index];
							 | 
						|
								    if (p_top < q_top) {
							 | 
						|
									res = cuddZddIntersect(zdd, cuddE(P), Q);
							 | 
						|
									if (res == NULL) return(NULL);
							 | 
						|
								    } else if (p_top > q_top) {
							 | 
						|
									res = cuddZddIntersect(zdd, P, cuddE(Q));
							 | 
						|
									if (res == NULL) return(NULL);
							 | 
						|
								    } else {
							 | 
						|
									t = cuddZddIntersect(zdd, cuddT(P), cuddT(Q));
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
									e = cuddZddIntersect(zdd, cuddE(P), cuddE(Q));
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(table, cuddZddIntersect, P, Q, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddIntersect */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddDiff.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddDiff(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * Q)
							 | 
						|
								{
							 | 
						|
								    int		p_top, q_top;
							 | 
						|
								    DdNode	*empty = DD_ZERO(zdd), *t, *e, *res;
							 | 
						|
								    DdManager	*table = zdd;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    if (P == empty)
							 | 
						|
									return(empty);
							 | 
						|
								    if (Q == empty)
							 | 
						|
									return(P);
							 | 
						|
								    if (P == Q)
							 | 
						|
									return(empty);
							 | 
						|
								
							 | 
						|
								    /* Check cache.  The cache is shared by Cudd_zddDiffConst(). */
							 | 
						|
								    res = cuddCacheLookup2Zdd(table, cuddZddDiff, P, Q);
							 | 
						|
								    if (res != NULL && res != DD_NON_CONSTANT)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P))
							 | 
						|
									p_top = P->index;
							 | 
						|
								    else
							 | 
						|
									p_top = zdd->permZ[P->index];
							 | 
						|
								    if (cuddIsConstant(Q))
							 | 
						|
									q_top = Q->index;
							 | 
						|
								    else
							 | 
						|
									q_top = zdd->permZ[Q->index];
							 | 
						|
								    if (p_top < q_top) {
							 | 
						|
									e = cuddZddDiff(zdd, cuddE(P), Q);
							 | 
						|
									if (e == NULL) return(NULL);
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, cuddT(P), e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    } else if (p_top > q_top) {
							 | 
						|
									res = cuddZddDiff(zdd, P, cuddE(Q));
							 | 
						|
									if (res == NULL) return(NULL);
							 | 
						|
								    } else {
							 | 
						|
									t = cuddZddDiff(zdd, cuddT(P), cuddT(Q));
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
									e = cuddZddDiff(zdd, cuddE(P), cuddE(Q));
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(table, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(table, cuddZddDiff, P, Q, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddDiff */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddChange.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddChangeAux(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * zvar)
							 | 
						|
								{
							 | 
						|
								    int		top_var, level;
							 | 
						|
								    DdNode	*res, *t, *e;
							 | 
						|
								    DdNode	*base = DD_ONE(zdd);
							 | 
						|
								    DdNode	*empty = DD_ZERO(zdd);
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    if (P == empty)
							 | 
						|
									return(empty);
							 | 
						|
								    if (P == base)
							 | 
						|
									return(zvar);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    res = cuddCacheLookup2Zdd(zdd, cuddZddChangeAux, P, zvar);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    top_var = zdd->permZ[P->index];
							 | 
						|
								    level = zdd->permZ[zvar->index];
							 | 
						|
								
							 | 
						|
								    if (top_var > level) {
							 | 
						|
									res = cuddZddGetNode(zdd, zvar->index, P, DD_ZERO(zdd));
							 | 
						|
									if (res == NULL) return(NULL);
							 | 
						|
								    } else if (top_var == level) {
							 | 
						|
									res = cuddZddGetNode(zdd, zvar->index, cuddE(P), cuddT(P));
							 | 
						|
									if (res == NULL) return(NULL);
							 | 
						|
								    } else {
							 | 
						|
									t = cuddZddChangeAux(zdd, cuddT(P), zvar);
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
									e = cuddZddChangeAux(zdd, cuddE(P), zvar);
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
									res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(zdd, cuddZddChangeAux, P, zvar, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddChangeAux */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the positive cofactor of a ZDD w.r.t. a variable.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the positive cofactor of a ZDD w.r.t. a
							 | 
						|
								  variable. In terms of combinations, the result is the set of all
							 | 
						|
								  combinations in which the variable is asserted. Returns a pointer to
							 | 
						|
								  the result if successful; NULL otherwise. cuddZddSubset1 performs
							 | 
						|
								  the same function as Cudd_zddSubset1, but does not restart if
							 | 
						|
								  reordering has taken place. Therefore it can be called from within a
							 | 
						|
								  recursive procedure.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddZddSubset0 Cudd_zddSubset1]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddSubset1(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*zvar, *r;
							 | 
						|
								    DdNode	*base, *empty;
							 | 
						|
								
							 | 
						|
								    base = DD_ONE(dd);
							 | 
						|
								    empty = DD_ZERO(dd);
							 | 
						|
								
							 | 
						|
								    zvar = cuddUniqueInterZdd(dd, var, base, empty);
							 | 
						|
								    if (zvar == NULL) {
							 | 
						|
									return(NULL);
							 | 
						|
								    } else {
							 | 
						|
									cuddRef(zvar);
							 | 
						|
									r = zdd_subset1_aux(dd, P, zvar);
							 | 
						|
									if (r == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd, zvar);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(r);
							 | 
						|
									Cudd_RecursiveDerefZdd(dd, zvar);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddDeref(r);
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddSubset1 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Computes the negative cofactor of a ZDD w.r.t. a variable.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the negative cofactor of a ZDD w.r.t. a
							 | 
						|
								  variable. In terms of combinations, the result is the set of all
							 | 
						|
								  combinations in which the variable is negated. Returns a pointer to
							 | 
						|
								  the result if successful; NULL otherwise. cuddZddSubset0 performs
							 | 
						|
								  the same function as Cudd_zddSubset0, but does not restart if
							 | 
						|
								  reordering has taken place. Therefore it can be called from within a
							 | 
						|
								  recursive procedure.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddZddSubset1 Cudd_zddSubset0]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddSubset0(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*zvar, *r;
							 | 
						|
								    DdNode	*base, *empty;
							 | 
						|
								
							 | 
						|
								    base = DD_ONE(dd);
							 | 
						|
								    empty = DD_ZERO(dd);
							 | 
						|
								
							 | 
						|
								    zvar = cuddUniqueInterZdd(dd, var, base, empty);
							 | 
						|
								    if (zvar == NULL) {
							 | 
						|
									return(NULL);
							 | 
						|
								    } else {
							 | 
						|
									cuddRef(zvar);
							 | 
						|
									r = zdd_subset0_aux(dd, P, zvar);
							 | 
						|
									if (r == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(dd, zvar);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(r);
							 | 
						|
									Cudd_RecursiveDerefZdd(dd, zvar);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddDeref(r);
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddSubset0 */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Substitutes a variable with its complement in a ZDD.]
							 | 
						|
								
							 | 
						|
								  Description [Substitutes a variable with its complement in a ZDD.
							 | 
						|
								  returns a pointer to the result if successful; NULL
							 | 
						|
								  otherwise. cuddZddChange performs the same function as
							 | 
						|
								  Cudd_zddChange, but does not restart if reordering has taken
							 | 
						|
								  place. Therefore it can be called from within a recursive
							 | 
						|
								  procedure.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_zddChange]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddZddChange(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  int  var)
							 | 
						|
								{
							 | 
						|
								    DdNode	*zvar, *res;
							 | 
						|
								
							 | 
						|
								    zvar = cuddUniqueInterZdd(dd, var, DD_ONE(dd), DD_ZERO(dd));
							 | 
						|
								    if (zvar == NULL) return(NULL);
							 | 
						|
								    cuddRef(zvar);
							 | 
						|
								
							 | 
						|
								    res = cuddZddChangeAux(dd, P, zvar);
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDerefZdd(dd,zvar);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(res);
							 | 
						|
								    Cudd_RecursiveDerefZdd(dd,zvar);
							 | 
						|
								    cuddDeref(res);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddZddChange */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of static functions                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddSubset1.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static DdNode *
							 | 
						|
								zdd_subset1_aux(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * zvar)
							 | 
						|
								{
							 | 
						|
								    int		top_var, level;
							 | 
						|
								    DdNode	*res, *t, *e;
							 | 
						|
								    DdNode	*empty;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								    empty = DD_ZERO(zdd);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    res = cuddCacheLookup2Zdd(zdd, zdd_subset1_aux, P, zvar);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P)) {
							 | 
						|
									res = empty;
							 | 
						|
									cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    top_var = zdd->permZ[P->index];
							 | 
						|
								    level = zdd->permZ[zvar->index];
							 | 
						|
								
							 | 
						|
								    if (top_var > level) {
							 | 
						|
								        res = empty;
							 | 
						|
								    } else if (top_var == level) {
							 | 
						|
									res = cuddT(P);
							 | 
						|
								    } else {
							 | 
						|
								        t = zdd_subset1_aux(zdd, cuddT(P), zvar);
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
								        e = zdd_subset1_aux(zdd, cuddE(P), zvar);
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
								        res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(zdd, zdd_subset1_aux, P, zvar, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of zdd_subset1_aux */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis [Performs the recursive step of Cudd_zddSubset0.]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static DdNode *
							 | 
						|
								zdd_subset0_aux(
							 | 
						|
								  DdManager * zdd,
							 | 
						|
								  DdNode * P,
							 | 
						|
								  DdNode * zvar)
							 | 
						|
								{
							 | 
						|
								    int		top_var, level;
							 | 
						|
								    DdNode	*res, *t, *e;
							 | 
						|
								
							 | 
						|
								    statLine(zdd);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    res = cuddCacheLookup2Zdd(zdd, zdd_subset0_aux, P, zvar);
							 | 
						|
								    if (res != NULL)
							 | 
						|
									return(res);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(P)) {
							 | 
						|
									res = P;
							 | 
						|
									cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    top_var = zdd->permZ[P->index];
							 | 
						|
								    level = zdd->permZ[zvar->index];
							 | 
						|
								
							 | 
						|
								    if (top_var > level) {
							 | 
						|
								        res = P;
							 | 
						|
								    }
							 | 
						|
								    else if (top_var == level) {
							 | 
						|
								        res = cuddE(P);
							 | 
						|
								    }
							 | 
						|
								    else {
							 | 
						|
								        t = zdd_subset0_aux(zdd, cuddT(P), zvar);
							 | 
						|
									if (t == NULL) return(NULL);
							 | 
						|
									cuddRef(t);
							 | 
						|
								        e = zdd_subset0_aux(zdd, cuddE(P), zvar);
							 | 
						|
									if (e == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(e);
							 | 
						|
								        res = cuddZddGetNode(zdd, P->index, t, e);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, t);
							 | 
						|
									    Cudd_RecursiveDerefZdd(zdd, e);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddDeref(t);
							 | 
						|
									cuddDeref(e);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(zdd, zdd_subset0_aux, P, zvar, res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of zdd_subset0_aux */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Replaces variables with constants if possible (part of
							 | 
						|
								  canonical form).]
							 | 
						|
								
							 | 
						|
								  Description []
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static void
							 | 
						|
								zddVarToConst(
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode ** gp,
							 | 
						|
								  DdNode ** hp,
							 | 
						|
								  DdNode * base,
							 | 
						|
								  DdNode * empty)
							 | 
						|
								{
							 | 
						|
								    DdNode *g = *gp;
							 | 
						|
								    DdNode *h = *hp;
							 | 
						|
								
							 | 
						|
								    if (f == g) { /* ITE(F,F,H) = ITE(F,1,H) = F + H */
							 | 
						|
									*gp = base;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (f == h) { /* ITE(F,G,F) = ITE(F,G,0) = F * G */
							 | 
						|
									*hp = empty;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								} /* end of zddVarToConst */
							 | 
						|
								
							 |