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.

1070 lines
26 KiB

2 months ago
  1. /**
  2. @file
  3. @ingroup cudd
  4. @brief Arbitrary precision arithmetic functions.
  5. @details This file provides just enough functionality as needed
  6. by CUDD to compute the number of minterms of functions with many
  7. variables.
  8. @author Fabio Somenzi
  9. @copyright@parblock
  10. Copyright (c) 1995-2015, Regents of the University of Colorado
  11. All rights reserved.
  12. Redistribution and use in source and binary forms, with or without
  13. modification, are permitted provided that the following conditions
  14. are met:
  15. Redistributions of source code must retain the above copyright
  16. notice, this list of conditions and the following disclaimer.
  17. Redistributions in binary form must reproduce the above copyright
  18. notice, this list of conditions and the following disclaimer in the
  19. documentation and/or other materials provided with the distribution.
  20. Neither the name of the University of Colorado nor the names of its
  21. contributors may be used to endorse or promote products derived from
  22. this software without specific prior written permission.
  23. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  26. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  27. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  29. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  30. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  31. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  33. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. POSSIBILITY OF SUCH DAMAGE.
  35. @endparblock
  36. */
  37. #include "util.h"
  38. #include "cuddInt.h"
  39. /*---------------------------------------------------------------------------*/
  40. /* Constant declarations */
  41. /*---------------------------------------------------------------------------*/
  42. /* These constants define the digits used in the representation of
  43. ** arbitrary precision integers.
  44. */
  45. #define DD_APA_BITS ((int) sizeof(DdApaDigit) * 8)
  46. #define DD_APA_BASE ((DdApaDoubleDigit) 1 << DD_APA_BITS)
  47. #define DD_APA_MASK (DD_APA_BASE - 1)
  48. /*---------------------------------------------------------------------------*/
  49. /* Stucture declarations */
  50. /*---------------------------------------------------------------------------*/
  51. /*---------------------------------------------------------------------------*/
  52. /* Type declarations */
  53. /*---------------------------------------------------------------------------*/
  54. /**
  55. @brief Type used for intermediate results.
  56. */
  57. typedef uint64_t DdApaDoubleDigit;
  58. /*---------------------------------------------------------------------------*/
  59. /* Variable declarations */
  60. /*---------------------------------------------------------------------------*/
  61. /*---------------------------------------------------------------------------*/
  62. /* Macro declarations */
  63. /*---------------------------------------------------------------------------*/
  64. /**
  65. @brief Extract the least significant digit of a double digit.
  66. @sideeffect None
  67. @see DD_MSDIGIT
  68. */
  69. #define DD_LSDIGIT(x) ((x) & DD_APA_MASK)
  70. /**
  71. @brief Extract the most significant digit of a double digit.
  72. @sideeffect None
  73. @see DD_LSDIGIT
  74. */
  75. #define DD_MSDIGIT(x) ((x) >> DD_APA_BITS)
  76. /** \cond */
  77. /*---------------------------------------------------------------------------*/
  78. /* Static function prototypes */
  79. /*---------------------------------------------------------------------------*/
  80. static DdApaNumber cuddApaCountMintermAux (DdManager const * manager, DdNode * node, int digits, DdApaNumber mmax, DdApaNumber mmin, st_table * table);
  81. static enum st_retval cuddApaStCountfree (void * key, void * value, void * arg);
  82. /** \endcond */
  83. /*---------------------------------------------------------------------------*/
  84. /* Definition of exported functions */
  85. /*---------------------------------------------------------------------------*/
  86. /**
  87. @brief Returns the number of digits for an arbitrary precision
  88. integer.
  89. @details Finds the number of digits for an arbitrary precision
  90. integer given the maximum number of binary digits. The number of
  91. binary digits should be positive.
  92. @sideeffect None
  93. */
  94. int
  95. Cudd_ApaNumberOfDigits(
  96. int binaryDigits)
  97. {
  98. int digits;
  99. digits = binaryDigits / DD_APA_BITS;
  100. if ((digits * DD_APA_BITS) != binaryDigits)
  101. digits++;
  102. return(digits);
  103. } /* end of Cudd_ApaNumberOfDigits */
  104. /**
  105. @brief Allocates memory for an arbitrary precision integer.
  106. @return a pointer to the allocated memory if successful;
  107. NULL otherwise.
  108. @sideeffect None
  109. @see Cudd_FreeApaNumber
  110. */
  111. DdApaNumber
  112. Cudd_NewApaNumber(
  113. int digits)
  114. {
  115. return(ALLOC(DdApaDigit, digits));
  116. } /* end of Cudd_NewApaNumber */
  117. /**
  118. @brief Frees an arbitrary precision integer.
  119. @sideeffect None
  120. @see Cudd_NewApaNumber
  121. */
  122. void
  123. Cudd_FreeApaNumber(
  124. DdApaNumber number)
  125. {
  126. FREE(number);
  127. } /* end of Cudd_FreeApaNumber */
  128. /**
  129. @brief Makes a copy of an arbitrary precision integer.
  130. @sideeffect Changes parameter <code>dest</code>.
  131. */
  132. void
  133. Cudd_ApaCopy(
  134. int digits,
  135. DdConstApaNumber source,
  136. DdApaNumber dest)
  137. {
  138. int i;
  139. for (i = 0; i < digits; i++) {
  140. dest[i] = source[i];
  141. }
  142. } /* end of Cudd_ApaCopy */
  143. /**
  144. @brief Adds two arbitrary precision integers.
  145. @return the carry out of the most significant digit.
  146. @sideeffect The result of the sum is stored in parameter <code>sum</code>.
  147. */
  148. DdApaDigit
  149. Cudd_ApaAdd(
  150. int digits,
  151. DdConstApaNumber a,
  152. DdConstApaNumber b,
  153. DdApaNumber sum)
  154. {
  155. int i;
  156. DdApaDoubleDigit partial = 0;
  157. for (i = digits - 1; i >= 0; i--) {
  158. partial = DD_MSDIGIT(partial) + a[i] + b[i];
  159. sum[i] = (DdApaDigit) DD_LSDIGIT(partial);
  160. }
  161. return((DdApaDigit) DD_MSDIGIT(partial));
  162. } /* end of Cudd_ApaAdd */
  163. /**
  164. @brief Subtracts two arbitrary precision integers.
  165. @return the borrow out of the most significant digit.
  166. @sideeffect The result of the subtraction is stored in parameter
  167. <code>diff</code>.
  168. */
  169. DdApaDigit
  170. Cudd_ApaSubtract(
  171. int digits,
  172. DdConstApaNumber a,
  173. DdConstApaNumber b,
  174. DdApaNumber diff)
  175. {
  176. int i;
  177. DdApaDoubleDigit partial = DD_APA_BASE;
  178. for (i = digits - 1; i >= 0; i--) {
  179. partial = DD_MSDIGIT(partial) + DD_APA_MASK + a[i] - b[i];
  180. diff[i] = (DdApaDigit) DD_LSDIGIT(partial);
  181. }
  182. return((DdApaDigit) DD_MSDIGIT(partial) - 1);
  183. } /* end of Cudd_ApaSubtract */
  184. /**
  185. @brief Divides an arbitrary precision integer by a digit.
  186. @return the remainder digit.
  187. @sideeffect The quotient is returned in parameter <code>quotient</code>.
  188. */
  189. DdApaDigit
  190. Cudd_ApaShortDivision(
  191. int digits,
  192. DdConstApaNumber dividend,
  193. DdApaDigit divisor,
  194. DdApaNumber quotient)
  195. {
  196. int i;
  197. DdApaDigit remainder;
  198. DdApaDoubleDigit partial;
  199. remainder = 0;
  200. for (i = 0; i < digits; i++) {
  201. partial = remainder * DD_APA_BASE + dividend[i];
  202. quotient[i] = (DdApaDigit) (partial/(DdApaDoubleDigit)divisor);
  203. remainder = (DdApaDigit) (partial % divisor);
  204. }
  205. return(remainder);
  206. } /* end of Cudd_ApaShortDivision */
  207. /**
  208. @brief Divides an arbitrary precision integer by an integer.
  209. @details Divides an arbitrary precision integer by a 32-bit unsigned
  210. integer. This procedure relies on the assumption that the number of
  211. bits of a DdApaDigit plus the number of bits of an unsigned int is
  212. less the number of bits of the mantissa of a double. This guarantees
  213. that the product of a DdApaDigit and an unsigned int can be
  214. represented without loss of precision by a double. On machines where
  215. this assumption is not satisfied, this procedure will malfunction.
  216. @return the remainder.
  217. @sideeffect The quotient is returned in parameter <code>quotient</code>.
  218. @deprecated The assumption on which the correctness of this function rests
  219. is not satisfied by modern-day 64-bit CPUs.
  220. @see Cudd_ApaShortDivision
  221. */
  222. unsigned int
  223. Cudd_ApaIntDivision(
  224. int digits,
  225. DdConstApaNumber dividend,
  226. unsigned int divisor,
  227. DdApaNumber quotient)
  228. {
  229. int i;
  230. double partial;
  231. unsigned int remainder = 0;
  232. double ddiv = (double) divisor;
  233. for (i = 0; i < digits; i++) {
  234. partial = (double) remainder * DD_APA_BASE + dividend[i];
  235. quotient[i] = (DdApaDigit) (partial / ddiv);
  236. remainder = (unsigned int) (partial - ((double)quotient[i] * ddiv));
  237. }
  238. return(remainder);
  239. } /* end of Cudd_ApaIntDivision */
  240. /**
  241. @brief Shifts right an arbitrary precision integer by one binary
  242. place.
  243. @details The most significant binary digit of the result is taken
  244. from parameter <code>in</code>.
  245. @sideeffect The result is returned in parameter <code>b</code>.
  246. */
  247. void
  248. Cudd_ApaShiftRight(
  249. int digits,
  250. DdApaDigit in,
  251. DdConstApaNumber a,
  252. DdApaNumber b)
  253. {
  254. int i;
  255. for (i = digits - 1; i > 0; i--) {
  256. b[i] = (a[i] >> 1) | ((a[i-1] & 1) << (DD_APA_BITS - 1));
  257. }
  258. b[0] = (a[0] >> 1) | (in << (DD_APA_BITS - 1));
  259. } /* end of Cudd_ApaShiftRight */
  260. /**
  261. @brief Sets an arbitrary precision integer to a one-digit literal.
  262. @sideeffect The result is returned in parameter <code>number</code>.
  263. */
  264. void
  265. Cudd_ApaSetToLiteral(
  266. int digits,
  267. DdApaNumber number,
  268. DdApaDigit literal)
  269. {
  270. int i;
  271. for (i = 0; i < digits - 1; i++)
  272. number[i] = 0;
  273. number[digits - 1] = literal;
  274. } /* end of Cudd_ApaSetToLiteral */
  275. /**
  276. @brief Sets an arbitrary precision integer to a power of two.
  277. @details If the power of two is too large to be represented, the number
  278. is set to 0.
  279. @sideeffect The result is returned in parameter <code>number</code>.
  280. */
  281. void
  282. Cudd_ApaPowerOfTwo(
  283. int digits,
  284. DdApaNumber number,
  285. int power)
  286. {
  287. int i;
  288. int index;
  289. for (i = 0; i < digits; i++)
  290. number[i] = 0;
  291. i = digits - 1 - power / DD_APA_BITS;
  292. if (i < 0) return;
  293. index = power & (DD_APA_BITS - 1);
  294. number[i] = (DdApaDigit) 1 << index;
  295. } /* end of Cudd_ApaPowerOfTwo */
  296. /**
  297. @brief Compares two arbitrary precision integers.
  298. @return 1 if the first number is larger; 0 if they are equal; -1 if
  299. the second number is larger.
  300. @sideeffect None
  301. */
  302. int
  303. Cudd_ApaCompare(
  304. int digitsFirst,
  305. DdConstApaNumber first,
  306. int digitsSecond,
  307. DdConstApaNumber second)
  308. {
  309. int i;
  310. int firstNZ, secondNZ;
  311. /* Find first non-zero in both numbers. */
  312. for (firstNZ = 0; firstNZ < digitsFirst; firstNZ++)
  313. if (first[firstNZ] != 0) break;
  314. for (secondNZ = 0; secondNZ < digitsSecond; secondNZ++)
  315. if (second[secondNZ] != 0) break;
  316. if (digitsFirst - firstNZ > digitsSecond - secondNZ) return(1);
  317. else if (digitsFirst - firstNZ < digitsSecond - secondNZ) return(-1);
  318. for (i = 0; i < digitsFirst - firstNZ; i++) {
  319. if (first[firstNZ + i] > second[secondNZ + i]) return(1);
  320. else if (first[firstNZ + i] < second[secondNZ + i]) return(-1);
  321. }
  322. return(0);
  323. } /* end of Cudd_ApaCompare */
  324. /**
  325. @brief Compares the ratios of two arbitrary precision integers to two
  326. unsigned ints.
  327. @return 1 if the first number is larger; 0 if they are equal; -1 if
  328. the second number is larger.
  329. @sideeffect None
  330. */
  331. int
  332. Cudd_ApaCompareRatios(
  333. int digitsFirst,
  334. DdConstApaNumber firstNum,
  335. unsigned int firstDen,
  336. int digitsSecond,
  337. DdConstApaNumber secondNum,
  338. unsigned int secondDen)
  339. {
  340. int result;
  341. DdApaNumber first, second;
  342. unsigned int firstRem, secondRem;
  343. first = Cudd_NewApaNumber(digitsFirst);
  344. firstRem = Cudd_ApaIntDivision(digitsFirst,firstNum,firstDen,first);
  345. second = Cudd_NewApaNumber(digitsSecond);
  346. secondRem = Cudd_ApaIntDivision(digitsSecond,secondNum,secondDen,second);
  347. result = Cudd_ApaCompare(digitsFirst,first,digitsSecond,second);
  348. FREE(first);
  349. FREE(second);
  350. if (result == 0) {
  351. if ((double)firstRem/firstDen > (double)secondRem/secondDen)
  352. return(1);
  353. else if ((double)firstRem/firstDen < (double)secondRem/secondDen)
  354. return(-1);
  355. }
  356. return(result);
  357. } /* end of Cudd_ApaCompareRatios */
  358. /**
  359. @brief Prints an arbitrary precision integer in hexadecimal format.
  360. @return 1 if successful; 0 otherwise.
  361. @sideeffect None
  362. @see Cudd_ApaPrintDecimal Cudd_ApaPrintExponential
  363. */
  364. int
  365. Cudd_ApaPrintHex(
  366. FILE * fp,
  367. int digits,
  368. DdConstApaNumber number)
  369. {
  370. int i, result;
  371. for (i = 0; i < digits; i++) {
  372. result = fprintf(fp, "%0*x", (int) sizeof(DdApaDigit) * 2, number[i]);
  373. if (result == EOF)
  374. return(0);
  375. }
  376. return(1);
  377. } /* end of Cudd_ApaPrintHex */
  378. /**
  379. @brief Prints an arbitrary precision integer in decimal format.
  380. @return 1 if successful; 0 otherwise.
  381. @sideeffect None
  382. @see Cudd_ApaPrintHex Cudd_ApaPrintExponential
  383. */
  384. int
  385. Cudd_ApaPrintDecimal(
  386. FILE * fp,
  387. int digits,
  388. DdConstApaNumber number)
  389. {
  390. int i, result;
  391. DdApaDigit remainder;
  392. DdApaNumber work;
  393. unsigned char *decimal;
  394. int leadingzero;
  395. int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
  396. work = Cudd_NewApaNumber(digits);
  397. if (work == NULL)
  398. return(0);
  399. decimal = ALLOC(unsigned char, decimalDigits);
  400. if (decimal == NULL) {
  401. FREE(work);
  402. return(0);
  403. }
  404. Cudd_ApaCopy(digits,number,work);
  405. for (i = decimalDigits - 1; i >= 0; i--) {
  406. remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
  407. decimal[i] = (unsigned char) remainder;
  408. }
  409. FREE(work);
  410. leadingzero = 1;
  411. for (i = 0; i < decimalDigits; i++) {
  412. leadingzero = leadingzero && (decimal[i] == 0);
  413. if ((!leadingzero) || (i == (decimalDigits - 1))) {
  414. result = fprintf(fp,"%1d",decimal[i]);
  415. if (result == EOF) {
  416. FREE(decimal);
  417. return(0);
  418. }
  419. }
  420. }
  421. FREE(decimal);
  422. return(1);
  423. } /* end of Cudd_ApaPrintDecimal */
  424. /**
  425. @brief converts an arbitrary precision integer to a string in decimal format.
  426. @return the string if successful; NULL otherwise.
  427. @sideeffect None
  428. @see Cudd_ApaPrintDecimal
  429. */
  430. char *
  431. Cudd_ApaStringDecimal(
  432. int digits,
  433. DdConstApaNumber number)
  434. {
  435. int i, fsd;
  436. DdApaDigit remainder;
  437. DdApaNumber work;
  438. char *decimal, *ret;
  439. int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 1;
  440. work = Cudd_NewApaNumber(digits);
  441. if (work == NULL) {
  442. return(0);
  443. }
  444. decimal = ALLOC(char, decimalDigits);
  445. if (decimal == NULL) {
  446. FREE(work);
  447. return(0);
  448. }
  449. Cudd_ApaCopy(digits,number,work);
  450. for (i = decimalDigits - 1; i >= 0; i--) {
  451. remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
  452. decimal[i] = (char) remainder;
  453. }
  454. FREE(work);
  455. /* Find first significant digit. */
  456. for (fsd = 0; fsd < decimalDigits-1; fsd++) {
  457. if (decimal[fsd] != 0)
  458. break;
  459. }
  460. ret = ALLOC(char, decimalDigits - fsd + 1);
  461. if (ret == NULL) {
  462. FREE(decimal);
  463. return(NULL);
  464. }
  465. for (i = fsd; i < decimalDigits; i++) {
  466. ret[i-fsd] = decimal[i] + '0';
  467. }
  468. ret[decimalDigits-fsd] = '\0';
  469. FREE(decimal);
  470. return(ret);
  471. } /* end of Cudd_ApaStringDecimal */
  472. /**
  473. @brief Prints an arbitrary precision integer in exponential format.
  474. @details Prints as an integer if precision is at least the number of
  475. digits to be printed. If precision does not allow printing of all
  476. digits, rounds to nearest breaking ties so that the last printed
  477. digit is even.
  478. @return 1 if successful; 0 otherwise.
  479. @sideeffect None
  480. @see Cudd_ApaPrintHex Cudd_ApaPrintDecimal
  481. */
  482. int
  483. Cudd_ApaPrintExponential(
  484. FILE * fp,
  485. int digits,
  486. DdConstApaNumber number,
  487. int precision)
  488. {
  489. int i, first, last, result;
  490. DdApaDigit remainder;
  491. DdApaNumber work;
  492. unsigned char *decimal, carry;
  493. /* We add an extra digit to have room for rounding up. */
  494. int decimalDigits = (int) (digits * log10((double) DD_APA_BASE)) + 2;
  495. /* Convert to decimal. */
  496. work = Cudd_NewApaNumber(digits);
  497. if (work == NULL)
  498. return(0);
  499. decimal = ALLOC(unsigned char, decimalDigits);
  500. if (decimal == NULL) {
  501. FREE(work);
  502. return(0);
  503. }
  504. Cudd_ApaCopy(digits,number,work);
  505. first = decimalDigits - 1;
  506. for (i = decimalDigits - 1; i >= 0; i--) {
  507. remainder = Cudd_ApaShortDivision(digits,work,(DdApaDigit) 10,work);
  508. decimal[i] = (unsigned char) remainder;
  509. if (remainder != 0) first = i; /* keep track of MS non-zero */
  510. }
  511. FREE(work);
  512. last = ddMin(first + precision, decimalDigits);
  513. /* See if we can print as integer. */
  514. if (decimalDigits - first <= precision) {
  515. for (i = first; i < last; i++) {
  516. result = fprintf(fp,"%1d", decimal[i]);
  517. if (result == EOF) {
  518. FREE(decimal);
  519. return(0);
  520. }
  521. }
  522. FREE(decimal);
  523. return(1);
  524. }
  525. /* If we get here we need to print an exponent. Take care of rounding. */
  526. if (last == decimalDigits) {
  527. carry = 0;
  528. } else if (decimal[last] < 5) {
  529. carry = 0;
  530. } else if (decimal[last] == 5) {
  531. int nonZero = CUDD_FALSE;
  532. for (i = last + 1; i < decimalDigits; i++) {
  533. if (decimal[i] > 0) {
  534. nonZero = CUDD_TRUE;
  535. break;
  536. }
  537. }
  538. if (nonZero) {
  539. carry = 1;
  540. } else if (decimal[last - 1] & 1) { /* odd */
  541. carry = 1;
  542. } else {
  543. carry = 0;
  544. }
  545. } else {
  546. carry = 1;
  547. }
  548. /* Add carry. */
  549. for (i = last - 1; i >= 0; i--) {
  550. unsigned char tmp = decimal[i] + carry;
  551. if (tmp < 10) {
  552. decimal[i] = tmp;
  553. break;
  554. } else {
  555. decimal[i] = tmp - 10;
  556. }
  557. }
  558. /* Don't print trailing zeros. */
  559. while (last > first && decimal[last - 1] == 0)
  560. last--;
  561. /* Print. */
  562. for (i = first; i < last; i++) {
  563. result = fprintf(fp,"%s%1d",i == first+1 ? "." : "", decimal[i]);
  564. if (result == EOF) {
  565. FREE(decimal);
  566. return(0);
  567. }
  568. }
  569. FREE(decimal);
  570. result = fprintf(fp,"e+%02d",decimalDigits - first - 1);
  571. if (result == EOF) {
  572. return(0);
  573. }
  574. return(1);
  575. } /* end of Cudd_ApaPrintExponential */
  576. /**
  577. @brief Counts the number of minterms of a %DD.
  578. @details The function is assumed to depend on nvars variables. The
  579. minterm count is represented as an arbitrary precision unsigned
  580. integer, to allow for any number of variables CUDD supports.
  581. @return a pointer to the array representing the number of minterms
  582. of the function rooted at node if successful; NULL otherwise.
  583. @sideeffect The number of digits of the result is returned in
  584. parameter <code>digits</code>.
  585. @see Cudd_CountMinterm
  586. */
  587. DdApaNumber
  588. Cudd_ApaCountMinterm(
  589. DdManager const * manager,
  590. DdNode * node,
  591. int nvars,
  592. int * digits)
  593. {
  594. DdApaNumber mmax, mmin;
  595. st_table *table;
  596. DdApaNumber i,count;
  597. *digits = Cudd_ApaNumberOfDigits(nvars+1);
  598. mmax = Cudd_NewApaNumber(*digits);
  599. if (mmax == NULL) {
  600. return(NULL);
  601. }
  602. Cudd_ApaPowerOfTwo(*digits,mmax,nvars);
  603. mmin = Cudd_NewApaNumber(*digits);
  604. if (mmin == NULL) {
  605. FREE(mmax);
  606. return(NULL);
  607. }
  608. Cudd_ApaSetToLiteral(*digits,mmin,0);
  609. table = st_init_table(st_ptrcmp,st_ptrhash);
  610. if (table == NULL) {
  611. FREE(mmax);
  612. FREE(mmin);
  613. return(NULL);
  614. }
  615. i = cuddApaCountMintermAux(manager, Cudd_Regular(node),*digits,mmax,mmin,table);
  616. if (i == NULL) {
  617. FREE(mmax);
  618. FREE(mmin);
  619. st_foreach(table, cuddApaStCountfree, NULL);
  620. st_free_table(table);
  621. return(NULL);
  622. }
  623. count = Cudd_NewApaNumber(*digits);
  624. if (count == NULL) {
  625. FREE(mmax);
  626. FREE(mmin);
  627. st_foreach(table, cuddApaStCountfree, NULL);
  628. st_free_table(table);
  629. if (Cudd_Regular(node)->ref == 1) FREE(i);
  630. return(NULL);
  631. }
  632. if (Cudd_IsComplement(node)) {
  633. (void) Cudd_ApaSubtract(*digits,mmax,i,count);
  634. } else {
  635. Cudd_ApaCopy(*digits,i,count);
  636. }
  637. FREE(mmax);
  638. FREE(mmin);
  639. st_foreach(table, cuddApaStCountfree, NULL);
  640. st_free_table(table);
  641. if (Cudd_Regular(node)->ref == 1) FREE(i);
  642. return(count);
  643. } /* end of Cudd_ApaCountMinterm */
  644. /**
  645. @brief Prints the number of minterms of a %BDD or %ADD using arbitrary
  646. precision arithmetic.
  647. @return 1 if successful; 0 otherwise.
  648. @sideeffect None
  649. @see Cudd_ApaPrintMintermExp
  650. */
  651. int
  652. Cudd_ApaPrintMinterm(
  653. FILE * fp,
  654. DdManager const * dd,
  655. DdNode * node,
  656. int nvars)
  657. {
  658. int digits;
  659. int result;
  660. DdApaNumber count;
  661. count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
  662. if (count == NULL)
  663. return(0);
  664. result = Cudd_ApaPrintDecimal(fp,digits,count);
  665. FREE(count);
  666. if (fprintf(fp,"\n") == EOF) {
  667. return(0);
  668. }
  669. return(result);
  670. } /* end of Cudd_ApaPrintMinterm */
  671. /**
  672. @brief Prints the number of minterms of a %BDD or %ADD in
  673. exponential format using arbitrary precision arithmetic.
  674. @details Parameter precision controls the number of signficant
  675. digits printed.
  676. @return 1 if successful; 0 otherwise.
  677. @sideeffect None
  678. @see Cudd_ApaPrintMinterm
  679. */
  680. int
  681. Cudd_ApaPrintMintermExp(
  682. FILE * fp,
  683. DdManager const * dd,
  684. DdNode * node,
  685. int nvars,
  686. int precision)
  687. {
  688. int digits;
  689. int result;
  690. DdApaNumber count;
  691. count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
  692. if (count == NULL)
  693. return(0);
  694. result = Cudd_ApaPrintExponential(fp,digits,count,precision);
  695. FREE(count);
  696. if (fprintf(fp,"\n") == EOF) {
  697. return(0);
  698. }
  699. return(result);
  700. } /* end of Cudd_ApaPrintMintermExp */
  701. /**
  702. @brief Prints the density of a %BDD or %ADD using arbitrary
  703. precision arithmetic.
  704. @return 1 if successful; 0 otherwise.
  705. @sideeffect None
  706. */
  707. int
  708. Cudd_ApaPrintDensity(
  709. FILE * fp,
  710. DdManager * dd,
  711. DdNode * node,
  712. int nvars)
  713. {
  714. int digits;
  715. int result;
  716. DdApaNumber count,density;
  717. unsigned int size, remainder, fractional;
  718. count = Cudd_ApaCountMinterm(dd,node,nvars,&digits);
  719. if (count == NULL)
  720. return(0);
  721. size = (unsigned int) Cudd_DagSize(node);
  722. density = Cudd_NewApaNumber(digits);
  723. remainder = Cudd_ApaIntDivision(digits,count,size,density);
  724. result = Cudd_ApaPrintDecimal(fp,digits,density);
  725. FREE(count);
  726. FREE(density);
  727. fractional = (unsigned int)((double)remainder / size * 1000000);
  728. if (fprintf(fp,".%u\n", fractional) == EOF) {
  729. return(0);
  730. }
  731. return(result);
  732. } /* end of Cudd_ApaPrintDensity */
  733. /*---------------------------------------------------------------------------*/
  734. /* Definition of internal functions */
  735. /*---------------------------------------------------------------------------*/
  736. /*---------------------------------------------------------------------------*/
  737. /* Definition of static functions */
  738. /*---------------------------------------------------------------------------*/
  739. /**
  740. @brief Performs the recursive step of Cudd_ApaCountMinterm.
  741. @details It is based on the following identity. Let <code>|f|</code> be the
  742. number of minterms of <code>f</code>. Then:
  743. |f| = (|f0|+|f1|)/2
  744. where f0 and f1 are the two cofactors of f.
  745. Uses the identity <code>|f'| = mmax - |f|</code>.
  746. The procedure expects the argument "node" to be a regular pointer, and
  747. guarantees this condition is met in the recursive calls.
  748. For efficiency, the result of a call is cached only if the node has
  749. a reference count greater than 1.
  750. @return the number of minterms of the function rooted at node.
  751. @sideeffect None
  752. */
  753. static DdApaNumber
  754. cuddApaCountMintermAux(
  755. DdManager const * manager,
  756. DdNode * node,
  757. int digits,
  758. DdApaNumber mmax,
  759. DdApaNumber mmin,
  760. st_table * table)
  761. {
  762. DdNode *Nt, *Ne;
  763. DdApaNumber mint, mint1, mint2;
  764. DdApaDigit carryout;
  765. if (cuddIsConstant(node)) {
  766. int singleRef = Cudd_Regular(node)->ref == 1;
  767. if (node == manager->background || node == Cudd_Not(manager->one)) {
  768. if (singleRef) {
  769. mint = Cudd_NewApaNumber(digits);
  770. if (mint == NULL) {
  771. return(NULL);
  772. }
  773. Cudd_ApaCopy(digits, mmin, mint);
  774. return(mint);
  775. } else {
  776. return(mmin);
  777. }
  778. } else {
  779. if (singleRef) {
  780. mint = Cudd_NewApaNumber(digits);
  781. if (mint == NULL) {
  782. return(NULL);
  783. }
  784. Cudd_ApaCopy(digits, mmax, mint);
  785. return(mint);
  786. } else {
  787. return(mmax);
  788. }
  789. }
  790. }
  791. if (node->ref > 1 && st_lookup(table, node, (void **) &mint)) {
  792. return(mint);
  793. }
  794. Nt = cuddT(node); Ne = cuddE(node);
  795. mint1 = cuddApaCountMintermAux(manager, Nt, digits, mmax, mmin, table);
  796. if (mint1 == NULL) return(NULL);
  797. mint2 = cuddApaCountMintermAux(manager, Cudd_Regular(Ne), digits, mmax, mmin, table);
  798. if (mint2 == NULL) {
  799. if (Nt->ref == 1) FREE(mint1);
  800. return(NULL);
  801. }
  802. mint = Cudd_NewApaNumber(digits);
  803. if (mint == NULL) {
  804. if (Nt->ref == 1) FREE(mint1);
  805. if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
  806. return(NULL);
  807. }
  808. if (Cudd_IsComplement(Ne)) {
  809. (void) Cudd_ApaSubtract(digits,mmax,mint2,mint);
  810. carryout = Cudd_ApaAdd(digits,mint1,mint,mint);
  811. } else {
  812. carryout = Cudd_ApaAdd(digits,mint1,mint2,mint);
  813. }
  814. Cudd_ApaShiftRight(digits,carryout,mint,mint);
  815. /* If the refernce count of a child is 1, its minterm count
  816. ** hasn't been stored in table. Therefore, it must be explicitly
  817. ** freed here. */
  818. if (Nt->ref == 1) FREE(mint1);
  819. if (Cudd_Regular(Ne)->ref == 1) FREE(mint2);
  820. if (node->ref > 1) {
  821. if (st_insert(table, node, mint) == ST_OUT_OF_MEM) {
  822. FREE(mint);
  823. return(NULL);
  824. }
  825. }
  826. return(mint);
  827. } /* end of cuddApaCountMintermAux */
  828. /**
  829. @brief Frees the memory used to store the minterm counts recorded
  830. in the visited table.
  831. @return ST_CONTINUE.
  832. @sideeffect None
  833. */
  834. static enum st_retval
  835. cuddApaStCountfree(
  836. void * key,
  837. void * value,
  838. void * arg)
  839. {
  840. DdApaNumber d;
  841. (void) key; /* avoid warning */
  842. (void) arg; /* avoid warning */
  843. d = (DdApaNumber) value;
  844. FREE(d);
  845. return(ST_CONTINUE);
  846. } /* end of cuddApaStCountfree */