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.
		
		
		
		
		
			
		
			
				
					
					
						
							1121 lines
						
					
					
						
							27 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							1121 lines
						
					
					
						
							27 KiB
						
					
					
				
								/**CFile***********************************************************************
							 | 
						|
								
							 | 
						|
								  FileName    [cuddAddApply.c]
							 | 
						|
								
							 | 
						|
								  PackageName [cudd]
							 | 
						|
								
							 | 
						|
								  Synopsis    [Apply functions for ADDs and their operators.]
							 | 
						|
								
							 | 
						|
								  Description [External procedures included in this module:
							 | 
						|
										<ul>
							 | 
						|
										<li> Cudd_addApply()
							 | 
						|
										<li> Cudd_addMonadicApply()
							 | 
						|
										<li> Cudd_addPlus()
							 | 
						|
										<li> Cudd_addTimes()
							 | 
						|
										<li> Cudd_addThreshold()
							 | 
						|
										<li> Cudd_addSetNZ()
							 | 
						|
										<li> Cudd_addDivide()
							 | 
						|
										<li> Cudd_addMinus()
							 | 
						|
										<li> Cudd_addMinimum()
							 | 
						|
										<li> Cudd_addMaximum()
							 | 
						|
										<li> Cudd_addOneZeroMaximum()
							 | 
						|
										<li> Cudd_addDiff()
							 | 
						|
										<li> Cudd_addAgreement()
							 | 
						|
										<li> Cudd_addOr()
							 | 
						|
										<li> Cudd_addNand()
							 | 
						|
										<li> Cudd_addNor()
							 | 
						|
										<li> Cudd_addXor()
							 | 
						|
										<li> Cudd_addXnor()
							 | 
						|
										</ul>
							 | 
						|
									    Internal procedures included in this module:
							 | 
						|
										<ul>
							 | 
						|
										<li> cuddAddApplyRecur()
							 | 
						|
										<li> cuddAddMonadicApplyRecur()
							 | 
						|
										</ul>]
							 | 
						|
								
							 | 
						|
								  Author      [Fabio Somenzi]
							 | 
						|
								
							 | 
						|
								  Copyright   [Copyright (c) 1995-2012, Regents of the University of Colorado
							 | 
						|
								
							 | 
						|
								  All rights reserved.
							 | 
						|
								
							 | 
						|
								  Redistribution and use in source and binary forms, with or without
							 | 
						|
								  modification, are permitted provided that the following conditions
							 | 
						|
								  are met:
							 | 
						|
								
							 | 
						|
								  Redistributions of source code must retain the above copyright
							 | 
						|
								  notice, this list of conditions and the following disclaimer.
							 | 
						|
								
							 | 
						|
								  Redistributions in binary form must reproduce the above copyright
							 | 
						|
								  notice, this list of conditions and the following disclaimer in the
							 | 
						|
								  documentation and/or other materials provided with the distribution.
							 | 
						|
								
							 | 
						|
								  Neither the name of the University of Colorado nor the names of its
							 | 
						|
								  contributors may be used to endorse or promote products derived from
							 | 
						|
								  this software without specific prior written permission.
							 | 
						|
								
							 | 
						|
								  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
							 | 
						|
								  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
							 | 
						|
								  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
							 | 
						|
								  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
							 | 
						|
								  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
							 | 
						|
								  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
							 | 
						|
								  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
							 | 
						|
								  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
							 | 
						|
								  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
							 | 
						|
								  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
							 | 
						|
								  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
							 | 
						|
								  POSSIBILITY OF SUCH DAMAGE.]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								
							 | 
						|
								#include "util.h"
							 | 
						|
								#include "cuddInt.h"
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Constant declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Stucture declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Type declarations                                                         */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Variable declarations                                                     */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								#ifndef lint
							 | 
						|
								static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.19 2012/02/05 01:07:18 fabio Exp $";
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Macro declarations                                                        */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**AutomaticStart*************************************************************/
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Static function prototypes                                                */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**AutomaticEnd***************************************************************/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of exported functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Applies op to the corresponding discriminants of f and g.]
							 | 
						|
								
							 | 
						|
								  Description [Applies op to the corresponding discriminants of f and g.
							 | 
						|
								  Returns a pointer to the result if succssful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
							 | 
						|
								  Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
							 | 
						|
								  Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
							 | 
						|
								  Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addApply(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DD_AOP op,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddApplyRecur(dd,op,f,g);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addApply */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point addition.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point addition. Returns NULL if not
							 | 
						|
								  a terminal case; f+g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addPlus(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								    CUDD_VALUE_TYPE value;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_ZERO(dd)) return(G);
							 | 
						|
								    if (G == DD_ZERO(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									value = cuddV(F)+cuddV(G);
							 | 
						|
									res = cuddUniqueConst(dd,value);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addPlus */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point multiplication.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point multiplication. Returns NULL
							 | 
						|
								  if not a terminal case; f * g otherwise.  This function can be used also
							 | 
						|
								  to take the AND of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addTimes(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								    CUDD_VALUE_TYPE value;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
							 | 
						|
								    if (F == DD_ONE(dd)) return(G);
							 | 
						|
								    if (G == DD_ONE(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									value = cuddV(F)*cuddV(G);
							 | 
						|
									res = cuddUniqueConst(dd,value);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addTimes */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [f if f>=g; 0 if f<g.]
							 | 
						|
								
							 | 
						|
								  Description [Threshold operator for Apply (f if f >=g; 0 if f<g).
							 | 
						|
								  Returns NULL if not a terminal case; f op g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addThreshold(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									if (cuddV(F) >= cuddV(G)) {
							 | 
						|
									    return(F);
							 | 
						|
									} else {
							 | 
						|
									    return(DD_ZERO(dd));
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addThreshold */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [This operator sets f to the value of g wherever g != 0.]
							 | 
						|
								
							 | 
						|
								  Description [This operator sets f to the value of g wherever g != 0.
							 | 
						|
								  Returns NULL if not a terminal case; f op g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addSetNZ(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(F);
							 | 
						|
								    if (F == DD_ZERO(dd)) return(G);
							 | 
						|
								    if (G == DD_ZERO(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(G)) return(G);
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addSetNZ */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point division.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point division. Returns NULL if not
							 | 
						|
								  a terminal case; f / g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addDivide(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								    CUDD_VALUE_TYPE value;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    /* We would like to use F == G -> F/G == 1, but F and G may
							 | 
						|
								    ** contain zeroes. */
							 | 
						|
								    if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
							 | 
						|
								    if (G == DD_ONE(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									value = cuddV(F)/cuddV(G);
							 | 
						|
									res = cuddUniqueConst(dd,value);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addDivide */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point subtraction.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point subtraction. Returns NULL if
							 | 
						|
								  not a terminal case; f - g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addMinus(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								    CUDD_VALUE_TYPE value;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ZERO(dd));
							 | 
						|
								    if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
							 | 
						|
								    if (G == DD_ZERO(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									value = cuddV(F)-cuddV(G);
							 | 
						|
									res = cuddUniqueConst(dd,value);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addMinus */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point min.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point min for Cudd_addApply.
							 | 
						|
								  Returns NULL if not a terminal case; min(f,g) otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addMinimum(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_PLUS_INFINITY(dd)) return(G);
							 | 
						|
								    if (G == DD_PLUS_INFINITY(dd)) return(F);
							 | 
						|
								    if (F == G) return(F);
							 | 
						|
								#if 0
							 | 
						|
								    /* These special cases probably do not pay off. */
							 | 
						|
								    if (F == DD_MINUS_INFINITY(dd)) return(F);
							 | 
						|
								    if (G == DD_MINUS_INFINITY(dd)) return(G);
							 | 
						|
								#endif
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									if (cuddV(F) <= cuddV(G)) {
							 | 
						|
									    return(F);
							 | 
						|
									} else {
							 | 
						|
									    return(G);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addMinimum */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Integer and floating point max.]
							 | 
						|
								
							 | 
						|
								  Description [Integer and floating point max for Cudd_addApply.
							 | 
						|
								  Returns NULL if not a terminal case; max(f,g) otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addMaximum(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(F);
							 | 
						|
								    if (F == DD_MINUS_INFINITY(dd)) return(G);
							 | 
						|
								    if (G == DD_MINUS_INFINITY(dd)) return(F);
							 | 
						|
								#if 0
							 | 
						|
								    /* These special cases probably do not pay off. */
							 | 
						|
								    if (F == DD_PLUS_INFINITY(dd)) return(F);
							 | 
						|
								    if (G == DD_PLUS_INFINITY(dd)) return(G);
							 | 
						|
								#endif
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									if (cuddV(F) >= cuddV(G)) {
							 | 
						|
									    return(F);
							 | 
						|
									} else {
							 | 
						|
									    return(G);
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addMaximum */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Returns 1 if f > g and 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns 1 if f > g and 0 otherwise. Used in
							 | 
						|
								  conjunction with Cudd_addApply. Returns NULL if not a terminal
							 | 
						|
								  case.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addOneZeroMaximum(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								
							 | 
						|
								    if (*f == *g) return(DD_ZERO(dd));
							 | 
						|
								    if (*g == DD_PLUS_INFINITY(dd))
							 | 
						|
									return DD_ZERO(dd);
							 | 
						|
								    if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
							 | 
						|
									if (cuddV(*f) > cuddV(*g)) {
							 | 
						|
									    return(DD_ONE(dd));
							 | 
						|
									} else {
							 | 
						|
									    return(DD_ZERO(dd));
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addOneZeroMaximum */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addDiff(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_PLUS_INFINITY(dd));
							 | 
						|
								    if (F == DD_PLUS_INFINITY(dd)) return(G);
							 | 
						|
								    if (G == DD_PLUS_INFINITY(dd)) return(F);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
									if (cuddV(F) != cuddV(G)) {
							 | 
						|
									    if (cuddV(F) < cuddV(G)) {
							 | 
						|
										return(F);
							 | 
						|
									    } else {
							 | 
						|
										return(G);
							 | 
						|
									    }
							 | 
						|
									} else {
							 | 
						|
									    return(DD_PLUS_INFINITY(dd));
							 | 
						|
									}
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addDiff */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [f if f==g; background if f!=g.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is f if f==g; background if f!=g.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addAgreement(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(F);
							 | 
						|
								    if (F == dd->background) return(F);
							 | 
						|
								    if (G == dd->background) return(G);
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addAgreement */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Disjunction of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [Disjunction of two 0-1 ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; f OR g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addOr(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F)) return(G);
							 | 
						|
								    if (cuddIsConstant(G)) return(F);
							 | 
						|
								    if (F == G) return(F);
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addOr */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [NAND of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [NAND of two 0-1 ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; f NAND g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addNand(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addNand */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [NOR of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [NOR of two 0-1 ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; f NOR g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addNor(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addNor */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [XOR of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [XOR of two 0-1 ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; f XOR g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addXor(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ZERO(dd));
							 | 
						|
								    if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addXor */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [XNOR of two 0-1 ADDs.]
							 | 
						|
								
							 | 
						|
								  Description [XNOR of two 0-1 ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; f XNOR g otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addXnor(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ONE(dd));
							 | 
						|
								    if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addXnor */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Applies op to the discriminants of f.]
							 | 
						|
								
							 | 
						|
								  Description [Applies op to the discriminants of f.
							 | 
						|
								  Returns a pointer to the result if succssful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply Cudd_addLog]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addMonadicApply(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DD_MAOP op,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    DdNode *res;
							 | 
						|
								
							 | 
						|
								    do {
							 | 
						|
									dd->reordered = 0;
							 | 
						|
									res = cuddAddMonadicApplyRecur(dd,op,f);
							 | 
						|
								    } while (dd->reordered == 1);
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addMonadicApply */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Natural logarithm of an ADD.]
							 | 
						|
								
							 | 
						|
								  Description [Natural logarithm of an ADDs. Returns NULL
							 | 
						|
								  if not a terminal case; log(f) otherwise.  The discriminants of f must
							 | 
						|
								  be positive double's.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addMonadicApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addLog(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    if (cuddIsConstant(f)) {
							 | 
						|
									CUDD_VALUE_TYPE value = log(cuddV(f));
							 | 
						|
									DdNode *res = cuddUniqueConst(dd,value);
							 | 
						|
									return(res);
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addLog */
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f==g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f==g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addEquals(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addEquals */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f!=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f!=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addNotEquals(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ZERO(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
							 | 
						|
								    if (F > G) { /* swap f and g */
							 | 
						|
									*f = G;
							 | 
						|
									*g = F;
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addNotEquals */
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f>g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f>g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addGreaterThan(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ZERO(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
										if (cuddV(F)>cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addGreaterThan */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f>=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f>=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addGreaterThanEquals(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
										if (cuddV(F)>=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addGreaterThanEquals */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f<g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f<g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addLessThan(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ZERO(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
										if (cuddV(F)<cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addLessThan */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [1 if f<=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  Description [Returns NULL if not a terminal case; f op g otherwise,
							 | 
						|
								  where f op g is 1 if f<=g; 0 otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [Cudd_addApply]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								Cudd_addLessThanEquals(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DdNode ** f,
							 | 
						|
								  DdNode ** g)
							 | 
						|
								{
							 | 
						|
								    DdNode *F, *G;
							 | 
						|
								
							 | 
						|
								    F = *f; G = *g;
							 | 
						|
								    if (F == G) return(DD_ONE(dd));
							 | 
						|
								    if (cuddIsConstant(F) && cuddIsConstant(G)) {
							 | 
						|
										if (cuddV(F)<=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
							 | 
						|
								    }
							 | 
						|
								    return(NULL);
							 | 
						|
								
							 | 
						|
								} /* end of Cudd_addLessThanEquals */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of internal functions                                          */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_addApply.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_addApply. Returns a
							 | 
						|
								  pointer to the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddAddMonadicApplyRecur]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddAddApplyRecur(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DD_AOP op,
							 | 
						|
								  DdNode * f,
							 | 
						|
								  DdNode * g)
							 | 
						|
								{
							 | 
						|
								    DdNode *res,
							 | 
						|
									   *fv, *fvn, *gv, *gvn,
							 | 
						|
									   *T, *E;
							 | 
						|
								    unsigned int ford, gord;
							 | 
						|
								    unsigned int index;
							 | 
						|
								    DD_CTFP cacheOp;
							 | 
						|
								
							 | 
						|
								    /* Check terminal cases. Op may swap f and g to increase the
							 | 
						|
								     * cache hit rate.
							 | 
						|
								     */
							 | 
						|
								    statLine(dd);
							 | 
						|
								    res = (*op)(dd,&f,&g);
							 | 
						|
								    if (res != NULL) return(res);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    cacheOp = (DD_CTFP) op;
							 | 
						|
								    res = cuddCacheLookup2(dd,cacheOp,f,g);
							 | 
						|
								    if (res != NULL) return(res);
							 | 
						|
								
							 | 
						|
								    /* Recursive step. */
							 | 
						|
								    ford = cuddI(dd,f->index);
							 | 
						|
								    gord = cuddI(dd,g->index);
							 | 
						|
								    if (ford <= gord) {
							 | 
						|
									index = f->index;
							 | 
						|
									fv = cuddT(f);
							 | 
						|
									fvn = cuddE(f);
							 | 
						|
								    } else {
							 | 
						|
									index = g->index;
							 | 
						|
									fv = fvn = f;
							 | 
						|
								    }
							 | 
						|
								    if (gord <= ford) {
							 | 
						|
									gv = cuddT(g);
							 | 
						|
									gvn = cuddE(g);
							 | 
						|
								    } else {
							 | 
						|
									gv = gvn = g;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    T = cuddAddApplyRecur(dd,op,fv,gv);
							 | 
						|
								    if (T == NULL) return(NULL);
							 | 
						|
								    cuddRef(T);
							 | 
						|
								
							 | 
						|
								    E = cuddAddApplyRecur(dd,op,fvn,gvn);
							 | 
						|
								    if (E == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,T);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(E);
							 | 
						|
								
							 | 
						|
								    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, T);
							 | 
						|
									Cudd_RecursiveDeref(dd, E);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(T);
							 | 
						|
								    cuddDeref(E);
							 | 
						|
								
							 | 
						|
								    /* Store result. */
							 | 
						|
								    cuddCacheInsert2(dd,cacheOp,f,g,res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddAddApplyRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/**Function********************************************************************
							 | 
						|
								
							 | 
						|
								  Synopsis    [Performs the recursive step of Cudd_addMonadicApply.]
							 | 
						|
								
							 | 
						|
								  Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
							 | 
						|
								  pointer to the result if successful; NULL otherwise.]
							 | 
						|
								
							 | 
						|
								  SideEffects [None]
							 | 
						|
								
							 | 
						|
								  SeeAlso     [cuddAddApplyRecur]
							 | 
						|
								
							 | 
						|
								******************************************************************************/
							 | 
						|
								DdNode *
							 | 
						|
								cuddAddMonadicApplyRecur(
							 | 
						|
								  DdManager * dd,
							 | 
						|
								  DD_MAOP op,
							 | 
						|
								  DdNode * f)
							 | 
						|
								{
							 | 
						|
								    DdNode *res, *ft, *fe, *T, *E;
							 | 
						|
								    unsigned int index;
							 | 
						|
								
							 | 
						|
								    /* Check terminal cases. */
							 | 
						|
								    statLine(dd);
							 | 
						|
								    res = (*op)(dd,f);
							 | 
						|
								    if (res != NULL) return(res);
							 | 
						|
								
							 | 
						|
								    /* Check cache. */
							 | 
						|
								    res = cuddCacheLookup1(dd,op,f);
							 | 
						|
								    if (res != NULL) return(res);
							 | 
						|
								
							 | 
						|
								    /* Recursive step. */
							 | 
						|
								    index = f->index;
							 | 
						|
								    ft = cuddT(f);
							 | 
						|
								    fe = cuddE(f);
							 | 
						|
								
							 | 
						|
								    T = cuddAddMonadicApplyRecur(dd,op,ft);
							 | 
						|
								    if (T == NULL) return(NULL);
							 | 
						|
								    cuddRef(T);
							 | 
						|
								
							 | 
						|
								    E = cuddAddMonadicApplyRecur(dd,op,fe);
							 | 
						|
								    if (E == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd,T);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddRef(E);
							 | 
						|
								
							 | 
						|
								    res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
							 | 
						|
								    if (res == NULL) {
							 | 
						|
									Cudd_RecursiveDeref(dd, T);
							 | 
						|
									Cudd_RecursiveDeref(dd, E);
							 | 
						|
									return(NULL);
							 | 
						|
								    }
							 | 
						|
								    cuddDeref(T);
							 | 
						|
								    cuddDeref(E);
							 | 
						|
								
							 | 
						|
								    /* Store result. */
							 | 
						|
								    cuddCacheInsert1(dd,op,f,res);
							 | 
						|
								
							 | 
						|
								    return(res);
							 | 
						|
								
							 | 
						|
								} /* end of cuddAddMonadicApplyRecur */
							 | 
						|
								
							 | 
						|
								
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 | 
						|
								/* Definition of static functions                                            */
							 | 
						|
								/*---------------------------------------------------------------------------*/
							 |