]>
Commit | Line | Data |
---|---|---|
7086e707 AD |
1 | /* General bitsets. |
2 | Copyright (C) 2002 Free Software Foundation, Inc. | |
3 | Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz). | |
4 | ||
ef017502 AD |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 2 of the License, or | |
8 | (at your option) any later version. | |
7086e707 | 9 | |
ef017502 AD |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
7086e707 | 14 | |
ef017502 AD |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software | |
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
7086e707 AD |
18 | |
19 | #ifdef HAVE_CONFIG_H | |
20 | #include "config.h" | |
21 | #endif | |
22 | ||
23 | #include <stdlib.h> | |
24 | #include "bitset.h" | |
ef017502 AD |
25 | #include "sbitset.h" |
26 | #include "lbitset.h" | |
27 | #include "ebitset.h" | |
7086e707 AD |
28 | #include "obstack.h" |
29 | ||
30 | static void bitset_print PARAMS ((FILE *, bitset, int)); | |
31 | ||
7086e707 AD |
32 | #if BITSET_STATS |
33 | #define BITSET_STATS_FILE "bitset.dat" | |
34 | ||
35 | #define BITSET_LOG_COUNT_BINS 10 | |
36 | #define BITSET_LOG_SIZE_BINS 16 | |
37 | #define BITSET_DENSITY_BINS 20 | |
38 | ||
39 | struct bitset_type_stats_struct | |
40 | { | |
41 | unsigned int xmallocs; | |
42 | unsigned int xfrees; | |
43 | unsigned int oballocs; | |
44 | unsigned int obfrees; | |
45 | unsigned int lists; | |
46 | unsigned int list_counts[BITSET_LOG_COUNT_BINS]; | |
47 | unsigned int list_sizes[BITSET_LOG_SIZE_BINS]; | |
48 | unsigned int list_density[BITSET_DENSITY_BINS]; | |
49 | }; | |
50 | ||
51 | struct bitset_stats_struct | |
52 | { | |
ef017502 AD |
53 | unsigned int runs; |
54 | struct bitset_type_stats_struct types[BITSET_TYPE_NUM]; | |
7086e707 AD |
55 | }; |
56 | ||
57 | struct bitset_stats_struct bitset_stats_data; | |
58 | struct bitset_stats_struct *bitset_stats; | |
59 | ||
60 | static void bitset_percent_histogram_print PARAMS ((FILE *, const char *, | |
61 | const char *, | |
62 | unsigned int, | |
63 | unsigned int *)); | |
64 | static void bitset_log_histogram_print PARAMS ((FILE *, const char *, | |
65 | const char *, | |
ef017502 AD |
66 | unsigned int, |
67 | unsigned int *)); | |
68 | static void bitset_stats_print_1 | |
69 | PARAMS ((FILE *, const char *, struct bitset_type_stats_struct *)); | |
7086e707 AD |
70 | static void bitset_stats_print PARAMS ((FILE *, int)); |
71 | static void bitset_stats_read PARAMS ((void)); | |
72 | static void bitset_stats_write PARAMS ((void)); | |
73 | ||
74 | #define BITSET_STATS_XMALLOCS_INC(TYPE) \ | |
75 | if (bitset_stats) \ | |
76 | bitset_stats->types[(TYPE)].xmallocs++ | |
77 | ||
78 | #define BITSET_STATS_XFREES_INC(BSET) \ | |
79 | if (bitset_stats) \ | |
ef017502 | 80 | bitset_stats->types[BITSET_TYPE_ (BSET)].xfrees++ |
7086e707 AD |
81 | |
82 | #define BITSET_STATS_OBALLOCS_INC(TYPE) \ | |
83 | if (bitset_stats) \ | |
84 | bitset_stats->types[(TYPE)].oballocs++ | |
85 | ||
ef017502 | 86 | #define BITSET_STATS_OBFREES_INC(BSET) \ |
7086e707 | 87 | if (bitset_stats) \ |
ef017502 | 88 | bitset_stats->types[BITSET_TYPE_ (BSET)].obfrees++ |
7086e707 AD |
89 | |
90 | #define BITSET_STATS_LISTS_INC(BSET) \ | |
91 | if (bitset_stats) \ | |
ef017502 | 92 | bitset_stats->types[BITSET_TYPE_ (BSET)].lists++ |
7086e707 AD |
93 | |
94 | #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) \ | |
95 | if (bitset_stats) \ | |
ef017502 | 96 | bitset_stats->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++ |
7086e707 AD |
97 | |
98 | #define BITSET_STATS_LIST_SIZES_INC(BSET, I) \ | |
99 | if (bitset_stats) \ | |
ef017502 | 100 | bitset_stats->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++ |
7086e707 AD |
101 | |
102 | #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) \ | |
103 | if (bitset_stats) \ | |
ef017502 | 104 | bitset_stats->types[BITSET_TYPE_ (BSET)].list_density[(I)]++ |
7086e707 AD |
105 | |
106 | #else | |
107 | #define BITSET_STATS_XMALLOCS_INC(TYPE) | |
108 | ||
109 | #define BITSET_STATS_XFREES_INC(BSET) | |
110 | ||
111 | #define BITSET_STATS_OBALLOCS_INC(TYPE) | |
112 | ||
113 | #define BITSET_STATS_OBFREES_INC(BSET) | |
114 | ||
115 | #define BITSET_STATS_LISTS_INC(BSET) | |
116 | ||
117 | #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) | |
118 | ||
119 | #define BITSET_STATS_LIST_SIZES_INC(BSET, I) | |
120 | ||
121 | #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) | |
122 | #endif /* BITSET_STATS */ | |
123 | ||
124 | ||
7086e707 AD |
125 | /* Return number of bytes required to create a N_BIT bitset |
126 | of TYPE. The bitset may grow to require more bytes than this. */ | |
127 | int | |
128 | bitset_bytes (type, n_bits) | |
129 | enum bitset_type type; | |
130 | bitset_bindex n_bits; | |
131 | { | |
132 | unsigned int bytes; | |
133 | ||
134 | switch (type) | |
135 | { | |
136 | case BITSET_ARRAY: | |
137 | bytes = sbitset_bytes (n_bits); | |
138 | break; | |
139 | ||
140 | case BITSET_LIST: | |
141 | bytes = lbitset_bytes (n_bits); | |
142 | break; | |
143 | ||
144 | case BITSET_TABLE: | |
145 | bytes = ebitset_bytes (n_bits); | |
146 | break; | |
147 | ||
148 | default: | |
149 | abort (); | |
150 | } | |
151 | ||
152 | return bytes; | |
153 | } | |
154 | ||
155 | ||
156 | /* Initialise bitset BSET of TYPE for N_BITS. */ | |
157 | bitset | |
158 | bitset_init (bset, n_bits, type) | |
159 | bitset bset; | |
160 | bitset_bindex n_bits; | |
161 | enum bitset_type type; | |
162 | { | |
163 | switch (type) | |
164 | { | |
165 | case BITSET_ARRAY: | |
166 | return sbitset_init (bset, n_bits); | |
167 | ||
168 | case BITSET_LIST: | |
169 | return lbitset_init (bset, n_bits); | |
170 | ||
171 | case BITSET_TABLE: | |
172 | return ebitset_init (bset, n_bits); | |
173 | ||
174 | default: | |
175 | abort (); | |
176 | } | |
177 | } | |
178 | ||
179 | ||
180 | /* Select a bitset type for a set of N_BITS and with attribute hints | |
181 | specified by ATTR. For variable size bitsets, N_BITS is only a | |
182 | hint and may be zero. */ | |
183 | enum bitset_type | |
184 | bitset_type_choose (n_bits, attr) | |
185 | bitset_bindex n_bits ATTRIBUTE_UNUSED; | |
186 | unsigned int attr; | |
187 | { | |
188 | enum bitset_type type; | |
189 | ||
ef017502 | 190 | #if BITSET_CHECK |
7086e707 AD |
191 | /* Check attributes. */ |
192 | if (attr & BITSET_FIXED && attr & BITSET_VARIABLE) | |
193 | abort (); | |
194 | if (attr & BITSET_SPARSE && attr & BITSET_DENSE) | |
195 | abort (); | |
196 | ||
197 | /* Note that sometimes we will be asked for a zero length | |
198 | fixed size bitset. */ | |
199 | #endif | |
200 | ||
201 | /* Choose the type of bitset. */ | |
202 | ||
203 | type = BITSET_ARRAY; | |
204 | /* Currently, the simple bitsets do not support a variable size. */ | |
205 | if (attr & BITSET_VARIABLE || attr & BITSET_SPARSE) | |
206 | { | |
207 | type = BITSET_LIST; | |
208 | if (attr & BITSET_DENSE || attr & BITSET_GREEDY) | |
209 | type = BITSET_TABLE; | |
210 | } | |
211 | ||
212 | return type; | |
213 | } | |
214 | ||
215 | ||
216 | /* Create a bitset of N_BITS of type TYPE. */ | |
217 | bitset | |
218 | bitset_alloc (n_bits, type) | |
219 | bitset_bindex n_bits; | |
220 | enum bitset_type type; | |
221 | { | |
222 | unsigned int bytes; | |
223 | bitset bset; | |
224 | ||
225 | BITSET_STATS_XMALLOCS_INC (type); | |
226 | ||
227 | bytes = bitset_bytes (type, n_bits); | |
228 | ||
ef017502 AD |
229 | bset = (bitset) xcalloc (1, bytes); |
230 | ||
231 | /* The cache is disabled until some elements are allocated. If we | |
232 | have variable length arrays, then we may need to allocate dummy | |
233 | element. */ | |
7086e707 AD |
234 | |
235 | return bitset_init (bset, n_bits, type); | |
236 | } | |
237 | ||
238 | ||
239 | /* Create a bitset of N_BITS of type TYPE. */ | |
240 | bitset | |
241 | bitset_obstack_alloc (bobstack, n_bits, type) | |
ef017502 AD |
242 | struct obstack *bobstack; |
243 | bitset_bindex n_bits; | |
244 | enum bitset_type type; | |
7086e707 AD |
245 | { |
246 | unsigned int bytes; | |
ef017502 | 247 | bitset bset; |
7086e707 AD |
248 | |
249 | BITSET_STATS_OBALLOCS_INC (type); | |
250 | ||
251 | bytes = bitset_bytes (type, n_bits); | |
252 | ||
ef017502 AD |
253 | bset = obstack_alloc (bobstack, bytes); |
254 | memset (bset, 0, bytes); | |
255 | ||
256 | return bitset_init (bset, n_bits, type); | |
7086e707 AD |
257 | } |
258 | ||
259 | ||
260 | /* Create a bitset of N_BITS and with attribute hints specified by | |
261 | ATTR. */ | |
262 | bitset | |
263 | bitset_create (n_bits, attr) | |
264 | bitset_bindex n_bits; | |
265 | unsigned int attr; | |
266 | { | |
267 | enum bitset_type type; | |
268 | ||
269 | type = bitset_type_choose (n_bits, attr); | |
270 | ||
271 | return bitset_alloc (n_bits, type); | |
272 | } | |
273 | ||
274 | ||
275 | /* Free bitset BSET. */ | |
276 | void | |
277 | bitset_free (bset) | |
278 | bitset bset; | |
279 | { | |
280 | BITSET_STATS_XFREES_INC (bset); | |
281 | ||
ef017502 | 282 | BITSET_FREE_ (bset); |
7086e707 AD |
283 | free (bset); |
284 | } | |
285 | ||
286 | ||
287 | /* Free bitset BSET allocated on obstack. */ | |
288 | void | |
289 | bitset_obstack_free (bset) | |
290 | bitset bset; | |
291 | { | |
292 | BITSET_STATS_OBFREES_INC (bset); | |
293 | ||
ef017502 | 294 | BITSET_FREE_ (bset); |
7086e707 AD |
295 | } |
296 | ||
297 | ||
298 | /* Find next bit set in SRC starting from and including BITNO. | |
299 | Return -1 if SRC empty. */ | |
300 | int | |
301 | bitset_next (src, bitno) | |
302 | bitset src; | |
303 | bitset_bindex bitno; | |
304 | { | |
305 | bitset_bindex val; | |
306 | bitset_bindex next = bitno; | |
307 | ||
308 | if (!bitset_list (src, &val, 1, &next)) | |
309 | return -1; | |
310 | return val; | |
311 | } | |
312 | ||
313 | ||
314 | /* Find previous bit set in SRC starting from and including BITNO. | |
315 | Return -1 if SRC empty. */ | |
316 | int | |
317 | bitset_prev (src, bitno) | |
318 | bitset src; | |
319 | bitset_bindex bitno; | |
320 | { | |
321 | bitset_bindex val; | |
322 | bitset_bindex next = bitno; | |
323 | ||
324 | if (!bitset_reverse_list (src, &val, 1, &next)) | |
325 | return -1; | |
326 | return val; | |
327 | } | |
328 | ||
329 | ||
330 | /* Find first set bit. */ | |
331 | int | |
332 | bitset_first (src) | |
333 | bitset src; | |
334 | { | |
335 | return bitset_next (src, 0); | |
336 | } | |
337 | ||
338 | ||
339 | /* Find last set bit. */ | |
340 | int | |
341 | bitset_last (src) | |
342 | bitset src; | |
343 | { | |
344 | return bitset_prev (src, 0); | |
345 | } | |
346 | ||
347 | ||
345cea78 AD |
348 | /* Return non-zero if BITNO in SRC is the only set bit. */ |
349 | int | |
350 | bitset_only_set_p (src, bitno) | |
351 | bitset src; | |
352 | bitset_bindex bitno; | |
353 | { | |
354 | bitset_bindex val[2]; | |
355 | bitset_bindex next = 0; | |
356 | ||
357 | if (bitset_list (src, val, 2, &next) != 1) | |
358 | return 0; | |
359 | return val[0] == bitno; | |
360 | } | |
361 | ||
362 | ||
363 | /* Toggle bit BITNO in bitset BSET and return non-zero if now set. */ | |
364 | int | |
365 | bitset_toggle (bset, bitno) | |
366 | bitset bset; | |
367 | bitset_bindex bitno; | |
368 | { | |
369 | /* This routine is for completeness. It could be optimized if | |
370 | required. */ | |
371 | if (bitset_test (bset, bitno)) | |
372 | { | |
373 | bitset_reset (bset, bitno); | |
374 | return 0; | |
375 | } | |
376 | else | |
377 | { | |
378 | bitset_set (bset, bitno); | |
379 | return 1; | |
380 | } | |
381 | } | |
382 | ||
383 | ||
ef017502 | 384 | /* Print contents of bitset BSET to FILE. */ |
7086e707 AD |
385 | static void |
386 | bitset_print (file, bset, verbose) | |
387 | FILE *file; | |
388 | bitset bset; | |
389 | int verbose; | |
390 | { | |
391 | unsigned int i, pos; | |
392 | ||
393 | if (verbose) | |
394 | fprintf (file, "n_bits = %d, set = {", bitset_size (bset)); | |
395 | ||
396 | pos = 30; | |
397 | BITSET_EXECUTE (bset, 0, i, | |
398 | { | |
399 | if (pos > 70) | |
400 | { | |
401 | fprintf (file, "\n"); | |
402 | pos = 0; | |
403 | } | |
404 | ||
405 | fprintf (file, "%d ", i); | |
406 | pos += 1 + (i >= 10) + (i >= 100); | |
407 | }); | |
408 | ||
409 | if (verbose) | |
410 | fprintf (file, "}\n"); | |
411 | } | |
412 | ||
413 | ||
ef017502 | 414 | /* DST = SRC. Return non-zero if DST != SRC. */ |
7086e707 AD |
415 | int |
416 | bitset_copy (dst, src) | |
ef017502 AD |
417 | bitset dst; |
418 | bitset src; | |
7086e707 | 419 | { |
ef017502 | 420 | unsigned int i; |
7086e707 | 421 | |
ef017502 AD |
422 | if (BITSET_COMPATIBLE_ (dst, src)) |
423 | return BITSET_COPY_ (dst, src); | |
7086e707 | 424 | |
ef017502 AD |
425 | /* Convert bitset types. We assume that the DST bitset |
426 | is large enough to hold the SRC bitset. */ | |
427 | bitset_zero (dst); | |
428 | BITSET_EXECUTE (src, 0, i, | |
429 | { | |
430 | bitset_set (dst, i); | |
431 | }); | |
7086e707 | 432 | |
ef017502 | 433 | return 1; |
7086e707 AD |
434 | } |
435 | ||
436 | ||
437 | /* Return size in bits of bitset SRC. */ | |
438 | int | |
439 | bitset_size (src) | |
ef017502 AD |
440 | bitset src; |
441 | { | |
442 | return BITSET_SIZE_ (src); | |
443 | } | |
444 | ||
445 | ||
446 | /* Return number of bits set in bitset SRC. */ | |
447 | int | |
448 | bitset_count (src) | |
449 | bitset src; | |
7086e707 | 450 | { |
ef017502 AD |
451 | bitset_bindex list[BITSET_LIST_SIZE]; |
452 | bitset_bindex next; | |
453 | int num; | |
454 | int count; | |
455 | ||
456 | next = 0; | |
457 | for (count = 0; (num = bitset_list (src, list, BITSET_LIST_SIZE, &next)); | |
458 | count += num) | |
459 | continue; | |
460 | ||
461 | return count; | |
7086e707 AD |
462 | } |
463 | ||
464 | ||
465 | /* DST = 0. */ | |
466 | int | |
467 | bitset_zero (dst) | |
ef017502 | 468 | bitset dst; |
7086e707 | 469 | { |
ef017502 | 470 | return BITSET_ZERO_ (dst); |
7086e707 AD |
471 | } |
472 | ||
473 | ||
474 | /* DST = ~0. */ | |
475 | int | |
476 | bitset_ones (dst) | |
ef017502 | 477 | bitset dst; |
7086e707 | 478 | { |
ef017502 | 479 | return BITSET_ONES_ (dst); |
7086e707 AD |
480 | } |
481 | ||
482 | ||
ef017502 | 483 | /* Return SRC == 0. */ |
7086e707 AD |
484 | int |
485 | bitset_empty_p (src) | |
ef017502 | 486 | bitset src; |
7086e707 | 487 | { |
ef017502 | 488 | return BITSET_EMPTY_P_ (src); |
7086e707 AD |
489 | } |
490 | ||
491 | ||
492 | /* Return DST == DST | SRC. */ | |
493 | int | |
494 | bitset_subset_p (dst, src) | |
ef017502 AD |
495 | bitset dst; |
496 | bitset src; | |
7086e707 | 497 | { |
ef017502 AD |
498 | BITSET_CHECK2_ (dst, src); |
499 | return BITSET_SUBSET_P_ (dst, src); | |
7086e707 AD |
500 | } |
501 | ||
502 | ||
503 | /* Return DST == SRC. */ | |
504 | int | |
505 | bitset_equal_p (dst, src) | |
ef017502 AD |
506 | bitset dst; |
507 | bitset src; | |
7086e707 | 508 | { |
ef017502 AD |
509 | BITSET_CHECK2_ (dst, src); |
510 | return BITSET_EQUAL_P_ (dst, src); | |
511 | } | |
512 | ||
513 | ||
514 | /* Return DST & SRC == 0. */ | |
515 | int | |
516 | bitset_disjoint_p (dst, src) | |
517 | bitset dst; | |
518 | bitset src; | |
519 | { | |
520 | BITSET_CHECK2_ (dst, src); | |
521 | return BITSET_DISJOINT_P_ (dst, src); | |
7086e707 AD |
522 | } |
523 | ||
524 | ||
525 | /* DST = ~SRC. */ | |
526 | int | |
527 | bitset_not (dst, src) | |
ef017502 AD |
528 | bitset dst; |
529 | bitset src; | |
7086e707 | 530 | { |
ef017502 AD |
531 | BITSET_CHECK2_ (dst, src); |
532 | return BITSET_NOT_ (dst, src); | |
7086e707 AD |
533 | } |
534 | ||
535 | ||
536 | /* DST = SRC1 | SRC2. Return non-zero if DST != SRC1 | SRC2. */ | |
537 | int | |
538 | bitset_or (dst, src1, src2) | |
ef017502 AD |
539 | bitset dst; |
540 | bitset src1; | |
541 | bitset src2; | |
7086e707 | 542 | { |
ef017502 AD |
543 | BITSET_CHECK3_ (dst, src1, src2); |
544 | return BITSET_OR_ (dst, src1, src2); | |
7086e707 AD |
545 | } |
546 | ||
547 | ||
548 | /* DST = SRC1 & SRC2. Return non-zero if DST != SRC1 & SRC2. */ | |
549 | int | |
550 | bitset_and (dst, src1, src2) | |
ef017502 AD |
551 | bitset dst; |
552 | bitset src1; | |
553 | bitset src2; | |
7086e707 | 554 | { |
ef017502 AD |
555 | BITSET_CHECK3_ (dst, src1, src2); |
556 | return BITSET_AND_ (dst, src1, src2); | |
7086e707 AD |
557 | } |
558 | ||
559 | ||
560 | /* DST = SRC1 ^ SRC2. Return non-zero if DST != SRC1 ^ SRC2. */ | |
561 | int | |
562 | bitset_xor (dst, src1, src2) | |
ef017502 AD |
563 | bitset dst; |
564 | bitset src1; | |
565 | bitset src2; | |
7086e707 | 566 | { |
ef017502 AD |
567 | BITSET_CHECK3_ (dst, src1, src2); |
568 | return BITSET_XOR_ (dst, src1, src2); | |
7086e707 AD |
569 | } |
570 | ||
571 | ||
572 | /* DST = SRC1 & ~SRC2. Return non-zero if DST != SRC1 & ~SRC2. */ | |
573 | int | |
574 | bitset_andn (dst, src1, src2) | |
ef017502 AD |
575 | bitset dst; |
576 | bitset src1; | |
577 | bitset src2; | |
7086e707 | 578 | { |
ef017502 AD |
579 | BITSET_CHECK3_ (dst, src1, src2); |
580 | return BITSET_ANDN_ (dst, src1, src2); | |
7086e707 AD |
581 | } |
582 | ||
583 | ||
ef017502 AD |
584 | int |
585 | bitset_op4 (dst, src1, src2, src3, op) | |
586 | bitset dst; | |
587 | bitset src1; | |
588 | bitset src2; | |
589 | bitset src3; | |
590 | enum bitset_ops op; | |
591 | { | |
592 | int changed = 0; | |
593 | bitset tmp; | |
594 | ||
595 | /* Create temporary bitset. */ | |
345cea78 | 596 | tmp = bitset_alloc (0, BITSET_TYPE_ (dst)); |
ef017502 AD |
597 | |
598 | switch (op) | |
599 | { | |
600 | case BITSET_OP_OR_AND: | |
601 | BITSET_OR_ (tmp, src1, src2); | |
602 | changed = BITSET_AND_ (dst, src3, tmp); | |
603 | break; | |
604 | ||
605 | case BITSET_OP_AND_OR: | |
606 | BITSET_AND_ (tmp, src1, src2); | |
607 | changed = BITSET_OR_ (dst, src3, tmp); | |
608 | break; | |
609 | ||
610 | case BITSET_OP_ANDN_OR: | |
611 | BITSET_ANDN_ (tmp, src1, src2); | |
612 | changed = BITSET_OR_ (dst, src3, tmp); | |
613 | break; | |
614 | ||
615 | default: | |
616 | abort (); | |
617 | } | |
618 | ||
619 | bitset_free (tmp); | |
620 | return changed; | |
7086e707 AD |
621 | } |
622 | ||
623 | ||
624 | /* DST = (SRC1 | SRC2) & SRC3. Return non-zero if | |
625 | DST != (SRC1 | SRC2) & SRC3. */ | |
626 | int | |
627 | bitset_or_and (dst, src1, src2, src3) | |
ef017502 AD |
628 | bitset dst; |
629 | bitset src1; | |
630 | bitset src2; | |
631 | bitset src3; | |
7086e707 | 632 | { |
ef017502 AD |
633 | BITSET_CHECK4_ (dst, src1, src2, src3); |
634 | return BITSET_OR_AND_ (dst, src1, src2, src3); | |
7086e707 AD |
635 | } |
636 | ||
637 | ||
638 | /* DST = (SRC1 & SRC2) | SRC3. Return non-zero if | |
639 | DST != (SRC1 & SRC2) | SRC3. */ | |
640 | int | |
641 | bitset_and_or (dst, src1, src2, src3) | |
ef017502 AD |
642 | bitset dst; |
643 | bitset src1; | |
644 | bitset src2; | |
645 | bitset src3; | |
646 | { | |
647 | BITSET_CHECK4_ (dst, src1, src2, src3); | |
648 | return BITSET_AND_OR_ (dst, src1, src2, src3); | |
649 | } | |
650 | ||
651 | ||
652 | /* DST = (SRC1 & ~SRC2) | SRC3. Return non-zero if | |
653 | DST != (SRC1 & ~SRC2) | SRC3. */ | |
654 | int | |
655 | bitset_andn_or (dst, src1, src2, src3) | |
656 | bitset dst; | |
657 | bitset src1; | |
658 | bitset src2; | |
659 | bitset src3; | |
7086e707 | 660 | { |
ef017502 AD |
661 | BITSET_CHECK4_ (dst, src1, src2, src3); |
662 | return BITSET_ANDN_OR_ (dst, src1, src2, src3); | |
7086e707 AD |
663 | } |
664 | ||
665 | ||
666 | /* Dump bitset BSET to FILE. */ | |
667 | void | |
668 | bitset_dump (file, bset) | |
669 | FILE *file; | |
670 | bitset bset; | |
671 | { | |
672 | bitset_print (file, bset, 0); | |
673 | } | |
674 | ||
675 | ||
676 | /* Function to be called from debugger to print bitset. */ | |
677 | void | |
678 | debug_bitset (bset) | |
679 | bitset bset; | |
680 | { | |
ef017502 AD |
681 | if (bset) |
682 | bitset_print (stderr, bset, 1); | |
7086e707 AD |
683 | } |
684 | ||
685 | ||
686 | /* Release memory associated with bitsets. */ | |
687 | void | |
688 | bitset_release_memory () | |
689 | { | |
690 | lbitset_release_memory (); | |
691 | ebitset_release_memory (); | |
692 | } | |
693 | ||
694 | ||
695 | #if BITSET_STATS | |
696 | int | |
697 | bitset_list (bset, list, num, next) | |
ef017502 AD |
698 | bitset bset; |
699 | bitset_bindex *list; | |
700 | bitset_bindex num; | |
701 | bitset_bindex *next; | |
7086e707 | 702 | { |
ef017502 | 703 | bitset_bindex count; |
7086e707 | 704 | |
ef017502 | 705 | count = BITSET_LIST_ (bset, list, num, next); |
7086e707 | 706 | |
ef017502 AD |
707 | if (bitset_stats) |
708 | { | |
709 | bitset_bindex tmp; | |
710 | bitset_bindex size; | |
711 | bitset_bindex i; | |
712 | enum bitset_type type; | |
713 | ||
714 | type = BITSET_TYPE_ (bset); | |
715 | BITSET_STATS_LISTS_INC (bset); | |
716 | ||
717 | /* Log histogram of number of set bits. */ | |
718 | for (i = 0, tmp = count; tmp; tmp >>= 1, i++) | |
719 | continue; | |
720 | if (i >= BITSET_LOG_COUNT_BINS) | |
721 | i = BITSET_LOG_COUNT_BINS - 1; | |
722 | BITSET_STATS_LIST_COUNTS_INC (bset, i); | |
723 | ||
724 | /* Log histogram of number of bits in set. */ | |
725 | size = bitset_size (bset); | |
726 | for (i = 0, tmp = size; tmp; tmp >>= 1, i++) | |
727 | continue; | |
728 | if (i >= BITSET_LOG_SIZE_BINS) | |
729 | i = BITSET_LOG_SIZE_BINS - 1; | |
730 | BITSET_STATS_LIST_SIZES_INC (bset, i); | |
731 | ||
732 | /* Histogram of fraction of bits set. */ | |
733 | i = size ? (count * BITSET_DENSITY_BINS) / size : 0; | |
734 | if (i >= BITSET_DENSITY_BINS) | |
735 | i = BITSET_DENSITY_BINS - 1; | |
736 | BITSET_STATS_LIST_DENSITY_INC (bset, i); | |
737 | } | |
738 | return count; | |
7086e707 AD |
739 | } |
740 | ||
741 | ||
742 | /* Print a percentage histogram with message MSG to FILE. */ | |
743 | static void | |
744 | bitset_percent_histogram_print (file, name, msg, n_bins, bins) | |
745 | FILE *file; | |
746 | const char *name; | |
747 | const char *msg; | |
748 | unsigned int n_bins; | |
749 | unsigned int *bins; | |
750 | { | |
751 | unsigned int i; | |
752 | unsigned int total; | |
753 | ||
754 | total = 0; | |
755 | for (i = 0; i < n_bins; i++) | |
756 | total += bins[i]; | |
757 | ||
758 | if (!total) | |
ef017502 | 759 | return; |
7086e707 AD |
760 | |
761 | fprintf (file, "%s %s", name, msg); | |
762 | for (i = 0; i < n_bins; i++) | |
763 | fprintf (file, "%.0f-%.0f%%\t%8d (%5.1f%%)\n", | |
764 | i * 100.0 / n_bins, | |
ef017502 AD |
765 | (i + 1) * 100.0 / n_bins, bins[i], |
766 | (100.0 * bins[i]) / total); | |
7086e707 AD |
767 | } |
768 | ||
769 | ||
770 | /* Print a log histogram with message MSG to FILE. */ | |
771 | static void | |
772 | bitset_log_histogram_print (file, name, msg, n_bins, bins) | |
773 | FILE *file; | |
774 | const char *name; | |
775 | const char *msg; | |
776 | unsigned int n_bins; | |
777 | unsigned int *bins; | |
778 | { | |
779 | unsigned int i; | |
780 | unsigned int total; | |
781 | unsigned int max_width; | |
782 | ||
783 | total = 0; | |
784 | for (i = 0; i < n_bins; i++) | |
785 | total += bins[i]; | |
786 | ||
787 | if (!total) | |
ef017502 | 788 | return; |
7086e707 AD |
789 | |
790 | /* 2 * ceil (log10(2) * (N - 1)) + 1 */ | |
ef017502 | 791 | max_width = 2 * (unsigned int) (0.30103 * (n_bins - 1) + 0.9999) + 1; |
7086e707 AD |
792 | |
793 | fprintf (file, "%s %s", name, msg); | |
794 | for (i = 0; i < 2; i++) | |
795 | fprintf (file, "%*d\t%8d (%5.1f%%)\n", | |
796 | max_width, i, bins[i], 100.0 * bins[i] / total); | |
797 | ||
798 | /* Perhaps we should bail out once the histogram goes to zero. */ | |
799 | for (; i < n_bins; i++) | |
800 | fprintf (file, "%*d-%d\t%8d (%5.1f%%)\n", | |
801 | max_width - ((unsigned int) (0.30103 * (i) + 0.9999) + 1), | |
ef017502 AD |
802 | 1 << (i - 1), (1 << i) - 1, bins[i], |
803 | (100.0 * bins[i]) / total); | |
7086e707 AD |
804 | } |
805 | ||
806 | ||
807 | /* Print bitset statistics to FILE. */ | |
808 | static void | |
809 | bitset_stats_print_1 (file, name, stats) | |
810 | FILE *file; | |
811 | const char *name; | |
812 | struct bitset_type_stats_struct *stats; | |
813 | { | |
814 | if (!stats) | |
815 | return; | |
816 | ||
817 | fprintf (file, "%d %ss xmalloced, %d freed.\n", | |
818 | stats->xmallocs, name, stats->xfrees); | |
819 | fprintf (file, "%d %ss oballoced, %d freed.\n", | |
820 | stats->oballocs, name, stats->obfrees); | |
821 | ||
822 | fprintf (file, "%d bitset_lists\n", stats->lists); | |
823 | ||
824 | bitset_log_histogram_print (file, name, "count log histogram\n", | |
ef017502 | 825 | BITSET_LOG_COUNT_BINS, stats->list_counts); |
7086e707 AD |
826 | |
827 | bitset_log_histogram_print (file, name, "size log histogram\n", | |
ef017502 | 828 | BITSET_LOG_SIZE_BINS, stats->list_sizes); |
7086e707 AD |
829 | |
830 | bitset_percent_histogram_print (file, name, "density histogram\n", | |
831 | BITSET_DENSITY_BINS, stats->list_density); | |
832 | } | |
833 | ||
834 | ||
835 | /* Print all bitset statistics to FILE. */ | |
836 | static void | |
837 | bitset_stats_print (file, verbose) | |
838 | FILE *file; | |
839 | int verbose ATTRIBUTE_UNUSED; | |
840 | { | |
841 | int i; | |
ef017502 | 842 | static const char *names[] = BITSET_TYPE_NAMES; |
7086e707 AD |
843 | |
844 | if (!bitset_stats) | |
845 | return; | |
846 | ||
847 | fprintf (file, "Bitset statistics:\n\n"); | |
848 | ||
849 | if (bitset_stats->runs > 1) | |
850 | fprintf (file, "Accumulated runs = %d\n", bitset_stats->runs); | |
851 | ||
852 | for (i = 0; i < BITSET_TYPE_NUM; i++) | |
ef017502 | 853 | bitset_stats_print_1 (file, names[i], &bitset_stats->types[i]); |
7086e707 AD |
854 | } |
855 | #endif /* BITSET_STATS */ | |
856 | ||
857 | ||
858 | /* Initialise bitset statistics logging. */ | |
859 | void | |
860 | bitset_stats_init () | |
861 | { | |
862 | #if BITSET_STATS | |
ef017502 AD |
863 | bitset_stats = &bitset_stats_data; |
864 | bitset_stats_read (); | |
865 | #endif /* BITSET_STATS */ | |
7086e707 AD |
866 | } |
867 | ||
868 | ||
869 | /* Read bitset statistics file. */ | |
870 | static void | |
871 | bitset_stats_read () | |
872 | { | |
ef017502 | 873 | FILE *file; |
7086e707 | 874 | |
ef017502 AD |
875 | if (!bitset_stats) |
876 | return; | |
7086e707 | 877 | |
ef017502 AD |
878 | file = fopen (BITSET_STATS_FILE, "r"); |
879 | if (file) | |
880 | { | |
881 | if (fread (&bitset_stats_data, sizeof (bitset_stats_data), | |
882 | 1, file) != 1) | |
883 | { | |
884 | if (ferror (file)) | |
885 | perror ("Could not read stats file."); | |
886 | else | |
887 | fprintf (stderr, "Bad stats file size.\n"); | |
888 | } | |
889 | fclose (file); | |
890 | } | |
891 | bitset_stats_data.runs++; | |
7086e707 AD |
892 | } |
893 | ||
894 | ||
895 | /* Write bitset statistics file. */ | |
896 | static void | |
897 | bitset_stats_write () | |
898 | { | |
ef017502 | 899 | FILE *file; |
7086e707 | 900 | |
ef017502 AD |
901 | if (!bitset_stats) |
902 | return; | |
7086e707 | 903 | |
ef017502 AD |
904 | file = fopen (BITSET_STATS_FILE, "w"); |
905 | if (file) | |
906 | { | |
907 | if (fwrite (&bitset_stats_data, sizeof (bitset_stats_data), | |
908 | 1, file) != 1) | |
909 | perror ("Could not write stats file."); | |
910 | fclose (file); | |
911 | } | |
912 | else | |
913 | perror ("Could not open stats file for writing."); | |
7086e707 AD |
914 | } |
915 | ||
916 | ||
917 | /* Dump bitset statistics to FILE. */ | |
918 | void | |
919 | bitset_stats_dump (file) | |
920 | FILE *file; | |
921 | { | |
922 | #if BITSET_STATS | |
923 | bitset_stats_print (file, 0); | |
924 | bitset_stats_write (); | |
925 | #endif /* BITSET_STATS */ | |
926 | } | |
927 | ||
928 | ||
929 | /* Function to be called from debugger to print bitset stats. */ | |
930 | void | |
931 | debug_bitset_stats (void) | |
932 | { | |
933 | #if BITSET_STATS | |
934 | bitset_stats_print (stderr, 1); | |
935 | #endif /* BITSET_STATS */ | |
936 | } |