/**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 */
Example #2
0
/**Function********************************************************************

  Synopsis    [Converts an ADD to a BDD by extracting the i-th bit from
  the leaves.]

  Description [Converts an ADD to a BDD by replacing all
  discriminants whose i-th bit is equal to 1 with 1, and all other
  discriminants with 0. The i-th bit refers to the integer
  representation of the leaf value. If the value is has a fractional
  part, it is ignored. Repeated calls to this procedure allow one to
  transform an integer-valued ADD into an array of BDDs, one for each
  bit of the leaf values. Returns a pointer to the resulting BDD if
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd]

******************************************************************************/
DdNode *
Cudd_addBddIthBit(
  DdManager * dd,
  DdNode * f,
  ptrint  bit)
{
    DdNode *res;
    DdNode *index;

    /* NuSMV: begin add */
    abort(); /* NOT USED BY NUSMV */
    /* NuSMV: begin end */

    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
    if (index == NULL) return(NULL);
    cuddRef(index);

    do {
	dd->reordered = 0;
	res = addBddDoIthBit(dd, f, index);
    } while (dd->reordered == 1);

    if (res == NULL) {
	Cudd_RecursiveDeref(dd, index);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd, index);
    cuddDeref(res);
    return(res);

} /* end of Cudd_addBddIthBit */
Example #3
0
/**Function********************************************************************

  Synopsis    [Converts an ADD to a BDD.]

  Description [Converts an ADD to a BDD by replacing all
  discriminants STRICTLY greater than value with 1, and all other
  discriminants with 0. Returns a pointer to the resulting BDD if
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addBddInterval Cudd_addBddPattern Cudd_BddToAdd 
  Cudd_addBddThreshold]

******************************************************************************/
DdNode *
Cudd_addBddStrictThreshold(
  DdManager * dd,
  DdNode * f,
  CUDD_VALUE_TYPE  value)
{
    DdNode *res;
    DdNode *val;
    /* NuSMV: begin add */
    abort(); /* NOT USED BY NUSMV */
    /* NuSMV: begin end */
    
    val = cuddUniqueConst(dd,value);
    if (val == NULL) return(NULL);
    cuddRef(val);

    do {
	dd->reordered = 0;
	res = addBddDoStrictThreshold(dd, f, val);
    } while (dd->reordered == 1);

    if (res == NULL) {
	Cudd_RecursiveDeref(dd, val);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd, val);
    cuddDeref(res);
    return(res);

} /* end of Cudd_addBddStrictThreshold */
Example #4
0
/**Function********************************************************************

  Synopsis    [Existentially Abstracts all the variables in cube from f.]

  Description [Abstracts all the variables in cube from f by summing
  over all possible values taken by the variables. Returns the
  abstracted ADD.]

  SideEffects [None]

  SeeAlso     [Cudd_addUnivAbstract Cudd_bddExistAbstract
  Cudd_addOrAbstract]

******************************************************************************/
DdNode *
Cudd_addExistAbstract(
  DdManager * manager,
  DdNode * f,
  DdNode * cube)
{
    DdNode *res;

    two = cuddUniqueConst(manager,(CUDD_VALUE_TYPE) 2);
    if (two == NULL) return(NULL);
    cuddRef(two);

    if (addCheckPositiveCube(manager, cube) == 0) {
        (void) fprintf(manager->err,"Error: Can only abstract cubes");
        return(NULL);
    }

    do {
	manager->reordered = 0;
	res = cuddAddExistAbstractRecur(manager, f, cube);
    } while (manager->reordered == 1);

    if (res == NULL) {
	Cudd_RecursiveDeref(manager,two);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(manager,two);
    cuddDeref(res);

    return(res);

} /* end of Cudd_addExistAbstract */
/**Function********************************************************************

  Synopsis    [Extracts the i-th bit from an ADD.]

  Description [Produces an ADD from another ADD by replacing all
  discriminants whose i-th bit is equal to 1 with 1, and all other
  discriminants with 0. The i-th bit refers to the integer
  representation of the leaf value. If the value is has a fractional
  part, it is ignored. Repeated calls to this procedure allow one to
  transform an integer-valued ADD into an array of ADDs, one for each
  bit of the leaf values. Returns a pointer to the resulting ADD if
  successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addBddIthBit]

******************************************************************************/
DdNode *
Cudd_addIthBit(
  DdManager * dd,
  DdNode * f,
  int  bit)
{
    DdNode *res;
    DdNode *index;
    
    /* Use a constant node to remember the bit, so that we can use the
    ** global cache.
    */
    index = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) bit);
    if (index == NULL) return(NULL);
    cuddRef(index);

    do {
	dd->reordered = 0;
	res = addDoIthBit(dd, f, index);
    } while (dd->reordered == 1);

    if (res == NULL) {
	Cudd_RecursiveDeref(dd, index);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd, index);
    cuddDeref(res);
    return(res);

} /* end of Cudd_addIthBit */
Example #6
0
/**Function********************************************************************

  Synopsis    [Converts an ADD to a BDD.]

  Description [Converts an ADD to a BDD by replacing all
  discriminants greater than or equal to lower and less than or equal to
  upper with 1, and all other discriminants with 0. Returns a pointer to
  the resulting BDD if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_addBddThreshold Cudd_addBddStrictThreshold 
  Cudd_addBddPattern Cudd_BddToAdd]

******************************************************************************/
DdNode *
Cudd_addBddInterval(
  DdManager * dd,
  DdNode * f,
  CUDD_VALUE_TYPE  lower,
  CUDD_VALUE_TYPE  upper)
{
    DdNode *res;
    DdNode *l;
    DdNode *u;

    /* NuSMV: begin add */
    abort(); /* NOT USED BY NUSMV */
    /* NuSMV: begin end */

    /* Create constant nodes for the interval bounds, so that we can use
    ** the global cache.
    */
    l = cuddUniqueConst(dd,lower);
    if (l == NULL) return(NULL);
    cuddRef(l);
    u = cuddUniqueConst(dd,upper);
    if (u == NULL) {
	Cudd_RecursiveDeref(dd,l);
	return(NULL);
    }
    cuddRef(u);

    do {
	dd->reordered = 0;
	res = addBddDoInterval(dd, f, l, u);
    } while (dd->reordered == 1);

    if (res == NULL) {
	Cudd_RecursiveDeref(dd, l);
	Cudd_RecursiveDeref(dd, u);
	return(NULL);
    }
    cuddRef(res);
    Cudd_RecursiveDeref(dd, l);
    Cudd_RecursiveDeref(dd, u);
    cuddDeref(res);
    return(res);

} /* end of Cudd_addBddInterval */
/**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 */
Example #8
0
/**
  @brief Implements the recursive step of Cudd_addRoundOff.

  @return a pointer to the result.

  @sideeffect None

*/
DdNode *
cuddAddRoundOffRecur(
  DdManager * dd,
  DdNode * f,
  double  trunc)
{

    DdNode *res, *fv, *fvn, *T, *E;
    double n;
    DD_CTFP1 cacheOp;

    statLine(dd);
    if (cuddIsConstant(f)) {
	n = ceil(cuddV(f)*trunc)/trunc;
	res = cuddUniqueConst(dd,n);
	return(res);
    }
    cacheOp = (DD_CTFP1) Cudd_addRoundOff;
    res = cuddCacheLookup1(dd,cacheOp,f);
    if (res != NULL) {
	return(res);
    }
    checkWhetherToGiveUp(dd);
    /* Recursive Step */
    fv = cuddT(f);
    fvn = cuddE(f);
    T = cuddAddRoundOffRecur(dd,fv,trunc);
    if (T == NULL) {
       return(NULL);
    }
    cuddRef(T);
    E = cuddAddRoundOffRecur(dd,fvn,trunc);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);
    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd,T);
	Cudd_RecursiveDeref(dd,E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,cacheOp,f,res);
    return(res);

} /* end of cuddAddRoundOffRecur */
Example #9
0
/**
  @brief Implements the recursive step of Cudd_addNegate.

  @return a pointer to the result.

  @sideeffect None

*/
DdNode *
cuddAddNegateRecur(
  DdManager * dd,
  DdNode * f)
{
    DdNode *res,
	    *fv, *fvn,
	    *T, *E;

    statLine(dd);
    /* Check terminal cases. */
    if (cuddIsConstant(f)) {
	res = cuddUniqueConst(dd,-cuddV(f));
	return(res);
    }

    /* Check cache */
    res = cuddCacheLookup1(dd,Cudd_addNegate,f);
    if (res != NULL) return(res);

    checkWhetherToGiveUp(dd);

    /* Recursive Step */
    fv = cuddT(f);
    fvn = cuddE(f);
    T = cuddAddNegateRecur(dd,fv);
    if (T == NULL) return(NULL);
    cuddRef(T);

    E = cuddAddNegateRecur(dd,fvn);
    if (E == NULL) {
	Cudd_RecursiveDeref(dd,T);
	return(NULL);
    }
    cuddRef(E);
    res = (T == E) ? T : cuddUniqueInter(dd,(int)f->index,T,E);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, T);
	Cudd_RecursiveDeref(dd, E);
	return(NULL);
    }
    cuddDeref(T);
    cuddDeref(E);

    /* Store result. */
    cuddCacheInsert1(dd,Cudd_addNegate,f,res);

    return(res);

} /* end of cuddAddNegateRecur */
Example #10
0
/**
  @brief Performs the recursive step of addScalarInverse.

  @return a pointer to the resulting %ADD in case of success. Returns
  NULL if any discriminants smaller than epsilon is encountered.

  @sideeffect None

*/
DdNode *
cuddAddScalarInverseRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * epsilon)
{
    DdNode *t, *e, *res;
    CUDD_VALUE_TYPE value;

    statLine(dd);
    if (cuddIsConstant(f)) {
	if (ddAbs(cuddV(f)) < cuddV(epsilon)) return(NULL);
	value = 1.0 / cuddV(f);
	res = cuddUniqueConst(dd,value);
	return(res);
    }

    res = cuddCacheLookup2(dd,Cudd_addScalarInverse,f,epsilon);
    if (res != NULL) return(res);

    checkWhetherToGiveUp(dd);

    t = cuddAddScalarInverseRecur(dd,cuddT(f),epsilon);
    if (t == NULL) return(NULL);
    cuddRef(t);

    e = cuddAddScalarInverseRecur(dd,cuddE(f),epsilon);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    res = (t == e) ? t : cuddUniqueInter(dd,(int)f->index,t,e);
    if (res == NULL) {
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
	return(NULL);
    }
    cuddDeref(t);
    cuddDeref(e);

    cuddCacheInsert2(dd,Cudd_addScalarInverse,f,epsilon,res);

    return(res);

} /* end of cuddAddScalarInverseRecur */
Example #11
0
/**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 == 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 */
Example #12
0
/**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;
    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 */
Example #13
0
/**Function********************************************************************

  Synopsis    [Takes the ADD of Haar and returns the ADD of inverse Haar.]

  Description []

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode * Extra_bddHaarInverse( 
  DdManager * dd,    /* the manager */
  DdNode * aFunc,    /* the Haar that should be inverted */
  DdNode * bVars)    /* the variables on which the function depends */
{
	static int Vars[MAXINPUTS];
	static int InverseMap[MAXINPUTS];
	int k, nVars = 0;
	DdNode * bTemp;
	DdNode * aStepFirst;
    DdNode * aRes;

	/////////////////////////////////////////////////////////
	// create the array of variables in the set bVars
	for ( bTemp = bVars; bTemp != b1; bTemp = cuddT(bTemp) )
		Vars[nVars++] = bTemp->index;

	// compute the inverse mapping of variable into the one that 
	// has the same distance from the bottom as this one from the top
	k = 0;
	for ( bTemp = bVars; bTemp != b1; bTemp = cuddT(bTemp), k++ )
		InverseMap[bTemp->index] = Vars[nVars-1-k];
	/////////////////////////////////////////////////////////

	// get the constant ADD representing the first step
	aStepFirst = cuddUniqueConst( dd, 0.0 ); Cudd_Ref(aStepFirst);

    do 
	{
		dd->reordered = 0;
		aRes = extraBddHaarInverse(dd, aFunc, aStepFirst, bVars, bVars, nVars, InverseMap);
    } 
	while (dd->reordered == 1);

	Cudd_RecursiveDeref( dd, aStepFirst );
    return(aRes);

} /* end of Extra_bddHaarInverse */
/**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 */
Example #15
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addMatrixMultiply.]

  Description [Performs the recursive step of Cudd_addMatrixMultiply.
  Returns a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

******************************************************************************/
static DdNode *
addMMRecur(
  DdManager * dd,
  DdNode * A,
  DdNode * B,
  int  topP,
  int * vars)
{
    DdNode *zero,
           *At,		/* positive cofactor of first operand */
	   *Ae,		/* negative cofactor of first operand */
	   *Bt,		/* positive cofactor of second operand */
	   *Be,		/* negative cofactor of second operand */
	   *t,		/* positive cofactor of result */
	   *e,		/* negative cofactor of result */
	   *scaled,	/* scaled result */
	   *add_scale,	/* ADD representing the scaling factor */
	   *res;
    int	i;		/* loop index */
    double scale;	/* scaling factor */
    int index;		/* index of the top variable */
    CUDD_VALUE_TYPE value;
    unsigned int topA, topB, topV;
    DD_CTFP cacheOp;

    statLine(dd);
    zero = DD_ZERO(dd);

    if (A == zero || B == zero) {
        return(zero);
    }

    if (cuddIsConstant(A) && cuddIsConstant(B)) {
	/* Compute the scaling factor. It is 2^k, where k is the
	** number of summation variables below the current variable.
	** Indeed, these constants represent blocks of 2^k identical
	** constant values in both A and B.
	*/
	value = cuddV(A) * cuddV(B);
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP) {
		    value *= (CUDD_VALUE_TYPE) 2;
		}
	    }
	}
	res = cuddUniqueConst(dd, value);
	return(res);
    }

    /* Standardize to increase cache efficiency. Clearly, A*B != B*A
    ** in matrix multiplication. However, which matrix is which is
    ** determined by the variables appearing in the ADDs and not by
    ** which one is passed as first argument.
    */
    if (A > B) {
	DdNode *tmp = A;
	A = B;
	B = tmp;
    }

    topA = cuddI(dd,A->index); topB = cuddI(dd,B->index);
    topV = ddMin(topA,topB);

    cacheOp = (DD_CTFP) addMMRecur;
    res = cuddCacheLookup2(dd,cacheOp,A,B);
    if (res != NULL) {
	/* If the result is 0, there is no need to normalize.
	** Otherwise we count the number of z variables between
	** the current depth and the top of the ADDs. These are
	** the missing variables that determine the size of the
	** constant blocks.
	*/
	if (res == zero) return(res);
	scale = 1.0;
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
		    scale *= 2;
		}
	    }
	}
	if (scale > 1.0) {
	    cuddRef(res);
	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
	    if (add_scale == NULL) {
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(add_scale);
	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
	    if (scaled == NULL) {
		Cudd_RecursiveDeref(dd, add_scale);
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(scaled);
	    Cudd_RecursiveDeref(dd, add_scale);
	    Cudd_RecursiveDeref(dd, res);
	    res = scaled;
	    cuddDeref(res);
	}
        return(res);
    }

    /* compute the cofactors */
    if (topV == topA) {
	At = cuddT(A);
	Ae = cuddE(A);
    } else {
	At = Ae = A;
    }
    if (topV == topB) {
	Bt = cuddT(B);
	Be = cuddE(B);
    } else {
	Bt = Be = B;
    }

    t = addMMRecur(dd, At, Bt, (int)topV, vars);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = addMMRecur(dd, Ae, Be, (int)topV, vars);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    index = dd->invperm[topV];
    if (vars[index] == 0) {
	/* We have split on either the rows of A or the columns
	** of B. We just need to connect the two subresults,
	** which correspond to two submatrices of the result.
	*/
	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	cuddDeref(t);
	cuddDeref(e);
    } else {
	/* we have simultaneously split on the columns of A and
	** the rows of B. The two subresults must be added.
	*/
	res = cuddAddApplyRecur(dd,Cudd_addPlus,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
    }

    cuddCacheInsert2(dd,cacheOp,A,B,res);

    /* We have computed (and stored in the computed table) a minimal
    ** result; that is, a result that assumes no summation variables
    ** between the current depth of the recursion and its top
    ** variable. We now take into account the z variables by properly
    ** scaling the result.
    */
    if (res != zero) {
	scale = 1.0;
	for (i = 0; i < dd->size; i++) {
	    if (vars[i]) {
		if (dd->perm[i] > topP && (unsigned) dd->perm[i] < topV) {
		    scale *= 2;
		}
	    }
	}
	if (scale > 1.0) {
	    add_scale = cuddUniqueConst(dd,(CUDD_VALUE_TYPE)scale);
	    if (add_scale == NULL) {
		Cudd_RecursiveDeref(dd, res);
		return(NULL);
	    }
	    cuddRef(add_scale);
	    scaled = cuddAddApplyRecur(dd,Cudd_addTimes,res,add_scale);
	    if (scaled == NULL) {
		Cudd_RecursiveDeref(dd, res);
		Cudd_RecursiveDeref(dd, add_scale);
		return(NULL);
	    }
	    cuddRef(scaled);
	    Cudd_RecursiveDeref(dd, add_scale);
	    Cudd_RecursiveDeref(dd, res);
	    res = scaled;
	}
    }
    cuddDeref(res);
    return(res);

} /* end of addMMRecur */
Example #16
0
/**
  @brief Implements the recursive step of Cudd_addWalsh.

  @return a pointer to the matrixi if successful; NULL otherwise.

  @sideeffect None

  @see Cudd_addWalsh

*/
static DdNode *
addWalshInt(
  DdManager * dd,
  DdNode ** x,
  DdNode ** y,
  int  n)
{
    DdNode *one, *minusone;
    DdNode *t = NULL, *u, *t1, *u1, *v, *w;
    int     i;

    one = DD_ONE(dd);
    if (n == 0) return(one);

    /* Build bottom part of ADD outside loop */
    minusone = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) -1);
    if (minusone == NULL) return(NULL);
    cuddRef(minusone);
    v = Cudd_addIte(dd, y[n-1], minusone, one);
    if (v == NULL) {
	Cudd_RecursiveDeref(dd, minusone);
	return(NULL);
    }
    cuddRef(v);
    u = Cudd_addIte(dd, x[n-1], v, one);
    if (u == NULL) {
	Cudd_RecursiveDeref(dd, minusone);
	Cudd_RecursiveDeref(dd, v);
	return(NULL);
    }
    cuddRef(u);
    Cudd_RecursiveDeref(dd, v);
    if (n>1) {
	w = Cudd_addIte(dd, y[n-1], one, minusone);
	if (w == NULL) {
	    Cudd_RecursiveDeref(dd, minusone);
	    Cudd_RecursiveDeref(dd, u);
	    return(NULL);
	}
	cuddRef(w);
	t = Cudd_addIte(dd, x[n-1], w, minusone);
	if (t == NULL) {
	    Cudd_RecursiveDeref(dd, minusone);
	    Cudd_RecursiveDeref(dd, u);
	    Cudd_RecursiveDeref(dd, w);
	    return(NULL);
	}
	cuddRef(t);
	Cudd_RecursiveDeref(dd, w);
    }
    cuddDeref(minusone); /* minusone is in the result; it won't die */

    /* Loop to build the rest of the ADD */
    for (i=n-2; i>=0; i--) {
	t1 = t; u1 = u;
	v = Cudd_addIte(dd, y[i], t1, u1);
	if (v == NULL) {
	    Cudd_RecursiveDeref(dd, u1);
	    Cudd_RecursiveDeref(dd, t1);
	    return(NULL);
	}
	cuddRef(v);
	u = Cudd_addIte(dd, x[i], v, u1);
	if (u == NULL) {
	    Cudd_RecursiveDeref(dd, u1);
	    Cudd_RecursiveDeref(dd, t1);
	    Cudd_RecursiveDeref(dd, v);
	    return(NULL);
	}
	cuddRef(u);
	Cudd_RecursiveDeref(dd, v);
	if (i>0) {
	    w = Cudd_addIte(dd, y[i], u1, t1);
	    if (w == NULL) {
		Cudd_RecursiveDeref(dd, u1);
		Cudd_RecursiveDeref(dd, t1);
		Cudd_RecursiveDeref(dd, u);
		return(NULL);
	    }
	    cuddRef(w);
	    t = Cudd_addIte(dd, x[i], w, t1);
	    if (u == NULL) {
		Cudd_RecursiveDeref(dd, u1);
		Cudd_RecursiveDeref(dd, t1);
		Cudd_RecursiveDeref(dd, u);
		Cudd_RecursiveDeref(dd, w);
		return(NULL);
	    }
	    cuddRef(t);
	    Cudd_RecursiveDeref(dd, w);
	}
	Cudd_RecursiveDeref(dd, u1);
	Cudd_RecursiveDeref(dd, t1);
    }

    cuddDeref(u);
    return(u);

} /* end of addWalshInt */
Example #17
0
/**
  @brief Builds an %ADD for the residue modulo m of an n-bit
  number.

  @details The modulus must be at least 2, and the number of bits at
  least 1. Parameter options specifies whether the MSB should be on top
  or the LSB; and whther the number whose residue is computed is in
  two's complement notation or not. The macro CUDD_RESIDUE_DEFAULT
  specifies LSB on top and unsigned number. The macro CUDD_RESIDUE_MSB
  specifies MSB on top, and the macro CUDD_RESIDUE_TC specifies two's
  complement residue. To request MSB on top and two's complement residue
  simultaneously, one can OR the two macros:
  CUDD_RESIDUE_MSB | CUDD_RESIDUE_TC.

  @return a pointer to the resulting %ADD if successful; NULL
  otherwise.

  @sideeffect None

*/
DdNode *
Cudd_addResidue(
  DdManager * dd /**< manager */,
  int  n /**< number of bits */,
  int  m /**< modulus */,
  int  options /**< options */,
  int  top /**< index of top variable */)
{
    int msbLsb;	/* MSB on top (1) or LSB on top (0) */
    int tc;	/* two's complement (1) or unsigned (0) */
    int i, j, k, t, residue, thisOne, previous, index;
    DdNode **array[2], *var, *tmp, *res;

    /* Sanity check. */
    if (n < 1 && m < 2) return(NULL);

    msbLsb = options & CUDD_RESIDUE_MSB;
    tc = options & CUDD_RESIDUE_TC;

    /* Allocate and initialize working arrays. */
    array[0] = ALLOC(DdNode *,m);
    if (array[0] == NULL) {
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    array[1] = ALLOC(DdNode *,m);
    if (array[1] == NULL) {
	FREE(array[0]);
	dd->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    for (i = 0; i < m; i++) {
	array[0][i] = array[1][i] = NULL;
    }

    /* Initialize residues. */
    for (i = 0; i < m; i++) {
	tmp = cuddUniqueConst(dd,(CUDD_VALUE_TYPE) i);
	if (tmp == NULL) {
	    for (j = 0; j < i; j++) {
		Cudd_RecursiveDeref(dd,array[1][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(tmp);
	array[1][i] = tmp;
    }

    /* Main iteration. */
    residue = 1;	/* residue of 2**0 */
    for (k = 0; k < n; k++) {
	/* Choose current and previous arrays. */
	thisOne = k & 1;
	previous = thisOne ^ 1;
	/* Build an ADD projection function. */
	if (msbLsb) {
	    index = top+n-k-1;
	} else {
	    index = top+k;
	}
	var = cuddUniqueInter(dd,index,DD_ONE(dd),DD_ZERO(dd));
	if (var == NULL) {
	    for (j = 0; j < m; j++) {
		Cudd_RecursiveDeref(dd,array[previous][j]);
	    }
	    FREE(array[0]);
	    FREE(array[1]);
	    return(NULL);
	}
	cuddRef(var);
	for (i = 0; i < m; i ++) {
	    t = (i + residue) % m;
	    tmp = Cudd_addIte(dd,var,array[previous][t],array[previous][i]);
	    if (tmp == NULL) {
		for (j = 0; j < i; j++) {
		    Cudd_RecursiveDeref(dd,array[thisOne][j]);
		}
		for (j = 0; j < m; j++) {
		    Cudd_RecursiveDeref(dd,array[previous][j]);
		}
		FREE(array[0]);
		FREE(array[1]);
		return(NULL);
	    }
	    cuddRef(tmp);
	    array[thisOne][i] = tmp;
	}
	/* One layer completed. Free the other array for the next iteration. */
	for (i = 0; i < m; i++) {
	    Cudd_RecursiveDeref(dd,array[previous][i]);
	}
	Cudd_RecursiveDeref(dd,var);
	/* Update residue of 2**k. */
	residue = (2 * residue) % m;
	/* Adjust residue for MSB, if this is a two's complement number. */
	if (tc && (k == n - 1)) {
	    residue = (m - residue) % m;
	}
    }

    /* We are only interested in the 0-residue node of the top layer. */
    for (i = 1; i < m; i++) {
	Cudd_RecursiveDeref(dd,array[(n - 1) & 1][i]);
    }
    res = array[(n - 1) & 1][0];

    FREE(array[0]);
    FREE(array[1]);

    cuddDeref(res);
    return(res);

} /* end of Cudd_addResidue */
Example #18
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_MinHammingDist.]

  Description [Performs the recursive step of Cudd_MinHammingDist.
  It is based on the following identity. Let H(f) be the
  minimum Hamming distance of the minterms of f from the reference
  minterm. Then:
  <xmp>
    H(f) = min(H(f0)+h0,H(f1)+h1)
  </xmp>
  where f0 and f1 are the two cofactors of f with respect to its top
  variable; h0 is 1 if the minterm assigns 1 to the top variable of f;
  h1 is 1 if the minterm assigns 0 to the top variable of f.
  The upper bound on the distance is used to bound the depth of the
  recursion.
  Returns the minimum distance unless it exceeds the upper bound or
  computation fails.]

  SideEffects [None]

  SeeAlso     [Cudd_MinHammingDist]

******************************************************************************/
static int
cuddMinHammingDistRecur(
  DdNode * f,
  int *minterm,
  DdHashTable * table,
  int upperBound)
{
    DdNode	*F, *Ft, *Fe;
    double	h, hT, hE;
    DdNode	*zero, *res;
    DdManager	*dd = table->manager;

    statLine(dd);
    if (upperBound == 0) return(0);

    F = Cudd_Regular(f);

    if (cuddIsConstant(F)) {
	zero = Cudd_Not(DD_ONE(dd));
	if (f == dd->background || f == zero) {
	    return(upperBound);
	} else {
	    return(0);
	}
    }
    if ((res = cuddHashTableLookup1(table,f)) != NULL) {
      //Rob Apr 6 2001: might need to change this, not sure what it does.....
      h = (*cuddV(res)).get_val();
      if (res->ref == 0) {
	dd->dead++;
	dd->constants.dead++;
      }
      return((int) h);
    }

    Ft = cuddT(F); Fe = cuddE(F);
    if (Cudd_IsComplement(f)) {
	Ft = Cudd_Not(Ft); Fe = Cudd_Not(Fe);
    }
    if (minterm[F->index] == 0) {
	DdNode *temp = Ft;
	Ft = Fe; Fe = temp;
    }

    hT = cuddMinHammingDistRecur(Ft,minterm,table,upperBound);
    if (hT == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    if (hT == 0) {
	hE = upperBound;
    } else {
	hE = cuddMinHammingDistRecur(Fe,minterm,table,upperBound - 1);
	if (hE == CUDD_OUT_OF_MEM) return(CUDD_OUT_OF_MEM);
    }
    h = ddMin(hT, hE + 1);

    if (F->ref != 1) {
	ptrint fanout = (ptrint) F->ref;
	cuddSatDec(fanout);
	Terminal hTerminal;
	hTerminal.set((double) h);
	res = cuddUniqueConst(dd,&hTerminal);
	//res = cuddUniqueConst(dd, (CUDD_VALUE_TYPE) h);
	if (!cuddHashTableInsert1(table,f,res,fanout)) {
	    cuddRef(res); Cudd_RecursiveDeref(dd, res);
	    return(CUDD_OUT_OF_MEM);
	}
    }

    return((int) h);

} /* end of cuddMinHammingDistRecur */
/**Function********************************************************************

  Synopsis    [Creates a new DD manager.]

  Description [Creates a new DD manager, initializes the table, the
  basic constants and the projection functions. If maxMemory is 0,
  Cudd_Init decides suitable values for the maximum size of the cache
  and for the limit for fast unique table growth based on the available
  memory. Returns a pointer to the manager if successful; NULL
  otherwise.]

  SideEffects [None]

  SeeAlso     [Cudd_Quit]

******************************************************************************/
DdManager *
Cudd_Init(
  unsigned int numVars /* initial number of BDD variables (i.e., subtables) */,
  unsigned int numVarsZ /* initial number of ZDD variables (i.e., subtables) */,
  unsigned int numSlots /* initial size of the unique tables */,
  unsigned int cacheSize /* initial size of the cache */,
  unsigned long maxMemory /* target maximum memory occupation */)
{
    DdManager *unique;
    int i,result;
    DdNode *one, *zero;
    unsigned int maxCacheSize;
    unsigned int looseUpTo;
    extern void (*MMoutOfMemory)(long);
    void (*saveHandler)(long);

    if (maxMemory == 0) {
	maxMemory = getSoftDataLimit();
    }
    looseUpTo = (unsigned int) ((maxMemory / sizeof(DdNode)) /
				DD_MAX_LOOSE_FRACTION);
    unique = cuddInitTable(numVars,numVarsZ,numSlots,looseUpTo);
    unique->maxmem = (unsigned) maxMemory / 10 * 9;
    if (unique == NULL) return(NULL);
    maxCacheSize = (unsigned int) ((maxMemory / sizeof(DdCache)) /
				   DD_MAX_CACHE_FRACTION);
    result = cuddInitCache(unique,cacheSize,maxCacheSize);
    if (result == 0) return(NULL);

    saveHandler = MMoutOfMemory;
    MMoutOfMemory = Cudd_OutOfMem;
    unique->stash = ALLOC(char,(maxMemory / DD_STASH_FRACTION) + 4);
    MMoutOfMemory = saveHandler;
    if (unique->stash == NULL) {
	(void) fprintf(unique->err,"Unable to set aside memory\n");
    }

    /* Initialize constants. */
    unique->one = cuddUniqueConst(unique,1.0);
    if (unique->one == NULL) return(0);
    cuddRef(unique->one);
    unique->zero = cuddUniqueConst(unique,0.0);
    if (unique->zero == NULL) return(0);
    cuddRef(unique->zero);
#ifdef HAVE_IEEE_754
    if (DD_PLUS_INF_VAL != DD_PLUS_INF_VAL * 3 ||
	DD_PLUS_INF_VAL != DD_PLUS_INF_VAL / 3) {
	(void) fprintf(unique->err,"Warning: Crippled infinite values\n");
	(void) fprintf(unique->err,"Recompile without -DHAVE_IEEE_754\n");
    }
#endif
    unique->plusinfinity = cuddUniqueConst(unique,DD_PLUS_INF_VAL);
    if (unique->plusinfinity == NULL) return(0);
    cuddRef(unique->plusinfinity);
    unique->minusinfinity = cuddUniqueConst(unique,DD_MINUS_INF_VAL);
    if (unique->minusinfinity == NULL) return(0);
    cuddRef(unique->minusinfinity);
    unique->background = unique->zero;

    /* The logical zero is different from the CUDD_VALUE_TYPE zero! */
    one = unique->one;
    zero = Cudd_Not(one);
    /* Create the projection functions. */
    unique->vars = ALLOC(DdNodePtr,unique->maxSize);
    if (unique->vars == NULL) {
	unique->errorCode = CUDD_MEMORY_OUT;
	return(NULL);
    }
    for (i = 0; i < unique->size; i++) {
	unique->vars[i] = cuddUniqueInter(unique,i,one,zero);
	if (unique->vars[i] == NULL) return(0);
	cuddRef(unique->vars[i]);
    }

    if (unique->sizeZ)
	cuddZddInitUniv(unique);

    unique->memused += sizeof(DdNode *) * unique->maxSize;

    return(unique);

} /* end of Cudd_Init */
Example #20
0
/**Function********************************************************************

  Synopsis    [Performs the reordering-sensitive step of Extra_bddHaarInverse().]

  Description [Generates in a bottom-up fashion an ADD for the inverse Haar.]

  SideEffects [The third cached argument (bSteps) is the BDD of the elementary variable
  whose index equal to the number of lazy steps made thus far plus one. On the top-most
  level it is 0, next it is 1, etc.]

  SeeAlso     []

******************************************************************************/
DdNode * extraBddHaarInverse( 
  DdManager * dd,    /* the manager */
  DdNode * aFunc,    /* the function whose spectrum is being computed */
  DdNode * aSteps,   /* the index of this variable indicates the number of previous lazy recursive calls */
  DdNode * bVars,    /* the variables, on which the function depends */
  DdNode * bVarsAll, /* the set of all variables, which will never change through the calls */
  int      nVarsAll, /* the number of vars in the set */
  int    * InverseMap ) /* the variable map mapping the var index into its inverse var index */
{
	DdNode * aRes;
	DdNode * bCacheCube;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{ // return a terminal node with a value equal to cuddV(aFunc) * 2^(nSteps-1)
		if ( cuddV(aSteps) == 0.0 )
			return cuddUniqueConst( dd, cuddV(aFunc) ); 
		else
			return cuddUniqueConst( dd, cuddV(aFunc) * Extra_Power2( (int)(cuddV(aSteps)-1) ) ); 
	}

    /* check cache */
    /* the last two arguments are derivitives, therefore there are useless for caching */
	/* the other two arguments (bVars and bVarsAll) can be combined into one argument */
	bCacheCube = extraCachingCube( dd, bVarsAll, bVars );  Cudd_Ref( bCacheCube );
    if ( aRes = cuddCacheLookup(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube) )
	{
		Cudd_RecursiveDeref( dd, bCacheCube );
   		return aRes;
	}
	else
	{
		DdNode * aFunc0, * aFunc1;   /* cofactors of the function */
		DdNode * aInvH0, * aInvH1;   /* partial solutions of the problem */
		DdNode * aRes0,  * aRes1;    /* partial results to be composed by ITE */
		DdNode * aStepNext;

		/* aFunc cannot depend on a variable that is not in bVars */
		assert( cuddI(dd,aFunc->index) >= cuddI(dd,bVars->index) );

		/* cofactor the ADD */
		if ( aFunc->index == bVars->index )
		{
			aFunc0 = cuddE(aFunc);
			aFunc1 = cuddT(aFunc);
		}
		else /* bVars is higher in the variable order */
			aFunc0 = aFunc1 = aFunc;


		if ( cuddV(aSteps) > 0.0 ) /* meaning that it is a lazy call */
		{
			/* solve subproblems */
			aStepNext = cuddUniqueConst( dd, cuddV(aSteps)+1 );
			if ( aStepNext == NULL )
				return NULL;
			cuddRef( aStepNext );

			aInvH0 = extraBddHaarInverse( dd, aFunc0, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				return NULL;
			}
			cuddRef( aInvH0 );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );

			aRes0 = aInvH0;
			aRes1 = aInvH1;
		}
		else // if ( cuddV(aSteps) == 0.0 )
		{
			/* solve subproblems */
			aInvH0 = extraBddHaarInverse( dd, aFunc0, aSteps, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH0 == NULL )
				return NULL;
			cuddRef( aInvH0 );

			aStepNext = cuddUniqueConst( dd, 1.0 );
			if ( aStepNext == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aStepNext );

			aInvH1 = extraBddHaarInverse( dd, aFunc1, aStepNext, cuddT(bVars), bVarsAll, nVarsAll, InverseMap );
			if ( aInvH1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aStepNext );
				Cudd_RecursiveDeref( dd, aInvH0 );
				return NULL;
			}
			cuddRef( aInvH1 );
			Cudd_RecursiveDeref( dd, aStepNext );


			/* compute  aRes0 = aWalsh0 + aWalsh1 */
			aRes0 = cuddAddApplyRecur( dd, Cudd_addPlus, aInvH0, aInvH1 );
			if ( aRes0 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				return NULL;
			}
			cuddRef( aRes0 );

			/* compute  aRes1 = aWalsh0 - aWalsh1 */
			aRes1 = cuddAddApplyRecur( dd, Cudd_addMinus, aInvH0, aInvH1 );
			if ( aRes1 == NULL )
			{
				Cudd_RecursiveDeref( dd, aInvH0 );
				Cudd_RecursiveDeref( dd, aInvH1 );
				Cudd_RecursiveDeref( dd, aRes0 );
				return NULL;
			}
			cuddRef( aRes1 );

			Cudd_RecursiveDeref(dd, aInvH0);
			Cudd_RecursiveDeref(dd, aInvH1);
		}

		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = extraAddIteRecurGeneral( dd, dd->vars[ InverseMap[bVars->index] ], aRes1, aRes0 );
		if (aRes == NULL) 
		{
			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
		cuddRef( aRes );
		Cudd_RecursiveDeref(dd, aRes1);
		Cudd_RecursiveDeref(dd, aRes0);
		cuddDeref( aRes );

		/* insert the result into cache */
		cuddCacheInsert(dd, DD_ADD_HAAR_INVERSE_TAG, aFunc, aSteps, bCacheCube, aRes);
		Cudd_RecursiveDeref( dd, bCacheCube );
		return aRes;
	}
} /* end of extraBddHaarInverse */
/**Function*************************************************************

  Synopsis    [Creates the DD from the internal reordering data structure.]

  Description [It is important that the hash table is lossless.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
DdNode * reoTransferUnitsToNodes_rec( reo_man * p, reo_unit * pUnit )
{
	DdManager * dd = p->dd;
	DdNode * bRes, * E, * T;
	int HKey, fComp;

	fComp = Cudd_IsComplement(pUnit);
	pUnit = Unit_Regular(pUnit);

	// check the hash-table
	if ( pUnit->n != 1 )
	{
		for ( HKey = hashKey2(p->Signature,pUnit,p->nTableSize); p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize )
			if ( p->HTable[HKey].Arg1 == pUnit )
			{
				bRes = (DdNode*) p->HTable[HKey].Arg2;  
				assert( bRes );
				return Cudd_NotCond( bRes, fComp );
			}
	}

	// treat the case of constants
	if ( Unit_IsConstant(pUnit) )
	{
		bRes = cuddUniqueConst( dd, ((double)((int)(pUnit->pE))) );
		cuddRef( bRes );
	}
	else
	{
		// split and recur on children of this node
		E = reoTransferUnitsToNodes_rec( p, pUnit->pE );
		if ( E == NULL )
			return NULL;
		cuddRef(E);

		T = reoTransferUnitsToNodes_rec( p, pUnit->pT );
		if ( T == NULL )
		{
			Cudd_RecursiveDeref(dd, E);
			return NULL;
		}
		cuddRef(T);
		
		// consider the case when Res0 and Res1 are the same node
		assert( E != T );
		assert( !Cudd_IsComplement(T) );

		bRes = cuddUniqueInter( dd, p->pMapToDdVarsFinal[pUnit->lev], T, E );
		if ( bRes == NULL ) 
		{
			Cudd_RecursiveDeref(dd,E);
			Cudd_RecursiveDeref(dd,T);
			return NULL;
		}
		cuddRef( bRes );
		cuddDeref( E );
		cuddDeref( T );
	}

	// do not keep the result if the ref count is only 1, since it will not be visited again
	if ( pUnit->n != 1 )
	{
		 // while we traversed the diagram, the hash entry to which HKey points,
		 // might have been used. Make sure that its signature is different.
		 for ( ; p->HTable[HKey].Sign == p->Signature; HKey = (HKey+1) % p->nTableSize );
		 p->HTable[HKey].Sign = p->Signature;
		 p->HTable[HKey].Arg1 = pUnit;
		 p->HTable[HKey].Arg2 = (reo_unit *)bRes;  

		 // add the DD to the referenced DD list in order to be able to store it in cache
		 p->pRefNodes[p->nRefNodes++] = bRes;  Cudd_Ref( bRes ); 
		 // no need to do this, because the garbage collection will not take bRes away
		 // it is held by the diagram in the making
	}
	// increment the counter of nodes
	p->nNodesCur++;
	cuddDeref( bRes );
	return Cudd_NotCond( bRes, fComp );
}
Example #22
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_bddTransfer.]

  Description [Performs the recursive step of Cudd_bddTransfer.
  Returns a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     [cuddauxAddTransfer]

******************************************************************************/
static DdNode *
cuddauxAddTransferRecur(
  DdManager * ddS,
  DdManager * ddD,
  DdNode * f,
  st_table * table)
{
  DdNode *ft, *fe, *t, *e, *var, *res;
  DdNode *one, *zero;
  int	   index;

  /* Trivial cases. */
  if (cuddIsConstant(f)){
    double v = cuddV(f);
    return (cuddUniqueConst(ddD,v));
  }
  /* Check the cache. */
  if(st_lookup(table, f, &res))
    return(res);
    
  /* Recursive step. */
  index = f->index;
  ft = cuddT(f); fe = cuddE(f);

  t = cuddauxAddTransferRecur(ddS, ddD, ft, table);
  if (t == NULL) {
    return(NULL);
  }
  cuddRef(t);

  e = cuddauxAddTransferRecur(ddS, ddD, fe, table);
  if (e == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    return(NULL);
  }
  cuddRef(e);

  one = DD_ONE(ddD);
  zero = Cudd_Not(one);
  var = cuddUniqueInter(ddD,index,one,zero);
  if (var == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    Cudd_RecursiveDeref(ddD, e);
    return(NULL);
  }
  res = cuddauxAddIteRecur(ddD,var,t,e);
  if (res == NULL) {
    Cudd_RecursiveDeref(ddD, t);
    Cudd_RecursiveDeref(ddD, e);
    return(NULL);
  }
  cuddRef(res);
  Cudd_RecursiveDeref(ddD, t);
  Cudd_RecursiveDeref(ddD, e);

  if (st_add_direct(table, (char *) f, (char *) res) == ST_OUT_OF_MEM) {
    Cudd_RecursiveDeref(ddD, res);
    return(NULL);
  }
  return(res);

} /* end of cuddauxAddTransferRecur */
Example #23
0
/**Function********************************************************************

  Synopsis    [Performs the reordering-sensitive step of Extra_bddHaar().]

  Description [Generates in a bottom-up fashion an ADD for all spectral
               coefficients of the functions represented by a BDD.]

  SideEffects []

  SeeAlso     []

******************************************************************************/
DdNode* extraBddHaar( 
  DdManager * dd,    /* the manager */
  DdNode * bFunc,    /* the function whose spectrum is being computed */
  DdNode * bVars)    /* the variables on which the function depends */
{
	DdNode * aRes;
    statLine(dd); 

	/* terminal cases */
	if ( bVars == b1 )
	{
		assert( Cudd_IsConstant(bFunc) );
		if ( bFunc == b0 )
			return a0;
		else
			return a1;
	}

    /* check cache */
//	if ( bFunc->ref != 1 )
    if ( aRes = cuddCacheLookup2(dd, extraBddHaar, bFunc, bVars) )
    	return aRes;
	else
	{
		DdNode * bFunc0, * bFunc1;   /* cofactors of the function */
		DdNode * aHaar0, * aHaar1;   /* partial solutions of the problem */
		DdNode * aNode0, * aNode1;   /* the special terminal nodes */
		DdNode * aRes0,  * aRes1;    /* partial results to be composed by ITE */
		DdNode * bFuncR = Cudd_Regular(bFunc); /* the regular pointer to the function */
		DdNode * aTemp;
		double   dValue0, dValue1;

		/* bFunc cannot depend on a variable that is not in bVars */
		assert( cuddI(dd,bFuncR->index) >= cuddI(dd,bVars->index) );


		/* cofactor the BDD */
		if ( bFuncR->index == bVars->index )
		{
			if ( bFuncR != bFunc ) /* bFunc is complemented */
			{
				bFunc0 = Cudd_Not( cuddE(bFuncR) );
				bFunc1 = Cudd_Not( cuddT(bFuncR) );
			}
			else
			{
				bFunc0 = cuddE(bFuncR);
				bFunc1 = cuddT(bFuncR);
			}
		}
		else /* bVars is higher in the variable order */
			bFunc0 = bFunc1 = bFunc;


		/* solve subproblems */
		aHaar0 = extraBddHaar( dd, bFunc0, cuddT(bVars) );
		if ( aHaar0 == NULL )
			return NULL;
		cuddRef( aHaar0 );

		aHaar1 = extraBddHaar( dd, bFunc1, cuddT(bVars) );
		if ( aHaar1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			return NULL;
		}
		cuddRef( aHaar1 );

		/* retrieve the terminal values in aHaar0 and aHaar1 */
		for ( aTemp = aHaar0; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) );
		dValue0 = cuddV( aTemp );
		for ( aTemp = aHaar1; aTemp->index != CUDD_CONST_INDEX; aTemp = cuddE(aTemp) );
		dValue1 = cuddV( aTemp );

		/* get the new terminal nodes */
		aNode0 = cuddUniqueConst( dd, dValue0 + dValue1 );
		if ( aNode0 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			return NULL;
		}
		cuddRef( aNode0 );

		aNode1 = cuddUniqueConst( dd, dValue0 - dValue1 );
		if ( aNode1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			return NULL;
		}
		cuddRef( aNode1 );


		/* replace the terminal nodes in the cofactor ADDs */
		aRes0 = extraAddUpdateZeroCubeValue( dd, aHaar0, cuddT(bVars), aNode0  );
		if ( aRes0 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			Cudd_RecursiveDeref( dd, aNode1 );
			return NULL;
		}
		cuddRef( aRes0 );

		aRes1 = extraAddUpdateZeroCubeValue( dd, aHaar1, cuddT(bVars), aNode1  );
		if ( aRes1 == NULL )
		{
			Cudd_RecursiveDeref( dd, aHaar0 );
			Cudd_RecursiveDeref( dd, aHaar1 );
			Cudd_RecursiveDeref( dd, aNode0 );
			Cudd_RecursiveDeref( dd, aNode1 );
			Cudd_RecursiveDeref( dd, aRes0 );
			return NULL;
		}
		cuddRef( aRes1 );

		Cudd_RecursiveDeref(dd, aHaar0);
		Cudd_RecursiveDeref(dd, aHaar1);

		Cudd_RecursiveDeref(dd, aNode0);
		Cudd_RecursiveDeref(dd, aNode1);


		/* only aRes0 and aRes1 are referenced at this point */

		/* consider the case when Res0 and Res1 are the same node */
		aRes = (aRes1 == aRes0) ? aRes1 : cuddUniqueInter( dd, bVars->index, aRes1, aRes0 );
		if (aRes == NULL) 
		{
			Cudd_RecursiveDeref(dd, aRes1);
			Cudd_RecursiveDeref(dd, aRes0);
			return NULL;
		}
		cuddDeref(aRes1);
		cuddDeref(aRes0);

		/* insert the result into cache */
//		if ( bFunc->ref != 1 )
		cuddCacheInsert2(dd, extraBddHaar, bFunc, bVars, aRes);
		return aRes;
	}
} /* end of extraBddHaar */
Example #24
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addOuterSum.]

  Description [Performs the recursive step of Cudd_addOuterSum.
  Returns a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

  SeeAlso     []

******************************************************************************/
static DdNode *
cuddAddOuterSumRecur(
  DdManager *dd,
  DdNode *M,
  DdNode *r,
  DdNode *c)
{
    DdNode *P, *R, *Mt, *Me, *rt, *re, *ct, *ce, *Rt, *Re;
    int topM, topc, topr;
    int v, index;

    statLine(dd);
    /* Check special cases. */
    if (r == DD_PLUS_INFINITY(dd) || c == DD_PLUS_INFINITY(dd)) return(M); 

    if (cuddIsConstant(c) && cuddIsConstant(r)) {
	R = cuddUniqueConst(dd,Cudd_V(c)+Cudd_V(r));
	cuddRef(R);
	if (cuddIsConstant(M)) {
	    if (cuddV(R) <= cuddV(M)) {
		cuddDeref(R);
	        return(R);
	    } else {
	        Cudd_RecursiveDeref(dd,R);       
		return(M);
	    }
	} else {
	    P = Cudd_addApply(dd,Cudd_addMinimum,R,M);
	    cuddRef(P);
	    Cudd_RecursiveDeref(dd,R);
	    cuddDeref(P);
	    return(P);
	}
    }

    /* Check the cache. */
    R = cuddCacheLookup(dd,DD_ADD_OUT_SUM_TAG,M,r,c);
    if (R != NULL) return(R);

    topM = cuddI(dd,M->index); topr = cuddI(dd,r->index);
    topc = cuddI(dd,c->index);
    v = ddMin(topM,ddMin(topr,topc));

    /* Compute cofactors. */
    if (topM == v) { Mt = cuddT(M); Me = cuddE(M); } else { Mt = Me = M; }
    if (topr == v) { rt = cuddT(r); re = cuddE(r); } else { rt = re = r; }
    if (topc == v) { ct = cuddT(c); ce = cuddE(c); } else { ct = ce = c; }

    /* Recursively solve. */
    Rt = cuddAddOuterSumRecur(dd,Mt,rt,ct);
    if (Rt == NULL) return(NULL);
    cuddRef(Rt);
    Re = cuddAddOuterSumRecur(dd,Me,re,ce);
    if (Re == NULL) {
	Cudd_RecursiveDeref(dd, Rt);
	return(NULL);
    }
    cuddRef(Re);
    index = dd->invperm[v];
    R = (Rt == Re) ? Rt : cuddUniqueInter(dd,index,Rt,Re);
    if (R == NULL) {
	Cudd_RecursiveDeref(dd, Rt);
	Cudd_RecursiveDeref(dd, Re);
	return(NULL);
    }
    cuddDeref(Rt);
    cuddDeref(Re);

    /* Store the result in the cache. */
    cuddCacheInsert(dd,DD_ADD_OUT_SUM_TAG,M,r,c,R);

    return(R);

} /* end of cuddAddOuterSumRecur */
Example #25
0
/**Function********************************************************************

  Synopsis    [Performs the recursive step of Cudd_addTriangle.]

  Description [Performs the recursive step of Cudd_addTriangle. Returns
  a pointer to the result if successful; NULL otherwise.]

  SideEffects [None]

******************************************************************************/
static DdNode *
addTriangleRecur(
  DdManager * dd,
  DdNode * f,
  DdNode * g,
  int * vars,
  DdNode *cube)
{
    DdNode *fv, *fvn, *gv, *gvn, *t, *e, *res;
    CUDD_VALUE_TYPE value;
    int top, topf, topg, index;

    statLine(dd);
    if (f == DD_PLUS_INFINITY(dd) || g == DD_PLUS_INFINITY(dd)) {
	return(DD_PLUS_INFINITY(dd));
    }

    if (cuddIsConstant(f) && cuddIsConstant(g)) {
	value = cuddV(f) + cuddV(g);
	res = cuddUniqueConst(dd, value);
	return(res);
    }
    if (f < g) {
	DdNode *tmp = f;
	f = g;
	g = tmp;
    }

    if (f->ref != 1 || g->ref != 1) {
	res = cuddCacheLookup(dd, DD_ADD_TRIANGLE_TAG, f, g, cube);
	if (res != NULL) {
	    return(res);
	}
    }

    topf = cuddI(dd,f->index); topg = cuddI(dd,g->index);
    top = ddMin(topf,topg);

    if (top == topf) {fv = cuddT(f); fvn = cuddE(f);} else {fv = fvn = f;}
    if (top == topg) {gv = cuddT(g); gvn = cuddE(g);} else {gv = gvn = g;}

    t = addTriangleRecur(dd, fv, gv, vars, cube);
    if (t == NULL) return(NULL);
    cuddRef(t);
    e = addTriangleRecur(dd, fvn, gvn, vars, cube);
    if (e == NULL) {
	Cudd_RecursiveDeref(dd, t);
	return(NULL);
    }
    cuddRef(e);

    index = dd->invperm[top];
    if (vars[index] < 0) {
	res = (t == e) ? t : cuddUniqueInter(dd,index,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddDeref(t);
	cuddDeref(e);
    } else {
	res = cuddAddApplyRecur(dd,Cudd_addMinimum,t,e);
	if (res == NULL) {
	    Cudd_RecursiveDeref(dd, t);
	    Cudd_RecursiveDeref(dd, e);
	    return(NULL);
	}
	cuddRef(res);
	Cudd_RecursiveDeref(dd, t);
	Cudd_RecursiveDeref(dd, e);
	cuddDeref(res);
    }

    if (f->ref != 1 || g->ref != 1) {
	cuddCacheInsert(dd, DD_ADD_TRIANGLE_TAG, f, g, cube, res);
    }

    return(res);

} /* end of addTriangleRecur */