emergency commit
[cl-cudd.git] / distr / cudd / cuddAddApply.c
blob944d7a42febcc607c2dbcab40b40f7913ac4f13d
1 /**CFile***********************************************************************
3 FileName [cuddAddApply.c]
5 PackageName [cudd]
7 Synopsis [Apply functions for ADDs and their operators.]
9 Description [External procedures included in this module:
10 <ul>
11 <li> Cudd_addApply()
12 <li> Cudd_addMonadicApply()
13 <li> Cudd_addPlus()
14 <li> Cudd_addTimes()
15 <li> Cudd_addThreshold()
16 <li> Cudd_addSetNZ()
17 <li> Cudd_addDivide()
18 <li> Cudd_addMinus()
19 <li> Cudd_addMinimum()
20 <li> Cudd_addMaximum()
21 <li> Cudd_addOneZeroMaximum()
22 <li> Cudd_addDiff()
23 <li> Cudd_addAgreement()
24 <li> Cudd_addOr()
25 <li> Cudd_addNand()
26 <li> Cudd_addNor()
27 <li> Cudd_addXor()
28 <li> Cudd_addXnor()
29 </ul>
30 Internal procedures included in this module:
31 <ul>
32 <li> cuddAddApplyRecur()
33 <li> cuddAddMonadicApplyRecur()
34 </ul>]
36 Author [Fabio Somenzi]
38 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
40 All rights reserved.
42 Redistribution and use in source and binary forms, with or without
43 modification, are permitted provided that the following conditions
44 are met:
46 Redistributions of source code must retain the above copyright
47 notice, this list of conditions and the following disclaimer.
49 Redistributions in binary form must reproduce the above copyright
50 notice, this list of conditions and the following disclaimer in the
51 documentation and/or other materials provided with the distribution.
53 Neither the name of the University of Colorado nor the names of its
54 contributors may be used to endorse or promote products derived from
55 this software without specific prior written permission.
57 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
58 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
59 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
60 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
61 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
62 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
63 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
64 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
65 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
67 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
68 POSSIBILITY OF SUCH DAMAGE.]
70 ******************************************************************************/
72 #include "util.h"
73 #include "cuddInt.h"
75 /*---------------------------------------------------------------------------*/
76 /* Constant declarations */
77 /*---------------------------------------------------------------------------*/
80 /*---------------------------------------------------------------------------*/
81 /* Stucture declarations */
82 /*---------------------------------------------------------------------------*/
85 /*---------------------------------------------------------------------------*/
86 /* Type declarations */
87 /*---------------------------------------------------------------------------*/
90 /*---------------------------------------------------------------------------*/
91 /* Variable declarations */
92 /*---------------------------------------------------------------------------*/
94 #ifndef lint
95 static char rcsid[] DD_UNUSED = "$Id: cuddAddApply.c,v 1.18 2009/02/19 16:15:26 fabio Exp $";
96 #endif
99 /*---------------------------------------------------------------------------*/
100 /* Macro declarations */
101 /*---------------------------------------------------------------------------*/
104 /**AutomaticStart*************************************************************/
106 /*---------------------------------------------------------------------------*/
107 /* Static function prototypes */
108 /*---------------------------------------------------------------------------*/
111 /**AutomaticEnd***************************************************************/
114 /*---------------------------------------------------------------------------*/
115 /* Definition of exported functions */
116 /*---------------------------------------------------------------------------*/
118 /**Function********************************************************************
120 Synopsis [Applies op to the corresponding discriminants of f and g.]
122 Description [Applies op to the corresponding discriminants of f and g.
123 Returns a pointer to the result if succssful; NULL otherwise.]
125 SideEffects [None]
127 SeeAlso [Cudd_addMonadicApply Cudd_addPlus Cudd_addTimes
128 Cudd_addThreshold Cudd_addSetNZ Cudd_addDivide Cudd_addMinus Cudd_addMinimum
129 Cudd_addMaximum Cudd_addOneZeroMaximum Cudd_addDiff Cudd_addAgreement
130 Cudd_addOr Cudd_addNand Cudd_addNor Cudd_addXor Cudd_addXnor]
132 ******************************************************************************/
133 DdNode *
134 Cudd_addApply(
135 DdManager * dd,
136 DD_AOP op,
137 DdNode * f,
138 DdNode * g)
140 DdNode *res;
142 do {
143 dd->reordered = 0;
144 res = cuddAddApplyRecur(dd,op,f,g);
145 } while (dd->reordered == 1);
146 return(res);
148 } /* end of Cudd_addApply */
151 /**Function********************************************************************
153 Synopsis [Integer and floating point addition.]
155 Description [Integer and floating point addition. Returns NULL if not
156 a terminal case; f+g otherwise.]
158 SideEffects [None]
160 SeeAlso [Cudd_addApply]
162 ******************************************************************************/
163 DdNode *
164 Cudd_addPlus(
165 DdManager * dd,
166 DdNode ** f,
167 DdNode ** g)
169 DdNode *res;
170 DdNode *F, *G;
171 CUDD_VALUE_TYPE value;
173 F = *f; G = *g;
174 if (F == DD_ZERO(dd)) return(G);
175 if (G == DD_ZERO(dd)) return(F);
176 if (cuddIsConstant(F) && cuddIsConstant(G)) {
177 value = cuddV(F)+cuddV(G);
178 res = cuddUniqueConst(dd,value);
179 return(res);
181 if (F > G) { /* swap f and g */
182 *f = G;
183 *g = F;
185 return(NULL);
187 } /* end of Cudd_addPlus */
190 /**Function********************************************************************
192 Synopsis [Integer and floating point multiplication.]
194 Description [Integer and floating point multiplication. Returns NULL
195 if not a terminal case; f * g otherwise. This function can be used also
196 to take the AND of two 0-1 ADDs.]
198 SideEffects [None]
200 SeeAlso [Cudd_addApply]
202 ******************************************************************************/
203 DdNode *
204 Cudd_addTimes(
205 DdManager * dd,
206 DdNode ** f,
207 DdNode ** g)
209 DdNode *res;
210 DdNode *F, *G;
211 CUDD_VALUE_TYPE value;
213 F = *f; G = *g;
214 if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ZERO(dd));
215 if (F == DD_ONE(dd)) return(G);
216 if (G == DD_ONE(dd)) return(F);
217 if (cuddIsConstant(F) && cuddIsConstant(G)) {
218 value = cuddV(F)*cuddV(G);
219 res = cuddUniqueConst(dd,value);
220 return(res);
222 if (F > G) { /* swap f and g */
223 *f = G;
224 *g = F;
226 return(NULL);
228 } /* end of Cudd_addTimes */
231 /**Function********************************************************************
233 Synopsis [f if f&gt;=g; 0 if f&lt;g.]
235 Description [Threshold operator for Apply (f if f &gt;=g; 0 if f&lt;g).
236 Returns NULL if not a terminal case; f op g otherwise.]
238 SideEffects [None]
240 SeeAlso [Cudd_addApply]
242 ******************************************************************************/
243 DdNode *
244 Cudd_addThreshold(
245 DdManager * dd,
246 DdNode ** f,
247 DdNode ** g)
249 DdNode *F, *G;
251 F = *f; G = *g;
252 if (F == G || F == DD_PLUS_INFINITY(dd)) return(F);
253 if (cuddIsConstant(F) && cuddIsConstant(G)) {
254 if (cuddV(F) >= cuddV(G)) {
255 return(F);
256 } else {
257 return(DD_ZERO(dd));
260 return(NULL);
262 } /* end of Cudd_addThreshold */
265 /**Function********************************************************************
267 Synopsis [This operator sets f to the value of g wherever g != 0.]
269 Description [This operator sets f to the value of g wherever g != 0.
270 Returns NULL if not a terminal case; f op g otherwise.]
272 SideEffects [None]
274 SeeAlso [Cudd_addApply]
276 ******************************************************************************/
277 DdNode *
278 Cudd_addSetNZ(
279 DdManager * dd,
280 DdNode ** f,
281 DdNode ** g)
283 DdNode *F, *G;
285 F = *f; G = *g;
286 if (F == G) return(F);
287 if (F == DD_ZERO(dd)) return(G);
288 if (G == DD_ZERO(dd)) return(F);
289 if (cuddIsConstant(G)) return(G);
290 return(NULL);
292 } /* end of Cudd_addSetNZ */
295 /**Function********************************************************************
297 Synopsis [Integer and floating point division.]
299 Description [Integer and floating point division. Returns NULL if not
300 a terminal case; f / g otherwise.]
302 SideEffects [None]
304 SeeAlso [Cudd_addApply]
306 ******************************************************************************/
307 DdNode *
308 Cudd_addDivide(
309 DdManager * dd,
310 DdNode ** f,
311 DdNode ** g)
313 DdNode *res;
314 DdNode *F, *G;
315 CUDD_VALUE_TYPE value;
317 F = *f; G = *g;
318 /* We would like to use F == G -> F/G == 1, but F and G may
319 ** contain zeroes. */
320 if (F == DD_ZERO(dd)) return(DD_ZERO(dd));
321 if (G == DD_ONE(dd)) return(F);
322 if (cuddIsConstant(F) && cuddIsConstant(G)) {
323 value = cuddV(F)/cuddV(G);
324 res = cuddUniqueConst(dd,value);
325 return(res);
327 return(NULL);
329 } /* end of Cudd_addDivide */
332 /**Function********************************************************************
334 Synopsis [Integer and floating point subtraction.]
336 Description [Integer and floating point subtraction. Returns NULL if
337 not a terminal case; f - g otherwise.]
339 SideEffects [None]
341 SeeAlso [Cudd_addApply]
343 ******************************************************************************/
344 DdNode *
345 Cudd_addMinus(
346 DdManager * dd,
347 DdNode ** f,
348 DdNode ** g)
350 DdNode *res;
351 DdNode *F, *G;
352 CUDD_VALUE_TYPE value;
354 F = *f; G = *g;
355 if (F == G) return(DD_ZERO(dd));
356 if (F == DD_ZERO(dd)) return(cuddAddNegateRecur(dd,G));
357 if (G == DD_ZERO(dd)) return(F);
358 if (cuddIsConstant(F) && cuddIsConstant(G)) {
359 value = cuddV(F)-cuddV(G);
360 res = cuddUniqueConst(dd,value);
361 return(res);
363 return(NULL);
365 } /* end of Cudd_addMinus */
368 /**Function********************************************************************
370 Synopsis [Integer and floating point min.]
372 Description [Integer and floating point min for Cudd_addApply.
373 Returns NULL if not a terminal case; min(f,g) otherwise.]
375 SideEffects [None]
377 SeeAlso [Cudd_addApply]
379 ******************************************************************************/
380 DdNode *
381 Cudd_addMinimum(
382 DdManager * dd,
383 DdNode ** f,
384 DdNode ** g)
386 DdNode *F, *G;
388 F = *f; G = *g;
389 if (F == DD_PLUS_INFINITY(dd)) return(G);
390 if (G == DD_PLUS_INFINITY(dd)) return(F);
391 if (F == G) return(F);
392 #if 0
393 /* These special cases probably do not pay off. */
394 if (F == DD_MINUS_INFINITY(dd)) return(F);
395 if (G == DD_MINUS_INFINITY(dd)) return(G);
396 #endif
397 if (cuddIsConstant(F) && cuddIsConstant(G)) {
398 if (cuddV(F) <= cuddV(G)) {
399 return(F);
400 } else {
401 return(G);
404 if (F > G) { /* swap f and g */
405 *f = G;
406 *g = F;
408 return(NULL);
410 } /* end of Cudd_addMinimum */
413 /**Function********************************************************************
415 Synopsis [Integer and floating point max.]
417 Description [Integer and floating point max for Cudd_addApply.
418 Returns NULL if not a terminal case; max(f,g) otherwise.]
420 SideEffects [None]
422 SeeAlso [Cudd_addApply]
424 ******************************************************************************/
425 DdNode *
426 Cudd_addMaximum(
427 DdManager * dd,
428 DdNode ** f,
429 DdNode ** g)
431 DdNode *F, *G;
433 F = *f; G = *g;
434 if (F == G) return(F);
435 if (F == DD_MINUS_INFINITY(dd)) return(G);
436 if (G == DD_MINUS_INFINITY(dd)) return(F);
437 #if 0
438 /* These special cases probably do not pay off. */
439 if (F == DD_PLUS_INFINITY(dd)) return(F);
440 if (G == DD_PLUS_INFINITY(dd)) return(G);
441 #endif
442 if (cuddIsConstant(F) && cuddIsConstant(G)) {
443 if (cuddV(F) >= cuddV(G)) {
444 return(F);
445 } else {
446 return(G);
449 if (F > G) { /* swap f and g */
450 *f = G;
451 *g = F;
453 return(NULL);
455 } /* end of Cudd_addMaximum */
458 /**Function********************************************************************
460 Synopsis [Returns 1 if f &gt; g and 0 otherwise.]
462 Description [Returns 1 if f &gt; g and 0 otherwise. Used in
463 conjunction with Cudd_addApply. Returns NULL if not a terminal
464 case.]
466 SideEffects [None]
468 SeeAlso [Cudd_addApply]
470 ******************************************************************************/
471 DdNode *
472 Cudd_addOneZeroMaximum(
473 DdManager * dd,
474 DdNode ** f,
475 DdNode ** g)
478 if (*f == *g) return(DD_ZERO(dd));
479 if (*g == DD_PLUS_INFINITY(dd))
480 return DD_ZERO(dd);
481 if (cuddIsConstant(*f) && cuddIsConstant(*g)) {
482 if (cuddV(*f) > cuddV(*g)) {
483 return(DD_ONE(dd));
484 } else {
485 return(DD_ZERO(dd));
489 return(NULL);
491 } /* end of Cudd_addOneZeroMaximum */
494 /**Function********************************************************************
496 Synopsis [Returns plusinfinity if f=g; returns min(f,g) if f!=g.]
498 Description [Returns NULL if not a terminal case; f op g otherwise,
499 where f op g is plusinfinity if f=g; min(f,g) if f!=g.]
501 SideEffects [None]
503 SeeAlso [Cudd_addApply]
505 ******************************************************************************/
506 DdNode *
507 Cudd_addDiff(
508 DdManager * dd,
509 DdNode ** f,
510 DdNode ** g)
512 DdNode *F, *G;
514 F = *f; G = *g;
515 if (F == G) return(DD_PLUS_INFINITY(dd));
516 if (F == DD_PLUS_INFINITY(dd)) return(G);
517 if (G == DD_PLUS_INFINITY(dd)) return(F);
518 if (cuddIsConstant(F) && cuddIsConstant(G)) {
519 if (cuddV(F) != cuddV(G)) {
520 if (cuddV(F) < cuddV(G)) {
521 return(F);
522 } else {
523 return(G);
525 } else {
526 return(DD_PLUS_INFINITY(dd));
529 return(NULL);
531 } /* end of Cudd_addDiff */
534 /**Function********************************************************************
536 Synopsis [f if f==g; background if f!=g.]
538 Description [Returns NULL if not a terminal case; f op g otherwise,
539 where f op g is f if f==g; background if f!=g.]
541 SideEffects [None]
543 SeeAlso [Cudd_addApply]
545 ******************************************************************************/
546 DdNode *
547 Cudd_addAgreement(
548 DdManager * dd,
549 DdNode ** f,
550 DdNode ** g)
552 DdNode *F, *G;
554 F = *f; G = *g;
555 if (F == G) return(F);
556 if (F == dd->background) return(F);
557 if (G == dd->background) return(G);
558 if (cuddIsConstant(F) && cuddIsConstant(G)) return(dd->background);
559 return(NULL);
561 } /* end of Cudd_addAgreement */
564 /**Function********************************************************************
566 Synopsis [Disjunction of two 0-1 ADDs.]
568 Description [Disjunction of two 0-1 ADDs. Returns NULL
569 if not a terminal case; f OR g otherwise.]
571 SideEffects [None]
573 SeeAlso [Cudd_addApply]
575 ******************************************************************************/
576 DdNode *
577 Cudd_addOr(
578 DdManager * dd,
579 DdNode ** f,
580 DdNode ** g)
582 DdNode *F, *G;
584 F = *f; G = *g;
585 if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ONE(dd));
586 if (cuddIsConstant(F)) return(G);
587 if (cuddIsConstant(G)) return(F);
588 if (F == G) return(F);
589 if (F > G) { /* swap f and g */
590 *f = G;
591 *g = F;
593 return(NULL);
595 } /* end of Cudd_addOr */
598 /**Function********************************************************************
600 Synopsis [NAND of two 0-1 ADDs.]
602 Description [NAND of two 0-1 ADDs. Returns NULL
603 if not a terminal case; f NAND g otherwise.]
605 SideEffects [None]
607 SeeAlso [Cudd_addApply]
609 ******************************************************************************/
610 DdNode *
611 Cudd_addNand(
612 DdManager * dd,
613 DdNode ** f,
614 DdNode ** g)
616 DdNode *F, *G;
618 F = *f; G = *g;
619 if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
620 if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
621 if (F > G) { /* swap f and g */
622 *f = G;
623 *g = F;
625 return(NULL);
627 } /* end of Cudd_addNand */
630 /**Function********************************************************************
632 Synopsis [NOR of two 0-1 ADDs.]
634 Description [NOR of two 0-1 ADDs. Returns NULL
635 if not a terminal case; f NOR g otherwise.]
637 SideEffects [None]
639 SeeAlso [Cudd_addApply]
641 ******************************************************************************/
642 DdNode *
643 Cudd_addNor(
644 DdManager * dd,
645 DdNode ** f,
646 DdNode ** g)
648 DdNode *F, *G;
650 F = *f; G = *g;
651 if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
652 if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
653 if (F > G) { /* swap f and g */
654 *f = G;
655 *g = F;
657 return(NULL);
659 } /* end of Cudd_addNor */
662 /**Function********************************************************************
664 Synopsis [XOR of two 0-1 ADDs.]
666 Description [XOR of two 0-1 ADDs. Returns NULL
667 if not a terminal case; f XOR g otherwise.]
669 SideEffects [None]
671 SeeAlso [Cudd_addApply]
673 ******************************************************************************/
674 DdNode *
675 Cudd_addXor(
676 DdManager * dd,
677 DdNode ** f,
678 DdNode ** g)
680 DdNode *F, *G;
682 F = *f; G = *g;
683 if (F == G) return(DD_ZERO(dd));
684 if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
685 if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
686 if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
687 if (F > G) { /* swap f and g */
688 *f = G;
689 *g = F;
691 return(NULL);
693 } /* end of Cudd_addXor */
696 /**Function********************************************************************
698 Synopsis [XNOR of two 0-1 ADDs.]
700 Description [XNOR of two 0-1 ADDs. Returns NULL
701 if not a terminal case; f XNOR g otherwise.]
703 SideEffects [None]
705 SeeAlso [Cudd_addApply]
707 ******************************************************************************/
708 DdNode *
709 Cudd_addXnor(
710 DdManager * dd,
711 DdNode ** f,
712 DdNode ** g)
714 DdNode *F, *G;
716 F = *f; G = *g;
717 if (F == G) return(DD_ONE(dd));
718 if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
719 if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
720 if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
721 if (F > G) { /* swap f and g */
722 *f = G;
723 *g = F;
725 return(NULL);
727 } /* end of Cudd_addXnor */
730 /**Function********************************************************************
732 Synopsis [Applies op to the discriminants of f.]
734 Description [Applies op to the discriminants of f.
735 Returns a pointer to the result if succssful; NULL otherwise.]
737 SideEffects [None]
739 SeeAlso [Cudd_addApply Cudd_addLog]
741 ******************************************************************************/
742 DdNode *
743 Cudd_addMonadicApply(
744 DdManager * dd,
745 DD_MAOP op,
746 DdNode * f)
748 DdNode *res;
750 do {
751 dd->reordered = 0;
752 res = cuddAddMonadicApplyRecur(dd,op,f);
753 } while (dd->reordered == 1);
754 return(res);
756 } /* end of Cudd_addMonadicApply */
759 /**Function********************************************************************
761 Synopsis [Natural logarithm of an ADD.]
763 Description [Natural logarithm of an ADDs. Returns NULL
764 if not a terminal case; log(f) otherwise. The discriminants of f must
765 be positive double's.]
767 SideEffects [None]
769 SeeAlso [Cudd_addMonadicApply]
771 ******************************************************************************/
772 DdNode *
773 Cudd_addLog(
774 DdManager * dd,
775 DdNode * f)
777 if (cuddIsConstant(f)) {
778 CUDD_VALUE_TYPE value = log(cuddV(f));
779 DdNode *res = cuddUniqueConst(dd,value);
780 return(res);
782 return(NULL);
784 } /* end of Cudd_addLog */
787 /*---------------------------------------------------------------------------*/
788 /* Definition of internal functions */
789 /*---------------------------------------------------------------------------*/
792 /**Function********************************************************************
794 Synopsis [Performs the recursive step of Cudd_addApply.]
796 Description [Performs the recursive step of Cudd_addApply. Returns a
797 pointer to the result if successful; NULL otherwise.]
799 SideEffects [None]
801 SeeAlso [cuddAddMonadicApplyRecur]
803 ******************************************************************************/
804 DdNode *
805 cuddAddApplyRecur(
806 DdManager * dd,
807 DD_AOP op,
808 DdNode * f,
809 DdNode * g)
811 DdNode *res,
812 *fv, *fvn, *gv, *gvn,
813 *T, *E;
814 unsigned int ford, gord;
815 unsigned int index;
816 DD_CTFP cacheOp;
818 /* Check terminal cases. Op may swap f and g to increase the
819 * cache hit rate.
821 statLine(dd);
822 res = (*op)(dd,&f,&g);
823 if (res != NULL) return(res);
825 /* Check cache. */
826 cacheOp = (DD_CTFP) op;
827 res = cuddCacheLookup2(dd,cacheOp,f,g);
828 if (res != NULL) return(res);
830 /* Recursive step. */
831 ford = cuddI(dd,f->index);
832 gord = cuddI(dd,g->index);
833 if (ford <= gord) {
834 index = f->index;
835 fv = cuddT(f);
836 fvn = cuddE(f);
837 } else {
838 index = g->index;
839 fv = fvn = f;
841 if (gord <= ford) {
842 gv = cuddT(g);
843 gvn = cuddE(g);
844 } else {
845 gv = gvn = g;
848 T = cuddAddApplyRecur(dd,op,fv,gv);
849 if (T == NULL) return(NULL);
850 cuddRef(T);
852 E = cuddAddApplyRecur(dd,op,fvn,gvn);
853 if (E == NULL) {
854 Cudd_RecursiveDeref(dd,T);
855 return(NULL);
857 cuddRef(E);
859 res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
860 if (res == NULL) {
861 Cudd_RecursiveDeref(dd, T);
862 Cudd_RecursiveDeref(dd, E);
863 return(NULL);
865 cuddDeref(T);
866 cuddDeref(E);
868 /* Store result. */
869 cuddCacheInsert2(dd,cacheOp,f,g,res);
871 return(res);
873 } /* end of cuddAddApplyRecur */
876 /**Function********************************************************************
878 Synopsis [Performs the recursive step of Cudd_addMonadicApply.]
880 Description [Performs the recursive step of Cudd_addMonadicApply. Returns a
881 pointer to the result if successful; NULL otherwise.]
883 SideEffects [None]
885 SeeAlso [cuddAddApplyRecur]
887 ******************************************************************************/
888 DdNode *
889 cuddAddMonadicApplyRecur(
890 DdManager * dd,
891 DD_MAOP op,
892 DdNode * f)
894 DdNode *res, *ft, *fe, *T, *E;
895 unsigned int index;
897 /* Check terminal cases. */
898 statLine(dd);
899 res = (*op)(dd,f);
900 if (res != NULL) return(res);
902 /* Check cache. */
903 res = cuddCacheLookup1(dd,op,f);
904 if (res != NULL) return(res);
906 /* Recursive step. */
907 index = f->index;
908 ft = cuddT(f);
909 fe = cuddE(f);
911 T = cuddAddMonadicApplyRecur(dd,op,ft);
912 if (T == NULL) return(NULL);
913 cuddRef(T);
915 E = cuddAddMonadicApplyRecur(dd,op,fe);
916 if (E == NULL) {
917 Cudd_RecursiveDeref(dd,T);
918 return(NULL);
920 cuddRef(E);
922 res = (T == E) ? T : cuddUniqueInter(dd,(int)index,T,E);
923 if (res == NULL) {
924 Cudd_RecursiveDeref(dd, T);
925 Cudd_RecursiveDeref(dd, E);
926 return(NULL);
928 cuddDeref(T);
929 cuddDeref(E);
931 /* Store result. */
932 cuddCacheInsert1(dd,op,f,res);
934 return(res);
936 } /* end of cuddAddMonadicApplyRecur */
939 /*---------------------------------------------------------------------------*/
940 /* Definition of static functions */
941 /*---------------------------------------------------------------------------*/