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.
979 lines
27 KiB
979 lines
27 KiB
/**CFile***********************************************************************
|
|
|
|
FileName [cuddApa.c]
|
|
|
|
PackageName [cudd]
|
|
|
|
Synopsis [Arbitrary precision arithmetic functions.]
|
|
|
|
Description [External procedures included in this module:
|
|
<ul>
|
|
<li> Cudd_ApaNumberOfDigits()
|
|
<li> Cudd_NewApaNumber()
|
|
<li> Cudd_ApaCopy()
|
|
<li> Cudd_ApaAdd()
|
|
<li> Cudd_ApaSubtract()
|
|
<li> Cudd_ApaShortDivision()
|
|
<li> Cudd_ApaIntDivision()
|
|
<li> Cudd_ApaShiftRight()
|
|
<li> Cudd_ApaSetToLiteral()
|
|
<li> Cudd_ApaPowerOfTwo()
|
|
<li> Cudd_ApaCompare()
|
|
<li> Cudd_ApaCompareRatios()
|
|
<li> Cudd_ApaPrintHex()
|
|
<li> Cudd_ApaPrintDecimal()
|
|
<li> Cudd_ApaPrintExponential()
|
|
<li> Cudd_ApaCountMinterm()
|
|
<li> Cudd_ApaPrintMinterm()
|
|
<li> Cudd_ApaPrintMintermExp()
|
|
<li> Cudd_ApaPrintDensity()
|
|
</ul>
|
|
Static procedures included in this module:
|
|
<ul>
|
|
<li> cuddApaCountMintermAux()
|
|
<li> cuddApaStCountfree()
|
|
</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: cuddApa.c,v 1.20 2012/02/05 01:07:18 fabio Exp $";
|
|
#endif
|
|
|
|
static DdNode *background, *zero;
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Macro declarations */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/**AutomaticStart*************************************************************/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Static function prototypes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
static DdApaNumber cuddApaCountMintermAux (DdNode * node, int digits, DdApaNumber max, DdApaNumber min, st_table * table);
|
|
static enum st_retval cuddApaStCountfree (char * key, char * value, char * arg);
|
|
|
|
/**AutomaticEnd***************************************************************/
|
|
|
|
#ifdef __cplusplus
|
|
} /* end of extern "C" */
|
|
#endif
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of exported functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Finds the number of digits for an arbitrary precision
|
|
integer.]
|
|
|
|
Description [Finds the number of digits for an arbitrary precision
|
|
integer given the maximum number of binary digits. The number of
|
|
binary digits should be positive. Returns the number of digits if
|
|
successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaNumberOfDigits(
|
|
int binaryDigits)
|
|
{
|
|
int digits;
|
|
|
|
digits = binaryDigits / DD_APA_BITS;
|
|
if ((digits * DD_APA_BITS) != binaryDigits)
|
|
digits++;
|
|
return(digits);
|
|
|
|
} /* end of Cudd_ApaNumberOfDigits */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Allocates memory for an arbitrary precision integer.]
|
|
|
|
Description [Allocates memory for an arbitrary precision
|
|
integer. Returns a pointer to the allocated memory if successful;
|
|
NULL otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdApaNumber
|
|
Cudd_NewApaNumber(
|
|
int digits)
|
|
{
|
|
return(ALLOC(DdApaDigit, digits));
|
|
|
|
} /* end of Cudd_NewApaNumber */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Makes a copy of an arbitrary precision integer.]
|
|
|
|
Description [Makes a copy of an arbitrary precision integer.]
|
|
|
|
SideEffects [Changes parameter <code>dest</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
void
|
|
Cudd_ApaCopy(
|
|
int digits,
|
|
DdApaNumber source,
|
|
DdApaNumber dest)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < digits; i++) {
|
|
dest[i] = source[i];
|
|
}
|
|
|
|
} /* end of Cudd_ApaCopy */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Adds two arbitrary precision integers.]
|
|
|
|
Description [Adds two arbitrary precision integers. Returns the
|
|
carry out of the most significant digit.]
|
|
|
|
SideEffects [The result of the sum is stored in parameter <code>sum</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdApaDigit
|
|
Cudd_ApaAdd(
|
|
int digits,
|
|
DdApaNumber a,
|
|
DdApaNumber b,
|
|
DdApaNumber sum)
|
|
{
|
|
int i;
|
|
DdApaDoubleDigit partial = 0;
|
|
|
|
for (i = digits - 1; i >= 0; i--) {
|
|
partial = a[i] + b[i] + DD_MSDIGIT(partial);
|
|
sum[i] = (DdApaDigit) DD_LSDIGIT(partial);
|
|
}
|
|
return((DdApaDigit) DD_MSDIGIT(partial));
|
|
|
|
} /* end of Cudd_ApaAdd */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Subtracts two arbitrary precision integers.]
|
|
|
|
Description [Subtracts two arbitrary precision integers. Returns the
|
|
borrow out of the most significant digit.]
|
|
|
|
SideEffects [The result of the subtraction is stored in parameter
|
|
<code>diff</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdApaDigit
|
|
Cudd_ApaSubtract(
|
|
int digits,
|
|
DdApaNumber a,
|
|
DdApaNumber b,
|
|
DdApaNumber diff)
|
|
{
|
|
int i;
|
|
DdApaDoubleDigit partial = DD_APA_BASE;
|
|
|
|
for (i = digits - 1; i >= 0; i--) {
|
|
partial = DD_MSDIGIT(partial) + DD_APA_MASK + a[i] - b[i];
|
|
diff[i] = (DdApaDigit) DD_LSDIGIT(partial);
|
|
}
|
|
return((DdApaDigit) DD_MSDIGIT(partial) - 1);
|
|
|
|
} /* end of Cudd_ApaSubtract */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Divides an arbitrary precision integer by a digit.]
|
|
|
|
Description [Divides an arbitrary precision integer by a digit.]
|
|
|
|
SideEffects [The quotient is returned in parameter <code>quotient</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
DdApaDigit
|
|
Cudd_ApaShortDivision(
|
|
int digits,
|
|
DdApaNumber dividend,
|
|
DdApaDigit divisor,
|
|
DdApaNumber quotient)
|
|
{
|
|
int i;
|
|
DdApaDigit remainder;
|
|
DdApaDoubleDigit partial;
|
|
|
|
remainder = 0;
|
|
for (i = 0; i < digits; i++) {
|
|
partial = remainder * DD_APA_BASE + dividend[i];
|
|
quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor);
|
|
remainder = (DdApaDigit) (partial % divisor);
|
|
}
|
|
|
|
return(remainder);
|
|
|
|
} /* end of Cudd_ApaShortDivision */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Divides an arbitrary precision integer by an integer.]
|
|
|
|
Description [Divides an arbitrary precision integer by a 32-bit
|
|
unsigned integer. Returns the remainder of the division. This
|
|
procedure relies on the assumption that the number of bits of a
|
|
DdApaDigit plus the number of bits of an unsigned int is less the
|
|
number of bits of the mantissa of a double. This guarantees that the
|
|
product of a DdApaDigit and an unsigned int can be represented
|
|
without loss of precision by a double. On machines where this
|
|
assumption is not satisfied, this procedure will malfunction.]
|
|
|
|
SideEffects [The quotient is returned in parameter <code>quotient</code>.]
|
|
|
|
SeeAlso [Cudd_ApaShortDivision]
|
|
|
|
******************************************************************************/
|
|
unsigned int
|
|
Cudd_ApaIntDivision(
|
|
int digits,
|
|
DdApaNumber dividend,
|
|
unsigned int divisor,
|
|
DdApaNumber quotient)
|
|
{
|
|
int i;
|
|
double partial;
|
|
unsigned int remainder = 0;
|
|
double ddiv = (double) divisor;
|
|
|
|
for (i = 0; i < digits; i++) {
|
|
partial = (double) remainder * DD_APA_BASE + dividend[i];
|
|
quotient[i] = (DdApaDigit) (partial / ddiv);
|
|
remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv));
|
|
}
|
|
|
|
return(remainder);
|
|
|
|
} /* end of Cudd_ApaIntDivision */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Shifts right an arbitrary precision integer by one binary
|
|
place.]
|
|
|
|
Description [Shifts right an arbitrary precision integer by one
|
|
binary place. The most significant binary digit of the result is
|
|
taken from parameter <code>in</code>.]
|
|
|
|
SideEffects [The result is returned in parameter <code>b</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
void
|
|
Cudd_ApaShiftRight(
|
|
int digits,
|
|
DdApaDigit in,
|
|
DdApaNumber a,
|
|
DdApaNumber b)
|
|
{
|
|
int i;
|
|
|
|
for (i = digits - 1; i > 0; i--) {
|
|
b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1));
|
|
}
|
|
b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1));
|
|
|
|
} /* end of Cudd_ApaShiftRight */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Sets an arbitrary precision integer to a one-digit literal.]
|
|
|
|
Description [Sets an arbitrary precision integer to a one-digit literal.]
|
|
|
|
SideEffects [The result is returned in parameter <code>number</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
void
|
|
Cudd_ApaSetToLiteral(
|
|
int digits,
|
|
DdApaNumber number,
|
|
DdApaDigit literal)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < digits - 1; i++)
|
|
number[i] = 0;
|
|
number[digits - 1] = literal;
|
|
|
|
} /* end of Cudd_ApaSetToLiteral */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Sets an arbitrary precision integer to a power of two.]
|
|
|
|
Description [Sets an arbitrary precision integer to a power of
|
|
two. If the power of two is too large to be represented, the number
|
|
is set to 0.]
|
|
|
|
SideEffects [The result is returned in parameter <code>number</code>.]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
void
|
|
Cudd_ApaPowerOfTwo(
|
|
int digits,
|
|
DdApaNumber number,
|
|
int power)
|
|
{
|
|
int i;
|
|
int index;
|
|
|
|
for (i = 0; i < digits; i++)
|
|
number[i] = 0;
|
|
i = digits - 1 - power / DD_APA_BITS;
|
|
if (i < 0) return;
|
|
index = power & (DD_APA_BITS - 1);
|
|
number[i] = 1 << index;
|
|
|
|
} /* end of Cudd_ApaPowerOfTwo */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Compares two arbitrary precision integers.]
|
|
|
|
Description [Compares two arbitrary precision integers. Returns 1 if
|
|
the first number is larger; 0 if they are equal; -1 if the second
|
|
number is larger.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaCompare(
|
|
int digitsFirst,
|
|
DdApaNumber first,
|
|
int digitsSecond,
|
|
DdApaNumber second)
|
|
{
|
|
int i;
|
|
int firstNZ, secondNZ;
|
|
|
|
/* Find first non-zero in both numbers. */
|
|
for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++)
|
|
if (first[firstNZ] != 0) break;
|
|
for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++)
|
|
if (second[secondNZ] != 0) break;
|
|
if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1);
|
|
else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1);
|
|
for (i = 0; i < digitsFirst - firstNZ; i++) {
|
|
if (first[firstNZ + i] > second[secondNZ + i]) return(1);
|
|
else if (first[firstNZ + i] < second[secondNZ + i]) return(-1);
|
|
}
|
|
return(0);
|
|
|
|
} /* end of Cudd_ApaCompare */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Compares the ratios of two arbitrary precision integers to two
|
|
unsigned ints.]
|
|
|
|
Description [Compares the ratios of two arbitrary precision integers
|
|
to two unsigned ints. Returns 1 if the first number is larger; 0 if
|
|
they are equal; -1 if the second number is larger.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaCompareRatios(
|
|
int digitsFirst,
|
|
DdApaNumber firstNum,
|
|
unsigned int firstDen,
|
|
int digitsSecond,
|
|
DdApaNumber secondNum,
|
|
unsigned int secondDen)
|
|
{
|
|
int result;
|
|
DdApaNumber first, second;
|
|
unsigned int firstRem, secondRem;
|
|
|
|
first = Cudd_NewApaNumber(digitsFirst);
|
|
firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first);
|
|
second = Cudd_NewApaNumber(digitsSecond);
|
|
secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second);
|
|
result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second);
|
|
FREE(first);
|
|
FREE(second);
|
|
if (result == 0) {
|
|
if ((double)firstRem/firstDen > (double)secondRem/secondDen)
|
|
return(1);
|
|
else if ((double)firstRem/firstDen < (double)secondRem/secondDen)
|
|
return(-1);
|
|
}
|
|
return(result);
|
|
|
|
} /* end of Cudd_ApaCompareRatios */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints an arbitrary precision integer in hexadecimal format.]
|
|
|
|
Description [Prints an arbitrary precision integer in hexadecimal format.
|
|
Returns 1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso [Cudd_ApaPrintDecimal Cudd_ApaPrintExponential]
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintHex(
|
|
FILE * fp,
|
|
int digits,
|
|
DdApaNumber number)
|
|
{
|
|
int i, result;
|
|
|
|
for (i = 0; i < digits; i++) {
|
|
result = fprintf(fp,DD_APA_HEXPRINT,number[i]);
|
|
if (result == EOF)
|
|
return(0);
|
|
}
|
|
return(1);
|
|
|
|
} /* end of Cudd_ApaPrintHex */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints an arbitrary precision integer in decimal format.]
|
|
|
|
Description [Prints an arbitrary precision integer in decimal format.
|
|
Returns 1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintExponential]
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintDecimal(
|
|
FILE * fp,
|
|
int digits,
|
|
DdApaNumber number)
|
|
{
|
|
int i, result;
|
|
DdApaDigit remainder;
|
|
DdApaNumber work;
|
|
unsigned char *decimal;
|
|
int leadingzero;
|
|
int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
|
|
|
|
work = Cudd_NewApaNumber(digits);
|
|
if (work == NULL)
|
|
return(0);
|
|
decimal = ALLOC(unsigned char, decimalDigits);
|
|
if (decimal == NULL) {
|
|
FREE(work);
|
|
return(0);
|
|
}
|
|
Cudd_ApaCopy(digits,number,work);
|
|
for (i = decimalDigits - 1; i >= 0; i--) {
|
|
remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
|
|
decimal[i] = (unsigned char) remainder;
|
|
}
|
|
FREE(work);
|
|
|
|
leadingzero = 1;
|
|
for (i = 0; i < decimalDigits; i++) {
|
|
leadingzero = leadingzero && (decimal[i] == 0);
|
|
if ((!leadingzero) || (i == (decimalDigits - 1))) {
|
|
result = fprintf(fp,"%1d",decimal[i]);
|
|
if (result == EOF) {
|
|
FREE(decimal);
|
|
return(0);
|
|
}
|
|
}
|
|
}
|
|
FREE(decimal);
|
|
return(1);
|
|
|
|
} /* end of Cudd_ApaPrintDecimal */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints an arbitrary precision integer in exponential format.]
|
|
|
|
Description [Prints an arbitrary precision integer in exponential format.
|
|
Returns 1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso [Cudd_ApaPrintHex Cudd_ApaPrintDecimal]
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintExponential(
|
|
FILE * fp,
|
|
int digits,
|
|
DdApaNumber number,
|
|
int precision)
|
|
{
|
|
int i, first, last, result;
|
|
DdApaDigit remainder;
|
|
DdApaNumber work;
|
|
unsigned char *decimal;
|
|
int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
|
|
|
|
work = Cudd_NewApaNumber(digits);
|
|
if (work == NULL)
|
|
return(0);
|
|
decimal = ALLOC(unsigned char, decimalDigits);
|
|
if (decimal == NULL) {
|
|
FREE(work);
|
|
return(0);
|
|
}
|
|
Cudd_ApaCopy(digits,number,work);
|
|
first = decimalDigits - 1;
|
|
for (i = decimalDigits - 1; i >= 0; i--) {
|
|
remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
|
|
decimal[i] = (unsigned char) remainder;
|
|
if (remainder != 0) first = i; /* keep track of MS non-zero */
|
|
}
|
|
FREE(work);
|
|
last = ddMin(first + precision, decimalDigits);
|
|
|
|
for (i = first; i < last; i++) {
|
|
result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]);
|
|
if (result == EOF) {
|
|
FREE(decimal);
|
|
return(0);
|
|
}
|
|
}
|
|
FREE(decimal);
|
|
result = fprintf(fp,"e+%d",decimalDigits - first - 1);
|
|
if (result == EOF) {
|
|
return(0);
|
|
}
|
|
return(1);
|
|
|
|
} /* end of Cudd_ApaPrintExponential */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Counts the number of minterms of a DD.]
|
|
|
|
Description [Counts the number of minterms of a DD. The function is
|
|
assumed to depend on nvars variables. The minterm count is
|
|
represented as an arbitrary precision unsigned integer, to allow for
|
|
any number of variables CUDD supports. Returns a pointer to the
|
|
array representing the number of minterms of the function rooted at
|
|
node if successful; NULL otherwise.]
|
|
|
|
SideEffects [The number of digits of the result is returned in
|
|
parameter <code>digits</code>.]
|
|
|
|
SeeAlso [Cudd_CountMinterm]
|
|
|
|
******************************************************************************/
|
|
DdApaNumber
|
|
Cudd_ApaCountMinterm(
|
|
DdManager * manager,
|
|
DdNode * node,
|
|
int nvars,
|
|
int * digits)
|
|
{
|
|
DdApaNumber max, min;
|
|
st_table *table;
|
|
DdApaNumber i,count;
|
|
|
|
background = manager->background;
|
|
zero = Cudd_Not(manager->one);
|
|
|
|
*digits = Cudd_ApaNumberOfDigits(nvars+1);
|
|
max = Cudd_NewApaNumber(*digits);
|
|
if (max == NULL) {
|
|
return(NULL);
|
|
}
|
|
Cudd_ApaPowerOfTwo(*digits,max,nvars);
|
|
min = Cudd_NewApaNumber(*digits);
|
|
if (min == NULL) {
|
|
FREE(max);
|
|
return(NULL);
|
|
}
|
|
Cudd_ApaSetToLiteral(*digits,min,0);
|
|
table = st_init_table(st_ptrcmp,st_ptrhash);
|
|
if (table == NULL) {
|
|
FREE(max);
|
|
FREE(min);
|
|
return(NULL);
|
|
}
|
|
i = cuddApaCountMintermAux(Cudd_Regular(node),*digits,max,min,table);
|
|
if (i == NULL) {
|
|
FREE(max);
|
|
FREE(min);
|
|
st_foreach(table, cuddApaStCountfree, NULL);
|
|
st_free_table(table);
|
|
return(NULL);
|
|
}
|
|
count = Cudd_NewApaNumber(*digits);
|
|
if (count == NULL) {
|
|
FREE(max);
|
|
FREE(min);
|
|
st_foreach(table, cuddApaStCountfree, NULL);
|
|
st_free_table(table);
|
|
if (Cudd_Regular(node)->ref == 1) FREE(i);
|
|
return(NULL);
|
|
}
|
|
if (Cudd_IsComplement(node)) {
|
|
(void) Cudd_ApaSubtract(*digits,max,i,count);
|
|
} else {
|
|
Cudd_ApaCopy(*digits,i,count);
|
|
}
|
|
FREE(max);
|
|
FREE(min);
|
|
st_foreach(table, cuddApaStCountfree, NULL);
|
|
st_free_table(table);
|
|
if (Cudd_Regular(node)->ref == 1) FREE(i);
|
|
return(count);
|
|
|
|
} /* end of Cudd_ApaCountMinterm */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints the number of minterms of a BDD or ADD using
|
|
arbitrary precision arithmetic.]
|
|
|
|
Description [Prints the number of minterms of a BDD or ADD using
|
|
arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso [Cudd_ApaPrintMintermExp]
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintMinterm(
|
|
FILE * fp,
|
|
DdManager * dd,
|
|
DdNode * node,
|
|
int nvars)
|
|
{
|
|
int digits;
|
|
int result;
|
|
DdApaNumber count;
|
|
|
|
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
|
|
if (count == NULL)
|
|
return(0);
|
|
result = Cudd_ApaPrintDecimal(fp,digits,count);
|
|
FREE(count);
|
|
if (fprintf(fp,"\n") == EOF) {
|
|
return(0);
|
|
}
|
|
return(result);
|
|
|
|
} /* end of Cudd_ApaPrintMinterm */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints the number of minterms of a BDD or ADD in exponential
|
|
format using arbitrary precision arithmetic.]
|
|
|
|
Description [Prints the number of minterms of a BDD or ADD in
|
|
exponential format using arbitrary precision arithmetic. Parameter
|
|
precision controls the number of signficant digits printed. Returns
|
|
1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso [Cudd_ApaPrintMinterm]
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintMintermExp(
|
|
FILE * fp,
|
|
DdManager * dd,
|
|
DdNode * node,
|
|
int nvars,
|
|
int precision)
|
|
{
|
|
int digits;
|
|
int result;
|
|
DdApaNumber count;
|
|
|
|
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
|
|
if (count == NULL)
|
|
return(0);
|
|
result = Cudd_ApaPrintExponential(fp,digits,count,precision);
|
|
FREE(count);
|
|
if (fprintf(fp,"\n") == EOF) {
|
|
return(0);
|
|
}
|
|
return(result);
|
|
|
|
} /* end of Cudd_ApaPrintMintermExp */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Prints the density of a BDD or ADD using
|
|
arbitrary precision arithmetic.]
|
|
|
|
Description [Prints the density of a BDD or ADD using
|
|
arbitrary precision arithmetic. Returns 1 if successful; 0 otherwise.]
|
|
|
|
SideEffects [None]
|
|
|
|
SeeAlso []
|
|
|
|
******************************************************************************/
|
|
int
|
|
Cudd_ApaPrintDensity(
|
|
FILE * fp,
|
|
DdManager * dd,
|
|
DdNode * node,
|
|
int nvars)
|
|
{
|
|
int digits;
|
|
int result;
|
|
DdApaNumber count,density;
|
|
unsigned int size, remainder, fractional;
|
|
|
|
count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
|
|
if (count == NULL)
|
|
return(0);
|
|
size = Cudd_DagSize(node);
|
|
density = Cudd_NewApaNumber(digits);
|
|
remainder = Cudd_ApaIntDivision(digits,count,size,density);
|
|
result = Cudd_ApaPrintDecimal(fp,digits,density);
|
|
FREE(count);
|
|
FREE(density);
|
|
fractional = (unsigned int)((double)remainder / size * 1000000);
|
|
if (fprintf(fp,".%u\n", fractional) == EOF) {
|
|
return(0);
|
|
}
|
|
return(result);
|
|
|
|
} /* end of Cudd_ApaPrintDensity */
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of internal functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Definition of static functions */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Performs the recursive step of Cudd_ApaCountMinterm.]
|
|
|
|
Description [Performs the recursive step of Cudd_ApaCountMinterm.
|
|
It is based on the following identity. Let |f| be the
|
|
number of minterms of f. Then:
|
|
<xmp>
|
|
|f| = (|f0|+|f1|)/2
|
|
</xmp>
|
|
where f0 and f1 are the two cofactors of f.
|
|
Uses the identity <code>|f'| = max - |f|</code>.
|
|
The procedure expects the argument "node" to be a regular pointer, and
|
|
guarantees this condition is met in the recursive calls.
|
|
For efficiency, the result of a call is cached only if the node has
|
|
a reference count greater than 1.
|
|
Returns the number of minterms of the function rooted at node.]
|
|
|
|
SideEffects [None]
|
|
|
|
******************************************************************************/
|
|
static DdApaNumber
|
|
cuddApaCountMintermAux(
|
|
DdNode * node,
|
|
int digits,
|
|
DdApaNumber max,
|
|
DdApaNumber min,
|
|
st_table * table)
|
|
{
|
|
DdNode *Nt, *Ne;
|
|
DdApaNumber mint, mint1, mint2;
|
|
DdApaDigit carryout;
|
|
|
|
if (cuddIsConstant(node)) {
|
|
if (node == background || node == zero) {
|
|
return(min);
|
|
} else {
|
|
return(max);
|
|
}
|
|
}
|
|
if (node->ref > 1 && st_lookup(table, node, &mint)) {
|
|
return(mint);
|
|
}
|
|
|
|
Nt = cuddT(node); Ne = cuddE(node);
|
|
|
|
mint1 = cuddApaCountMintermAux(Nt, digits, max, min, table);
|
|
if (mint1 == NULL) return(NULL);
|
|
mint2 = cuddApaCountMintermAux(Cudd_Regular(Ne), digits, max, min, table);
|
|
if (mint2 == NULL) {
|
|
if (Nt->ref == 1) FREE(mint1);
|
|
return(NULL);
|
|
}
|
|
mint = Cudd_NewApaNumber(digits);
|
|
if (mint == NULL) {
|
|
if (Nt->ref == 1) FREE(mint1);
|
|
if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
|
|
return(NULL);
|
|
}
|
|
if (Cudd_IsComplement(Ne)) {
|
|
(void) Cudd_ApaSubtract(digits,max,mint2,mint);
|
|
carryout = Cudd_ApaAdd(digits,mint1,mint,mint);
|
|
} else {
|
|
carryout = Cudd_ApaAdd(digits,mint1,mint2,mint);
|
|
}
|
|
Cudd_ApaShiftRight(digits,carryout,mint,mint);
|
|
/* If the refernce count of a child is 1, its minterm count
|
|
** hasn't been stored in table. Therefore, it must be explicitly
|
|
** freed here. */
|
|
if (Nt->ref == 1) FREE(mint1);
|
|
if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
|
|
|
|
if (node->ref > 1) {
|
|
if (st_insert(table, (char *)node, (char *)mint) == ST_OUT_OF_MEM) {
|
|
FREE(mint);
|
|
return(NULL);
|
|
}
|
|
}
|
|
return(mint);
|
|
|
|
} /* end of cuddApaCountMintermAux */
|
|
|
|
|
|
/**Function********************************************************************
|
|
|
|
Synopsis [Frees the memory used to store the minterm counts recorded
|
|
in the visited table.]
|
|
|
|
Description [Frees the memory used to store the minterm counts
|
|
recorded in the visited table. Returns ST_CONTINUE.]
|
|
|
|
SideEffects [None]
|
|
|
|
******************************************************************************/
|
|
static enum st_retval
|
|
cuddApaStCountfree(
|
|
char * key,
|
|
char * value,
|
|
char * arg)
|
|
{
|
|
DdApaNumber d;
|
|
|
|
d = (DdApaNumber) value;
|
|
FREE(d);
|
|
return(ST_CONTINUE);
|
|
|
|
} /* end of cuddApaStCountfree */
|