]> git.saurik.com Git - bison.git/blame - lib/bitset.c
and Akim Demaille <akim@epita.fr>
[bison.git] / lib / bitset.c
CommitLineData
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
30static 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
39struct 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
51struct bitset_stats_struct
52{
ef017502
AD
53 unsigned int runs;
54 struct bitset_type_stats_struct types[BITSET_TYPE_NUM];
7086e707
AD
55};
56
57struct bitset_stats_struct bitset_stats_data;
58struct bitset_stats_struct *bitset_stats;
59
60static void bitset_percent_histogram_print PARAMS ((FILE *, const char *,
61 const char *,
62 unsigned int,
63 unsigned int *));
64static void bitset_log_histogram_print PARAMS ((FILE *, const char *,
65 const char *,
ef017502
AD
66 unsigned int,
67 unsigned int *));
68static void bitset_stats_print_1
69PARAMS ((FILE *, const char *, struct bitset_type_stats_struct *));
7086e707
AD
70static void bitset_stats_print PARAMS ((FILE *, int));
71static void bitset_stats_read PARAMS ((void));
72static 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. */
127int
128bitset_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. */
157bitset
158bitset_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. */
183enum bitset_type
184bitset_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. */
217bitset
218bitset_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. */
240bitset
241bitset_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. */
262bitset
263bitset_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. */
276void
277bitset_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. */
288void
289bitset_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. */
300int
301bitset_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. */
316int
317bitset_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. */
331int
332bitset_first (src)
333 bitset src;
334{
335 return bitset_next (src, 0);
336}
337
338
339/* Find last set bit. */
340int
341bitset_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. */
349int
350bitset_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. */
364int
365bitset_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
385static void
386bitset_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
415int
416bitset_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. */
438int
439bitset_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. */
447int
448bitset_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. */
466int
467bitset_zero (dst)
ef017502 468 bitset dst;
7086e707 469{
ef017502 470 return BITSET_ZERO_ (dst);
7086e707
AD
471}
472
473
474/* DST = ~0. */
475int
476bitset_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
484int
485bitset_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. */
493int
494bitset_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. */
504int
505bitset_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. */
515int
516bitset_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. */
526int
527bitset_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. */
537int
538bitset_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. */
549int
550bitset_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. */
561int
562bitset_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. */
573int
574bitset_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
584int
585bitset_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. */
626int
627bitset_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. */
640int
641bitset_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. */
654int
655bitset_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. */
667void
668bitset_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. */
677void
678debug_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. */
687void
688bitset_release_memory ()
689{
690 lbitset_release_memory ();
691 ebitset_release_memory ();
692}
693
694
695#if BITSET_STATS
696int
697bitset_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. */
743static void
744bitset_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. */
771static void
772bitset_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. */
808static void
809bitset_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. */
836static void
837bitset_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. */
859void
860bitset_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. */
870static void
871bitset_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. */
896static void
897bitset_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. */
918void
919bitset_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. */
930void
931debug_bitset_stats (void)
932{
933#if BITSET_STATS
934 bitset_stats_print (stderr, 1);
935#endif /* BITSET_STATS */
936}