1 /**CFile***********************************************************************
7 Synopsis [Functions for cache insertion and lookup.]
9 Description [Internal procedures included in this module:
12 <li> cuddCacheInsert()
13 <li> cuddCacheInsert2()
14 <li> cuddCacheLookup()
15 <li> cuddCacheLookupZdd()
16 <li> cuddCacheLookup2()
17 <li> cuddCacheLookup2Zdd()
18 <li> cuddConstantLookup()
19 <li> cuddCacheProfile()
20 <li> cuddCacheResize()
22 <li> cuddComputeFloorLog2()
24 Static procedures included in this module:
30 Author [Fabio Somenzi]
32 Copyright [Copyright (c) 1995-2004, Regents of the University of Colorado
36 Redistribution and use in source and binary forms, with or without
37 modification, are permitted provided that the following conditions
40 Redistributions of source code must retain the above copyright
41 notice, this list of conditions and the following disclaimer.
43 Redistributions in binary form must reproduce the above copyright
44 notice, this list of conditions and the following disclaimer in the
45 documentation and/or other materials provided with the distribution.
47 Neither the name of the University of Colorado nor the names of its
48 contributors may be used to endorse or promote products derived from
49 this software without specific prior written permission.
51 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
52 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
53 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
54 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
55 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
56 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
57 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
59 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
61 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
62 POSSIBILITY OF SUCH DAMAGE.]
64 ******************************************************************************/
69 /*---------------------------------------------------------------------------*/
70 /* Constant declarations */
71 /*---------------------------------------------------------------------------*/
73 #ifdef DD_CACHE_PROFILE
74 #define DD_HYSTO_BINS 8
77 /*---------------------------------------------------------------------------*/
78 /* Stucture declarations */
79 /*---------------------------------------------------------------------------*/
82 /*---------------------------------------------------------------------------*/
83 /* Type declarations */
84 /*---------------------------------------------------------------------------*/
87 /*---------------------------------------------------------------------------*/
88 /* Variable declarations */
89 /*---------------------------------------------------------------------------*/
92 static char rcsid
[] DD_UNUSED
= "$Id: cuddCache.c,v 1.34 2009/02/19 16:17:50 fabio Exp $";
95 /*---------------------------------------------------------------------------*/
96 /* Macro declarations */
97 /*---------------------------------------------------------------------------*/
100 /**AutomaticStart*************************************************************/
102 /*---------------------------------------------------------------------------*/
103 /* Static function prototypes */
104 /*---------------------------------------------------------------------------*/
107 /**AutomaticEnd***************************************************************/
110 /*---------------------------------------------------------------------------*/
111 /* Definition of exported functions */
112 /*---------------------------------------------------------------------------*/
114 /*---------------------------------------------------------------------------*/
115 /* Definition of internal functions */
116 /*---------------------------------------------------------------------------*/
119 /**Function********************************************************************
121 Synopsis [Initializes the computed table.]
123 Description [Initializes the computed table. It is called by
124 Cudd_Init. Returns 1 in case of success; 0 otherwise.]
130 ******************************************************************************/
133 DdManager
* unique
/* unique table */,
134 unsigned int cacheSize
/* initial size of the cache */,
135 unsigned int maxCacheSize
/* cache size beyond which no resizing occurs */)
138 unsigned int logSize
;
139 #ifndef DD_CACHE_PROFILE
144 /* Round cacheSize to largest power of 2 not greater than the requested
145 ** initial cache size. */
146 logSize
= cuddComputeFloorLog2(ddMax(cacheSize
,unique
->slots
/2));
147 cacheSize
= 1 << logSize
;
148 unique
->acache
= ALLOC(DdCache
,cacheSize
+1);
149 if (unique
->acache
== NULL
) {
150 unique
->errorCode
= CUDD_MEMORY_OUT
;
153 /* If the size of the cache entry is a power of 2, we want to
154 ** enforce alignment to that power of two. This happens when
155 ** DD_CACHE_PROFILE is not defined. */
156 #ifdef DD_CACHE_PROFILE
157 unique
->cache
= unique
->acache
;
158 unique
->memused
+= (cacheSize
) * sizeof(DdCache
);
160 mem
= (DdNodePtr
*) unique
->acache
;
161 offset
= (ptruint
) mem
& (sizeof(DdCache
) - 1);
162 mem
+= (sizeof(DdCache
) - offset
) / sizeof(DdNodePtr
);
163 unique
->cache
= (DdCache
*) mem
;
164 assert(((ptruint
) unique
->cache
& (sizeof(DdCache
) - 1)) == 0);
165 unique
->memused
+= (cacheSize
+1) * sizeof(DdCache
);
167 unique
->cacheSlots
= cacheSize
;
168 unique
->cacheShift
= sizeof(int) * 8 - logSize
;
169 unique
->maxCacheHard
= maxCacheSize
;
170 /* If cacheSlack is non-negative, we can resize. */
171 unique
->cacheSlack
= (int) ddMin(maxCacheSize
,
172 DD_MAX_CACHE_TO_SLOTS_RATIO
*unique
->slots
) -
174 Cudd_SetMinHit(unique
,DD_MIN_HIT
);
175 /* Initialize to avoid division by 0 and immediate resizing. */
176 unique
->cacheMisses
= (double) (int) (cacheSize
* unique
->minHit
+ 1);
177 unique
->cacheHits
= 0;
178 unique
->totCachehits
= 0;
179 /* The sum of cacheMisses and totCacheMisses is always correct,
180 ** even though cacheMisses is larger than it should for the reasons
181 ** explained above. */
182 unique
->totCacheMisses
= -unique
->cacheMisses
;
183 unique
->cachecollisions
= 0;
184 unique
->cacheinserts
= 0;
185 unique
->cacheLastInserts
= 0;
186 unique
->cachedeletions
= 0;
188 /* Initialize the cache */
189 for (i
= 0; (unsigned) i
< cacheSize
; i
++) {
190 unique
->cache
[i
].h
= 0; /* unused slots */
191 unique
->cache
[i
].data
= NULL
; /* invalid entry */
192 #ifdef DD_CACHE_PROFILE
193 unique
->cache
[i
].count
= 0;
199 } /* end of cuddInitCache */
202 /**Function********************************************************************
204 Synopsis [Inserts a result in the cache.]
210 SeeAlso [cuddCacheInsert2 cuddCacheInsert1]
212 ******************************************************************************/
223 register DdCache
*entry
;
226 uf
= (ptruint
) f
| (op
& 0xe);
227 ug
= (ptruint
) g
| (op
>> 4);
230 posn
= ddCHash2(uh
,uf
,ug
,table
->cacheShift
);
231 entry
= &table
->cache
[posn
];
233 table
->cachecollisions
+= entry
->data
!= NULL
;
234 table
->cacheinserts
++;
236 entry
->f
= (DdNode
*) uf
;
237 entry
->g
= (DdNode
*) ug
;
240 #ifdef DD_CACHE_PROFILE
244 } /* end of cuddCacheInsert */
247 /**Function********************************************************************
249 Synopsis [Inserts a result in the cache for a function with two
256 SeeAlso [cuddCacheInsert cuddCacheInsert1]
258 ******************************************************************************/
268 register DdCache
*entry
;
270 posn
= ddCHash2(op
,f
,g
,table
->cacheShift
);
271 entry
= &table
->cache
[posn
];
273 if (entry
->data
!= NULL
) {
274 table
->cachecollisions
++;
276 table
->cacheinserts
++;
280 entry
->h
= (ptruint
) op
;
282 #ifdef DD_CACHE_PROFILE
286 } /* end of cuddCacheInsert2 */
289 /**Function********************************************************************
291 Synopsis [Inserts a result in the cache for a function with two
298 SeeAlso [cuddCacheInsert cuddCacheInsert2]
300 ******************************************************************************/
309 register DdCache
*entry
;
311 posn
= ddCHash2(op
,f
,f
,table
->cacheShift
);
312 entry
= &table
->cache
[posn
];
314 if (entry
->data
!= NULL
) {
315 table
->cachecollisions
++;
317 table
->cacheinserts
++;
321 entry
->h
= (ptruint
) op
;
323 #ifdef DD_CACHE_PROFILE
327 } /* end of cuddCacheInsert1 */
330 /**Function********************************************************************
332 Synopsis [Looks up in the cache for the result of op applied to f,
335 Description [Returns the result if found; it returns NULL if no
340 SeeAlso [cuddCacheLookup2 cuddCacheLookup1]
342 ******************************************************************************/
356 uf
= (ptruint
) f
| (op
& 0xe);
357 ug
= (ptruint
) g
| (op
>> 4);
360 cache
= table
->cache
;
367 posn
= ddCHash2(uh
,uf
,ug
,table
->cacheShift
);
369 if (en
->data
!= NULL
&& en
->f
==(DdNodePtr
)uf
&& en
->g
==(DdNodePtr
)ug
&&
371 data
= Cudd_Regular(en
->data
);
373 if (data
->ref
== 0) {
374 cuddReclaim(table
,data
);
379 /* Cache miss: decide whether to resize. */
380 table
->cacheMisses
++;
382 if (table
->cacheSlack
>= 0 &&
383 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
384 cuddCacheResize(table
);
389 } /* end of cuddCacheLookup */
392 /**Function********************************************************************
394 Synopsis [Looks up in the cache for the result of op applied to f,
397 Description [Returns the result if found; it returns NULL if no
402 SeeAlso [cuddCacheLookup2Zdd cuddCacheLookup1Zdd]
404 ******************************************************************************/
418 uf
= (ptruint
) f
| (op
& 0xe);
419 ug
= (ptruint
) g
| (op
>> 4);
422 cache
= table
->cache
;
429 posn
= ddCHash2(uh
,uf
,ug
,table
->cacheShift
);
431 if (en
->data
!= NULL
&& en
->f
==(DdNodePtr
)uf
&& en
->g
==(DdNodePtr
)ug
&&
433 data
= Cudd_Regular(en
->data
);
435 if (data
->ref
== 0) {
436 cuddReclaimZdd(table
,data
);
441 /* Cache miss: decide whether to resize. */
442 table
->cacheMisses
++;
444 if (table
->cacheSlack
>= 0 &&
445 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
446 cuddCacheResize(table
);
451 } /* end of cuddCacheLookupZdd */
454 /**Function********************************************************************
456 Synopsis [Looks up in the cache for the result of op applied to f
459 Description [Returns the result if found; it returns NULL if no
464 SeeAlso [cuddCacheLookup cuddCacheLookup1]
466 ******************************************************************************/
478 cache
= table
->cache
;
485 posn
= ddCHash2(op
,f
,g
,table
->cacheShift
);
487 if (en
->data
!= NULL
&& en
->f
==f
&& en
->g
==g
&& en
->h
==(ptruint
)op
) {
488 data
= Cudd_Regular(en
->data
);
490 if (data
->ref
== 0) {
491 cuddReclaim(table
,data
);
496 /* Cache miss: decide whether to resize. */
497 table
->cacheMisses
++;
499 if (table
->cacheSlack
>= 0 &&
500 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
501 cuddCacheResize(table
);
506 } /* end of cuddCacheLookup2 */
509 /**Function********************************************************************
511 Synopsis [Looks up in the cache for the result of op applied to f.]
513 Description [Returns the result if found; it returns NULL if no
518 SeeAlso [cuddCacheLookup cuddCacheLookup2]
520 ******************************************************************************/
531 cache
= table
->cache
;
538 posn
= ddCHash2(op
,f
,f
,table
->cacheShift
);
540 if (en
->data
!= NULL
&& en
->f
==f
&& en
->h
==(ptruint
)op
) {
541 data
= Cudd_Regular(en
->data
);
543 if (data
->ref
== 0) {
544 cuddReclaim(table
,data
);
549 /* Cache miss: decide whether to resize. */
550 table
->cacheMisses
++;
552 if (table
->cacheSlack
>= 0 &&
553 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
554 cuddCacheResize(table
);
559 } /* end of cuddCacheLookup1 */
562 /**Function********************************************************************
564 Synopsis [Looks up in the cache for the result of op applied to f
567 Description [Returns the result if found; it returns NULL if no
572 SeeAlso [cuddCacheLookupZdd cuddCacheLookup1Zdd]
574 ******************************************************************************/
586 cache
= table
->cache
;
593 posn
= ddCHash2(op
,f
,g
,table
->cacheShift
);
595 if (en
->data
!= NULL
&& en
->f
==f
&& en
->g
==g
&& en
->h
==(ptruint
)op
) {
596 data
= Cudd_Regular(en
->data
);
598 if (data
->ref
== 0) {
599 cuddReclaimZdd(table
,data
);
604 /* Cache miss: decide whether to resize. */
605 table
->cacheMisses
++;
607 if (table
->cacheSlack
>= 0 &&
608 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
609 cuddCacheResize(table
);
614 } /* end of cuddCacheLookup2Zdd */
617 /**Function********************************************************************
619 Synopsis [Looks up in the cache for the result of op applied to f.]
621 Description [Returns the result if found; it returns NULL if no
626 SeeAlso [cuddCacheLookupZdd cuddCacheLookup2Zdd]
628 ******************************************************************************/
639 cache
= table
->cache
;
646 posn
= ddCHash2(op
,f
,f
,table
->cacheShift
);
648 if (en
->data
!= NULL
&& en
->f
==f
&& en
->h
==(ptruint
)op
) {
649 data
= Cudd_Regular(en
->data
);
651 if (data
->ref
== 0) {
652 cuddReclaimZdd(table
,data
);
657 /* Cache miss: decide whether to resize. */
658 table
->cacheMisses
++;
660 if (table
->cacheSlack
>= 0 &&
661 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
662 cuddCacheResize(table
);
667 } /* end of cuddCacheLookup1Zdd */
670 /**Function********************************************************************
672 Synopsis [Looks up in the cache for the result of op applied to f,
675 Description [Looks up in the cache for the result of op applied to f,
676 g, and h. Assumes that the calling procedure (e.g.,
677 Cudd_bddIteConstant) is only interested in whether the result is
678 constant or not. Returns the result if found (possibly
679 DD_NON_CONSTANT); otherwise it returns NULL.]
683 SeeAlso [cuddCacheLookup]
685 ******************************************************************************/
698 uf
= (ptruint
) f
| (op
& 0xe);
699 ug
= (ptruint
) g
| (op
>> 4);
702 cache
= table
->cache
;
708 posn
= ddCHash2(uh
,uf
,ug
,table
->cacheShift
);
711 /* We do not reclaim here because the result should not be
712 * referenced, but only tested for being a constant.
714 if (en
->data
!= NULL
&&
715 en
->f
== (DdNodePtr
)uf
&& en
->g
== (DdNodePtr
)ug
&& en
->h
== uh
) {
720 /* Cache miss: decide whether to resize. */
721 table
->cacheMisses
++;
723 if (table
->cacheSlack
>= 0 &&
724 table
->cacheHits
> table
->cacheMisses
* table
->minHit
) {
725 cuddCacheResize(table
);
730 } /* end of cuddConstantLookup */
733 /**Function********************************************************************
735 Synopsis [Computes and prints a profile of the cache usage.]
737 Description [Computes and prints a profile of the cache usage.
738 Returns 1 if successful; 0 otherwise.]
744 ******************************************************************************/
750 DdCache
*cache
= table
->cache
;
751 int slots
= table
->cacheSlots
;
756 #ifdef DD_CACHE_PROFILE
757 double count
, mean
, meansq
, stddev
, expected
;
760 double *hystogramQ
, *hystogramR
; /* histograms by quotient and remainder */
761 int nbins
= DD_HYSTO_BINS
;
764 double totalcount
, exStddev
;
766 meansq
= mean
= expected
= 0.0;
767 max
= min
= (long) cache
[0].count
;
771 hystogramQ
= ALLOC(double, nbins
);
772 if (hystogramQ
== NULL
) {
773 table
->errorCode
= CUDD_MEMORY_OUT
;
776 hystogramR
= ALLOC(double, nbins
);
777 if (hystogramR
== NULL
) {
779 table
->errorCode
= CUDD_MEMORY_OUT
;
782 for (i
= 0; i
< nbins
; i
++) {
787 for (i
= 0; i
< slots
; i
++) {
788 thiscount
= (long) cache
[i
].count
;
789 if (thiscount
> max
) {
793 if (thiscount
< min
) {
797 if (thiscount
== 0) {
800 count
= (double) thiscount
;
802 meansq
+= count
* count
;
804 expected
+= count
* (double) i
;
805 bin
= (i
* nbins
) / slots
;
806 hystogramQ
[bin
] += (double) thiscount
;
808 hystogramR
[bin
] += (double) thiscount
;
810 mean
/= (double) slots
;
811 meansq
/= (double) slots
;
813 /* Compute the standard deviation from both the data and the
814 ** theoretical model for a random distribution. */
815 stddev
= sqrt(meansq
- mean
*mean
);
816 exStddev
= sqrt((1 - 1/(double) slots
) * totalcount
/ (double) slots
);
818 retval
= fprintf(fp
,"Cache average accesses = %g\n", mean
);
819 if (retval
== EOF
) return(0);
820 retval
= fprintf(fp
,"Cache access standard deviation = %g ", stddev
);
821 if (retval
== EOF
) return(0);
822 retval
= fprintf(fp
,"(expected = %g)\n", exStddev
);
823 if (retval
== EOF
) return(0);
824 retval
= fprintf(fp
,"Cache max accesses = %ld for slot %d\n", max
, imax
);
825 if (retval
== EOF
) return(0);
826 retval
= fprintf(fp
,"Cache min accesses = %ld for slot %d\n", min
, imin
);
827 if (retval
== EOF
) return(0);
828 exUsed
= 100.0 * (1.0 - exp(-totalcount
/ (double) slots
));
829 retval
= fprintf(fp
,"Cache used slots = %.2f%% (expected %.2f%%)\n",
830 100.0 - (double) nzeroes
* 100.0 / (double) slots
,
832 if (retval
== EOF
) return(0);
834 if (totalcount
> 0) {
835 expected
/= totalcount
;
836 retval
= fprintf(fp
,"Cache access hystogram for %d bins", nbins
);
837 if (retval
== EOF
) return(0);
838 retval
= fprintf(fp
," (expected bin value = %g)\nBy quotient:",
840 if (retval
== EOF
) return(0);
841 for (i
= nbins
- 1; i
>=0; i
--) {
842 retval
= fprintf(fp
," %.0f", hystogramQ
[i
]);
843 if (retval
== EOF
) return(0);
845 retval
= fprintf(fp
,"\nBy residue: ");
846 if (retval
== EOF
) return(0);
847 for (i
= nbins
- 1; i
>=0; i
--) {
848 retval
= fprintf(fp
," %.0f", hystogramR
[i
]);
849 if (retval
== EOF
) return(0);
851 retval
= fprintf(fp
,"\n");
852 if (retval
== EOF
) return(0);
858 for (i
= 0; i
< slots
; i
++) {
859 nzeroes
+= cache
[i
].h
== 0;
862 (1.0 - exp(-(table
->cacheinserts
- table
->cacheLastInserts
) /
864 retval
= fprintf(fp
,"Cache used slots = %.2f%% (expected %.2f%%)\n",
865 100.0 - (double) nzeroes
* 100.0 / (double) slots
,
867 if (retval
== EOF
) return(0);
871 } /* end of cuddCacheProfile */
874 /**Function********************************************************************
876 Synopsis [Resizes the cache.]
884 ******************************************************************************/
889 DdCache
*cache
, *oldcache
, *oldacache
, *entry
, *old
;
892 unsigned int slots
, oldslots
;
895 extern DD_OOMFP MMoutOfMemory
;
896 DD_OOMFP saveHandler
;
897 #ifndef DD_CACHE_PROFILE
898 ptruint misalignment
;
902 oldcache
= table
->cache
;
903 oldacache
= table
->acache
;
904 oldslots
= table
->cacheSlots
;
905 slots
= table
->cacheSlots
= oldslots
<< 1;
908 (void) fprintf(table
->err
,"Resizing the cache from %d to %d entries\n",
910 (void) fprintf(table
->err
,
911 "\thits = %g\tmisses = %g\thit ratio = %5.3f\n",
912 table
->cacheHits
, table
->cacheMisses
,
913 table
->cacheHits
/ (table
->cacheHits
+ table
->cacheMisses
));
916 saveHandler
= MMoutOfMemory
;
917 MMoutOfMemory
= Cudd_OutOfMem
;
918 table
->acache
= cache
= ALLOC(DdCache
,slots
+1);
919 MMoutOfMemory
= saveHandler
;
920 /* If we fail to allocate the new table we just give up. */
923 (void) fprintf(table
->err
,"Resizing failed. Giving up.\n");
925 table
->cacheSlots
= oldslots
;
926 table
->acache
= oldacache
;
927 /* Do not try to resize again. */
928 table
->maxCacheHard
= oldslots
- 1;
929 table
->cacheSlack
= - (int) (oldslots
+ 1);
932 /* If the size of the cache entry is a power of 2, we want to
933 ** enforce alignment to that power of two. This happens when
934 ** DD_CACHE_PROFILE is not defined. */
935 #ifdef DD_CACHE_PROFILE
936 table
->cache
= cache
;
938 mem
= (DdNodePtr
*) cache
;
939 misalignment
= (ptruint
) mem
& (sizeof(DdCache
) - 1);
940 mem
+= (sizeof(DdCache
) - misalignment
) / sizeof(DdNodePtr
);
941 table
->cache
= cache
= (DdCache
*) mem
;
942 assert(((ptruint
) table
->cache
& (sizeof(DdCache
) - 1)) == 0);
944 shift
= --(table
->cacheShift
);
945 table
->memused
+= (slots
- oldslots
) * sizeof(DdCache
);
946 table
->cacheSlack
-= slots
; /* need these many slots to double again */
948 /* Clear new cache. */
949 for (i
= 0; (unsigned) i
< slots
; i
++) {
950 cache
[i
].data
= NULL
;
952 #ifdef DD_CACHE_PROFILE
957 /* Copy from old cache to new one. */
958 for (i
= 0; (unsigned) i
< oldslots
; i
++) {
960 if (old
->data
!= NULL
) {
961 posn
= ddCHash2(old
->h
,old
->f
,old
->g
,shift
);
962 entry
= &cache
[posn
];
966 entry
->data
= old
->data
;
967 #ifdef DD_CACHE_PROFILE
976 /* Reinitialize measurements so as to avoid division by 0 and
977 ** immediate resizing.
979 offset
= (double) (int) (slots
* table
->minHit
+ 1);
980 table
->totCacheMisses
+= table
->cacheMisses
- offset
;
981 table
->cacheMisses
= offset
;
982 table
->totCachehits
+= table
->cacheHits
;
983 table
->cacheHits
= 0;
984 table
->cacheLastInserts
= table
->cacheinserts
- (double) moved
;
986 } /* end of cuddCacheResize */
989 /**Function********************************************************************
991 Synopsis [Flushes the cache.]
999 ******************************************************************************/
1007 slots
= table
->cacheSlots
;
1008 cache
= table
->cache
;
1009 for (i
= 0; i
< slots
; i
++) {
1010 table
->cachedeletions
+= cache
[i
].data
!= NULL
;
1011 cache
[i
].data
= NULL
;
1013 table
->cacheLastInserts
= table
->cacheinserts
;
1017 } /* end of cuddCacheFlush */
1020 /**Function********************************************************************
1022 Synopsis [Returns the floor of the logarithm to the base 2.]
1024 Description [Returns the floor of the logarithm to the base 2.
1025 The input value is assumed to be greater than 0.]
1031 ******************************************************************************/
1033 cuddComputeFloorLog2(
1046 } /* end of cuddComputeFloorLog2 */
1048 /*---------------------------------------------------------------------------*/
1049 /* Definition of static functions */
1050 /*---------------------------------------------------------------------------*/