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.

1609 lines
36 KiB

2 months ago
  1. /**
  2. @file
  3. @ingroup cudd
  4. @brief Apply functions for ADDs and their operators.
  5. @author Fabio Somenzi
  6. @copyright@parblock
  7. Copyright (c) 1995-2015, Regents of the University of Colorado
  8. All rights reserved.
  9. Redistribution and use in source and binary forms, with or without
  10. modification, are permitted provided that the following conditions
  11. are met:
  12. Redistributions of source code must retain the above copyright
  13. notice, this list of conditions and the following disclaimer.
  14. Redistributions in binary form must reproduce the above copyright
  15. notice, this list of conditions and the following disclaimer in the
  16. documentation and/or other materials provided with the distribution.
  17. Neither the name of the University of Colorado nor the names of its
  18. contributors may be used to endorse or promote products derived from
  19. this software without specific prior written permission.
  20. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  28. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  30. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. POSSIBILITY OF SUCH DAMAGE.
  32. @endparblock
  33. */
  34. #include "util.h"
  35. #include "cuddInt.h"
  36. /*---------------------------------------------------------------------------*/
  37. /* Constant declarations */
  38. /*---------------------------------------------------------------------------*/
  39. /*---------------------------------------------------------------------------*/
  40. /* Stucture declarations */
  41. /*---------------------------------------------------------------------------*/
  42. /*---------------------------------------------------------------------------*/
  43. /* Type declarations */
  44. /*---------------------------------------------------------------------------*/
  45. /*---------------------------------------------------------------------------*/
  46. /* Variable declarations */
  47. /*---------------------------------------------------------------------------*/
  48. /*---------------------------------------------------------------------------*/
  49. /* Macro declarations */
  50. /*---------------------------------------------------------------------------*/
  51. /** \cond */
  52. /*---------------------------------------------------------------------------*/
  53. /* Static function prototypes */
  54. /*---------------------------------------------------------------------------*/
  55. /** \endcond */
  56. /*---------------------------------------------------------------------------*/
  57. /* Definition of exported functions */
  58. /*---------------------------------------------------------------------------*/
  59. /**
  60. @brief Applies op to the corresponding discriminants of f and g.
  61. @return a pointer to the result if succssful; NULL otherwise.
  62. @sideeffect None
  63. @see Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
  64. Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
  65. Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
  66. Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor
  67. */
  68. DdNode *
  69. Cudd_addApply(
  70. DdManager * dd /**< manager */,
  71. DD_AOP op /**< operator */,
  72. DdNode * f /**< first operand */,
  73. DdNode * g /**< second operand */)
  74. {
  75. DdNode *res;
  76. do {
  77. dd->reordered = 0;
  78. res = cuddAddApplyRecur(dd,op,f,g);
  79. } while (dd->reordered == 1);
  80. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  81. dd->timeoutHandler(dd, dd->tohArg);
  82. }
  83. return(res);
  84. } /* end of Cudd_addApply */
  85. /**
  86. @brief Applies op to the corresponding discriminants of f and g and produces a BDD as a result.
  87. @return a pointer to the result if succssful; NULL otherwise.
  88. @sideeffect None
  89. @see Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
  90. Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
  91. Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
  92. Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor
  93. added 23/08/2016 by Christian Dehnert
  94. */
  95. DdNode *
  96. Cudd_addToBddApply(
  97. DdManager * dd /**< manager */,
  98. DD_AOP op /**< operator */,
  99. DdNode * f /**< first operand */,
  100. DdNode * g /**< second operand */)
  101. {
  102. DdNode *res;
  103. do {
  104. dd->reordered = 0;
  105. res = cuddAddToBddApplyRecur(dd,op,f,g);
  106. } while (dd->reordered == 1);
  107. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  108. dd->timeoutHandler(dd, dd->tohArg);
  109. }
  110. return(res);
  111. } /* end of Cudd_addToBddApply */
  112. /**
  113. @brief Integer and floating point addition.
  114. @return NULL if not a terminal case; f+g otherwise.
  115. @sideeffect None
  116. @see Cudd_addApply
  117. */
  118. DdNode *
  119. Cudd_addPlus(
  120. DdManager * dd,
  121. DdNode ** f,
  122. DdNode ** g)
  123. {
  124. DdNode *res;
  125. DdNode *F, *G;
  126. CUDD_VALUE_TYPE value;
  127. F = *f; G = *g;
  128. if (F == DD_ZERO(dd)) return(G);
  129. if (G == DD_ZERO(dd)) return(F);
  130. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  131. value = cuddV(F)+cuddV(G);
  132. res = cuddUniqueConst(dd,value);
  133. return(res);
  134. }
  135. if (F > G) { /* swap f and g */
  136. *f = G;
  137. *g = F;
  138. }
  139. return(NULL);
  140. } /* end of Cudd_addPlus */
  141. /**
  142. @brief Integer and floating point multiplication.
  143. @details This function can be used also to take the AND of two 0-1
  144. ADDs.
  145. @return NULL if not a terminal case; f * g otherwise.
  146. @sideeffect None
  147. @see Cudd_addApply
  148. */
  149. DdNode *
  150. Cudd_addTimes(
  151. DdManager * dd,
  152. DdNode ** f,
  153. DdNode ** g)
  154. {
  155. DdNode *res;
  156. DdNode *F, *G;
  157. CUDD_VALUE_TYPE value;
  158. F = *f; G = *g;
  159. if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
  160. if (F == DD_ONE(dd)) return(G);
  161. if (G == DD_ONE(dd)) return(F);
  162. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  163. value = cuddV(F)*cuddV(G);
  164. res = cuddUniqueConst(dd,value);
  165. return(res);
  166. }
  167. if (F > G) { /* swap f and g */
  168. *f = G;
  169. *g = F;
  170. }
  171. return(NULL);
  172. } /* end of Cudd_addTimes */
  173. /**
  174. @brief f if f&ge;g; 0 if f&lt;g.
  175. @details Threshold operator for Apply (f if f &ge;g; 0 if f&lt;g).
  176. @return NULL if not a terminal case; f op g otherwise.
  177. @sideeffect None
  178. @see Cudd_addApply
  179. */
  180. DdNode *
  181. Cudd_addThreshold(
  182. DdManager * dd,
  183. DdNode ** f,
  184. DdNode ** g)
  185. {
  186. DdNode *F, *G;
  187. F = *f; G = *g;
  188. if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
  189. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  190. if (cuddV(F) >= cuddV(G)) {
  191. return(F);
  192. } else {
  193. return(DD_ZERO(dd));
  194. }
  195. }
  196. return(NULL);
  197. } /* end of Cudd_addThreshold */
  198. /**
  199. @brief This operator sets f to the value of g wherever g != 0.
  200. @return NULL if not a terminal case; f op g otherwise.
  201. @sideeffect None
  202. @see 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. /**
  219. @brief Integer and floating point division.
  220. @return NULL if not a terminal case; f / g otherwise.
  221. @sideeffect None
  222. @see Cudd_addApply
  223. */
  224. DdNode *
  225. Cudd_addDivide(
  226. DdManager * dd,
  227. DdNode ** f,
  228. DdNode ** g)
  229. {
  230. DdNode *res;
  231. DdNode *F, *G;
  232. CUDD_VALUE_TYPE value;
  233. F = *f; G = *g;
  234. /* We would like to use F == G -> F/G == 1, but F and G may
  235. ** contain zeroes. */
  236. if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
  237. if (G == DD_ONE(dd)) return(F);
  238. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  239. value = cuddV(F)/cuddV(G);
  240. res = cuddUniqueConst(dd,value);
  241. return(res);
  242. }
  243. return(NULL);
  244. } /* end of Cudd_addDivide */
  245. /**
  246. @brief Integer and floating point subtraction.
  247. @return NULL if not a terminal case; f - g otherwise.
  248. @sideeffect None
  249. @see Cudd_addApply
  250. */
  251. DdNode *
  252. Cudd_addMinus(
  253. DdManager * dd,
  254. DdNode ** f,
  255. DdNode ** g)
  256. {
  257. DdNode *res;
  258. DdNode *F, *G;
  259. CUDD_VALUE_TYPE value;
  260. F = *f; G = *g;
  261. if (F == G) return(DD_ZERO(dd));
  262. // CHANGED BY CHRISTIAN DEHNERT.
  263. // Commented out this case to avoid issues with dynamic reordering (fix suggested by Fabio Somenzi).
  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. /**
  274. @brief Integer and floating point min.
  275. @details Integer and floating point min for Cudd_addApply.
  276. @return NULL if not a terminal case; min(f,g) otherwise.
  277. @sideeffect None
  278. @see 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. /**
  310. @brief Integer and floating point min.
  311. @details Integer and floating point min for Cudd_addApply.
  312. @return NULL if not a terminal case; min(f,g) otherwise.
  313. @sideeffect None
  314. @see Cudd_addApply
  315. added 24/08/2016
  316. */
  317. DdNode *
  318. Cudd_addMinimumExcept0(
  319. DdManager * dd,
  320. DdNode ** f,
  321. DdNode ** g)
  322. {
  323. DdNode *F, *G;
  324. F = *f; G = *g;
  325. if (F == DD_ZERO(dd)) return(G);
  326. if (G == DD_ZERO(dd)) return(F);
  327. if (F == DD_PLUS_INFINITY(dd)) return(G);
  328. if (G == DD_PLUS_INFINITY(dd)) return(F);
  329. if (F == G) return(F);
  330. #if 0
  331. /* These special cases probably do not pay off. */
  332. if (F == DD_MINUS_INFINITY(dd)) return(F);
  333. if (G == DD_MINUS_INFINITY(dd)) return(G);
  334. #endif
  335. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  336. if (cuddV(F) <= cuddV(G)) {
  337. return(F);
  338. } else {
  339. return(G);
  340. }
  341. }
  342. if (F > G) { /* swap f and g */
  343. *f = G;
  344. *g = F;
  345. }
  346. return(NULL);
  347. } /* end of Cudd_addMinimumExcept0 */
  348. /**
  349. @brief Integer and floating point max.
  350. @details Integer and floating point max for Cudd_addApply.
  351. @return NULL if not a terminal case; max(f,g) otherwise.
  352. @sideeffect None
  353. @see Cudd_addApply
  354. */
  355. DdNode *
  356. Cudd_addMaximum(
  357. DdManager * dd,
  358. DdNode ** f,
  359. DdNode ** g)
  360. {
  361. DdNode *F, *G;
  362. F = *f; G = *g;
  363. if (F == G) return(F);
  364. if (F == DD_MINUS_INFINITY(dd)) return(G);
  365. if (G == DD_MINUS_INFINITY(dd)) return(F);
  366. #if 0
  367. /* These special cases probably do not pay off. */
  368. if (F == DD_PLUS_INFINITY(dd)) return(F);
  369. if (G == DD_PLUS_INFINITY(dd)) return(G);
  370. #endif
  371. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  372. if (cuddV(F) >= cuddV(G)) {
  373. return(F);
  374. } else {
  375. return(G);
  376. }
  377. }
  378. if (F > G) { /* swap f and g */
  379. *f = G;
  380. *g = F;
  381. }
  382. return(NULL);
  383. } /* end of Cudd_addMaximum */
  384. /**
  385. @brief Returns 1 if f &gt; g and 0 otherwise.
  386. @details Used in conjunction with Cudd_addApply.
  387. @return NULL if not a terminal case.
  388. @sideeffect None
  389. @see Cudd_addApply
  390. */
  391. DdNode *
  392. Cudd_addOneZeroMaximum(
  393. DdManager * dd,
  394. DdNode ** f,
  395. DdNode ** g)
  396. {
  397. if (*f == *g) return(DD_ZERO(dd));
  398. if (*g == DD_PLUS_INFINITY(dd))
  399. return DD_ZERO(dd);
  400. if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
  401. if (cuddV(*f) > cuddV(*g)) {
  402. return(DD_ONE(dd));
  403. } else {
  404. return(DD_ZERO(dd));
  405. }
  406. }
  407. return(NULL);
  408. } /* end of Cudd_addOneZeroMaximum */
  409. /**
  410. @brief Returns plusinfinity if f=g; returns min(f,g) if f!=g.
  411. @return NULL if not a terminal case; f op g otherwise, where f op g
  412. is plusinfinity if f=g; min(f,g) if f!=g.
  413. @sideeffect None
  414. @see Cudd_addApply
  415. */
  416. DdNode *
  417. Cudd_addDiff(
  418. DdManager * dd,
  419. DdNode ** f,
  420. DdNode ** g)
  421. {
  422. DdNode *F, *G;
  423. F = *f; G = *g;
  424. if (F == G) return(DD_PLUS_INFINITY(dd));
  425. if (F == DD_PLUS_INFINITY(dd)) return(G);
  426. if (G == DD_PLUS_INFINITY(dd)) return(F);
  427. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  428. if (cuddV(F) != cuddV(G)) {
  429. if (cuddV(F) < cuddV(G)) {
  430. return(F);
  431. } else {
  432. return(G);
  433. }
  434. } else {
  435. return(DD_PLUS_INFINITY(dd));
  436. }
  437. }
  438. return(NULL);
  439. } /* end of Cudd_addDiff */
  440. /**
  441. @brief f if f==g; background if f!=g.
  442. @return NULL if not a terminal case; f op g otherwise, where f op g
  443. is f if f==g; background if f!=g.
  444. @sideeffect None
  445. @see Cudd_addApply
  446. */
  447. DdNode *
  448. Cudd_addAgreement(
  449. DdManager * dd,
  450. DdNode ** f,
  451. DdNode ** g)
  452. {
  453. DdNode *F, *G;
  454. F = *f; G = *g;
  455. if (F == G) return(F);
  456. if (F == dd->background) return(F);
  457. if (G == dd->background) return(G);
  458. if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
  459. return(NULL);
  460. } /* end of Cudd_addAgreement */
  461. /**
  462. @brief Disjunction of two 0-1 ADDs.
  463. @return NULL if not a terminal case; f OR g otherwise.
  464. @sideeffect None
  465. @see Cudd_addApply
  466. */
  467. DdNode *
  468. Cudd_addOr(
  469. DdManager * dd,
  470. DdNode ** f,
  471. DdNode ** g)
  472. {
  473. DdNode *F, *G;
  474. F = *f; G = *g;
  475. if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
  476. if (cuddIsConstant(F)) return(G);
  477. if (cuddIsConstant(G)) return(F);
  478. if (F == G) return(F);
  479. if (F > G) { /* swap f and g */
  480. *f = G;
  481. *g = F;
  482. }
  483. return(NULL);
  484. } /* end of Cudd_addOr */
  485. /**
  486. @brief NAND of two 0-1 ADDs.
  487. @return NULL if not a terminal case; f NAND g otherwise.
  488. @sideeffect None
  489. @see Cudd_addApply
  490. */
  491. DdNode *
  492. Cudd_addNand(
  493. DdManager * dd,
  494. DdNode ** f,
  495. DdNode ** g)
  496. {
  497. DdNode *F, *G;
  498. F = *f; G = *g;
  499. if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
  500. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  501. if (F > G) { /* swap f and g */
  502. *f = G;
  503. *g = F;
  504. }
  505. return(NULL);
  506. } /* end of Cudd_addNand */
  507. /**
  508. @brief NOR of two 0-1 ADDs.
  509. @return NULL if not a terminal case; f NOR g otherwise.
  510. @sideeffect None
  511. @see Cudd_addApply
  512. */
  513. DdNode *
  514. Cudd_addNor(
  515. DdManager * dd,
  516. DdNode ** f,
  517. DdNode ** g)
  518. {
  519. DdNode *F, *G;
  520. F = *f; G = *g;
  521. if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
  522. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
  523. if (F > G) { /* swap f and g */
  524. *f = G;
  525. *g = F;
  526. }
  527. return(NULL);
  528. } /* end of Cudd_addNor */
  529. /**
  530. @brief XOR of two 0-1 ADDs.
  531. @return NULL if not a terminal case; f XOR g otherwise.
  532. @sideeffect None
  533. @see Cudd_addApply
  534. */
  535. DdNode *
  536. Cudd_addXor(
  537. DdManager * dd,
  538. DdNode ** f,
  539. DdNode ** g)
  540. {
  541. DdNode *F, *G;
  542. F = *f; G = *g;
  543. if (F == G) return(DD_ZERO(dd));
  544. if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
  545. if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
  546. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  547. if (F > G) { /* swap f and g */
  548. *f = G;
  549. *g = F;
  550. }
  551. return(NULL);
  552. } /* end of Cudd_addXor */
  553. /**
  554. @brief XNOR of two 0-1 ADDs.
  555. @return NULL if not a terminal case; f XNOR g otherwise.
  556. @sideeffect None
  557. @see Cudd_addApply
  558. */
  559. DdNode *
  560. Cudd_addXnor(
  561. DdManager * dd,
  562. DdNode ** f,
  563. DdNode ** g)
  564. {
  565. DdNode *F, *G;
  566. F = *f; G = *g;
  567. if (F == G) return(DD_ONE(dd));
  568. if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
  569. if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
  570. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  571. if (F > G) { /* swap f and g */
  572. *f = G;
  573. *g = F;
  574. }
  575. return(NULL);
  576. } /* end of Cudd_addXnor */
  577. /**
  578. @brief Applies op to the discriminants of f.
  579. @return a pointer to the result if succssful; NULL otherwise.
  580. @sideeffect None
  581. @see Cudd_addApply Cudd_addLog
  582. */
  583. DdNode *
  584. Cudd_addMonadicApply(
  585. DdManager * dd,
  586. DD_MAOP op,
  587. DdNode * f)
  588. {
  589. DdNode *res;
  590. do {
  591. dd->reordered = 0;
  592. res = cuddAddMonadicApplyRecur(dd,op,f);
  593. } while (dd->reordered == 1);
  594. if (dd->errorCode == CUDD_TIMEOUT_EXPIRED && dd->timeoutHandler) {
  595. dd->timeoutHandler(dd, dd->tohArg);
  596. }
  597. return(res);
  598. } /* end of Cudd_addMonadicApply */
  599. /**
  600. @brief Natural logarithm of an %ADD.
  601. @details The discriminants of f must be positive double's.
  602. @return NULL if not a terminal case; log(f) otherwise.
  603. @sideeffect None
  604. @see Cudd_addMonadicApply
  605. */
  606. DdNode *
  607. Cudd_addLog(
  608. DdManager * dd,
  609. DdNode * f)
  610. {
  611. if (cuddIsConstant(f)) {
  612. CUDD_VALUE_TYPE value = log(cuddV(f));
  613. DdNode *res = cuddUniqueConst(dd,value);
  614. return(res);
  615. }
  616. return(NULL);
  617. } /* end of Cudd_addLog */
  618. /**Function********************************************************************
  619. Synopsis [Floor of an ADD.]
  620. Description [Floor of an ADD. Returns NULL
  621. if not a terminal case; floor(f) otherwise.]
  622. SideEffects [None]
  623. SeeAlso [Cudd_addMonadicApply]
  624. ******************************************************************************/
  625. DdNode *
  626. Cudd_addFloor(
  627. DdManager * dd,
  628. DdNode * f)
  629. {
  630. if (cuddIsConstant(f)) {
  631. CUDD_VALUE_TYPE value = floor(cuddV(f));
  632. DdNode *res = cuddUniqueConst(dd,value);
  633. return(res);
  634. }
  635. return(NULL);
  636. } /* end of Cudd_addFloor */
  637. /**Function********************************************************************
  638. Synopsis [Ceiling of an ADD.]
  639. Description [Ceiling of an ADD. Returns NULL
  640. if not a terminal case; ceil(f) otherwise.]
  641. SideEffects [None]
  642. SeeAlso [Cudd_addMonadicApply]
  643. ******************************************************************************/
  644. DdNode *
  645. Cudd_addCeil(
  646. DdManager * dd,
  647. DdNode * f)
  648. {
  649. if (cuddIsConstant(f)) {
  650. CUDD_VALUE_TYPE value = ceil(cuddV(f));
  651. DdNode *res = cuddUniqueConst(dd,value);
  652. return(res);
  653. }
  654. return(NULL);
  655. } /* end of Cudd_addCeiling */
  656. /**Function********************************************************************
  657. Synopsis [1 if f==g; 0 otherwise.]
  658. Description [Returns NULL if not a terminal case; f op g otherwise,
  659. where f op g is 1 if f==g; 0 otherwise.]
  660. SideEffects [None]
  661. SeeAlso [Cudd_addApply]
  662. ******************************************************************************/
  663. DdNode *
  664. Cudd_addEquals(
  665. DdManager * dd,
  666. DdNode ** f,
  667. DdNode ** g)
  668. {
  669. DdNode *F, *G;
  670. F = *f; G = *g;
  671. if (F == G) return(DD_ONE(dd));
  672. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
  673. if (F > G) { /* swap f and g */
  674. *f = G;
  675. *g = F;
  676. }
  677. return(NULL);
  678. } /* end of Cudd_addEquals */
  679. /**Function********************************************************************
  680. Synopsis [1 if f==g; 0 otherwise.]
  681. Description [Returns NULL if not a terminal case; f op g otherwise,
  682. where f op g is 1 if f==g; 0 otherwise.]
  683. SideEffects [None]
  684. SeeAlso [Cudd_addApply]
  685. Added 23/08/2016 by Christian Dehnert
  686. ******************************************************************************/
  687. DdNode *
  688. Cudd_addToBddEquals(
  689. DdManager * dd,
  690. DdNode ** f,
  691. DdNode ** g)
  692. {
  693. DdNode *F, *G;
  694. F = *f; G = *g;
  695. if (F == G) return(DD_ONE(dd));
  696. if (cuddIsConstant(F) && cuddIsConstant(G)) return(Cudd_Not(DD_ONE(dd)));
  697. if (F > G) { /* swap f and g */
  698. *f = G;
  699. *g = F;
  700. }
  701. return(NULL);
  702. } /* end of Cudd_addToBddEquals */
  703. /**Function********************************************************************
  704. Synopsis [1 if f!=g; 0 otherwise.]
  705. Description [Returns NULL if not a terminal case; f op g otherwise,
  706. where f op g is 1 if f!=g; 0 otherwise.]
  707. SideEffects [None]
  708. SeeAlso [Cudd_addApply]
  709. ******************************************************************************/
  710. DdNode *
  711. Cudd_addNotEquals(
  712. DdManager * dd,
  713. DdNode ** f,
  714. DdNode ** g)
  715. {
  716. DdNode *F, *G;
  717. F = *f; G = *g;
  718. if (F == G) return(DD_ZERO(dd));
  719. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
  720. if (F > G) { /* swap f and g */
  721. *f = G;
  722. *g = F;
  723. }
  724. return(NULL);
  725. } /* end of Cudd_addNotEquals */
  726. /**Function********************************************************************
  727. Synopsis [1 if f!=g; 0 otherwise.]
  728. Description [Returns NULL if not a terminal case; f op g otherwise,
  729. where f op g is 1 if f!=g; 0 otherwise.]
  730. SideEffects [None]
  731. SeeAlso [Cudd_addApply]
  732. Added 23/08/2016 by Christian Dehnert
  733. ******************************************************************************/
  734. DdNode *
  735. Cudd_addToBddNotEquals(
  736. DdManager * dd,
  737. DdNode ** f,
  738. DdNode ** g)
  739. {
  740. DdNode *F, *G;
  741. F = *f; G = *g;
  742. if (F == G) return(Cudd_Not(DD_ONE(dd)));
  743. if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
  744. if (F > G) { /* swap f and g */
  745. *f = G;
  746. *g = F;
  747. }
  748. return(NULL);
  749. } /* end of Cudd_addToBddNotEquals */
  750. /**Function********************************************************************
  751. Synopsis [1 if f>g; 0 otherwise.]
  752. Description [Returns NULL if not a terminal case; f op g otherwise,
  753. where f op g is 1 if f>g; 0 otherwise.]
  754. SideEffects [None]
  755. SeeAlso [Cudd_addApply]
  756. ******************************************************************************/
  757. DdNode *
  758. Cudd_addGreaterThan(
  759. DdManager * dd,
  760. DdNode ** f,
  761. DdNode ** g)
  762. {
  763. DdNode *F, *G;
  764. F = *f; G = *g;
  765. if (F == G) return(DD_ZERO(dd));
  766. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  767. if (cuddV(F)>cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  768. }
  769. return(NULL);
  770. } /* end of Cudd_addGreaterThan */
  771. /**Function********************************************************************
  772. Synopsis [1 if f>g; 0 otherwise.]
  773. Description [Returns NULL if not a terminal case; f op g otherwise,
  774. where f op g is 1 if f>g; 0 otherwise.]
  775. SideEffects [None]
  776. SeeAlso [Cudd_addApply]
  777. Added 23/08/2016 by Christian Dehnert
  778. ******************************************************************************/
  779. DdNode *
  780. Cudd_addToBddGreaterThan(
  781. DdManager * dd,
  782. DdNode ** f,
  783. DdNode ** g)
  784. {
  785. DdNode *F, *G;
  786. F = *f; G = *g;
  787. if (F == G) return(Cudd_Not(DD_ONE(dd)));
  788. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  789. if (cuddV(F)>cuddV(G)) return (DD_ONE(dd)); else return (Cudd_Not(DD_ONE(dd)));
  790. }
  791. return(NULL);
  792. } /* end of Cudd_addToBddGreaterThan */
  793. /**Function********************************************************************
  794. Synopsis [1 if f>=g; 0 otherwise.]
  795. Description [Returns NULL if not a terminal case; f op g otherwise,
  796. where f op g is 1 if f>=g; 0 otherwise.]
  797. SideEffects [None]
  798. SeeAlso [Cudd_addApply]
  799. ******************************************************************************/
  800. DdNode *
  801. Cudd_addGreaterThanEquals(
  802. DdManager * dd,
  803. DdNode ** f,
  804. DdNode ** g)
  805. {
  806. DdNode *F, *G;
  807. F = *f; G = *g;
  808. if (F == G) return(DD_ONE(dd));
  809. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  810. if (cuddV(F)>=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  811. }
  812. return(NULL);
  813. } /* end of Cudd_addGreaterThanEquals */
  814. /**Function********************************************************************
  815. Synopsis [1 if f>=g; 0 otherwise.]
  816. Description [Returns NULL if not a terminal case; f op g otherwise,
  817. where f op g is 1 if f>=g; 0 otherwise.]
  818. SideEffects [None]
  819. SeeAlso [Cudd_addApply]
  820. Added 23/08/2016 by Christian Dehnert
  821. ******************************************************************************/
  822. DdNode *
  823. Cudd_addToBddGreaterThanEquals(
  824. DdManager * dd,
  825. DdNode ** f,
  826. DdNode ** g)
  827. {
  828. DdNode *F, *G;
  829. F = *f; G = *g;
  830. if (F == G) return(DD_ONE(dd));
  831. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  832. if (cuddV(F)>=cuddV(G)) return (DD_ONE(dd)); else return (Cudd_Not(DD_ONE(dd)));
  833. }
  834. return(NULL);
  835. } /* end of Cudd_addToBddGreaterThanEquals */
  836. /**Function********************************************************************
  837. Synopsis [1 if f<g; 0 otherwise.]
  838. Description [Returns NULL if not a terminal case; f op g otherwise,
  839. where f op g is 1 if f<g; 0 otherwise.]
  840. SideEffects [None]
  841. SeeAlso [Cudd_addApply]
  842. ******************************************************************************/
  843. DdNode *
  844. Cudd_addLessThan(
  845. DdManager * dd,
  846. DdNode ** f,
  847. DdNode ** g)
  848. {
  849. DdNode *F, *G;
  850. F = *f; G = *g;
  851. if (F == G) return(DD_ZERO(dd));
  852. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  853. if (cuddV(F)<cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  854. }
  855. return(NULL);
  856. } /* end of Cudd_addLessThan */
  857. /**Function********************************************************************
  858. Synopsis [1 if f<g; 0 otherwise.]
  859. Description [Returns NULL if not a terminal case; f op g otherwise,
  860. where f op g is 1 if f<g; 0 otherwise.]
  861. SideEffects [None]
  862. SeeAlso [Cudd_addApply]
  863. Added 23/08/2016 by Christian Dehnert
  864. ******************************************************************************/
  865. DdNode *
  866. Cudd_addToBddLessThan(
  867. DdManager * dd,
  868. DdNode ** f,
  869. DdNode ** g)
  870. {
  871. DdNode *F, *G;
  872. F = *f; G = *g;
  873. if (F == G) return(Cudd_Not(DD_ONE(dd)));
  874. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  875. if (cuddV(F)<cuddV(G)) return (DD_ONE(dd)); else return (Cudd_Not(DD_ONE(dd)));
  876. }
  877. return(NULL);
  878. } /* end of Cudd_addToBddLessThan */
  879. /**Function********************************************************************
  880. Synopsis [1 if f<=g; 0 otherwise.]
  881. Description [Returns NULL if not a terminal case; f op g otherwise,
  882. where f op g is 1 if f<=g; 0 otherwise.]
  883. SideEffects [None]
  884. SeeAlso [Cudd_addApply]
  885. ******************************************************************************/
  886. DdNode *
  887. Cudd_addLessThanEquals(
  888. DdManager * dd,
  889. DdNode ** f,
  890. DdNode ** g)
  891. {
  892. DdNode *F, *G;
  893. F = *f; G = *g;
  894. if (F == G) return(DD_ONE(dd));
  895. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  896. if (cuddV(F)<=cuddV(G)) return (DD_ONE(dd)); else return (DD_ZERO(dd));
  897. }
  898. return(NULL);
  899. } /* end of Cudd_addLessThanEquals */
  900. /**Function********************************************************************
  901. Synopsis [1 if f<=g; 0 otherwise.]
  902. Description [Returns NULL if not a terminal case; f op g otherwise,
  903. where f op g is 1 if f<=g; 0 otherwise.]
  904. SideEffects [None]
  905. SeeAlso [Cudd_addApply]
  906. Added 23/08/2016 by Christian Dehnert
  907. ******************************************************************************/
  908. DdNode *
  909. Cudd_addToBddLessThanEquals(
  910. DdManager * dd,
  911. DdNode ** f,
  912. DdNode ** g)
  913. {
  914. DdNode *F, *G;
  915. F = *f; G = *g;
  916. if (F == G) return(DD_ONE(dd));
  917. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  918. if (cuddV(F)<=cuddV(G)) return (DD_ONE(dd)); else return (Cudd_Not(DD_ONE(dd)));
  919. }
  920. return(NULL);
  921. } /* end of Cudd_addToBddLessThanEquals */
  922. /**Function********************************************************************
  923. Synopsis [f to the power of g.]
  924. Description [Returns NULL if not a terminal case; f op g otherwise,
  925. where f op g is f to the power of g.]
  926. SideEffects [None]
  927. SeeAlso [Cudd_addApply]
  928. ******************************************************************************/
  929. DdNode *
  930. Cudd_addPow(
  931. DdManager * dd,
  932. DdNode ** f,
  933. DdNode ** g)
  934. {
  935. DdNode *res;
  936. DdNode *F, *G;
  937. CUDD_VALUE_TYPE value;
  938. F = *f; G = *g;
  939. if (G == DD_ZERO(dd)) return(DD_ONE(dd));
  940. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  941. value = pow(cuddV(F), cuddV(G));
  942. res = cuddUniqueConst(dd,value);
  943. return(res);
  944. }
  945. return(NULL);
  946. } /* end of Cudd_addPow */
  947. /**Function********************************************************************
  948. Synopsis [f modulo g.]
  949. Description [Returns NULL if not a terminal case; f op g otherwise,
  950. where f op g is f modulo g.]
  951. SideEffects [None]
  952. SeeAlso [Cudd_addApply]
  953. ******************************************************************************/
  954. DdNode *
  955. Cudd_addMod(
  956. DdManager * dd,
  957. DdNode ** f,
  958. DdNode ** g)
  959. {
  960. DdNode *res;
  961. DdNode *F, *G;
  962. int rem;
  963. CUDD_VALUE_TYPE value;
  964. F = *f; G = *g;
  965. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  966. // If g is <=0, then result is NaN
  967. if (cuddV(G) <= 0) value = (NAN);
  968. // Take care of negative case (% is remainder, not modulo)
  969. else {
  970. rem = ((int)cuddV(F) % (int)cuddV(G));
  971. if (rem < 0) rem += (int)cuddV(G);
  972. value = rem;
  973. }
  974. // Create/return result
  975. res = cuddUniqueConst(dd,value);
  976. return(res);
  977. }
  978. return(NULL);
  979. } /* end of Cudd_addMod */
  980. /**Function********************************************************************
  981. Synopsis [log f base g.]
  982. Description [Returns NULL if not a terminal case; f op g otherwise,
  983. where f op g is log f base g.]
  984. SideEffects [None]
  985. SeeAlso [Cudd_addApply]
  986. ******************************************************************************/
  987. DdNode *
  988. Cudd_addLogXY(
  989. DdManager * dd,
  990. DdNode ** f,
  991. DdNode ** g)
  992. {
  993. DdNode *res;
  994. DdNode *F, *G;
  995. CUDD_VALUE_TYPE value;
  996. F = *f; G = *g;
  997. if (cuddIsConstant(F) && cuddIsConstant(G)) {
  998. // If base is <=0 or ==1 (or +Inf/NaN), then result is NaN
  999. if (cuddV(G) <= 0 || cuddV(G) == 1.0 || G==DD_PLUS_INFINITY(dd) || cuddV(G) != cuddV(G)) value = (NAN);
  1000. // If arg is <0 or NaN, then result is NaN
  1001. else if (cuddV(F) < 0 || cuddV(F) != cuddV(F)) value = (NAN);
  1002. // If arg is +Inf, then result is +Inf
  1003. else if (F==DD_PLUS_INFINITY(dd)) return DD_PLUS_INFINITY(dd);
  1004. // If arg is (positive/negative) 0, then result is -Inf
  1005. else if (cuddV(F) == 0.0 || cuddV(F) == -0.0) return DD_MINUS_INFINITY(dd);
  1006. // Default case: normal log
  1007. else value = log(cuddV(F)) / log(cuddV(G));
  1008. // Create/return result
  1009. res = cuddUniqueConst(dd,value);
  1010. return(res);
  1011. }
  1012. return(NULL);
  1013. } /* end of Cudd_addLogXY */
  1014. /*---------------------------------------------------------------------------*/
  1015. /* Definition of internal functions */
  1016. /*---------------------------------------------------------------------------*/
  1017. /**
  1018. @brief Performs the recursive step of Cudd_addApply.
  1019. @return a pointer to the result if successful; NULL otherwise.
  1020. @sideeffect None
  1021. @see cuddAddMonadicApplyRecur
  1022. */
  1023. DdNode *
  1024. cuddAddApplyRecur(
  1025. DdManager * dd,
  1026. DD_AOP op,
  1027. DdNode * f,
  1028. DdNode * g)
  1029. {
  1030. DdNode *res,
  1031. *fv, *fvn, *gv, *gvn,
  1032. *T, *E;
  1033. int ford, gord;
  1034. unsigned int index;
  1035. DD_CTFP cacheOp;
  1036. /* Check terminal cases. Op may swap f and g to increase the
  1037. * cache hit rate.
  1038. */
  1039. statLine(dd);
  1040. res = (*op)(dd,&f,&g);
  1041. if (res != NULL) return(res);
  1042. /* Check cache. */
  1043. cacheOp = (DD_CTFP) op;
  1044. res = cuddCacheLookup2(dd,cacheOp,f,g);
  1045. if (res != NULL) return(res);
  1046. checkWhetherToGiveUp(dd);
  1047. /* Recursive step. */
  1048. ford = cuddI(dd,f->index);
  1049. gord = cuddI(dd,g->index);
  1050. if (ford <= gord) {
  1051. index = f->index;
  1052. fv = cuddT(f);
  1053. fvn = cuddE(f);
  1054. } else {
  1055. index = g->index;
  1056. fv = fvn = f;
  1057. }
  1058. if (gord <= ford) {
  1059. gv = cuddT(g);
  1060. gvn = cuddE(g);
  1061. } else {
  1062. gv = gvn = g;
  1063. }
  1064. T = cuddAddApplyRecur(dd,op,fv,gv);
  1065. if (T == NULL) return(NULL);
  1066. cuddRef(T);
  1067. E = cuddAddApplyRecur(dd,op,fvn,gvn);
  1068. if (E == NULL) {
  1069. Cudd_RecursiveDeref(dd,T);
  1070. return(NULL);
  1071. }
  1072. cuddRef(E);
  1073. res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
  1074. if (res == NULL) {
  1075. Cudd_RecursiveDeref(dd, T);
  1076. Cudd_RecursiveDeref(dd, E);
  1077. return(NULL);
  1078. }
  1079. cuddDeref(T);
  1080. cuddDeref(E);
  1081. /* Store result. */
  1082. cuddCacheInsert2(dd,cacheOp,f,g,res);
  1083. return(res);
  1084. } /* end of cuddAddApplyRecur */
  1085. /**
  1086. @brief Performs the recursive step of Cudd_addToBddApply.
  1087. @return a pointer to the result if successful; NULL otherwise.
  1088. @sideeffect None
  1089. @see cuddAddMonadicApplyRecur
  1090. added 23/08/2016 by Christian Dehnert
  1091. */
  1092. DdNode *
  1093. cuddAddToBddApplyRecur(
  1094. DdManager * dd,
  1095. DD_AOP op,
  1096. DdNode * f,
  1097. DdNode * g)
  1098. {
  1099. DdNode *res,
  1100. *fv, *fvn, *gv, *gvn,
  1101. *T, *E;
  1102. int ford, gord;
  1103. unsigned int index;
  1104. DD_CTFP cacheOp;
  1105. /* Check terminal cases. Op may swap f and g to increase the
  1106. * cache hit rate.
  1107. */
  1108. statLine(dd);
  1109. res = (*op)(dd,&f,&g);
  1110. if (res != NULL) return(res);
  1111. /* Check cache. */
  1112. cacheOp = (DD_CTFP) op;
  1113. res = cuddCacheLookup2(dd,cacheOp,f,g);
  1114. if (res != NULL) return(res);
  1115. checkWhetherToGiveUp(dd);
  1116. /* Recursive step. */
  1117. ford = cuddI(dd,f->index);
  1118. gord = cuddI(dd,g->index);
  1119. if (ford <= gord) {
  1120. index = f->index;
  1121. fv = cuddT(f);
  1122. fvn = cuddE(f);
  1123. } else {
  1124. index = g->index;
  1125. fv = fvn = f;
  1126. }
  1127. if (gord <= ford) {
  1128. gv = cuddT(g);
  1129. gvn = cuddE(g);
  1130. } else {
  1131. gv = gvn = g;
  1132. }
  1133. T = cuddAddToBddApplyRecur(dd,op,fv,gv);
  1134. if (T == NULL) return(NULL);
  1135. cuddRef(T);
  1136. E = cuddAddToBddApplyRecur(dd,op,fvn,gvn);
  1137. if (E == NULL) {
  1138. Cudd_IterDerefBdd(dd,T);
  1139. return(NULL);
  1140. }
  1141. cuddRef(E);
  1142. int complT = Cudd_IsComplement(T);
  1143. if (T == E) {
  1144. res = T;
  1145. } else {
  1146. res = cuddUniqueInter(dd,(int)index,Cudd_Regular(T),complT ? Cudd_Not(E) : E);
  1147. if (complT) {
  1148. res = Cudd_Not(res);
  1149. }
  1150. }
  1151. if (res == NULL) {
  1152. Cudd_IterDerefBdd(dd, T);
  1153. Cudd_IterDerefBdd(dd, E);
  1154. return(NULL);
  1155. }
  1156. cuddRef(res);
  1157. cuddDeref(T);
  1158. cuddDeref(E);
  1159. /* Store result. */
  1160. cuddCacheInsert2(dd,cacheOp,f,g,res);
  1161. cuddDeref(res);
  1162. return(res);
  1163. } /* end of cuddAddToBddApplyRecur */
  1164. /**
  1165. @brief Performs the recursive step of Cudd_addMonadicApply.
  1166. @return a pointer to the result if successful; NULL otherwise.
  1167. @sideeffect None
  1168. @see cuddAddApplyRecur
  1169. */
  1170. DdNode *
  1171. cuddAddMonadicApplyRecur(
  1172. DdManager * dd,
  1173. DD_MAOP op,
  1174. DdNode * f)
  1175. {
  1176. DdNode *res, *ft, *fe, *T, *E;
  1177. unsigned int index;
  1178. /* Check terminal cases. */
  1179. statLine(dd);
  1180. res = (*op)(dd,f);
  1181. if (res != NULL) return(res);
  1182. /* Check cache. */
  1183. res = cuddCacheLookup1(dd,op,f);
  1184. if (res != NULL) return(res);
  1185. checkWhetherToGiveUp(dd);
  1186. /* Recursive step. */
  1187. index = f->index;
  1188. ft = cuddT(f);
  1189. fe = cuddE(f);
  1190. T = cuddAddMonadicApplyRecur(dd,op,ft);
  1191. if (T == NULL) return(NULL);
  1192. cuddRef(T);
  1193. E = cuddAddMonadicApplyRecur(dd,op,fe);
  1194. if (E == NULL) {
  1195. Cudd_RecursiveDeref(dd,T);
  1196. return(NULL);
  1197. }
  1198. cuddRef(E);
  1199. res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
  1200. if (res == NULL) {
  1201. Cudd_RecursiveDeref(dd, T);
  1202. Cudd_RecursiveDeref(dd, E);
  1203. return(NULL);
  1204. }
  1205. cuddDeref(T);
  1206. cuddDeref(E);
  1207. /* Store result. */
  1208. cuddCacheInsert1(dd,op,f,res);
  1209. return(res);
  1210. } /* end of cuddAddMonadicApplyRecur */
  1211. /*---------------------------------------------------------------------------*/
  1212. /* Definition of static functions */
  1213. /*---------------------------------------------------------------------------*/