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.
		
		
		
		
		
			
		
			
				
					
					
						
							2027 lines
						
					
					
						
							58 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							2027 lines
						
					
					
						
							58 KiB
						
					
					
				
								/**CFile***********************************************************************
							 | 
						|
								
							 | 
						|
								  FileName    [cuddPriority.c]
							 | 
						|
								
							 | 
						|
								  PackageName [cudd]
							 | 
						|
								
							 | 
						|
								  Synopsis    [Priority functions.]
							 | 
						|
								
							 | 
						|
								  Description [External procedures included in this file:
							 | 
						|
									    <ul>
							 | 
						|
									    <li> Cudd_PrioritySelect()
							 | 
						|
									    <li> Cudd_Xgty()
							 | 
						|
									    <li> Cudd_Xeqy()
							 | 
						|
									    <li> Cudd_addXeqy()
							 | 
						|
									    <li> Cudd_Dxygtdxz()
							 | 
						|
									    <li> Cudd_Dxygtdyz()
							 | 
						|
									    <li> Cudd_Inequality()
							 | 
						|
									    <li> Cudd_Disequality()
							 | 
						|
									    <li> Cudd_bddInterval()
							 | 
						|
									    <li> Cudd_CProjection()
							 | 
						|
									    <li> Cudd_addHamming()
							 | 
						|
									    <li> Cudd_MinHammingDist()
							 | 
						|
									    <li> Cudd_bddClosestCube()
							 | 
						|
									    </ul>
							 | 
						|
									Internal procedures included in this module:
							 | 
						|
									    <ul>
							 | 
						|
									    <li> cuddCProjectionRecur()
							 | 
						|
									    <li> cuddBddClosestCube()
							 | 
						|
									    </ul>
							 | 
						|
									Static procedures included in this module:
							 | 
						|
									    <ul>
							 | 
						|
									    <li> cuddMinHammingDistRecur()
							 | 
						|
									    <li> separateCube()
							 | 
						|
									    <li> createResult()
							 | 
						|
									    </ul>
							 | 
						|
									    ]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								  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                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#define DD_DEBUG 1
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Stucture declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Type declarations                                                         */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Variable declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#ifndef lint
							 | 
						|
								static char rcsid[] DD_UNUSED = "$Id: cuddPriority.c,v 1.36 2012/02/05 01:07:19 fabio Exp $";
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**AutomaticStart*************************************************************/
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								static int cuddMinHammingDistRecur (DdNode * f, int *minterm, DdHashTable * table, int upperBound);
							 | 
						|
								static DdNode * separateCube (DdManager *dd, DdNode *f, CUDD_VALUE_TYPE *distance);
							 | 
						|
								static DdNode * createResult (DdManager *dd, unsigned int index, unsigned int phase, DdNode *cube, CUDD_VALUE_TYPE distance);
							 | 
						|
								
							 | 
						|
								/**AutomaticEnd***************************************************************/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of exported functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Selects pairs from R using a priority function.]
							 | 
						|
								
							 | 
						|
								  Description [Selects pairs from a relation R(x,y) (given as a BDD)
							 | 
						|
								  in such a way that a given x appears in one pair only. Uses a
							 | 
						|
								  priority function to determine which y should be paired to a given x.
							 | 
						|
								  Cudd_PrioritySelect returns a pointer to
							 | 
						|
								  the selected function if successful; NULL otherwise.
							 | 
						|
								  Three of the arguments--x, y, and z--are vectors of BDD variables.
							 | 
						|
								  The first two are the variables on which R depends. The third vector
							 | 
						|
								  is a vector of auxiliary variables, used during the computation. This
							 | 
						|
								  vector is optional. If a NULL value is passed instead,
							 | 
						|
								  Cudd_PrioritySelect will create the working variables on the fly.
							 | 
						|
								  The sizes of x and y (and z if it is not NULL) should equal n.
							 | 
						|
								  The priority function Pi can be passed as a BDD, or can be built by
							 | 
						|
								  Cudd_PrioritySelect. If NULL is passed instead of a DdNode *,
							 | 
						|
								  parameter Pifunc is used by Cudd_PrioritySelect to build a BDD for the
							 | 
						|
								  priority function. (Pifunc is a pointer to a C function.) If Pi is not
							 | 
						|
								  NULL, then Pifunc is ignored. Pifunc should have the same interface as
							 | 
						|
								  the standard priority functions (e.g., Cudd_Dxygtdxz).
							 | 
						|
								  Cudd_PrioritySelect and Cudd_CProjection can sometimes be used
							 | 
						|
								  interchangeably. Specifically, calling Cudd_PrioritySelect with
							 | 
						|
								  Cudd_Xgty as Pifunc produces the same result as calling
							 | 
						|
								  Cudd_CProjection with the all-zero minterm as reference minterm.
							 | 
						|
								  However, depending on the application, one or the other may be
							 | 
						|
								  preferable:
							 | 
						|
								  <ul>
							 | 
						|
								  <li> When extracting representatives from an equivalence relation,
							 | 
						|
								  Cudd_CProjection has the advantage of nor requiring the auxiliary
							 | 
						|
								  variables.
							 | 
						|
								  <li> When computing matchings in general bipartite graphs,
							 | 
						|
								  Cudd_PrioritySelect normally obtains better results because it can use
							 | 
						|
								  more powerful matching schemes (e.g., Cudd_Dxygtdxz).
							 | 
						|
								  </ul>
							 | 
						|
								  ]
							 | 
						|
								
							 | 
						|
								  SideEffects [If called with z == NULL, will create new variables in
							 | 
						|
								  the manager.]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Dxygtdxz Cudd_Dxygtdyz Cudd_Xgty
							 | 
						|
								  Cudd_bddAdjPermuteX Cudd_CProjection]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_PrioritySelect(
							 | 
						|
								  DdManager * dd /* manager */,
							 | 
						|
								  DdNode * R /* BDD of the relation */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */,
							 | 
						|
								  DdNode ** z /* array of z variables (optional: may be NULL) */,
							 | 
						|
								  DdNode * Pi /* BDD of the priority function (optional: may be NULL) */,
							 | 
						|
								  int  n /* size of x, y, and z */,
							 | 
						|
								  DD_PRFP Pifunc /* function used to build Pi if it is NULL */)
							 | 
						|
								{
							 | 
						|
								    DdNode *res = NULL;
							 | 
						|
								    DdNode *zcube = NULL;
							 | 
						|
								    DdNode *Rxz, *Q;
							 | 
						|
								    int createdZ = 0;
							 | 
						|
								    int createdPi = 0;
							 | 
						|
								    int i;
							 | 
						|
								
							 | 
						|
								    /* Create z variables if needed. */
							 | 
						|
								    if (z == NULL) {
							 | 
						|
									if (Pi != NULL) return(NULL);
							 | 
						|
									z = ALLOC(DdNode *,n);
							 | 
						|
									if (z == NULL) {
							 | 
						|
									    dd->errorCode = CUDD_MEMORY_OUT;
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									createdZ = 1;
							 | 
						|
									for (i = 0; i < n; i++) {
							 | 
						|
									    if (dd->size >= (int) CUDD_MAXINDEX - 1) goto endgame;
							 | 
						|
									    z[i] = cuddUniqueInter(dd,dd->size,dd->one,Cudd_Not(dd->one));
							 | 
						|
									    if (z[i] == NULL) goto endgame;
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Create priority function BDD if needed. */
							 | 
						|
								    if (Pi == NULL) {
							 | 
						|
									Pi = Pifunc(dd,n,x,y,z);
							 | 
						|
									if (Pi == NULL) goto endgame;
							 | 
						|
									createdPi = 1;
							 | 
						|
									cuddRef(Pi);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Initialize abstraction cube. */
							 | 
						|
								    zcube = DD_ONE(dd);
							 | 
						|
								    cuddRef(zcube);
							 | 
						|
								    for (i = n - 1; i >= 0; i--) {
							 | 
						|
									DdNode *tmpp;
							 | 
						|
									tmpp = Cudd_bddAnd(dd,z[i],zcube);
							 | 
						|
									if (tmpp == NULL) goto endgame;
							 | 
						|
									cuddRef(tmpp);
							 | 
						|
									Cudd_RecursiveDeref(dd,zcube);
							 | 
						|
									zcube = tmpp;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute subset of (x,y) pairs. */
							 | 
						|
								    Rxz = Cudd_bddSwapVariables(dd,R,y,z,n);
							 | 
						|
								    if (Rxz == NULL) goto endgame;
							 | 
						|
								    cuddRef(Rxz);
							 | 
						|
								    Q = Cudd_bddAndAbstract(dd,Rxz,Pi,zcube);
							 | 
						|
								    if (Q == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,Rxz);
							 | 
						|
									goto endgame;
							 | 
						|
								    }
							 | 
						|
								    cuddRef(Q);
							 | 
						|
								    Cudd_RecursiveDeref(dd,Rxz);
							 | 
						|
								    res = Cudd_bddAnd(dd,R,Cudd_Not(Q));
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,Q);
							 | 
						|
									goto endgame;
							 | 
						|
								    }
							 | 
						|
								    cuddRef(res);
							 | 
						|
								    Cudd_RecursiveDeref(dd,Q);
							 | 
						|
								
							 | 
						|
								endgame:
							 | 
						|
								    if (zcube != NULL) Cudd_RecursiveDeref(dd,zcube);
							 | 
						|
								    if (createdZ) {
							 | 
						|
									FREE(z);
							 | 
						|
								    }
							 | 
						|
								    if (createdPi) {
							 | 
						|
									Cudd_RecursiveDeref(dd,Pi);
							 | 
						|
								    }
							 | 
						|
								    if (res != NULL) cuddDeref(res);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* Cudd_PrioritySelect */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function x > y.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function x > y.
							 | 
						|
								  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has 3*N-1 internal nodes, if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].
							 | 
						|
								  Argument z is not used by Cudd_Xgty: it is included to make it
							 | 
						|
								  call-compatible to Cudd_Dxygtdxz and Cudd_Dxygtdyz.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Dxygtdyz]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Xgty(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x and y variables */,
							 | 
						|
								  DdNode ** z /* array of z variables: unused */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */)
							 | 
						|
								{
							 | 
						|
								    DdNode *u, *v, *w;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    /* Build bottom part of BDD outside loop. */
							 | 
						|
								    u = Cudd_bddAnd(dd, x[N-1], Cudd_Not(y[N-1]));
							 | 
						|
								    if (u == NULL) return(NULL);
							 | 
						|
								    cuddRef(u);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the BDD. */
							 | 
						|
								    for (i = N-2; i >= 0; i--) {
							 | 
						|
									v = Cudd_bddAnd(dd, y[i], Cudd_Not(u));
							 | 
						|
									if (v == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(v);
							 | 
						|
									w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
							 | 
						|
									if (w == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(w);
							 | 
						|
									Cudd_RecursiveDeref(dd, u);
							 | 
						|
									u = Cudd_bddIte(dd, x[i], Cudd_Not(v), w);
							 | 
						|
									if (u == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    Cudd_RecursiveDeref(dd, w);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(u);
							 | 
						|
									Cudd_RecursiveDeref(dd, v);
							 | 
						|
									Cudd_RecursiveDeref(dd, w);
							 | 
						|
								
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(u);
							 | 
						|
								    return(u);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Xgty */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function x==y.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function x==y.
							 | 
						|
								  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has 3*N-1 internal nodes, if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addXeqy]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Xeqy(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x and y variables */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */)
							 | 
						|
								{
							 | 
						|
								    DdNode *u, *v, *w;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    /* Build bottom part of BDD outside loop. */
							 | 
						|
								    u = Cudd_bddIte(dd, x[N-1], y[N-1], Cudd_Not(y[N-1]));
							 | 
						|
								    if (u == NULL) return(NULL);
							 | 
						|
								    cuddRef(u);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the BDD. */
							 | 
						|
								    for (i = N-2; i >= 0; i--) {
							 | 
						|
									v = Cudd_bddAnd(dd, y[i], u);
							 | 
						|
									if (v == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(v);
							 | 
						|
									w = Cudd_bddAnd(dd, Cudd_Not(y[i]), u);
							 | 
						|
									if (w == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(w);
							 | 
						|
									Cudd_RecursiveDeref(dd, u);
							 | 
						|
									u = Cudd_bddIte(dd, x[i], v, w);
							 | 
						|
									if (u == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    Cudd_RecursiveDeref(dd, w);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(u);
							 | 
						|
									Cudd_RecursiveDeref(dd, v);
							 | 
						|
									Cudd_RecursiveDeref(dd, w);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(u);
							 | 
						|
								    return(u);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Xeqy */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates an ADD for the function x==y.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates an ADD for the function x==y.
							 | 
						|
								  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
							 | 
						|
								  The ADD is built bottom-up.
							 | 
						|
								  It has 3*N-1 internal nodes, if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\]. ]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Xeqy]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addXeqy(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x and y variables */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */)
							 | 
						|
								{
							 | 
						|
								    DdNode *one, *zero;
							 | 
						|
								    DdNode *u, *v, *w;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    one = DD_ONE(dd);
							 | 
						|
								    zero = DD_ZERO(dd);
							 | 
						|
								
							 | 
						|
								    /* Build bottom part of ADD outside loop. */
							 | 
						|
								    v = Cudd_addIte(dd, y[N-1], one, zero);
							 | 
						|
								    if (v == NULL) return(NULL);
							 | 
						|
								    cuddRef(v);
							 | 
						|
								    w = Cudd_addIte(dd, y[N-1], zero, one);
							 | 
						|
								    if (w == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, v);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(w);
							 | 
						|
								    u = Cudd_addIte(dd, x[N-1], v, w);
							 | 
						|
								    if (u == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, v);
							 | 
						|
									Cudd_RecursiveDeref(dd, w);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(u);
							 | 
						|
								    Cudd_RecursiveDeref(dd, v);
							 | 
						|
								    Cudd_RecursiveDeref(dd, w);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the ADD. */
							 | 
						|
								    for (i = N-2; i >= 0; i--) {
							 | 
						|
									v = Cudd_addIte(dd, y[i], u, zero);
							 | 
						|
									if (v == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(v);
							 | 
						|
									w = Cudd_addIte(dd, y[i], zero, u);
							 | 
						|
									if (w == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, u);
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(w);
							 | 
						|
									Cudd_RecursiveDeref(dd, u);
							 | 
						|
									u = Cudd_addIte(dd, x[i], v, w);
							 | 
						|
									if (w == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, v);
							 | 
						|
									    Cudd_RecursiveDeref(dd, w);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(u);
							 | 
						|
									Cudd_RecursiveDeref(dd, v);
							 | 
						|
									Cudd_RecursiveDeref(dd, w);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(u);
							 | 
						|
								    return(u);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addXeqy */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function d(x,y) > d(x,z).]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function d(x,y)
							 | 
						|
								  > d(x,z);
							 | 
						|
								  x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\],
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], and z\[0\] z\[1\] ...  z\[N-1\],
							 | 
						|
								  with 0 the most significant bit.
							 | 
						|
								  The distance d(x,y) is defined as:
							 | 
						|
									\sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has 7*N-3 internal nodes, if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdyz Cudd_Xgty Cudd_bddAdjPermuteX]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Dxygtdxz(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x, y, and z variables */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */,
							 | 
						|
								  DdNode ** z /* array of z variables */)
							 | 
						|
								{
							 | 
						|
								    DdNode *one, *zero;
							 | 
						|
								    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    one = DD_ONE(dd);
							 | 
						|
								    zero = Cudd_Not(one);
							 | 
						|
								
							 | 
						|
								    /* Build bottom part of BDD outside loop. */
							 | 
						|
								    y1_ = Cudd_bddIte(dd, y[N-1], one, Cudd_Not(z[N-1]));
							 | 
						|
								    if (y1_ == NULL) return(NULL);
							 | 
						|
								    cuddRef(y1_);
							 | 
						|
								    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], one);
							 | 
						|
								    if (y2 == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(y2);
							 | 
						|
								    x1 = Cudd_bddIte(dd, x[N-1], y1_, y2);
							 | 
						|
								    if (x1 == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									Cudd_RecursiveDeref(dd, y2);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(x1);
							 | 
						|
								    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
								    Cudd_RecursiveDeref(dd, y2);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the BDD. */
							 | 
						|
								    for (i = N-2; i >= 0; i--) {
							 | 
						|
									z1 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
							 | 
						|
									if (z1 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z1);
							 | 
						|
									z2 = Cudd_bddIte(dd, z[i], x1, one);
							 | 
						|
									if (z2 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z2);
							 | 
						|
									z3 = Cudd_bddIte(dd, z[i], one, x1);
							 | 
						|
									if (z3 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z3);
							 | 
						|
									z4 = Cudd_bddIte(dd, z[i], x1, zero);
							 | 
						|
									if (z4 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z4);
							 | 
						|
									Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									y1_ = Cudd_bddIte(dd, y[i], z2, Cudd_Not(z1));
							 | 
						|
									if (y1_ == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(y1_);
							 | 
						|
									y2 = Cudd_bddIte(dd, y[i], z4, z3);
							 | 
						|
									if (y2 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(y2);
							 | 
						|
									Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									x1 = Cudd_bddIte(dd, x[i], y1_, y2);
							 | 
						|
									if (x1 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									    Cudd_RecursiveDeref(dd, y2);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(x1);
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									Cudd_RecursiveDeref(dd, y2);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(x1);
							 | 
						|
								    return(Cudd_Not(x1));
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Dxygtdxz */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function d(x,y) > d(y,z).]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function d(x,y)
							 | 
						|
								  > d(y,z);
							 | 
						|
								  x, y, and z are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\],
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], and z\[0\] z\[1\] ...  z\[N-1\],
							 | 
						|
								  with 0 the most significant bit.
							 | 
						|
								  The distance d(x,y) is defined as:
							 | 
						|
									\sum_{i=0}^{N-1}(|x_i - y_i| \cdot 2^{N-i-1}).
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has 7*N-3 internal nodes, if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] z\[0\] x\[1\] y\[1\] z\[1\] ... x\[N-1\] y\[N-1\] z\[N-1\]. ]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_PrioritySelect Cudd_Dxygtdxz Cudd_Xgty Cudd_bddAdjPermuteX]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Dxygtdyz(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x, y, and z variables */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */,
							 | 
						|
								  DdNode ** z /* array of z variables */)
							 | 
						|
								{
							 | 
						|
								    DdNode *one, *zero;
							 | 
						|
								    DdNode *z1, *z2, *z3, *z4, *y1_, *y2, *x1;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    one = DD_ONE(dd);
							 | 
						|
								    zero = Cudd_Not(one);
							 | 
						|
								
							 | 
						|
								    /* Build bottom part of BDD outside loop. */
							 | 
						|
								    y1_ = Cudd_bddIte(dd, y[N-1], one, z[N-1]);
							 | 
						|
								    if (y1_ == NULL) return(NULL);
							 | 
						|
								    cuddRef(y1_);
							 | 
						|
								    y2 = Cudd_bddIte(dd, y[N-1], z[N-1], zero);
							 | 
						|
								    if (y2 == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(y2);
							 | 
						|
								    x1 = Cudd_bddIte(dd, x[N-1], y1_, Cudd_Not(y2));
							 | 
						|
								    if (x1 == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									Cudd_RecursiveDeref(dd, y2);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(x1);
							 | 
						|
								    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
								    Cudd_RecursiveDeref(dd, y2);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the BDD. */
							 | 
						|
								    for (i = N-2; i >= 0; i--) {
							 | 
						|
									z1 = Cudd_bddIte(dd, z[i], x1, zero);
							 | 
						|
									if (z1 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z1);
							 | 
						|
									z2 = Cudd_bddIte(dd, z[i], x1, one);
							 | 
						|
									if (z2 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z2);
							 | 
						|
									z3 = Cudd_bddIte(dd, z[i], one, x1);
							 | 
						|
									if (z3 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z3);
							 | 
						|
									z4 = Cudd_bddIte(dd, z[i], one, Cudd_Not(x1));
							 | 
						|
									if (z4 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(z4);
							 | 
						|
									Cudd_RecursiveDeref(dd, x1);
							 | 
						|
									y1_ = Cudd_bddIte(dd, y[i], z2, z1);
							 | 
						|
									if (y1_ == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(y1_);
							 | 
						|
									y2 = Cudd_bddIte(dd, y[i], z4, Cudd_Not(z3));
							 | 
						|
									if (y2 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									    Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(y2);
							 | 
						|
									Cudd_RecursiveDeref(dd, z1);
							 | 
						|
									Cudd_RecursiveDeref(dd, z2);
							 | 
						|
									Cudd_RecursiveDeref(dd, z3);
							 | 
						|
									Cudd_RecursiveDeref(dd, z4);
							 | 
						|
									x1 = Cudd_bddIte(dd, x[i], y1_, Cudd_Not(y2));
							 | 
						|
									if (x1 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									    Cudd_RecursiveDeref(dd, y2);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(x1);
							 | 
						|
									Cudd_RecursiveDeref(dd, y1_);
							 | 
						|
									Cudd_RecursiveDeref(dd, y2);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(x1);
							 | 
						|
								    return(Cudd_Not(x1));
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Dxygtdyz */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function x - y ≥ c.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function x -y ≥ c.
							 | 
						|
								  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has a linear number of nodes if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Xgty]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Inequality(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x and y variables */,
							 | 
						|
								  int c /* right-hand side constant */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */)
							 | 
						|
								{
							 | 
						|
								    /* The nodes at level i represent values of the difference that are
							 | 
						|
								    ** multiples of 2^i.  We use variables with names starting with k
							 | 
						|
								    ** to denote the multipliers of 2^i in such multiples. */
							 | 
						|
								    int kTrue = c;
							 | 
						|
								    int kFalse = c - 1;
							 | 
						|
								    /* Mask used to compute the ceiling function.  Since we divide by 2^i,
							 | 
						|
								    ** we want to know whether the dividend is a multiple of 2^i.  If it is,
							 | 
						|
								    ** then ceiling and floor coincide; otherwise, they differ by one. */
							 | 
						|
								    int mask = 1;
							 | 
						|
								    int i;
							 | 
						|
								
							 | 
						|
								    DdNode *f = NULL;		/* the eventual result */
							 | 
						|
								    DdNode *one = DD_ONE(dd);
							 | 
						|
								    DdNode *zero = Cudd_Not(one);
							 | 
						|
								
							 | 
						|
								    /* Two x-labeled nodes are created at most at each iteration.  They are
							 | 
						|
								    ** stored, along with their k values, in these variables.  At each level,
							 | 
						|
								    ** the old nodes are freed and the new nodes are copied into the old map.
							 | 
						|
								    */
							 | 
						|
								    DdNode *map[2];
							 | 
						|
								    int invalidIndex = 1 << (N-1);
							 | 
						|
								    int index[2] = {invalidIndex, invalidIndex};
							 | 
						|
								
							 | 
						|
								    /* This should never happen. */
							 | 
						|
								    if (N < 0) return(NULL);
							 | 
						|
								
							 | 
						|
								    /* If there are no bits, both operands are 0.  The result depends on c. */
							 | 
						|
								    if (N == 0) {
							 | 
						|
									if (c >= 0) return(one);
							 | 
						|
									else return(zero);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* The maximum or the minimum difference comparing to c can generate the terminal case */
							 | 
						|
								    if ((1 << N) - 1 < c) return(zero);
							 | 
						|
								    else if ((-(1 << N) + 1) >= c) return(one);
							 | 
						|
								
							 | 
						|
								    /* Build the result bottom up. */
							 | 
						|
								    for (i = 1; i <= N; i++) {
							 | 
						|
									int kTrueLower, kFalseLower;
							 | 
						|
									int leftChild, middleChild, rightChild;
							 | 
						|
									DdNode *g0, *g1, *fplus, *fequal, *fminus;
							 | 
						|
									int j;
							 | 
						|
									DdNode *newMap[2];
							 | 
						|
									int newIndex[2];
							 | 
						|
								
							 | 
						|
									kTrueLower = kTrue;
							 | 
						|
									kFalseLower = kFalse;
							 | 
						|
									/* kTrue = ceiling((c-1)/2^i) + 1 */
							 | 
						|
									kTrue = ((c-1) >> i) + ((c & mask) != 1) + 1;
							 | 
						|
									mask = (mask << 1) | 1;
							 | 
						|
									/* kFalse = floor(c/2^i) - 1 */
							 | 
						|
									kFalse = (c >> i) - 1;
							 | 
						|
									newIndex[0] = invalidIndex;
							 | 
						|
									newIndex[1] = invalidIndex;
							 | 
						|
								
							 | 
						|
									for (j = kFalse + 1; j < kTrue; j++) {
							 | 
						|
									    /* Skip if node is not reachable from top of BDD. */
							 | 
						|
									    if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue;
							 | 
						|
								
							 | 
						|
									    /* Find f- */
							 | 
						|
									    leftChild = (j << 1) - 1;
							 | 
						|
									    if (leftChild >= kTrueLower) {
							 | 
						|
										fminus = one;
							 | 
						|
									    } else if (leftChild <= kFalseLower) {
							 | 
						|
										fminus = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(leftChild == index[0] || leftChild == index[1]);
							 | 
						|
										if (leftChild == index[0]) {
							 | 
						|
										    fminus = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fminus = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Find f= */
							 | 
						|
									    middleChild = j << 1;
							 | 
						|
									    if (middleChild >= kTrueLower) {
							 | 
						|
										fequal = one;
							 | 
						|
									    } else if (middleChild <= kFalseLower) {
							 | 
						|
										fequal = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(middleChild == index[0] || middleChild == index[1]);
							 | 
						|
										if (middleChild == index[0]) {
							 | 
						|
										    fequal = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fequal = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Find f+ */
							 | 
						|
									    rightChild = (j << 1) + 1;
							 | 
						|
									    if (rightChild >= kTrueLower) {
							 | 
						|
										fplus = one;
							 | 
						|
									    } else if (rightChild <= kFalseLower) {
							 | 
						|
										fplus = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(rightChild == index[0] || rightChild == index[1]);
							 | 
						|
										if (rightChild == index[0]) {
							 | 
						|
										    fplus = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fplus = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Build new nodes. */
							 | 
						|
									    g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus);
							 | 
						|
									    if (g1 == NULL) {
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(g1);
							 | 
						|
									    g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal);
							 | 
						|
									    if (g0 == NULL) {
							 | 
						|
										Cudd_IterDerefBdd(dd, g1);
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(g0);
							 | 
						|
									    f = Cudd_bddIte(dd, x[N - i], g1, g0);
							 | 
						|
									    if (f == NULL) {
							 | 
						|
										Cudd_IterDerefBdd(dd, g1);
							 | 
						|
										Cudd_IterDerefBdd(dd, g0);
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(f);
							 | 
						|
									    Cudd_IterDerefBdd(dd, g1);
							 | 
						|
									    Cudd_IterDerefBdd(dd, g0);
							 | 
						|
								
							 | 
						|
									    /* Save newly computed node in map. */
							 | 
						|
									    assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex);
							 | 
						|
									    if (newIndex[0] == invalidIndex) {
							 | 
						|
										newIndex[0] = j;
							 | 
						|
										newMap[0] = f;
							 | 
						|
									    } else {
							 | 
						|
										newIndex[1] = j;
							 | 
						|
										newMap[1] = f;
							 | 
						|
									    }
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/* Copy new map to map. */
							 | 
						|
									if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
									if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
									map[0] = newMap[0];
							 | 
						|
									map[1] = newMap[1];
							 | 
						|
									index[0] = newIndex[0];
							 | 
						|
									index[1] = newIndex[1];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddDeref(f);
							 | 
						|
								    return(f);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Inequality */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function x - y != c.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function x -y != c.
							 | 
						|
								  Both x and y are N-bit numbers, x\[0\] x\[1\] ... x\[N-1\] and
							 | 
						|
								  y\[0\] y\[1\] ...  y\[N-1\], with 0 the most significant bit.
							 | 
						|
								  The BDD is built bottom-up.
							 | 
						|
								  It has a linear number of nodes if the variables are ordered as follows:
							 | 
						|
								  x\[0\] y\[0\] x\[1\] y\[1\] ... x\[N-1\] y\[N-1\].]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Xgty]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_Disequality(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x and y variables */,
							 | 
						|
								  int c /* right-hand side constant */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  DdNode ** y /* array of y variables */)
							 | 
						|
								{
							 | 
						|
								    /* The nodes at level i represent values of the difference that are
							 | 
						|
								    ** multiples of 2^i.  We use variables with names starting with k
							 | 
						|
								    ** to denote the multipliers of 2^i in such multiples. */
							 | 
						|
								    int kTrueLb = c + 1;
							 | 
						|
								    int kTrueUb = c - 1;
							 | 
						|
								    int kFalse = c;
							 | 
						|
								    /* Mask used to compute the ceiling function.  Since we divide by 2^i,
							 | 
						|
								    ** we want to know whether the dividend is a multiple of 2^i.  If it is,
							 | 
						|
								    ** then ceiling and floor coincide; otherwise, they differ by one. */
							 | 
						|
								    int mask = 1;
							 | 
						|
								    int i;
							 | 
						|
								
							 | 
						|
								    DdNode *f = NULL;		/* the eventual result */
							 | 
						|
								    DdNode *one = DD_ONE(dd);
							 | 
						|
								    DdNode *zero = Cudd_Not(one);
							 | 
						|
								
							 | 
						|
								    /* Two x-labeled nodes are created at most at each iteration.  They are
							 | 
						|
								    ** stored, along with their k values, in these variables.  At each level,
							 | 
						|
								    ** the old nodes are freed and the new nodes are copied into the old map.
							 | 
						|
								    */
							 | 
						|
								    DdNode *map[2];
							 | 
						|
								    int invalidIndex = 1 << (N-1);
							 | 
						|
								    int index[2] = {invalidIndex, invalidIndex};
							 | 
						|
								
							 | 
						|
								    /* This should never happen. */
							 | 
						|
								    if (N < 0) return(NULL);
							 | 
						|
								
							 | 
						|
								    /* If there are no bits, both operands are 0.  The result depends on c. */
							 | 
						|
								    if (N == 0) {
							 | 
						|
									if (c != 0) return(one);
							 | 
						|
									else return(zero);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* The maximum or the minimum difference comparing to c can generate the terminal case */
							 | 
						|
								    if ((1 << N) - 1 < c || (-(1 << N) + 1) > c) return(one);
							 | 
						|
								
							 | 
						|
								    /* Build the result bottom up. */
							 | 
						|
								    for (i = 1; i <= N; i++) {
							 | 
						|
									int kTrueLbLower, kTrueUbLower;
							 | 
						|
									int leftChild, middleChild, rightChild;
							 | 
						|
									DdNode *g0, *g1, *fplus, *fequal, *fminus;
							 | 
						|
									int j;
							 | 
						|
									DdNode *newMap[2];
							 | 
						|
									int newIndex[2];
							 | 
						|
								
							 | 
						|
									kTrueLbLower = kTrueLb;
							 | 
						|
									kTrueUbLower = kTrueUb;
							 | 
						|
									/* kTrueLb = floor((c-1)/2^i) + 2 */
							 | 
						|
									kTrueLb = ((c-1) >> i) + 2;
							 | 
						|
									/* kTrueUb = ceiling((c+1)/2^i) - 2 */
							 | 
						|
									kTrueUb = ((c+1) >> i) + (((c+2) & mask) != 1) - 2;
							 | 
						|
									mask = (mask << 1) | 1;
							 | 
						|
									newIndex[0] = invalidIndex;
							 | 
						|
									newIndex[1] = invalidIndex;
							 | 
						|
								
							 | 
						|
									for (j = kTrueUb + 1; j < kTrueLb; j++) {
							 | 
						|
									    /* Skip if node is not reachable from top of BDD. */
							 | 
						|
									    if ((j >= (1 << (N - i))) || (j <= -(1 << (N -i)))) continue;
							 | 
						|
								
							 | 
						|
									    /* Find f- */
							 | 
						|
									    leftChild = (j << 1) - 1;
							 | 
						|
									    if (leftChild >= kTrueLbLower || leftChild <= kTrueUbLower) {
							 | 
						|
										fminus = one;
							 | 
						|
									    } else if (i == 1 && leftChild == kFalse) {
							 | 
						|
										fminus = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(leftChild == index[0] || leftChild == index[1]);
							 | 
						|
										if (leftChild == index[0]) {
							 | 
						|
										    fminus = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fminus = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Find f= */
							 | 
						|
									    middleChild = j << 1;
							 | 
						|
									    if (middleChild >= kTrueLbLower || middleChild <= kTrueUbLower) {
							 | 
						|
										fequal = one;
							 | 
						|
									    } else if (i == 1 && middleChild == kFalse) {
							 | 
						|
										fequal = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(middleChild == index[0] || middleChild == index[1]);
							 | 
						|
										if (middleChild == index[0]) {
							 | 
						|
										    fequal = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fequal = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Find f+ */
							 | 
						|
									    rightChild = (j << 1) + 1;
							 | 
						|
									    if (rightChild >= kTrueLbLower || rightChild <= kTrueUbLower) {
							 | 
						|
										fplus = one;
							 | 
						|
									    } else if (i == 1 && rightChild == kFalse) {
							 | 
						|
										fplus = zero;
							 | 
						|
									    } else {
							 | 
						|
										assert(rightChild == index[0] || rightChild == index[1]);
							 | 
						|
										if (rightChild == index[0]) {
							 | 
						|
										    fplus = map[0];
							 | 
						|
										} else {
							 | 
						|
										    fplus = map[1];
							 | 
						|
										}
							 | 
						|
									    }
							 | 
						|
								
							 | 
						|
									    /* Build new nodes. */
							 | 
						|
									    g1 = Cudd_bddIte(dd, y[N - i], fequal, fplus);
							 | 
						|
									    if (g1 == NULL) {
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(g1);
							 | 
						|
									    g0 = Cudd_bddIte(dd, y[N - i], fminus, fequal);
							 | 
						|
									    if (g0 == NULL) {
							 | 
						|
										Cudd_IterDerefBdd(dd, g1);
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(g0);
							 | 
						|
									    f = Cudd_bddIte(dd, x[N - i], g1, g0);
							 | 
						|
									    if (f == NULL) {
							 | 
						|
										Cudd_IterDerefBdd(dd, g1);
							 | 
						|
										Cudd_IterDerefBdd(dd, g0);
							 | 
						|
										if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
										if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
										if (newIndex[0] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[0]);
							 | 
						|
										if (newIndex[1] != invalidIndex) Cudd_IterDerefBdd(dd, newMap[1]);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(f);
							 | 
						|
									    Cudd_IterDerefBdd(dd, g1);
							 | 
						|
									    Cudd_IterDerefBdd(dd, g0);
							 | 
						|
								
							 | 
						|
									    /* Save newly computed node in map. */
							 | 
						|
									    assert(newIndex[0] == invalidIndex || newIndex[1] == invalidIndex);
							 | 
						|
									    if (newIndex[0] == invalidIndex) {
							 | 
						|
										newIndex[0] = j;
							 | 
						|
										newMap[0] = f;
							 | 
						|
									    } else {
							 | 
						|
										newIndex[1] = j;
							 | 
						|
										newMap[1] = f;
							 | 
						|
									    }
							 | 
						|
									}
							 | 
						|
								
							 | 
						|
									/* Copy new map to map. */
							 | 
						|
									if (index[0] != invalidIndex) Cudd_IterDerefBdd(dd, map[0]);
							 | 
						|
									if (index[1] != invalidIndex) Cudd_IterDerefBdd(dd, map[1]);
							 | 
						|
									map[0] = newMap[0];
							 | 
						|
									map[1] = newMap[1];
							 | 
						|
									index[0] = newIndex[0];
							 | 
						|
									index[1] = newIndex[1];
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddDeref(f);
							 | 
						|
								    return(f);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_Disequality */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Generates a BDD for the function lowerB ≤ x ≤ upperB.]
							 | 
						|
								
							 | 
						|
								  Description [This function generates a BDD for the function
							 | 
						|
								  lowerB ≤ x ≤ upperB, where x is an N-bit number,
							 | 
						|
								  x\[0\] x\[1\] ... x\[N-1\], with 0 the most significant bit (important!).
							 | 
						|
								  The number of variables N should be sufficient to represent the bounds;
							 | 
						|
								  otherwise, the bounds are truncated to their N least significant bits.
							 | 
						|
								  Two BDDs are built bottom-up for lowerB ≤ x and x ≤ upperB, and they
							 | 
						|
								  are finally conjoined.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_Xgty]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_bddInterval(
							 | 
						|
								  DdManager * dd /* DD manager */,
							 | 
						|
								  int  N /* number of x variables */,
							 | 
						|
								  DdNode ** x /* array of x variables */,
							 | 
						|
								  unsigned int lowerB /* lower bound */,
							 | 
						|
								  unsigned int upperB /* upper bound */)
							 | 
						|
								{
							 | 
						|
								    DdNode *one, *zero;
							 | 
						|
								    DdNode *r, *rl, *ru;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    one = DD_ONE(dd);
							 | 
						|
								    zero = Cudd_Not(one);
							 | 
						|
								
							 | 
						|
								    rl = one;
							 | 
						|
								    cuddRef(rl);
							 | 
						|
								    ru = one;
							 | 
						|
								    cuddRef(ru);
							 | 
						|
								
							 | 
						|
								    /* Loop to build the rest of the BDDs. */
							 | 
						|
								    for (i = N-1; i >= 0; i--) {
							 | 
						|
									DdNode *vl, *vu;
							 | 
						|
									vl = Cudd_bddIte(dd, x[i],
							 | 
						|
											 lowerB&1 ? rl : one,
							 | 
						|
											 lowerB&1 ? zero : rl);
							 | 
						|
									if (vl == NULL) {
							 | 
						|
									    Cudd_IterDerefBdd(dd, rl);
							 | 
						|
									    Cudd_IterDerefBdd(dd, ru);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(vl);
							 | 
						|
									Cudd_IterDerefBdd(dd, rl);
							 | 
						|
									rl = vl;
							 | 
						|
									lowerB >>= 1;
							 | 
						|
									vu = Cudd_bddIte(dd, x[i],
							 | 
						|
											 upperB&1 ? ru : zero,
							 | 
						|
											 upperB&1 ? one : ru);
							 | 
						|
									if (vu == NULL) {
							 | 
						|
									    Cudd_IterDerefBdd(dd, rl);
							 | 
						|
									    Cudd_IterDerefBdd(dd, ru);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(vu);
							 | 
						|
									Cudd_IterDerefBdd(dd, ru);
							 | 
						|
									ru = vu;
							 | 
						|
									upperB >>= 1;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Conjoin the two bounds. */
							 | 
						|
								    r = Cudd_bddAnd(dd, rl, ru);
							 | 
						|
								    if (r == NULL) {
							 | 
						|
									Cudd_IterDerefBdd(dd, rl);
							 | 
						|
									Cudd_IterDerefBdd(dd, ru);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(r);
							 | 
						|
								    Cudd_IterDerefBdd(dd, rl);
							 | 
						|
								    Cudd_IterDerefBdd(dd, ru);
							 | 
						|
								    cuddDeref(r);
							 | 
						|
								    return(r);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_bddInterval */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Computes the compatible projection of R w.r.t. cube Y.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the compatible projection of relation R with
							 | 
						|
								  respect to cube Y. Returns a pointer to the c-projection if
							 | 
						|
								  successful; NULL otherwise. For a comparison between Cudd_CProjection
							 | 
						|
								  and Cudd_PrioritySelect, see the documentation of the latter.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_PrioritySelect]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_CProjection(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * R,
							 | 
						|
								  DdNode * Y)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								    DdNode *support;
							 | 
						|
								
							 | 
						|
								    if (Cudd_CheckCube(dd,Y) == 0) {
							 | 
						|
									(void) fprintf(dd->err,
							 | 
						|
									"Error: The third argument of Cudd_CProjection should be a cube\n");
							 | 
						|
									dd->errorCode = CUDD_INVALID_ARG;
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Compute the support of Y, which is used by the abstraction step
							 | 
						|
								    ** in cuddCProjectionRecur.
							 | 
						|
								    */
							 | 
						|
								    support = Cudd_Support(dd,Y);
							 | 
						|
								    if (support == NULL) return(NULL);
							 | 
						|
								    cuddRef(support);
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddCProjectionRecur(dd,R,Y,support);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,support);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(res);
							 | 
						|
								    Cudd_RecursiveDeref(dd,support);
							 | 
						|
								    cuddDeref(res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_CProjection */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Computes the Hamming distance ADD.]
							 | 
						|
								
							 | 
						|
								  Description [Computes the Hamming distance ADD. Returns an ADD that
							 | 
						|
								  gives the Hamming distance between its two arguments if successful;
							 | 
						|
								  NULL otherwise. The two vectors xVars and yVars identify the variables
							 | 
						|
								  that form the two arguments.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     []
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addHamming(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** xVars,
							 | 
						|
								  DdNode ** yVars,
							 | 
						|
								  int  nVars)
							 | 
						|
								{
							 | 
						|
								    DdNode  *result,*tempBdd;
							 | 
						|
								    DdNode  *tempAdd,*temp;
							 | 
						|
								    int     i;
							 | 
						|
								
							 | 
						|
								    result = DD_ZERO(dd);
							 | 
						|
								    cuddRef(result);
							 | 
						|
								
							 | 
						|
								    for (i = 0; i < nVars; i++) {
							 | 
						|
									tempBdd = Cudd_bddIte(dd,xVars[i],Cudd_Not(yVars[i]),yVars[i]);
							 | 
						|
									if (tempBdd == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd,result);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(tempBdd);
							 | 
						|
									tempAdd = Cudd_BddToAdd(dd,tempBdd);
							 | 
						|
									if (tempAdd == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd,tempBdd);
							 | 
						|
									    Cudd_RecursiveDeref(dd,result);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(tempAdd);
							 | 
						|
									Cudd_RecursiveDeref(dd,tempBdd);
							 | 
						|
									temp = Cudd_addApply(dd,Cudd_addPlus,tempAdd,result);
							 | 
						|
									if (temp == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd,tempAdd);
							 | 
						|
									    Cudd_RecursiveDeref(dd,result);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(temp);
							 | 
						|
									Cudd_RecursiveDeref(dd,tempAdd);
							 | 
						|
									Cudd_RecursiveDeref(dd,result);
							 | 
						|
									result = temp;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddDeref(result);
							 | 
						|
								    return(result);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addHamming */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Returns the minimum Hamming distance between f and minterm.]
							 | 
						|
								
							 | 
						|
								  Description [Returns the minimum Hamming distance between the
							 | 
						|
								  minterms of a function f and a reference minterm. The function is
							 | 
						|
								  given as a BDD; the minterm is given as an array of integers, one
							 | 
						|
								  for each variable in the manager.  Returns the minimum distance if
							 | 
						|
								  it is less than the upper bound; the upper bound if the minimum
							 | 
						|
								  distance is at least as large; CUDD_OUT_OF_MEM in case of failure.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addHamming Cudd_bddClosestCube]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								int
							 | 
						|
								Cudd_MinHammingDist(
							 | 
						|
								  DdManager *dd /* DD manager */,
							 | 
						|
								  DdNode *f /* function to examine */,
							 | 
						|
								  int *minterm /* reference minterm */,
							 | 
						|
								  int upperBound /* distance above which an approximate answer is OK */)
							 | 
						|
								{
							 | 
						|
								    DdHashTable *table;
							 | 
						|
								    CUDD_VALUE_TYPE epsilon;
							 | 
						|
								    int res;
							 | 
						|
								
							 | 
						|
								    table = cuddHashTableInit(dd,1,2);
							 | 
						|
								    if (table == NULL) {
							 | 
						|
									return(CUDD_OUT_OF_MEM);
							 | 
						|
								    }
							 | 
						|
								    epsilon = Cudd_ReadEpsilon(dd);
							 | 
						|
								    Cudd_SetEpsilon(dd,(CUDD_VALUE_TYPE)0.0);
							 | 
						|
								    res = cuddMinHammingDistRecur(f,minterm,table,upperBound);
							 | 
						|
								    cuddHashTableQuit(table);
							 | 
						|
								    Cudd_SetEpsilon(dd,epsilon);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_MinHammingDist */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Finds a cube of f at minimum Hamming distance from g.]
							 | 
						|
								
							 | 
						|
								  Description [Finds a cube of f at minimum Hamming distance from the
							 | 
						|
								  minterms of g.  All the minterms of the cube are at the minimum
							 | 
						|
								  distance.  If the distance is 0, the cube belongs to the
							 | 
						|
								  intersection of f and g.  Returns the cube if successful; NULL
							 | 
						|
								  otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [The distance is returned as a side effect.]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_MinHammingDist]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_bddClosestCube(
							 | 
						|
								  DdManager *dd,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode *g,
							 | 
						|
								  int *distance)
							 | 
						|
								{
							 | 
						|
								    DdNode *res, *acube;
							 | 
						|
								    CUDD_VALUE_TYPE rdist;
							 | 
						|
								
							 | 
						|
								    /* Compute the cube and distance as a single ADD. */
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddBddClosestCube(dd,f,g,CUDD_CONST_INDEX + 1.0);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    if (res == NULL) return(NULL);
							 | 
						|
								    cuddRef(res);
							 | 
						|
								
							 | 
						|
								    /* Unpack distance and cube. */
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									acube = separateCube(dd, res, &rdist);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    if (acube == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, res);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(acube);
							 | 
						|
								    Cudd_RecursiveDeref(dd, res);
							 | 
						|
								
							 | 
						|
								    /* Convert cube from ADD to BDD. */
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddBddDoPattern(dd, acube);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, acube);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(res);
							 | 
						|
								    Cudd_RecursiveDeref(dd, acube);
							 | 
						|
								
							 | 
						|
								    *distance = (int) rdist;
							 | 
						|
								    cuddDeref(res);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_bddClosestCube */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_CProjection.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_CProjection. Returns
							 | 
						|
								  the projection if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_CProjection]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddCProjectionRecur(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * R,
							 | 
						|
								  DdNode * Y,
							 | 
						|
								  DdNode * Ysupp)
							 | 
						|
								{
							 | 
						|
								    DdNode *res, *res1, *res2, *resA;
							 | 
						|
								    DdNode *r, *y, *RT, *RE, *YT, *YE, *Yrest, *Ra, *Ran, *Gamma, *Alpha;
							 | 
						|
								    unsigned int topR, topY, top, index;
							 | 
						|
								    DdNode *one = DD_ONE(dd);
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    if (Y == one) return(R);
							 | 
						|
								
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
								    assert(!Cudd_IsConstant(Y));
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								    if (R == Cudd_Not(one)) return(R);
							 | 
						|
								
							 | 
						|
								    res = cuddCacheLookup2(dd, Cudd_CProjection, R, Y);
							 | 
						|
								    if (res != NULL) return(res);
							 | 
						|
								
							 | 
						|
								    r = Cudd_Regular(R);
							 | 
						|
								    topR = cuddI(dd,r->index);
							 | 
						|
								    y = Cudd_Regular(Y);
							 | 
						|
								    topY = cuddI(dd,y->index);
							 | 
						|
								
							 | 
						|
								    top = ddMin(topR, topY);
							 | 
						|
								
							 | 
						|
								    /* Compute the cofactors of R */
							 | 
						|
								    if (topR == top) {
							 | 
						|
									index = r->index;
							 | 
						|
									RT = cuddT(r);
							 | 
						|
									RE = cuddE(r);
							 | 
						|
									if (r != R) {
							 | 
						|
									    RT = Cudd_Not(RT); RE = Cudd_Not(RE);
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									RT = RE = R;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (topY > top) {
							 | 
						|
									/* Y does not depend on the current top variable.
							 | 
						|
									** We just need to compute the results on the two cofactors of R
							 | 
						|
									** and make them the children of a node labeled r->index.
							 | 
						|
									*/
							 | 
						|
									res1 = cuddCProjectionRecur(dd,RT,Y,Ysupp);
							 | 
						|
									if (res1 == NULL) return(NULL);
							 | 
						|
									cuddRef(res1);
							 | 
						|
									res2 = cuddCProjectionRecur(dd,RE,Y,Ysupp);
							 | 
						|
									if (res2 == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd,res1);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(res2);
							 | 
						|
									res = cuddBddIteRecur(dd, dd->vars[index], res1, res2);
							 | 
						|
									if (res == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd,res1);
							 | 
						|
									    Cudd_RecursiveDeref(dd,res2);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									/* If we have reached this point, res1 and res2 are now
							 | 
						|
									** incorporated in res. cuddDeref is therefore sufficient.
							 | 
						|
									*/
							 | 
						|
									cuddDeref(res1);
							 | 
						|
									cuddDeref(res2);
							 | 
						|
								    } else {
							 | 
						|
									/* Compute the cofactors of Y */
							 | 
						|
									index = y->index;
							 | 
						|
									YT = cuddT(y);
							 | 
						|
									YE = cuddE(y);
							 | 
						|
									if (y != Y) {
							 | 
						|
									    YT = Cudd_Not(YT); YE = Cudd_Not(YE);
							 | 
						|
									}
							 | 
						|
									if (YT == Cudd_Not(one)) {
							 | 
						|
									    Alpha  = Cudd_Not(dd->vars[index]);
							 | 
						|
									    Yrest = YE;
							 | 
						|
									    Ra = RE;
							 | 
						|
									    Ran = RT;
							 | 
						|
									} else {
							 | 
						|
									    Alpha = dd->vars[index];
							 | 
						|
									    Yrest = YT;
							 | 
						|
									    Ra = RT;
							 | 
						|
									    Ran = RE;
							 | 
						|
									}
							 | 
						|
									Gamma = cuddBddExistAbstractRecur(dd,Ra,cuddT(Ysupp));
							 | 
						|
									if (Gamma == NULL) return(NULL);
							 | 
						|
									if (Gamma == one) {
							 | 
						|
									    res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
							 | 
						|
									    if (res1 == NULL) return(NULL);
							 | 
						|
									    cuddRef(res1);
							 | 
						|
									    res = cuddBddAndRecur(dd, Alpha, res1);
							 | 
						|
									    if (res == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,res1);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddDeref(res1);
							 | 
						|
									} else if (Gamma == Cudd_Not(one)) {
							 | 
						|
									    res1 = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
							 | 
						|
									    if (res1 == NULL) return(NULL);
							 | 
						|
									    cuddRef(res1);
							 | 
						|
									    res = cuddBddAndRecur(dd, Cudd_Not(Alpha), res1);
							 | 
						|
									    if (res == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,res1);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddDeref(res1);
							 | 
						|
									} else {
							 | 
						|
									    cuddRef(Gamma);
							 | 
						|
									    resA = cuddCProjectionRecur(dd,Ran,Yrest,cuddT(Ysupp));
							 | 
						|
									    if (resA == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,Gamma);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(resA);
							 | 
						|
									    res2 = cuddBddAndRecur(dd, Cudd_Not(Gamma), resA);
							 | 
						|
									    if (res2 == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,Gamma);
							 | 
						|
										Cudd_RecursiveDeref(dd,resA);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(res2);
							 | 
						|
									    Cudd_RecursiveDeref(dd,Gamma);
							 | 
						|
									    Cudd_RecursiveDeref(dd,resA);
							 | 
						|
									    res1 = cuddCProjectionRecur(dd,Ra,Yrest,cuddT(Ysupp));
							 | 
						|
									    if (res1 == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,res2);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddRef(res1);
							 | 
						|
									    res = cuddBddIteRecur(dd, Alpha, res1, res2);
							 | 
						|
									    if (res == NULL) {
							 | 
						|
										Cudd_RecursiveDeref(dd,res1);
							 | 
						|
										Cudd_RecursiveDeref(dd,res2);
							 | 
						|
										return(NULL);
							 | 
						|
									    }
							 | 
						|
									    cuddDeref(res1);
							 | 
						|
									    cuddDeref(res2);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    cuddCacheInsert2(dd,Cudd_CProjection,R,Y,res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddCProjectionRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_bddClosestCube.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_bddClosestCube.
							 | 
						|
								  Returns the cube if succesful; NULL otherwise.  The procedure uses a
							 | 
						|
								  four-way recursion to examine all four combinations of cofactors of
							 | 
						|
								  <code>f</code> and <code>g</code> according to the following formula.
							 | 
						|
								  <pre>
							 | 
						|
								    H(f,g) = min(H(ft,gt), H(fe,ge), H(ft,ge)+1, H(fe,gt)+1)
							 | 
						|
								  </pre>
							 | 
						|
								  Bounding is based on the following observations.
							 | 
						|
								  <ul>
							 | 
						|
								  <li> If we already found two points at distance 0, there is no point in
							 | 
						|
								       continuing.  Furthermore,
							 | 
						|
								  <li> If F == not(G) then the best we can hope for is a minimum distance
							 | 
						|
								       of 1.  If we have already found two points at distance 1, there is
							 | 
						|
								       no point in continuing.  (Indeed, H(F,G) == 1 in this case.  We
							 | 
						|
								       have to continue, though, to find the cube.)
							 | 
						|
								  </ul>
							 | 
						|
								  The variable <code>bound</code> is set at the largest value of the distance
							 | 
						|
								  that we are still interested in.  Therefore, we desist when
							 | 
						|
								  <pre>
							 | 
						|
								    (bound == -1) and (F != not(G)) or (bound == 0) and (F == not(G)).
							 | 
						|
								  </pre>
							 | 
						|
								  If we were maximally aggressive in using the bound, we would always
							 | 
						|
								  set the bound to the minimum distance seen thus far minus one.  That
							 | 
						|
								  is, we would maintain the invariant
							 | 
						|
								  <pre>
							 | 
						|
								    bound < minD,
							 | 
						|
								  </pre>
							 | 
						|
								  except at the very beginning, when we have no value for
							 | 
						|
								  <code>minD</code>.<p>
							 | 
						|
								
							 | 
						|
								  However, we do not use <code>bound < minD</code> when examining the
							 | 
						|
								  two negative cofactors, because we try to find a large cube at
							 | 
						|
								  minimum distance.  To do so, we try to find a cube in the negative
							 | 
						|
								  cofactors at the same or smaller distance from the cube found in the
							 | 
						|
								  positive cofactors.<p>
							 | 
						|
								
							 | 
						|
								  When we compute <code>H(ft,ge)</code> and <code>H(fe,gt)</code> we
							 | 
						|
								  know that we are going to add 1 to the result of the recursive call
							 | 
						|
								  to account for the difference in the splitting variable.  Therefore,
							 | 
						|
								  we decrease the bound correspondingly.<p>
							 | 
						|
								
							 | 
						|
								  Another important observation concerns the need of examining all
							 | 
						|
								  four pairs of cofators only when both <code>f</code> and
							 | 
						|
								  <code>g</code> depend on the top variable.<p>
							 | 
						|
								
							 | 
						|
								  Suppose <code>gt == ge == g</code>.  (That is, <code>g</code> does
							 | 
						|
								  not depend on the top variable.)  Then
							 | 
						|
								  <pre>
							 | 
						|
								    H(f,g) = min(H(ft,g), H(fe,g), H(ft,g)+1, H(fe,g)+1)
							 | 
						|
									   = min(H(ft,g), H(fe,g)) .
							 | 
						|
								  </pre>
							 | 
						|
								  Therefore, under these circumstances, we skip the two "cross" cases.<p>
							 | 
						|
								
							 | 
						|
								  An interesting feature of this function is the scheme used for
							 | 
						|
								  caching the results in the global computed table.  Since we have a
							 | 
						|
								  cube and a distance, we combine them to form an ADD.  The
							 | 
						|
								  combination replaces the zero child of the top node of the cube with
							 | 
						|
								  the negative of the distance.  (The use of the negative is to avoid
							 | 
						|
								  ambiguity with 1.)  The degenerate cases (zero and one) are treated
							 | 
						|
								  specially because the distance is known (0 for one, and infinity for
							 | 
						|
								  zero).]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_bddClosestCube]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddBddClosestCube(
							 | 
						|
								  DdManager *dd,
							 | 
						|
								  DdNode *f,
							 | 
						|
								  DdNode *g,
							 | 
						|
								  CUDD_VALUE_TYPE bound)
							 | 
						|
								{
							 | 
						|
								    DdNode *res, *F, *G, *ft, *fe, *gt, *ge, *tt, *ee;
							 | 
						|
								    DdNode *ctt, *cee, *cte, *cet;
							 | 
						|
								    CUDD_VALUE_TYPE minD, dtt, dee, dte, det;
							 | 
						|
								    DdNode *one = DD_ONE(dd);
							 | 
						|
								    DdNode *lzero = Cudd_Not(one);
							 | 
						|
								    DdNode *azero = DD_ZERO(dd);
							 | 
						|
								    unsigned int topf, topg, index;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    if (bound < (f == Cudd_Not(g))) return(azero);
							 | 
						|
								    /* Terminal cases. */
							 | 
						|
								    if (g == lzero || f == lzero) return(azero);
							 | 
						|
								    if (f == one && g == one) return(one);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    F = Cudd_Regular(f);
							 | 
						|
								    G = Cudd_Regular(g);
							 | 
						|
								    if (F->ref != 1 || G->ref != 1) {
							 | 
						|
									res = cuddCacheLookup2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g);
							 | 
						|
									if (res != NULL) return(res);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    topf = cuddI(dd,F->index);
							 | 
						|
								    topg = cuddI(dd,G->index);
							 | 
						|
								
							 | 
						|
								    /* Compute cofactors. */
							 | 
						|
								    if (topf <= topg) {
							 | 
						|
									index = F->index;
							 | 
						|
									ft = cuddT(F);
							 | 
						|
									fe = cuddE(F);
							 | 
						|
									if (Cudd_IsComplement(f)) {
							 | 
						|
									    ft = Cudd_Not(ft);
							 | 
						|
									    fe = Cudd_Not(fe);
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									index = G->index;
							 | 
						|
									ft = fe = f;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (topg <= topf) {
							 | 
						|
									gt = cuddT(G);
							 | 
						|
									ge = cuddE(G);
							 | 
						|
									if (Cudd_IsComplement(g)) {
							 | 
						|
									    gt = Cudd_Not(gt);
							 | 
						|
									    ge = Cudd_Not(ge);
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									gt = ge = g;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    tt = cuddBddClosestCube(dd,ft,gt,bound);
							 | 
						|
								    if (tt == NULL) return(NULL);
							 | 
						|
								    cuddRef(tt);
							 | 
						|
								    ctt = separateCube(dd,tt,&dtt);
							 | 
						|
								    if (ctt == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, tt);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(ctt);
							 | 
						|
								    Cudd_RecursiveDeref(dd, tt);
							 | 
						|
								    minD = dtt;
							 | 
						|
								    bound = ddMin(bound,minD);
							 | 
						|
								
							 | 
						|
								    ee = cuddBddClosestCube(dd,fe,ge,bound);
							 | 
						|
								    if (ee == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(ee);
							 | 
						|
								    cee = separateCube(dd,ee,&dee);
							 | 
						|
								    if (cee == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									Cudd_RecursiveDeref(dd, ee);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(cee);
							 | 
						|
								    Cudd_RecursiveDeref(dd, ee);
							 | 
						|
								    minD = ddMin(dtt, dee);
							 | 
						|
								    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
							 | 
						|
								
							 | 
						|
								    if (minD > 0 && topf == topg) {
							 | 
						|
									DdNode *te = cuddBddClosestCube(dd,ft,ge,bound-1);
							 | 
						|
									if (te == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cee);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(te);
							 | 
						|
									cte = separateCube(dd,te,&dte);
							 | 
						|
									if (cte == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cee);
							 | 
						|
									    Cudd_RecursiveDeref(dd, te);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(cte);
							 | 
						|
									Cudd_RecursiveDeref(dd, te);
							 | 
						|
									dte += 1.0;
							 | 
						|
									minD = ddMin(minD, dte);
							 | 
						|
								    } else {
							 | 
						|
									cte = azero;
							 | 
						|
									cuddRef(cte);
							 | 
						|
									dte = CUDD_CONST_INDEX + 1.0;
							 | 
						|
								    }
							 | 
						|
								    if (minD <= CUDD_CONST_INDEX) bound = ddMin(bound,minD-1);
							 | 
						|
								
							 | 
						|
								    if (minD > 0 && topf == topg) {
							 | 
						|
									DdNode *et = cuddBddClosestCube(dd,fe,gt,bound-1);
							 | 
						|
									if (et == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cee);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cte);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(et);
							 | 
						|
									cet = separateCube(dd,et,&det);
							 | 
						|
									if (cet == NULL) {
							 | 
						|
									    Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cee);
							 | 
						|
									    Cudd_RecursiveDeref(dd, cte);
							 | 
						|
									    Cudd_RecursiveDeref(dd, et);
							 | 
						|
									    return(NULL);
							 | 
						|
									}
							 | 
						|
									cuddRef(cet);
							 | 
						|
									Cudd_RecursiveDeref(dd, et);
							 | 
						|
									det += 1.0;
							 | 
						|
									minD = ddMin(minD, det);
							 | 
						|
								    } else {
							 | 
						|
									cet = azero;
							 | 
						|
									cuddRef(cet);
							 | 
						|
									det = CUDD_CONST_INDEX + 1.0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    if (minD == dtt) {
							 | 
						|
									if (dtt == dee && ctt == cee) {
							 | 
						|
									    res = createResult(dd,CUDD_CONST_INDEX,1,ctt,dtt);
							 | 
						|
									} else {
							 | 
						|
									    res = createResult(dd,index,1,ctt,dtt);
							 | 
						|
									}
							 | 
						|
								    } else if (minD == dee) {
							 | 
						|
									res = createResult(dd,index,0,cee,dee);
							 | 
						|
								    } else if (minD == dte) {
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
									assert(topf == topg);
							 | 
						|
								#endif
							 | 
						|
									res = createResult(dd,index,1,cte,dte);
							 | 
						|
								    } else {
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
									assert(topf == topg);
							 | 
						|
								#endif
							 | 
						|
									res = createResult(dd,index,0,cet,det);
							 | 
						|
								    }
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
									Cudd_RecursiveDeref(dd, cee);
							 | 
						|
									Cudd_RecursiveDeref(dd, cte);
							 | 
						|
									Cudd_RecursiveDeref(dd, cet);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(res);
							 | 
						|
								    Cudd_RecursiveDeref(dd, ctt);
							 | 
						|
								    Cudd_RecursiveDeref(dd, cee);
							 | 
						|
								    Cudd_RecursiveDeref(dd, cte);
							 | 
						|
								    Cudd_RecursiveDeref(dd, cet);
							 | 
						|
								
							 | 
						|
								    /* Only cache results that are different from azero to avoid
							 | 
						|
								    ** storing results that depend on the value of the bound. */
							 | 
						|
								    if ((F->ref != 1 || G->ref != 1) && res != azero)
							 | 
						|
									cuddCacheInsert2(dd,(DD_CTFP) Cudd_bddClosestCube, f, g, res);
							 | 
						|
								
							 | 
						|
								    cuddDeref(res);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddBddClosestCube */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of static functions                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_MinHammingDist.
							 | 
						|
								  It is based on the following identity. Let H(f) be the
							 | 
						|
								  minimum Hamming distance of the minterms of f from the reference
							 | 
						|
								  minterm. Then:
							 | 
						|
								  <xmp>
							 | 
						|
								    H(f) = min(H(f0)+h0,H(f1)+h1)
							 | 
						|
								  </xmp>
							 | 
						|
								  where f0 and f1 are the two cofactors of f with respect to its top
							 | 
						|
								  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
							 | 
						|
								  h1 is 1 if the minterm assigns 0 to the top variable of f.
							 | 
						|
								  The upper bound on the distance is used to bound the depth of the
							 | 
						|
								  recursion.
							 | 
						|
								  Returns the minimum distance unless it exceeds the upper bound or
							 | 
						|
								  computation fails.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_MinHammingDist]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static int
							 | 
						|
								cuddMinHammingDistRecur(
							 | 
						|
								  DdNode * f,
							 | 
						|
								  int *minterm,
							 | 
						|
								  DdHashTable * table,
							 | 
						|
								  int upperBound)
							 | 
						|
								{
							 | 
						|
								    DdNode	*F, *Ft, *Fe;
							 | 
						|
								    double	h, hT, hE;
							 | 
						|
								    DdNode	*zero, *res;
							 | 
						|
								    DdManager	*dd = table->manager;
							 | 
						|
								
							 | 
						|
								    statLine(dd);
							 | 
						|
								    if (upperBound == 0) return(0);
							 | 
						|
								
							 | 
						|
								    F = Cudd_Regular(f);
							 | 
						|
								
							 | 
						|
								    if (cuddIsConstant(F)) {
							 | 
						|
									zero = Cudd_Not(DD_ONE(dd));
							 | 
						|
									if (f == dd->background || f == zero) {
							 | 
						|
									    return(upperBound);
							 | 
						|
									} else {
							 | 
						|
									    return(0);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
							 | 
						|
									h = cuddV(res);
							 | 
						|
									if (res->ref == 0) {
							 | 
						|
									    dd->dead++;
							 | 
						|
									    dd->constants.dead++;
							 | 
						|
									}
							 | 
						|
									return((int) h);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    Ft = cuddT(F); Fe = cuddE(F);
							 | 
						|
								    if (Cudd_IsComplement(f)) {
							 | 
						|
									Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
							 | 
						|
								    }
							 | 
						|
								    if (minterm[F->index] == 0) {
							 | 
						|
									DdNode *temp = Ft;
							 | 
						|
									Ft = Fe; Fe = temp;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
							 | 
						|
								    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
							 | 
						|
								    if (hT == 0) {
							 | 
						|
									hE = upperBound;
							 | 
						|
								    } else {
							 | 
						|
									hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
							 | 
						|
									if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
							 | 
						|
								    }
							 | 
						|
								    h = ddMin(hT, hE + 1);
							 | 
						|
								
							 | 
						|
								    if (F->ref != 1) {
							 | 
						|
									ptrint fanout = (ptrint) F->ref;
							 | 
						|
									cuddSatDec(fanout);
							 | 
						|
									res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
							 | 
						|
									if (!cuddHashTableInsert1(table,f,res,fanout)) {
							 | 
						|
									    cuddRef(res); Cudd_RecursiveDeref(dd, res);
							 | 
						|
									    return(CUDD_OUT_OF_MEM);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return((int) h);
							 | 
						|
								
							 | 
						|
								} /* end of cuddMinHammingDistRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Separates cube from distance.]
							 | 
						|
								
							 | 
						|
								  Description [Separates cube from distance.  Returns the cube if
							 | 
						|
								  successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [The distance is returned as a side effect.]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddBddClosestCube createResult]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static DdNode *
							 | 
						|
								separateCube(
							 | 
						|
								  DdManager *dd,
							 | 
						|
								  DdNode *f,
							 | 
						|
								  CUDD_VALUE_TYPE *distance)
							 | 
						|
								{
							 | 
						|
								    DdNode *cube, *t;
							 | 
						|
								
							 | 
						|
								    /* One and zero are special cases because the distance is implied. */
							 | 
						|
								    if (Cudd_IsConstant(f)) {
							 | 
						|
									*distance = (f == DD_ONE(dd)) ? 0.0 :
							 | 
						|
									    (1.0 + (CUDD_VALUE_TYPE) CUDD_CONST_INDEX);
							 | 
						|
									return(f);
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /* Find out which branch points to the distance and replace the top
							 | 
						|
								    ** node with one pointing to zero instead. */
							 | 
						|
								    t = cuddT(f);
							 | 
						|
								    if (Cudd_IsConstant(t) && cuddV(t) <= 0) {
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
									assert(!Cudd_IsConstant(cuddE(f)) || cuddE(f) == DD_ONE(dd));
							 | 
						|
								#endif
							 | 
						|
									*distance = -cuddV(t);
							 | 
						|
									cube = cuddUniqueInter(dd, f->index, DD_ZERO(dd), cuddE(f));
							 | 
						|
								    } else {
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
									assert(!Cudd_IsConstant(t) || t == DD_ONE(dd));
							 | 
						|
								#endif
							 | 
						|
									*distance = -cuddV(cuddE(f));
							 | 
						|
									cube = cuddUniqueInter(dd, f->index, t, DD_ZERO(dd));
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return(cube);
							 | 
						|
								
							 | 
						|
								} /* end of separateCube */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Builds a result for cache storage.]
							 | 
						|
								
							 | 
						|
								  Description [Builds a result for cache storage.  Returns a pointer
							 | 
						|
								  to the resulting ADD if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddBddClosestCube separateCube]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								static DdNode *
							 | 
						|
								createResult(
							 | 
						|
								  DdManager *dd,
							 | 
						|
								  unsigned int index,
							 | 
						|
								  unsigned int phase,
							 | 
						|
								  DdNode *cube,
							 | 
						|
								  CUDD_VALUE_TYPE distance)
							 | 
						|
								{
							 | 
						|
								    DdNode *res, *constant;
							 | 
						|
								
							 | 
						|
								    /* Special case.  The cube is either one or zero, and we do not
							 | 
						|
								    ** add any variables.  Hence, the result is also one or zero,
							 | 
						|
								    ** and the distance remains implied by the value of the constant. */
							 | 
						|
								    if (index == CUDD_CONST_INDEX && Cudd_IsConstant(cube)) return(cube);
							 | 
						|
								
							 | 
						|
								    constant = cuddUniqueConst(dd,-distance);
							 | 
						|
								    if (constant == NULL) return(NULL);
							 | 
						|
								    cuddRef(constant);
							 | 
						|
								
							 | 
						|
								    if (index == CUDD_CONST_INDEX) {
							 | 
						|
									/* Replace the top node. */
							 | 
						|
									if (cuddT(cube) == DD_ZERO(dd)) {
							 | 
						|
									    res = cuddUniqueInter(dd,cube->index,constant,cuddE(cube));
							 | 
						|
									} else {
							 | 
						|
									    res = cuddUniqueInter(dd,cube->index,cuddT(cube),constant);
							 | 
						|
									}
							 | 
						|
								    } else {
							 | 
						|
									/* Add a new top node. */
							 | 
						|
								#ifdef DD_DEBUG
							 | 
						|
									assert(cuddI(dd,index) < cuddI(dd,cube->index));
							 | 
						|
								#endif
							 | 
						|
									if (phase) {
							 | 
						|
									    res = cuddUniqueInter(dd,index,cube,constant);
							 | 
						|
									} else {
							 | 
						|
									    res = cuddUniqueInter(dd,index,constant,cube);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, constant);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(constant); /* safe because constant is part of res */
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of createResult */
							 |