You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1121 lines
27 KiB

  1. /**CFile***********************************************************************
  2. FileName [cuddAddApply.c]
  3. PackageName [cudd]
  4. Synopsis [Apply functions for ADDs and their operators.]
  5. Description [External procedures included in this module:
  6. <ul>
  7. <li> Cudd_addApply()
  8. <li> Cudd_addMonadicApply()
  9. <li> Cudd_addPlus()
  10. <li> Cudd_addTimes()
  11. <li> Cudd_addThreshold()
  12. <li> Cudd_addSetNZ()
  13. <li> Cudd_addDivide()
  14. <li> Cudd_addMinus()
  15. <li> Cudd_addMinimum()
  16. <li> Cudd_addMaximum()
  17. <li> Cudd_addOneZeroMaximum()
  18. <li> Cudd_addDiff()
  19. <li> Cudd_addAgreement()
  20. <li> Cudd_addOr()
  21. <li> Cudd_addNand()
  22. <li> Cudd_addNor()
  23. <li> Cudd_addXor()
  24. <li> Cudd_addXnor()
  25. </ul>
  26. Internal procedures included in this module:
  27. <ul>
  28. <li> cuddAddApplyRecur()
  29. <li> cuddAddMonadicApplyRecur()
  30. </ul>]
  31. Author [Fabio Somenzi]
  32. Copyright [Copyright (c) 1995-2012, Regents of the University of Colorado
  33. All rights reserved.
  34. Redistribution and use in source and binary forms, with or without
  35. modification, are permitted provided that the following conditions
  36. are met:
  37. Redistributions of source code must retain the above copyright
  38. notice, this list of conditions and the following disclaimer.
  39. Redistributions in binary form must reproduce the above copyright
  40. notice, this list of conditions and the following disclaimer in the
  41. documentation and/or other materials provided with the distribution.
  42. Neither the name of the University of Colorado nor the names of its
  43. contributors may be used to endorse or promote products derived from
  44. this software without specific prior written permission.
  45. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  46. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  47. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  48. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  49. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  50. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  51. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  52. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  53. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  54. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  55. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  56. POSSIBILITY OF SUCH DAMAGE.]
  57. ******************************************************************************/
  58. #include "util.h"
  59. #include "cuddInt.h"
  60. /*---------------------------------------------------------------------------*/
  61. /* Constant declarations */
  62. /*---------------------------------------------------------------------------*/
  63. /*---------------------------------------------------------------------------*/
  64. /* Stucture declarations */
  65. /*---------------------------------------------------------------------------*/
  66. /*---------------------------------------------------------------------------*/
  67. /* Type declarations */
  68. /*---------------------------------------------------------------------------*/
  69. /*---------------------------------------------------------------------------*/
  70. /* Variable declarations */
  71. /*---------------------------------------------------------------------------*/
  72. #ifndef lint
  73. static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.19 2012/02/05 01:07:18 fabio Exp $";
  74. #endif
  75. /*---------------------------------------------------------------------------*/
  76. /* Macro declarations */
  77. /*---------------------------------------------------------------------------*/
  78. /**AutomaticStart*************************************************************/
  79. /*---------------------------------------------------------------------------*/
  80. /* Static function prototypes */
  81. /*---------------------------------------------------------------------------*/
  82. /**AutomaticEnd***************************************************************/
  83. /*---------------------------------------------------------------------------*/
  84. /* Definition of exported functions */
  85. /*---------------------------------------------------------------------------*/
  86. /**Function********************************************************************
  87. Synopsis [Applies op to the corresponding discriminants of f and g.]
  88. Description [Applies op to the corresponding discriminants of f and g.
  89. Returns a pointer to the result if succssful; NULL otherwise.]
  90. SideEffects [None]
  91. SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
  92. Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
  93. Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
  94. Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
  95. ******************************************************************************/
  96. DdNode *
  97. Cudd_addApply(
  98. DdManager * dd,
  99. DD_AOP op,
  100. DdNode * f,
  101. DdNode * g)
  102. {
  103. DdNode *res;
  104. do {
  105. dd->reordered = 0;
  106. res = cuddAddApplyRecur(dd,op,f,g);
  107. } while (dd->reordered == 1);
  108. return(res);
  109. } /* end of Cudd_addApply */
  110. /**Function********************************************************************
  111. Synopsis [Integer and floating point addition.]
  112. Description [Integer and floating point addition. Returns NULL if not
  113. a terminal case; f+g otherwise.]
  114. SideEffects [None]
  115. SeeAlso [Cudd_addApply]
  116. ******************************************************************************/
  117. DdNode *
  118. Cudd_addPlus(
  119. DdManager * dd,
  120. DdNode ** f,
  121. DdNode ** g)
  122. {
  123. DdNode *res;
  124. DdNode *F, *G;
  125. CUDD_VALUE_TYPE value;
  126. F = *f; G = *g;
  127. if (F == DD_ZERO(dd)) return(G);
  128. if (G == DD_ZERO(dd)) return(F);
  129. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  130. value = cuddV(F)+cuddV(G);
  131. res = cuddUniqueConst(dd,value);
  132. return(res);
  133. }
  134. if (F > G) { /* swap f and g */
  135. *f = G;
  136. *g = F;
  137. }
  138. return(NULL);
  139. } /* end of Cudd_addPlus */
  140. /**Function********************************************************************
  141. Synopsis [Integer and floating point multiplication.]
  142. Description [Integer and floating point multiplication. Returns NULL
  143. if not a terminal case; f * g otherwise. This function can be used also
  144. to take the AND of two 0-1 ADDs.]
  145. SideEffects [None]
  146. SeeAlso [Cudd_addApply]
  147. ******************************************************************************/
  148. DdNode *
  149. Cudd_addTimes(
  150. DdManager * dd,
  151. DdNode ** f,
  152. DdNode ** g)
  153. {
  154. DdNode *res;
  155. DdNode *F, *G;
  156. CUDD_VALUE_TYPE value;
  157. F = *f; G = *g;
  158. if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
  159. if (F == DD_ONE(dd)) return(G);
  160. if (G == DD_ONE(dd)) return(F);
  161. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  162. value = cuddV(F)*cuddV(G);
  163. res = cuddUniqueConst(dd,value);
  164. return(res);
  165. }
  166. if (F > G) { /* swap f and g */
  167. *f = G;
  168. *g = F;
  169. }
  170. return(NULL);
  171. } /* end of Cudd_addTimes */
  172. /**Function********************************************************************
  173. Synopsis [f if f&gt;=g; 0 if f&lt;g.]
  174. Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
  175. Returns NULL if not a terminal case; f op g otherwise.]
  176. SideEffects [None]
  177. SeeAlso [Cudd_addApply]
  178. ******************************************************************************/
  179. DdNode *
  180. Cudd_addThreshold(
  181. DdManager * dd,
  182. DdNode ** f,
  183. DdNode ** g)
  184. {
  185. DdNode *F, *G;
  186. F = *f; G = *g;
  187. if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
  188. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  189. if (cuddV(F) >= cuddV(G)) {
  190. return(F);
  191. } else {
  192. return(DD_ZERO(dd));
  193. }
  194. }
  195. return(NULL);
  196. } /* end of Cudd_addThreshold */
  197. /**Function********************************************************************
  198. Synopsis [This operator sets f to the value of g wherever g != 0.]
  199. Description [This operator sets f to the value of g wherever g != 0.
  200. Returns NULL if not a terminal case; f op g otherwise.]
  201. SideEffects [None]
  202. SeeAlso [Cudd_addApply]
  203. ******************************************************************************/
  204. DdNode *
  205. Cudd_addSetNZ(
  206. DdManager * dd,
  207. DdNode ** f,
  208. DdNode ** g)
  209. {
  210. DdNode *F, *G;
  211. F = *f; G = *g;
  212. if (F == G) return(F);
  213. if (F == DD_ZERO(dd)) return(G);
  214. if (G == DD_ZERO(dd)) return(F);
  215. if (cuddIsConstant(G)) return(G);
  216. return(NULL);
  217. } /* end of Cudd_addSetNZ */
  218. /**Function********************************************************************
  219. Synopsis [Integer and floating point division.]
  220. Description [Integer and floating point division. Returns NULL if not
  221. a terminal case; f / g otherwise.]
  222. SideEffects [None]
  223. SeeAlso [Cudd_addApply]
  224. ******************************************************************************/
  225. DdNode *
  226. Cudd_addDivide(
  227. DdManager * dd,
  228. DdNode ** f,
  229. DdNode ** g)
  230. {
  231. DdNode *res;
  232. DdNode *F, *G;
  233. CUDD_VALUE_TYPE value;
  234. F = *f; G = *g;
  235. /* We would like to use F == G -> F/G == 1, but F and G may
  236. ** contain zeroes. */
  237. if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
  238. if (G == DD_ONE(dd)) return(F);
  239. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  240. value = cuddV(F)/cuddV(G);
  241. res = cuddUniqueConst(dd,value);
  242. return(res);
  243. }
  244. return(NULL);
  245. } /* end of Cudd_addDivide */
  246. /**Function********************************************************************
  247. Synopsis [Integer and floating point subtraction.]
  248. Description [Integer and floating point subtraction. Returns NULL if
  249. not a terminal case; f - g otherwise.]
  250. SideEffects [None]
  251. SeeAlso [Cudd_addApply]
  252. ******************************************************************************/
  253. DdNode *
  254. Cudd_addMinus(
  255. DdManager * dd,
  256. DdNode ** f,
  257. DdNode ** g)
  258. {
  259. DdNode *res;
  260. DdNode *F, *G;
  261. CUDD_VALUE_TYPE value;
  262. F = *f; G = *g;
  263. if (F == G) return(DD_ZERO(dd));
  264. if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
  265. if (G == DD_ZERO(dd)) return(F);
  266. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  267. value = cuddV(F)-cuddV(G);
  268. res = cuddUniqueConst(dd,value);
  269. return(res);
  270. }
  271. return(NULL);
  272. } /* end of Cudd_addMinus */
  273. /**Function********************************************************************
  274. Synopsis [Integer and floating point min.]
  275. Description [Integer and floating point min for Cudd_addApply.
  276. Returns NULL if not a terminal case; min(f,g) otherwise.]
  277. SideEffects [None]
  278. SeeAlso [Cudd_addApply]
  279. ******************************************************************************/
  280. DdNode *
  281. Cudd_addMinimum(
  282. DdManager * dd,
  283. DdNode ** f,
  284. DdNode ** g)
  285. {
  286. DdNode *F, *G;
  287. F = *f; G = *g;
  288. if (F == DD_PLUS_INFINITY(dd)) return(G);
  289. if (G == DD_PLUS_INFINITY(dd)) return(F);
  290. if (F == G) return(F);
  291. #if 0
  292. /* These special cases probably do not pay off. */
  293. if (F == DD_MINUS_INFINITY(dd)) return(F);
  294. if (G == DD_MINUS_INFINITY(dd)) return(G);
  295. #endif
  296. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  297. if (cuddV(F) <= cuddV(G)) {
  298. return(F);
  299. } else {
  300. return(G);
  301. }
  302. }
  303. if (F > G) { /* swap f and g */
  304. *f = G;
  305. *g = F;
  306. }
  307. return(NULL);
  308. } /* end of Cudd_addMinimum */
  309. /**Function********************************************************************
  310. Synopsis [Integer and floating point max.]
  311. Description [Integer and floating point max for Cudd_addApply.
  312. Returns NULL if not a terminal case; max(f,g) otherwise.]
  313. SideEffects [None]
  314. SeeAlso [Cudd_addApply]
  315. ******************************************************************************/
  316. DdNode *
  317. Cudd_addMaximum(
  318. DdManager * dd,
  319. DdNode ** f,
  320. DdNode ** g)
  321. {
  322. DdNode *F, *G;
  323. F = *f; G = *g;
  324. if (F == G) return(F);
  325. if (F == DD_MINUS_INFINITY(dd)) return(G);
  326. if (G == DD_MINUS_INFINITY(dd)) return(F);
  327. #if 0
  328. /* These special cases probably do not pay off. */
  329. if (F == DD_PLUS_INFINITY(dd)) return(F);
  330. if (G == DD_PLUS_INFINITY(dd)) return(G);
  331. #endif
  332. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  333. if (cuddV(F) >= cuddV(G)) {
  334. return(F);
  335. } else {
  336. return(G);
  337. }
  338. }
  339. if (F > G) { /* swap f and g */
  340. *f = G;
  341. *g = F;
  342. }
  343. return(NULL);
  344. } /* end of Cudd_addMaximum */
  345. /**Function********************************************************************
  346. Synopsis [Returns 1 if f &gt; g and 0 otherwise.]
  347. Description [Returns 1 if f &gt; g and 0 otherwise. Used in
  348. conjunction with Cudd_addApply. Returns NULL if not a terminal
  349. case.]
  350. SideEffects [None]
  351. SeeAlso [Cudd_addApply]
  352. ******************************************************************************/
  353. DdNode *
  354. Cudd_addOneZeroMaximum(
  355. DdManager * dd,
  356. DdNode ** f,
  357. DdNode ** g)
  358. {
  359. if (*f == *g) return(DD_ZERO(dd));
  360. if (*g == DD_PLUS_INFINITY(dd))
  361. return DD_ZERO(dd);
  362. if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
  363. if (cuddV(*f) > cuddV(*g)) {
  364. return(DD_ONE(dd));
  365. } else {
  366. return(DD_ZERO(dd));
  367. }
  368. }
  369. return(NULL);
  370. } /* end of Cudd_addOneZeroMaximum */
  371. /**Function********************************************************************
  372. Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
  373. Description [Returns NULL if not a terminal case; f op g otherwise,
  374. where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
  375. SideEffects [None]
  376. SeeAlso [Cudd_addApply]
  377. ******************************************************************************/
  378. DdNode *
  379. Cudd_addDiff(
  380. DdManager * dd,
  381. DdNode ** f,
  382. DdNode ** g)
  383. {
  384. DdNode *F, *G;
  385. F = *f; G = *g;
  386. if (F == G) return(DD_PLUS_INFINITY(dd));
  387. if (F == DD_PLUS_INFINITY(dd)) return(G);
  388. if (G == DD_PLUS_INFINITY(dd)) return(F);
  389. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  390. if (cuddV(F) != cuddV(G)) {
  391. if (cuddV(F) < cuddV(G)) {
  392. return(F);
  393. } else {
  394. return(G);
  395. }
  396. } else {
  397. return(DD_PLUS_INFINITY(dd));
  398. }
  399. }
  400. return(NULL);
  401. } /* end of Cudd_addDiff */
  402. /**Function********************************************************************
  403. Synopsis [f if f==g; background if f!=g.]
  404. Description [Returns NULL if not a terminal case; f op g otherwise,
  405. where f op g is f if f==g; background if f!=g.]
  406. SideEffects [None]
  407. SeeAlso [Cudd_addApply]
  408. ******************************************************************************/
  409. DdNode *
  410. Cudd_addAgreement(
  411. DdManager * dd,
  412. DdNode ** f,
  413. DdNode ** g)
  414. {
  415. DdNode *F, *G;
  416. F = *f; G = *g;
  417. if (F == G) return(F);
  418. if (F == dd->background) return(F);
  419. if (G == dd->background) return(G);
  420. if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
  421. return(NULL);
  422. } /* end of Cudd_addAgreement */
  423. /**Function********************************************************************
  424. Synopsis [Disjunction of two 0-1 ADDs.]
  425. Description [Disjunction of two 0-1 ADDs. Returns NULL
  426. if not a terminal case; f OR g otherwise.]
  427. SideEffects [None]
  428. SeeAlso [Cudd_addApply]
  429. ******************************************************************************/
  430. DdNode *
  431. Cudd_addOr(
  432. DdManager * dd,
  433. DdNode ** f,
  434. DdNode ** g)
  435. {
  436. DdNode *F, *G;
  437. F = *f; G = *g;
  438. if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
  439. if (cuddIsConstant(F)) return(G);
  440. if (cuddIsConstant(G)) return(F);
  441. if (F == G) return(F);
  442. if (F > G) { /* swap f and g */
  443. *f = G;
  444. *g = F;
  445. }
  446. return(NULL);
  447. } /* end of Cudd_addOr */
  448. /**Function********************************************************************
  449. Synopsis [NAND of two 0-1 ADDs.]
  450. Description [NAND of two 0-1 ADDs. Returns NULL
  451. if not a terminal case; f NAND g otherwise.]
  452. SideEffects [None]
  453. SeeAlso [Cudd_addApply]
  454. ******************************************************************************/
  455. DdNode *
  456. Cudd_addNand(
  457. DdManager * dd,
  458. DdNode ** f,
  459. DdNode ** g)
  460. {
  461. DdNode *F, *G;
  462. F = *f; G = *g;
  463. if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
  464. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  465. if (F > G) { /* swap f and g */
  466. *f = G;
  467. *g = F;
  468. }
  469. return(NULL);
  470. } /* end of Cudd_addNand */
  471. /**Function********************************************************************
  472. Synopsis [NOR of two 0-1 ADDs.]
  473. Description [NOR of two 0-1 ADDs. Returns NULL
  474. if not a terminal case; f NOR g otherwise.]
  475. SideEffects [None]
  476. SeeAlso [Cudd_addApply]
  477. ******************************************************************************/
  478. DdNode *
  479. Cudd_addNor(
  480. DdManager * dd,
  481. DdNode ** f,
  482. DdNode ** g)
  483. {
  484. DdNode *F, *G;
  485. F = *f; G = *g;
  486. if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
  487. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
  488. if (F > G) { /* swap f and g */
  489. *f = G;
  490. *g = F;
  491. }
  492. return(NULL);
  493. } /* end of Cudd_addNor */
  494. /**Function********************************************************************
  495. Synopsis [XOR of two 0-1 ADDs.]
  496. Description [XOR of two 0-1 ADDs. Returns NULL
  497. if not a terminal case; f XOR g otherwise.]
  498. SideEffects [None]
  499. SeeAlso [Cudd_addApply]
  500. ******************************************************************************/
  501. DdNode *
  502. Cudd_addXor(
  503. DdManager * dd,
  504. DdNode ** f,
  505. DdNode ** g)
  506. {
  507. DdNode *F, *G;
  508. F = *f; G = *g;
  509. if (F == G) return(DD_ZERO(dd));
  510. if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
  511. if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
  512. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  513. if (F > G) { /* swap f and g */
  514. *f = G;
  515. *g = F;
  516. }
  517. return(NULL);
  518. } /* end of Cudd_addXor */
  519. /**Function********************************************************************
  520. Synopsis [XNOR of two 0-1 ADDs.]
  521. Description [XNOR of two 0-1 ADDs. Returns NULL
  522. if not a terminal case; f XNOR g otherwise.]
  523. SideEffects [None]
  524. SeeAlso [Cudd_addApply]
  525. ******************************************************************************/
  526. DdNode *
  527. Cudd_addXnor(
  528. DdManager * dd,
  529. DdNode ** f,
  530. DdNode ** g)
  531. {
  532. DdNode *F, *G;
  533. F = *f; G = *g;
  534. if (F == G) return(DD_ONE(dd));
  535. if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
  536. if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
  537. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  538. if (F > G) { /* swap f and g */
  539. *f = G;
  540. *g = F;
  541. }
  542. return(NULL);
  543. } /* end of Cudd_addXnor */
  544. /**Function********************************************************************
  545. Synopsis [Applies op to the discriminants of f.]
  546. Description [Applies op to the discriminants of f.
  547. Returns a pointer to the result if succssful; NULL otherwise.]
  548. SideEffects [None]
  549. SeeAlso [Cudd_addApply Cudd_addLog]
  550. ******************************************************************************/
  551. DdNode *
  552. Cudd_addMonadicApply(
  553. DdManager * dd,
  554. DD_MAOP op,
  555. DdNode * f)
  556. {
  557. DdNode *res;
  558. do {
  559. dd->reordered = 0;
  560. res = cuddAddMonadicApplyRecur(dd,op,f);
  561. } while (dd->reordered == 1);
  562. return(res);
  563. } /* end of Cudd_addMonadicApply */
  564. /**Function********************************************************************
  565. Synopsis [Natural logarithm of an ADD.]
  566. Description [Natural logarithm of an ADDs. Returns NULL
  567. if not a terminal case; log(f) otherwise. The discriminants of f must
  568. be positive double's.]
  569. SideEffects [None]
  570. SeeAlso [Cudd_addMonadicApply]
  571. ******************************************************************************/
  572. DdNode *
  573. Cudd_addLog(
  574. DdManager * dd,
  575. DdNode * f)
  576. {
  577. if (cuddIsConstant(f)) {
  578. CUDD_VALUE_TYPE value = log(cuddV(f));
  579. DdNode *res = cuddUniqueConst(dd,value);
  580. return(res);
  581. }
  582. return(NULL);
  583. } /* end of Cudd_addLog */
  584. /**Function********************************************************************
  585. Synopsis [1 if f==g; 0 otherwise.]
  586. Description [Returns NULL if not a terminal case; f op g otherwise,
  587. where f op g is 1 if f==g; 0 otherwise.]
  588. SideEffects [None]
  589. SeeAlso [Cudd_addApply]
  590. ******************************************************************************/
  591. DdNode *
  592. Cudd_addEquals(
  593. DdManager * dd,
  594. DdNode ** f,
  595. DdNode ** g)
  596. {
  597. DdNode *F, *G;
  598. F = *f; G = *g;
  599. if (F == G) return(DD_ONE(dd));
  600. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  601. if (F > G) { /* swap f and g */
  602. *f = G;
  603. *g = F;
  604. }
  605. return(NULL);
  606. } /* end of Cudd_addEquals */
  607. /**Function********************************************************************
  608. Synopsis [1 if f!=g; 0 otherwise.]
  609. Description [Returns NULL if not a terminal case; f op g otherwise,
  610. where f op g is 1 if f!=g; 0 otherwise.]
  611. SideEffects [None]
  612. SeeAlso [Cudd_addApply]
  613. ******************************************************************************/
  614. DdNode *
  615. Cudd_addNotEquals(
  616. DdManager * dd,
  617. DdNode ** f,
  618. DdNode ** g)
  619. {
  620. DdNode *F, *G;
  621. F = *f; G = *g;
  622. if (F == G) return(DD_ZERO(dd));
  623. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
  624. if (F > G) { /* swap f and g */
  625. *f = G;
  626. *g = F;
  627. }
  628. return(NULL);
  629. } /* end of Cudd_addNotEquals */
  630. /**Function********************************************************************
  631. Synopsis [1 if f>g; 0 otherwise.]
  632. Description [Returns NULL if not a terminal case; f op g otherwise,
  633. where f op g is 1 if f>g; 0 otherwise.]
  634. SideEffects [None]
  635. SeeAlso [Cudd_addApply]
  636. ******************************************************************************/
  637. DdNode *
  638. Cudd_addGreaterThan(
  639. DdManager * dd,
  640. DdNode ** f,
  641. DdNode ** g)
  642. {
  643. DdNode *F, *G;
  644. F = *f; G = *g;
  645. if (F == G) return(DD_ZERO(dd));
  646. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  647. if (cuddV(F)>cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  648. }
  649. return(NULL);
  650. } /* end of Cudd_addGreaterThan */
  651. /**Function********************************************************************
  652. Synopsis [1 if f>=g; 0 otherwise.]
  653. Description [Returns NULL if not a terminal case; f op g otherwise,
  654. where f op g is 1 if f>=g; 0 otherwise.]
  655. SideEffects [None]
  656. SeeAlso [Cudd_addApply]
  657. ******************************************************************************/
  658. DdNode *
  659. Cudd_addGreaterThanEquals(
  660. DdManager * dd,
  661. DdNode ** f,
  662. DdNode ** g)
  663. {
  664. DdNode *F, *G;
  665. F = *f; G = *g;
  666. if (F == G) return(DD_ONE(dd));
  667. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  668. if (cuddV(F)>=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  669. }
  670. return(NULL);
  671. } /* end of Cudd_addGreaterThanEquals */
  672. /**Function********************************************************************
  673. Synopsis [1 if f<g; 0 otherwise.]
  674. Description [Returns NULL if not a terminal case; f op g otherwise,
  675. where f op g is 1 if f<g; 0 otherwise.]
  676. SideEffects [None]
  677. SeeAlso [Cudd_addApply]
  678. ******************************************************************************/
  679. DdNode *
  680. Cudd_addLessThan(
  681. DdManager * dd,
  682. DdNode ** f,
  683. DdNode ** g)
  684. {
  685. DdNode *F, *G;
  686. F = *f; G = *g;
  687. if (F == G) return(DD_ZERO(dd));
  688. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  689. if (cuddV(F)<cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  690. }
  691. return(NULL);
  692. } /* end of Cudd_addLessThan */
  693. /**Function********************************************************************
  694. Synopsis [1 if f<=g; 0 otherwise.]
  695. Description [Returns NULL if not a terminal case; f op g otherwise,
  696. where f op g is 1 if f<=g; 0 otherwise.]
  697. SideEffects [None]
  698. SeeAlso [Cudd_addApply]
  699. ******************************************************************************/
  700. DdNode *
  701. Cudd_addLessThanEquals(
  702. DdManager * dd,
  703. DdNode ** f,
  704. DdNode ** g)
  705. {
  706. DdNode *F, *G;
  707. F = *f; G = *g;
  708. if (F == G) return(DD_ONE(dd));
  709. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  710. if (cuddV(F)<=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  711. }
  712. return(NULL);
  713. } /* end of Cudd_addLessThanEquals */
  714. /*---------------------------------------------------------------------------*/
  715. /* Definition of internal functions */
  716. /*---------------------------------------------------------------------------*/
  717. /**Function********************************************************************
  718. Synopsis [Performs the recursive step of Cudd_addApply.]
  719. Description [Performs the recursive step of Cudd_addApply. Returns a
  720. pointer to the result if successful; NULL otherwise.]
  721. SideEffects [None]
  722. SeeAlso [cuddAddMonadicApplyRecur]
  723. ******************************************************************************/
  724. DdNode *
  725. cuddAddApplyRecur(
  726. DdManager * dd,
  727. DD_AOP op,
  728. DdNode * f,
  729. DdNode * g)
  730. {
  731. DdNode *res,
  732. *fv, *fvn, *gv, *gvn,
  733. *T, *E;
  734. unsigned int ford, gord;
  735. unsigned int index;
  736. DD_CTFP cacheOp;
  737. /* Check terminal cases. Op may swap f and g to increase the
  738. * cache hit rate.
  739. */
  740. statLine(dd);
  741. res = (*op)(dd,&f,&g);
  742. if (res != NULL) return(res);
  743. /* Check cache. */
  744. cacheOp = (DD_CTFP) op;
  745. res = cuddCacheLookup2(dd,cacheOp,f,g);
  746. if (res != NULL) return(res);
  747. /* Recursive step. */
  748. ford = cuddI(dd,f->index);
  749. gord = cuddI(dd,g->index);
  750. if (ford <= gord) {
  751. index = f->index;
  752. fv = cuddT(f);
  753. fvn = cuddE(f);
  754. } else {
  755. index = g->index;
  756. fv = fvn = f;
  757. }
  758. if (gord <= ford) {
  759. gv = cuddT(g);
  760. gvn = cuddE(g);
  761. } else {
  762. gv = gvn = g;
  763. }
  764. T = cuddAddApplyRecur(dd,op,fv,gv);
  765. if (T == NULL) return(NULL);
  766. cuddRef(T);
  767. E = cuddAddApplyRecur(dd,op,fvn,gvn);
  768. if (E == NULL) {
  769. Cudd_RecursiveDeref(dd,T);
  770. return(NULL);
  771. }
  772. cuddRef(E);
  773. res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
  774. if (res == NULL) {
  775. Cudd_RecursiveDeref(dd, T);
  776. Cudd_RecursiveDeref(dd, E);
  777. return(NULL);
  778. }
  779. cuddDeref(T);
  780. cuddDeref(E);
  781. /* Store result. */
  782. cuddCacheInsert2(dd,cacheOp,f,g,res);
  783. return(res);
  784. } /* end of cuddAddApplyRecur */
  785. /**Function********************************************************************
  786. Synopsis [Performs the recursive step of Cudd_addMonadicApply.]
  787. Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
  788. pointer to the result if successful; NULL otherwise.]
  789. SideEffects [None]
  790. SeeAlso [cuddAddApplyRecur]
  791. ******************************************************************************/
  792. DdNode *
  793. cuddAddMonadicApplyRecur(
  794. DdManager * dd,
  795. DD_MAOP op,
  796. DdNode * f)
  797. {
  798. DdNode *res, *ft, *fe, *T, *E;
  799. unsigned int index;
  800. /* Check terminal cases. */
  801. statLine(dd);
  802. res = (*op)(dd,f);
  803. if (res != NULL) return(res);
  804. /* Check cache. */
  805. res = cuddCacheLookup1(dd,op,f);
  806. if (res != NULL) return(res);
  807. /* Recursive step. */
  808. index = f->index;
  809. ft = cuddT(f);
  810. fe = cuddE(f);
  811. T = cuddAddMonadicApplyRecur(dd,op,ft);
  812. if (T == NULL) return(NULL);
  813. cuddRef(T);
  814. E = cuddAddMonadicApplyRecur(dd,op,fe);
  815. if (E == NULL) {
  816. Cudd_RecursiveDeref(dd,T);
  817. return(NULL);
  818. }
  819. cuddRef(E);
  820. res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
  821. if (res == NULL) {
  822. Cudd_RecursiveDeref(dd, T);
  823. Cudd_RecursiveDeref(dd, E);
  824. return(NULL);
  825. }
  826. cuddDeref(T);
  827. cuddDeref(E);
  828. /* Store result. */
  829. cuddCacheInsert1(dd,op,f,res);
  830. return(res);
  831. } /* end of cuddAddMonadicApplyRecur */
  832. /*---------------------------------------------------------------------------*/
  833. /* Definition of static functions */
  834. /*---------------------------------------------------------------------------*/