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.
		
		
		
		
		
			
		
			
				
					
					
						
							1630 lines
						
					
					
						
							40 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1630 lines
						
					
					
						
							40 KiB
						
					
					
				| /**CFile*********************************************************************** | |
|  | |
|   FileName    [cuddZddFuncs.c] | |
|  | |
|   PackageName [cudd] | |
|  | |
|   Synopsis    [Functions to manipulate covers represented as ZDDs.] | |
|  | |
|   Description [External procedures included in this module: | |
| 		    <ul> | |
| 		    <li> Cudd_zddProduct(); | |
| 		    <li> Cudd_zddUnateProduct(); | |
| 		    <li> Cudd_zddWeakDiv(); | |
| 		    <li> Cudd_zddWeakDivF(); | |
| 		    <li> Cudd_zddDivide(); | |
| 		    <li> Cudd_zddDivideF(); | |
| 		    <li> Cudd_zddComplement(); | |
| 		    </ul> | |
| 	       Internal procedures included in this module: | |
| 		    <ul> | |
| 		    <li> cuddZddProduct(); | |
| 		    <li> cuddZddUnateProduct(); | |
| 		    <li> cuddZddWeakDiv(); | |
| 		    <li> cuddZddWeakDivF(); | |
| 		    <li> cuddZddDivide(); | |
| 		    <li> cuddZddDivideF(); | |
| 		    <li> cuddZddGetCofactors3() | |
| 		    <li> cuddZddGetCofactors2() | |
| 		    <li> cuddZddComplement(); | |
| 		    <li> cuddZddGetPosVarIndex(); | |
| 		    <li> cuddZddGetNegVarIndex(); | |
| 		    <li> cuddZddGetPosVarLevel(); | |
| 		    <li> cuddZddGetNegVarLevel(); | |
| 		    </ul> | |
| 	       Static procedures included in this module: | |
| 		    <ul> | |
| 		    </ul> | |
| 	      ] | |
|  | |
|   SeeAlso     [] | |
|  | |
|   Author      [In-Ho Moon] | |
|  | |
|   Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado | |
|  | |
|   All rights reserved. | |
|  | |
|   Redistribution and use in source and binary forms, with or without | |
|   modification, are permitted provided that the following conditions | |
|   are met: | |
|  | |
|   Redistributions of source code must retain the above copyright | |
|   notice, this list of conditions and the following disclaimer. | |
|  | |
|   Redistributions in binary form must reproduce the above copyright | |
|   notice, this list of conditions and the following disclaimer in the | |
|   documentation and/or other materials provided with the distribution. | |
|  | |
|   Neither the name of the University of Colorado nor the names of its | |
|   contributors may be used to endorse or promote products derived from | |
|   this software without specific prior written permission. | |
|  | |
|   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
|   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
|   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
|   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
|   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
|   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
|   BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
|   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
|   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
|   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
|   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
|   POSSIBILITY OF SUCH DAMAGE.] | |
|  | |
| ******************************************************************************/ | |
| 
 | |
| #include "util.h" | |
| #include "cuddInt.h" | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Constant declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Stucture declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Type declarations                                                         */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Variable declarations                                                     */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| #ifndef lint | |
| static char rcsid[] DD_UNUSED = "$Id: cuddZddFuncs.c,v 1.17 2012/02/05 01:07:19 fabio Exp $"; | |
| #endif | |
|  | |
| /*---------------------------------------------------------------------------*/ | |
| /* Macro declarations                                                        */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticStart*************************************************************/ | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Static function prototypes                                                */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**AutomaticEnd***************************************************************/ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of exported functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the product of two covers represented by ZDDs.] | |
|  | |
|   Description [Computes the product of two covers represented by | |
|   ZDDs. The result is also a ZDD. Returns a pointer to the result if | |
|   successful; NULL otherwise.  The covers on which Cudd_zddProduct | |
|   operates use two ZDD variables for each function variable (one ZDD | |
|   variable for each literal of the variable). Those two ZDD variables | |
|   should be adjacent in the order.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddUnateProduct] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddProduct( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddProduct(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddProduct */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Computes the product of two unate covers.] | |
|  | |
|   Description [Computes the product of two unate covers represented as | |
|   ZDDs. Unate covers use one ZDD variable for each BDD | |
|   variable. Returns a pointer to the result if successful; NULL | |
|   otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddProduct] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddUnateProduct( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddUnateProduct(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddUnateProduct */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Applies weak division to two covers.] | |
|  | |
|   Description [Applies weak division to two ZDDs representing two | |
|   covers. Returns a pointer to the ZDD representing the result if | |
|   successful; NULL otherwise. The result of weak division depends on | |
|   the variable order. The covers on which Cudd_zddWeakDiv operates use | |
|   two ZDD variables for each function variable (one ZDD variable for | |
|   each literal of the variable). Those two ZDD variables should be | |
|   adjacent in the order.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddDivide] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddWeakDiv( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddWeakDiv(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddWeakDiv */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the quotient of two unate covers.] | |
|  | |
|   Description [Computes the quotient of two unate covers represented | |
|   by ZDDs.  Unate covers use one ZDD variable for each BDD | |
|   variable. Returns a pointer to the resulting ZDD if successful; NULL | |
|   otherwise.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddWeakDiv] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddDivide( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddDivide(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddDivide */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Modified version of Cudd_zddWeakDiv.] | |
|  | |
|   Description [Modified version of Cudd_zddWeakDiv. This function may | |
|   disappear in future releases.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddWeakDiv] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddWeakDivF( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddWeakDivF(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddWeakDivF */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Modified version of Cudd_zddDivide.] | |
|  | |
|   Description [Modified version of Cudd_zddDivide. This function may | |
|   disappear in future releases.] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddDivideF( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     DdNode	*res; | |
| 
 | |
|     do { | |
| 	dd->reordered = 0; | |
| 	res = cuddZddDivideF(dd, f, g); | |
|     } while (dd->reordered == 1); | |
|     return(res); | |
| 
 | |
| } /* end of Cudd_zddDivideF */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes a complement cover for a ZDD node.] | |
|  | |
|   Description [Computes a complement cover for a ZDD node. For lack of a | |
|   better method, we first extract the function BDD from the ZDD cover, | |
|   then make the complement of the ZDD cover from the complement of the | |
|   BDD node by using ISOP. Returns a pointer to the resulting cover if | |
|   successful; NULL otherwise. The result depends on current variable | |
|   order.] | |
|  | |
|   SideEffects [The result depends on current variable order.] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| Cudd_zddComplement( | |
|   DdManager *dd, | |
|   DdNode *node) | |
| { | |
|     DdNode	*b, *isop, *zdd_I; | |
| 
 | |
|     /* Check cache */ | |
|     zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); | |
|     if (zdd_I) | |
| 	return(zdd_I); | |
| 
 | |
|     b = Cudd_MakeBddFromZddCover(dd, node); | |
|     if (!b) | |
| 	return(NULL); | |
|     Cudd_Ref(b); | |
|     isop = Cudd_zddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); | |
|     if (!isop) { | |
| 	Cudd_RecursiveDeref(dd, b); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(isop); | |
|     Cudd_Ref(zdd_I); | |
|     Cudd_RecursiveDeref(dd, b); | |
|     Cudd_RecursiveDeref(dd, isop); | |
| 
 | |
|     cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); | |
|     Cudd_Deref(zdd_I); | |
|     return(zdd_I); | |
| } /* end of Cudd_zddComplement */ | |
| 
 | |
| 
 | |
| /*---------------------------------------------------------------------------*/ | |
| /* Definition of internal functions                                          */ | |
| /*---------------------------------------------------------------------------*/ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis [Performs the recursive step of Cudd_zddProduct.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddProduct] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddProduct( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v, top_f, top_g; | |
|     DdNode	*tmp, *term1, *term2, *term3; | |
|     DdNode	*f0, *f1, *fd, *g0, *g1, *gd; | |
|     DdNode	*R0, *R1, *Rd, *N0, *N1; | |
|     DdNode	*r; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     int		flag; | |
|     int		pv, nv; | |
| 
 | |
|     statLine(dd); | |
|     if (f == zero || g == zero) | |
|         return(zero); | |
|     if (f == one) | |
|         return(g); | |
|     if (g == one) | |
|         return(f); | |
| 
 | |
|     top_f = dd->permZ[f->index]; | |
|     top_g = dd->permZ[g->index]; | |
| 
 | |
|     if (top_f > top_g) | |
| 	return(cuddZddProduct(dd, g, f)); | |
| 
 | |
|     /* Check cache */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddProduct, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     v = f->index;	/* either yi or zi */ | |
|     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     Cudd_Ref(fd); | |
|     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
|     Cudd_Ref(gd); | |
|     pv = cuddZddGetPosVarIndex(dd, v); | |
|     nv = cuddZddGetNegVarIndex(dd, v); | |
| 
 | |
|     Rd = cuddZddProduct(dd, fd, gd); | |
|     if (Rd == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(Rd); | |
| 
 | |
|     term1 = cuddZddProduct(dd, f0, g0); | |
|     if (term1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term1); | |
|     term2 = cuddZddProduct(dd, f0, gd); | |
|     if (term2 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term2); | |
|     term3 = cuddZddProduct(dd, fd, g0); | |
|     if (term3 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term3); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
|     tmp = cuddZddUnion(dd, term1, term2); | |
|     if (tmp == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(tmp); | |
|     Cudd_RecursiveDerefZdd(dd, term1); | |
|     Cudd_RecursiveDerefZdd(dd, term2); | |
|     R0 = cuddZddUnion(dd, tmp, term3); | |
|     if (R0 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(R0); | |
|     Cudd_RecursiveDerefZdd(dd, tmp); | |
|     Cudd_RecursiveDerefZdd(dd, term3); | |
|     N0 = cuddZddGetNode(dd, nv, R0, Rd); /* nv = zi */ | |
|     if (N0 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, Rd); | |
| 	Cudd_RecursiveDerefZdd(dd, R0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(N0); | |
|     Cudd_RecursiveDerefZdd(dd, R0); | |
|     Cudd_RecursiveDerefZdd(dd, Rd); | |
| 
 | |
|     term1 = cuddZddProduct(dd, f1, g1); | |
|     if (term1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term1); | |
|     term2 = cuddZddProduct(dd, f1, gd); | |
|     if (term2 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term2); | |
|     term3 = cuddZddProduct(dd, fd, g1); | |
|     if (term3 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term3); | |
|     Cudd_RecursiveDerefZdd(dd, f1); | |
|     Cudd_RecursiveDerefZdd(dd, g1); | |
|     Cudd_RecursiveDerefZdd(dd, fd); | |
|     Cudd_RecursiveDerefZdd(dd, gd); | |
|     tmp = cuddZddUnion(dd, term1, term2); | |
|     if (tmp == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(tmp); | |
|     Cudd_RecursiveDerefZdd(dd, term1); | |
|     Cudd_RecursiveDerefZdd(dd, term2); | |
|     R1 = cuddZddUnion(dd, tmp, term3); | |
|     if (R1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(R1); | |
|     Cudd_RecursiveDerefZdd(dd, tmp); | |
|     Cudd_RecursiveDerefZdd(dd, term3); | |
|     N1 = cuddZddGetNode(dd, pv, R1, N0); /* pv = yi */ | |
|     if (N1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, N0); | |
| 	Cudd_RecursiveDerefZdd(dd, R1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(N1); | |
|     Cudd_RecursiveDerefZdd(dd, R1); | |
|     Cudd_RecursiveDerefZdd(dd, N0); | |
| 
 | |
|     cuddCacheInsert2(dd, cuddZddProduct, f, g, N1); | |
|     Cudd_Deref(N1); | |
|     return(N1); | |
| 
 | |
| } /* end of cuddZddProduct */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_zddUnateProduct.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddUnateProduct] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddUnateProduct( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v, top_f, top_g; | |
|     DdNode	*term1, *term2, *term3, *term4; | |
|     DdNode	*sum1, *sum2; | |
|     DdNode	*f0, *f1, *g0, *g1; | |
|     DdNode	*r; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     int		flag; | |
| 
 | |
|     statLine(dd); | |
|     if (f == zero || g == zero) | |
|         return(zero); | |
|     if (f == one) | |
|         return(g); | |
|     if (g == one) | |
|         return(f); | |
| 
 | |
|     top_f = dd->permZ[f->index]; | |
|     top_g = dd->permZ[g->index]; | |
| 
 | |
|     if (top_f > top_g) | |
| 	return(cuddZddUnateProduct(dd, g, f)); | |
| 
 | |
|     /* Check cache */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddUnateProduct, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     v = f->index;	/* either yi or zi */ | |
|     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0); | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
| 
 | |
|     term1 = cuddZddUnateProduct(dd, f1, g1); | |
|     if (term1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term1); | |
|     term2 = cuddZddUnateProduct(dd, f1, g0); | |
|     if (term2 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term2); | |
|     term3 = cuddZddUnateProduct(dd, f0, g1); | |
|     if (term3 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term3); | |
|     term4 = cuddZddUnateProduct(dd, f0, g0); | |
|     if (term4 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(term4); | |
|     Cudd_RecursiveDerefZdd(dd, f1); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g1); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
|     sum1 = cuddZddUnion(dd, term1, term2); | |
|     if (sum1 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, term2); | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	Cudd_RecursiveDerefZdd(dd, term4); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(sum1); | |
|     Cudd_RecursiveDerefZdd(dd, term1); | |
|     Cudd_RecursiveDerefZdd(dd, term2); | |
|     sum2 = cuddZddUnion(dd, sum1, term3); | |
|     if (sum2 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, term3); | |
| 	Cudd_RecursiveDerefZdd(dd, term4); | |
| 	Cudd_RecursiveDerefZdd(dd, sum1); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(sum2); | |
|     Cudd_RecursiveDerefZdd(dd, sum1); | |
|     Cudd_RecursiveDerefZdd(dd, term3); | |
|     r = cuddZddGetNode(dd, v, sum2, term4); | |
|     if (r == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, term4); | |
| 	Cudd_RecursiveDerefZdd(dd, sum2); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(r); | |
|     Cudd_RecursiveDerefZdd(dd, sum2); | |
|     Cudd_RecursiveDerefZdd(dd, term4); | |
| 
 | |
|     cuddCacheInsert2(dd, cuddZddUnateProduct, f, g, r); | |
|     Cudd_Deref(r); | |
|     return(r); | |
| 
 | |
| } /* end of cuddZddUnateProduct */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_zddWeakDiv.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddWeakDiv] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddWeakDiv( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     DdNode	*f0, *f1, *fd, *g0, *g1, *gd; | |
|     DdNode	*q, *tmp; | |
|     DdNode	*r; | |
|     int		flag; | |
| 
 | |
|     statLine(dd); | |
|     if (g == one) | |
| 	return(f); | |
|     if (f == zero || f == one) | |
| 	return(zero); | |
|     if (f == g) | |
| 	return(one); | |
| 
 | |
|     /* Check cache. */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddWeakDiv, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     v = g->index; | |
| 
 | |
|     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     Cudd_Ref(fd); | |
|     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
|     Cudd_Ref(gd); | |
| 
 | |
|     q = g; | |
| 
 | |
|     if (g0 != zero) { | |
| 	q = cuddZddWeakDiv(dd, f0, g0); | |
| 	if (q == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(q); | |
|     } | |
|     else | |
| 	Cudd_Ref(q); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
| 
 | |
|     if (q == zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); | |
| 	Cudd_Deref(q); | |
| 	return(zero); | |
|     } | |
| 
 | |
|     if (g1 != zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	tmp = cuddZddWeakDiv(dd, f1, g1); | |
| 	if (tmp == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(tmp); | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	if (q == g) | |
| 	    q = tmp; | |
| 	else { | |
| 	    q = cuddZddIntersect(dd, q, tmp); | |
| 	    if (q == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, fd); | |
| 		Cudd_RecursiveDerefZdd(dd, gd); | |
| 		return(NULL); | |
| 	    } | |
| 	    Cudd_Ref(q); | |
| 	    Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	} | |
|     } | |
|     else { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
|     } | |
| 
 | |
|     if (q == zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, zero); | |
| 	Cudd_Deref(q); | |
| 	return(zero); | |
|     } | |
| 
 | |
|     if (gd != zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	tmp = cuddZddWeakDiv(dd, fd, gd); | |
| 	if (tmp == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(tmp); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	if (q == g) | |
| 	    q = tmp; | |
| 	else { | |
| 	    q = cuddZddIntersect(dd, q, tmp); | |
| 	    if (q == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, tmp); | |
| 		return(NULL); | |
| 	    } | |
| 	    Cudd_Ref(q); | |
| 	    Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	} | |
|     } | |
|     else { | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
|     } | |
| 
 | |
|     cuddCacheInsert2(dd, cuddZddWeakDiv, f, g, q); | |
|     Cudd_Deref(q); | |
|     return(q); | |
| 
 | |
| } /* end of cuddZddWeakDiv */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_zddWeakDivF.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddWeakDivF] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddWeakDivF( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v, top_f, top_g, vf, vg; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     DdNode	*f0, *f1, *fd, *g0, *g1, *gd; | |
|     DdNode	*q, *tmp; | |
|     DdNode	*r; | |
|     DdNode	*term1, *term0, *termd; | |
|     int		flag; | |
|     int		pv, nv; | |
| 
 | |
|     statLine(dd); | |
|     if (g == one) | |
| 	return(f); | |
|     if (f == zero || f == one) | |
| 	return(zero); | |
|     if (f == g) | |
| 	return(one); | |
| 
 | |
|     /* Check cache. */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddWeakDivF, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     top_f = dd->permZ[f->index]; | |
|     top_g = dd->permZ[g->index]; | |
|     vf = top_f >> 1; | |
|     vg = top_g >> 1; | |
|     v = ddMin(top_f, top_g); | |
| 
 | |
|     if (v == top_f && vf < vg) { | |
| 	v = f->index; | |
| 	flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); | |
| 	if (flag == 1) | |
| 	    return(NULL); | |
| 	Cudd_Ref(f1); | |
| 	Cudd_Ref(f0); | |
| 	Cudd_Ref(fd); | |
| 
 | |
| 	pv = cuddZddGetPosVarIndex(dd, v); | |
| 	nv = cuddZddGetNegVarIndex(dd, v); | |
| 
 | |
| 	term1 = cuddZddWeakDivF(dd, f1, g); | |
| 	if (term1 == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(term1); | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	term0 = cuddZddWeakDivF(dd, f0, g); | |
| 	if (term0 == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, term1); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(term0); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	termd = cuddZddWeakDivF(dd, fd, g); | |
| 	if (termd == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, term1); | |
| 	    Cudd_RecursiveDerefZdd(dd, term0); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(termd); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 
 | |
| 	tmp = cuddZddGetNode(dd, nv, term0, termd); /* nv = zi */ | |
| 	if (tmp == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, term1); | |
| 	    Cudd_RecursiveDerefZdd(dd, term0); | |
| 	    Cudd_RecursiveDerefZdd(dd, termd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(tmp); | |
| 	Cudd_RecursiveDerefZdd(dd, term0); | |
| 	Cudd_RecursiveDerefZdd(dd, termd); | |
| 	q = cuddZddGetNode(dd, pv, term1, tmp); /* pv = yi */ | |
| 	if (q == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, term1); | |
| 	    Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(q); | |
| 	Cudd_RecursiveDerefZdd(dd, term1); | |
| 	Cudd_RecursiveDerefZdd(dd, tmp); | |
| 
 | |
| 	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); | |
| 	Cudd_Deref(q); | |
| 	return(q); | |
|     } | |
| 
 | |
|     if (v == top_f) | |
| 	v = f->index; | |
|     else | |
| 	v = g->index; | |
| 
 | |
|     flag = cuddZddGetCofactors3(dd, f, v, &f1, &f0, &fd); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     Cudd_Ref(fd); | |
|     flag = cuddZddGetCofactors3(dd, g, v, &g1, &g0, &gd); | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
|     Cudd_Ref(gd); | |
| 
 | |
|     q = g; | |
| 
 | |
|     if (g0 != zero) { | |
| 	q = cuddZddWeakDivF(dd, f0, g0); | |
| 	if (q == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(q); | |
|     } | |
|     else | |
| 	Cudd_Ref(q); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
| 
 | |
|     if (q == zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); | |
| 	Cudd_Deref(q); | |
| 	return(zero); | |
|     } | |
| 
 | |
|     if (g1 != zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	tmp = cuddZddWeakDivF(dd, f1, g1); | |
| 	if (tmp == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(tmp); | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	if (q == g) | |
| 	    q = tmp; | |
| 	else { | |
| 	    q = cuddZddIntersect(dd, q, tmp); | |
| 	    if (q == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, fd); | |
| 		Cudd_RecursiveDerefZdd(dd, gd); | |
| 		return(NULL); | |
| 	    } | |
| 	    Cudd_Ref(q); | |
| 	    Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	} | |
|     } | |
|     else { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
|     } | |
| 
 | |
|     if (q == zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, zero); | |
| 	Cudd_Deref(q); | |
| 	return(zero); | |
|     } | |
| 
 | |
|     if (gd != zero) { | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	tmp = cuddZddWeakDivF(dd, fd, gd); | |
| 	if (tmp == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, fd); | |
| 	    Cudd_RecursiveDerefZdd(dd, gd); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(tmp); | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
| 	if (q == g) | |
| 	    q = tmp; | |
| 	else { | |
| 	    q = cuddZddIntersect(dd, q, tmp); | |
| 	    if (q == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, tmp); | |
| 		return(NULL); | |
| 	    } | |
| 	    Cudd_Ref(q); | |
| 	    Cudd_RecursiveDerefZdd(dd, tmp); | |
| 	} | |
|     } | |
|     else { | |
| 	Cudd_RecursiveDerefZdd(dd, fd); | |
| 	Cudd_RecursiveDerefZdd(dd, gd); | |
|     } | |
| 
 | |
|     cuddCacheInsert2(dd, cuddZddWeakDivF, f, g, q); | |
|     Cudd_Deref(q); | |
|     return(q); | |
| 
 | |
| } /* end of cuddZddWeakDivF */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_zddDivide.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddDivide] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddDivide( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     DdNode	*f0, *f1, *g0, *g1; | |
|     DdNode	*q, *r, *tmp; | |
|     int		flag; | |
| 
 | |
|     statLine(dd); | |
|     if (g == one) | |
| 	return(f); | |
|     if (f == zero || f == one) | |
| 	return(zero); | |
|     if (f == g) | |
| 	return(one); | |
| 
 | |
|     /* Check cache. */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddDivide, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     v = g->index; | |
| 
 | |
|     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);	/* g1 != zero */ | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
| 
 | |
|     r = cuddZddDivide(dd, f1, g1); | |
|     if (r == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(r); | |
| 
 | |
|     if (r != zero && g0 != zero) { | |
| 	tmp = r; | |
| 	q = cuddZddDivide(dd, f0, g0); | |
| 	if (q == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(q); | |
| 	r = cuddZddIntersect(dd, r, q); | |
| 	if (r == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    Cudd_RecursiveDerefZdd(dd, q); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(r); | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	Cudd_RecursiveDerefZdd(dd, tmp); | |
|     } | |
| 
 | |
|     Cudd_RecursiveDerefZdd(dd, f1); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g1); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
|      | |
|     cuddCacheInsert2(dd, cuddZddDivide, f, g, r); | |
|     Cudd_Deref(r); | |
|     return(r); | |
| 
 | |
| } /* end of cuddZddDivide */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Performs the recursive step of Cudd_zddDivideF.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [None] | |
|  | |
|   SeeAlso     [Cudd_zddDivideF] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddDivideF( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   DdNode * g) | |
| { | |
|     int		v; | |
|     DdNode	*one = DD_ONE(dd); | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     DdNode	*f0, *f1, *g0, *g1; | |
|     DdNode	*q, *r, *tmp; | |
|     int		flag; | |
| 
 | |
|     statLine(dd); | |
|     if (g == one) | |
| 	return(f); | |
|     if (f == zero || f == one) | |
| 	return(zero); | |
|     if (f == g) | |
| 	return(one); | |
| 
 | |
|     /* Check cache. */ | |
|     r = cuddCacheLookup2Zdd(dd, cuddZddDivideF, f, g); | |
|     if (r) | |
| 	return(r); | |
| 
 | |
|     v = g->index; | |
| 
 | |
|     flag = cuddZddGetCofactors2(dd, f, v, &f1, &f0); | |
|     if (flag == 1) | |
| 	return(NULL); | |
|     Cudd_Ref(f1); | |
|     Cudd_Ref(f0); | |
|     flag = cuddZddGetCofactors2(dd, g, v, &g1, &g0);	/* g1 != zero */ | |
|     if (flag == 1) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(g1); | |
|     Cudd_Ref(g0); | |
| 
 | |
|     r = cuddZddDivideF(dd, f1, g1); | |
|     if (r == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, f1); | |
| 	Cudd_RecursiveDerefZdd(dd, f0); | |
| 	Cudd_RecursiveDerefZdd(dd, g1); | |
| 	Cudd_RecursiveDerefZdd(dd, g0); | |
| 	return(NULL); | |
|     } | |
|     Cudd_Ref(r); | |
| 
 | |
|     if (r != zero && g0 != zero) { | |
| 	tmp = r; | |
| 	q = cuddZddDivideF(dd, f0, g0); | |
| 	if (q == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(q); | |
| 	r = cuddZddIntersect(dd, r, q); | |
| 	if (r == NULL) { | |
| 	    Cudd_RecursiveDerefZdd(dd, f1); | |
| 	    Cudd_RecursiveDerefZdd(dd, f0); | |
| 	    Cudd_RecursiveDerefZdd(dd, g1); | |
| 	    Cudd_RecursiveDerefZdd(dd, g0); | |
| 	    Cudd_RecursiveDerefZdd(dd, q); | |
| 	    return(NULL); | |
| 	} | |
| 	Cudd_Ref(r); | |
| 	Cudd_RecursiveDerefZdd(dd, q); | |
| 	Cudd_RecursiveDerefZdd(dd, tmp); | |
|     } | |
| 
 | |
|     Cudd_RecursiveDerefZdd(dd, f1); | |
|     Cudd_RecursiveDerefZdd(dd, f0); | |
|     Cudd_RecursiveDerefZdd(dd, g1); | |
|     Cudd_RecursiveDerefZdd(dd, g0); | |
|      | |
|     cuddCacheInsert2(dd, cuddZddDivideF, f, g, r); | |
|     Cudd_Deref(r); | |
|     return(r); | |
| 
 | |
| } /* end of cuddZddDivideF */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the three-way decomposition of f w.r.t. v.] | |
|  | |
|   Description [Computes the three-way decomposition of function f (represented | |
|   by a ZDD) wit respect to variable v.  Returns 0 if successful; 1 otherwise.] | |
|  | |
|   SideEffects [The results are returned in f1, f0, and fd.] | |
|  | |
|   SeeAlso     [cuddZddGetCofactors2] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetCofactors3( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   int  v, | |
|   DdNode ** f1, | |
|   DdNode ** f0, | |
|   DdNode ** fd) | |
| { | |
|     DdNode	*pc, *nc; | |
|     DdNode	*zero = DD_ZERO(dd); | |
|     int		top, hv, ht, pv, nv; | |
|     int		level; | |
| 
 | |
|     top = dd->permZ[f->index]; | |
|     level = dd->permZ[v]; | |
|     hv = level >> 1; | |
|     ht = top >> 1; | |
| 
 | |
|     if (hv < ht) { | |
| 	*f1 = zero; | |
| 	*f0 = zero; | |
| 	*fd = f; | |
|     } | |
|     else { | |
| 	pv = cuddZddGetPosVarIndex(dd, v); | |
| 	nv = cuddZddGetNegVarIndex(dd, v); | |
| 
 | |
| 	/* not to create intermediate ZDD node */ | |
| 	if (cuddZddGetPosVarLevel(dd, v) < cuddZddGetNegVarLevel(dd, v)) { | |
| 	    pc = cuddZddSubset1(dd, f, pv); | |
| 	    if (pc == NULL) | |
| 		return(1); | |
| 	    Cudd_Ref(pc); | |
| 	    nc = cuddZddSubset0(dd, f, pv); | |
| 	    if (nc == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(nc); | |
| 
 | |
| 	    *f1 = cuddZddSubset0(dd, pc, nv); | |
| 	    if (*f1 == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*f1); | |
| 	    *f0 = cuddZddSubset1(dd, nc, nv); | |
| 	    if (*f0 == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		Cudd_RecursiveDerefZdd(dd, *f1); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*f0); | |
| 
 | |
| 	    *fd = cuddZddSubset0(dd, nc, nv); | |
| 	    if (*fd == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		Cudd_RecursiveDerefZdd(dd, *f1); | |
| 		Cudd_RecursiveDerefZdd(dd, *f0); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*fd); | |
| 	} else { | |
| 	    pc = cuddZddSubset1(dd, f, nv); | |
| 	    if (pc == NULL) | |
| 		return(1); | |
| 	    Cudd_Ref(pc); | |
| 	    nc = cuddZddSubset0(dd, f, nv); | |
| 	    if (nc == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(nc); | |
| 
 | |
| 	    *f0 = cuddZddSubset0(dd, pc, pv); | |
| 	    if (*f0 == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*f0); | |
| 	    *f1 = cuddZddSubset1(dd, nc, pv); | |
| 	    if (*f1 == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		Cudd_RecursiveDerefZdd(dd, *f0); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*f1); | |
| 
 | |
| 	    *fd = cuddZddSubset0(dd, nc, pv); | |
| 	    if (*fd == NULL) { | |
| 		Cudd_RecursiveDerefZdd(dd, pc); | |
| 		Cudd_RecursiveDerefZdd(dd, nc); | |
| 		Cudd_RecursiveDerefZdd(dd, *f1); | |
| 		Cudd_RecursiveDerefZdd(dd, *f0); | |
| 		return(1); | |
| 	    } | |
| 	    Cudd_Ref(*fd); | |
| 	} | |
| 
 | |
| 	Cudd_RecursiveDerefZdd(dd, pc); | |
| 	Cudd_RecursiveDerefZdd(dd, nc); | |
| 	Cudd_Deref(*f1); | |
| 	Cudd_Deref(*f0); | |
| 	Cudd_Deref(*fd); | |
|     } | |
|     return(0); | |
| 
 | |
| } /* end of cuddZddGetCofactors3 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes the two-way decomposition of f w.r.t. v.] | |
|  | |
|   Description [] | |
|  | |
|   SideEffects [The results are returned in f1 and f0.] | |
|  | |
|   SeeAlso     [cuddZddGetCofactors3] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetCofactors2( | |
|   DdManager * dd, | |
|   DdNode * f, | |
|   int  v, | |
|   DdNode ** f1, | |
|   DdNode ** f0) | |
| { | |
|     *f1 = cuddZddSubset1(dd, f, v); | |
|     if (*f1 == NULL) | |
| 	return(1); | |
|     *f0 = cuddZddSubset0(dd, f, v); | |
|     if (*f0 == NULL) { | |
| 	Cudd_RecursiveDerefZdd(dd, *f1); | |
| 	return(1); | |
|     } | |
|     return(0); | |
| 
 | |
| } /* end of cuddZddGetCofactors2 */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Computes a complement of a ZDD node.] | |
|  | |
|   Description [Computes the complement of a ZDD node. So far, since we | |
|   couldn't find a direct way to get the complement of a ZDD cover, we first | |
|   convert a ZDD cover to a BDD, then make the complement of the ZDD cover | |
|   from the complement of the BDD node by using ISOP.] | |
|  | |
|   SideEffects [The result depends on current variable order.] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| DdNode	* | |
| cuddZddComplement( | |
|   DdManager * dd, | |
|   DdNode *node) | |
| { | |
|     DdNode	*b, *isop, *zdd_I; | |
| 
 | |
|     /* Check cache */ | |
|     zdd_I = cuddCacheLookup1Zdd(dd, cuddZddComplement, node); | |
|     if (zdd_I) | |
| 	return(zdd_I); | |
| 
 | |
|     b = cuddMakeBddFromZddCover(dd, node); | |
|     if (!b) | |
| 	return(NULL); | |
|     cuddRef(b); | |
|     isop = cuddZddIsop(dd, Cudd_Not(b), Cudd_Not(b), &zdd_I); | |
|     if (!isop) { | |
| 	Cudd_RecursiveDeref(dd, b); | |
| 	return(NULL); | |
|     } | |
|     cuddRef(isop); | |
|     cuddRef(zdd_I); | |
|     Cudd_RecursiveDeref(dd, b); | |
|     Cudd_RecursiveDeref(dd, isop); | |
| 
 | |
|     cuddCacheInsert1(dd, cuddZddComplement, node, zdd_I); | |
|     cuddDeref(zdd_I); | |
|     return(zdd_I); | |
| } /* end of cuddZddComplement */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Returns the index of positive ZDD variable.] | |
|  | |
|   Description [Returns the index of positive ZDD variable.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetPosVarIndex( | |
|   DdManager * dd, | |
|   int index) | |
| { | |
|     int	pv = (index >> 1) << 1; | |
|     return(pv); | |
| } /* end of cuddZddGetPosVarIndex */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Returns the index of negative ZDD variable.] | |
|  | |
|   Description [Returns the index of negative ZDD variable.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetNegVarIndex( | |
|   DdManager * dd, | |
|   int index) | |
| { | |
|     int	nv = index | 0x1; | |
|     return(nv); | |
| } /* end of cuddZddGetPosVarIndex */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Returns the level of positive ZDD variable.] | |
|  | |
|   Description [Returns the level of positive ZDD variable.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetPosVarLevel( | |
|   DdManager * dd, | |
|   int index) | |
| { | |
|     int	pv = cuddZddGetPosVarIndex(dd, index); | |
|     return(dd->permZ[pv]); | |
| } /* end of cuddZddGetPosVarLevel */ | |
| 
 | |
| 
 | |
| /**Function******************************************************************** | |
|  | |
|   Synopsis    [Returns the level of negative ZDD variable.] | |
|  | |
|   Description [Returns the level of negative ZDD variable.] | |
|  | |
|   SideEffects [] | |
|  | |
|   SeeAlso     [] | |
|  | |
| ******************************************************************************/ | |
| int | |
| cuddZddGetNegVarLevel( | |
|   DdManager * dd, | |
|   int index) | |
| { | |
|     int	nv = cuddZddGetNegVarIndex(dd, index); | |
|     return(dd->permZ[nv]); | |
| } /* end of cuddZddGetNegVarLevel */
 |