1 /**CFile***********************************************************************
3 FileName [cuddAddApply.c]
7 Synopsis [Apply functions for ADDs and their operators.]
9 Description [External procedures included in this module:
12 <li> Cudd_addMonadicApply()
15 <li> Cudd_addThreshold()
19 <li> Cudd_addMinimum()
20 <li> Cudd_addMaximum()
21 <li> Cudd_addOneZeroMaximum()
23 <li> Cudd_addAgreement()
30 Internal procedures included in this module:
32 <li> cuddAddApplyRecur()
33 <li> cuddAddMonadicApplyRecur()
36 Author [Fabio Somenzi]
38 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
42 Redistribution and use in source and binary forms, with or without
43 modification, are permitted provided that the following conditions
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 ******************************************************************************/
75 /*---------------------------------------------------------------------------*/
76 /* Constant declarations */
77 /*---------------------------------------------------------------------------*/
80 /*---------------------------------------------------------------------------*/
81 /* Stucture declarations */
82 /*---------------------------------------------------------------------------*/
85 /*---------------------------------------------------------------------------*/
86 /* Type declarations */
87 /*---------------------------------------------------------------------------*/
90 /*---------------------------------------------------------------------------*/
91 /* Variable declarations */
92 /*---------------------------------------------------------------------------*/
95 static char rcsid
[] DD_UNUSED
= "$Id: cuddAddApply.c,v 1.18 2009/02/19 16:15:26 fabio Exp $";
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.]
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 ******************************************************************************/
144 res
= cuddAddApplyRecur(dd
,op
,f
,g
);
145 } while (dd
->reordered
== 1);
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.]
160 SeeAlso [Cudd_addApply]
162 ******************************************************************************/
171 CUDD_VALUE_TYPE value
;
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
);
181 if (F
> G
) { /* swap f and g */
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.]
200 SeeAlso [Cudd_addApply]
202 ******************************************************************************/
211 CUDD_VALUE_TYPE value
;
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
);
222 if (F
> G
) { /* swap f and g */
228 } /* end of Cudd_addTimes */
231 /**Function********************************************************************
233 Synopsis [f if f>=g; 0 if f<g.]
235 Description [Threshold operator for Apply (f if f >=g; 0 if f<g).
236 Returns NULL if not a terminal case; f op g otherwise.]
240 SeeAlso [Cudd_addApply]
242 ******************************************************************************/
252 if (F
== G
|| F
== DD_PLUS_INFINITY(dd
)) return(F
);
253 if (cuddIsConstant(F
) && cuddIsConstant(G
)) {
254 if (cuddV(F
) >= cuddV(G
)) {
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.]
274 SeeAlso [Cudd_addApply]
276 ******************************************************************************/
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
);
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.]
304 SeeAlso [Cudd_addApply]
306 ******************************************************************************/
315 CUDD_VALUE_TYPE value
;
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
);
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.]
341 SeeAlso [Cudd_addApply]
343 ******************************************************************************/
352 CUDD_VALUE_TYPE value
;
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
);
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.]
377 SeeAlso [Cudd_addApply]
379 ******************************************************************************/
389 if (F
== DD_PLUS_INFINITY(dd
)) return(G
);
390 if (G
== DD_PLUS_INFINITY(dd
)) return(F
);
391 if (F
== G
) return(F
);
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
);
397 if (cuddIsConstant(F
) && cuddIsConstant(G
)) {
398 if (cuddV(F
) <= cuddV(G
)) {
404 if (F
> G
) { /* swap f and g */
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.]
422 SeeAlso [Cudd_addApply]
424 ******************************************************************************/
434 if (F
== G
) return(F
);
435 if (F
== DD_MINUS_INFINITY(dd
)) return(G
);
436 if (G
== DD_MINUS_INFINITY(dd
)) return(F
);
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
);
442 if (cuddIsConstant(F
) && cuddIsConstant(G
)) {
443 if (cuddV(F
) >= cuddV(G
)) {
449 if (F
> G
) { /* swap f and g */
455 } /* end of Cudd_addMaximum */
458 /**Function********************************************************************
460 Synopsis [Returns 1 if f > g and 0 otherwise.]
462 Description [Returns 1 if f > g and 0 otherwise. Used in
463 conjunction with Cudd_addApply. Returns NULL if not a terminal
468 SeeAlso [Cudd_addApply]
470 ******************************************************************************/
472 Cudd_addOneZeroMaximum(
478 if (*f
== *g
) return(DD_ZERO(dd
));
479 if (*g
== DD_PLUS_INFINITY(dd
))
481 if (cuddIsConstant(*f
) && cuddIsConstant(*g
)) {
482 if (cuddV(*f
) > cuddV(*g
)) {
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.]
503 SeeAlso [Cudd_addApply]
505 ******************************************************************************/
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
)) {
526 return(DD_PLUS_INFINITY(dd
));
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.]
543 SeeAlso [Cudd_addApply]
545 ******************************************************************************/
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
);
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.]
573 SeeAlso [Cudd_addApply]
575 ******************************************************************************/
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 */
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.]
607 SeeAlso [Cudd_addApply]
609 ******************************************************************************/
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 */
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.]
639 SeeAlso [Cudd_addApply]
641 ******************************************************************************/
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 */
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.]
671 SeeAlso [Cudd_addApply]
673 ******************************************************************************/
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 */
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.]
705 SeeAlso [Cudd_addApply]
707 ******************************************************************************/
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 */
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.]
739 SeeAlso [Cudd_addApply Cudd_addLog]
741 ******************************************************************************/
743 Cudd_addMonadicApply(
752 res
= cuddAddMonadicApplyRecur(dd
,op
,f
);
753 } while (dd
->reordered
== 1);
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.]
769 SeeAlso [Cudd_addMonadicApply]
771 ******************************************************************************/
777 if (cuddIsConstant(f
)) {
778 CUDD_VALUE_TYPE value
= log(cuddV(f
));
779 DdNode
*res
= cuddUniqueConst(dd
,value
);
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.]
801 SeeAlso [cuddAddMonadicApplyRecur]
803 ******************************************************************************/
812 *fv
, *fvn
, *gv
, *gvn
,
814 unsigned int ford
, gord
;
818 /* Check terminal cases. Op may swap f and g to increase the
822 res
= (*op
)(dd
,&f
,&g
);
823 if (res
!= NULL
) return(res
);
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
);
848 T
= cuddAddApplyRecur(dd
,op
,fv
,gv
);
849 if (T
== NULL
) return(NULL
);
852 E
= cuddAddApplyRecur(dd
,op
,fvn
,gvn
);
854 Cudd_RecursiveDeref(dd
,T
);
859 res
= (T
== E
) ? T
: cuddUniqueInter(dd
,(int)index
,T
,E
);
861 Cudd_RecursiveDeref(dd
, T
);
862 Cudd_RecursiveDeref(dd
, E
);
869 cuddCacheInsert2(dd
,cacheOp
,f
,g
,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.]
885 SeeAlso [cuddAddApplyRecur]
887 ******************************************************************************/
889 cuddAddMonadicApplyRecur(
894 DdNode
*res
, *ft
, *fe
, *T
, *E
;
897 /* Check terminal cases. */
900 if (res
!= NULL
) return(res
);
903 res
= cuddCacheLookup1(dd
,op
,f
);
904 if (res
!= NULL
) return(res
);
906 /* Recursive step. */
911 T
= cuddAddMonadicApplyRecur(dd
,op
,ft
);
912 if (T
== NULL
) return(NULL
);
915 E
= cuddAddMonadicApplyRecur(dd
,op
,fe
);
917 Cudd_RecursiveDeref(dd
,T
);
922 res
= (T
== E
) ? T
: cuddUniqueInter(dd
,(int)index
,T
,E
);
924 Cudd_RecursiveDeref(dd
, T
);
925 Cudd_RecursiveDeref(dd
, E
);
932 cuddCacheInsert1(dd
,op
,f
,res
);
936 } /* end of cuddAddMonadicApplyRecur */
939 /*---------------------------------------------------------------------------*/
940 /* Definition of static functions */
941 /*---------------------------------------------------------------------------*/