1 /* Bitset statistics.
2 
3    Copyright (C) 2002-2006, 2009-2015, 2018-2020 Free Software Foundation, Inc.
4 
5    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz).
6 
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation, either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
19 
20 /* This file is a wrapper bitset implementation for the other bitset
21    implementations.  It provides bitset compatibility checking and
22    statistics gathering without having to instrument the bitset
23    implementations.  When statistics gathering is enabled, the bitset
24    operations get vectored through here and we then call the appropriate
25    routines.  */
26 
27 #include <config.h>
28 
29 #include "bitset/stats.h"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 
35 #include "gettext.h"
36 #define _(Msgid)  gettext (Msgid)
37 
38 #include "bitset/array.h"
39 #include "bitset/base.h"
40 #include "bitset/list.h"
41 #include "bitset/table.h"
42 #include "bitset/vector.h"
43 
44 /* Configuration macros.  */
45 #define BITSET_STATS_FILE "bitset.dat"
46 #define BITSET_LOG_COUNT_BINS 10
47 #define BITSET_LOG_SIZE_BINS  16
48 #define BITSET_DENSITY_BINS  20
49 
50 
51 /* Accessor macros.  */
52 #define BITSET_STATS_ALLOCS_INC(TYPE)                   \
53     bitset_stats_info->types[(TYPE)].allocs++
54 #define BITSET_STATS_FREES_INC(BSET)                    \
55     bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++
56 #define BITSET_STATS_SETS_INC(BSET)                     \
57     bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++
58 #define BITSET_STATS_CACHE_SETS_INC(BSET)               \
59     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++
60 #define BITSET_STATS_RESETS_INC(BSET)                   \
61     bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++
62 #define BITSET_STATS_CACHE_RESETS_INC(BSET)             \
63     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++
64 #define BITSET_STATS_TESTS_INC(BSET)                    \
65     bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++
66 #define BITSET_STATS_CACHE_TESTS_INC(BSET)              \
67     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++
68 #define BITSET_STATS_LISTS_INC(BSET)                    \
69     bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++
70 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I)           \
71     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++
72 #define BITSET_STATS_LIST_SIZES_INC(BSET, I)            \
73     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++
74 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I)          \
75     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++
76 
77 
78 struct bitset_type_info_struct
79 {
80   unsigned allocs;
81   unsigned frees;
82   unsigned lists;
83   unsigned sets;
84   unsigned cache_sets;
85   unsigned resets;
86   unsigned cache_resets;
87   unsigned tests;
88   unsigned cache_tests;
89   unsigned list_counts[BITSET_LOG_COUNT_BINS];
90   unsigned list_sizes[BITSET_LOG_SIZE_BINS];
91   unsigned list_density[BITSET_DENSITY_BINS];
92 };
93 
94 struct bitset_stats_info_struct
95 {
96   unsigned runs;
97   struct bitset_type_info_struct types[BITSET_TYPE_NUM];
98 };
99 
100 
101 struct bitset_stats_info_struct bitset_stats_info_data;
102 struct bitset_stats_info_struct *bitset_stats_info;
103 bool bitset_stats_enabled = false;
104 
105 
106 /* Print a percentage histogram with message MSG to FILE.  */
107 static void
bitset_percent_histogram_print(FILE * file,const char * name,const char * msg,unsigned n_bins,unsigned * bins)108 bitset_percent_histogram_print (FILE *file, const char *name, const char *msg,
109                                 unsigned n_bins, unsigned *bins)
110 {
111   unsigned total = 0;
112   for (unsigned i = 0; i < n_bins; i++)
113     total += bins[i];
114 
115   if (!total)
116     return;
117 
118   fprintf (file, "%s %s", name, msg);
119   for (unsigned i = 0; i < n_bins; i++)
120     fprintf (file, "%.0f-%.0f%%\t%8u (%5.1f%%)\n",
121              i * 100.0 / n_bins,
122              (i + 1) * 100.0 / n_bins, bins[i],
123              (100.0 * bins[i]) / total);
124 }
125 
126 
127 /* Print a log histogram with message MSG to FILE.  */
128 static void
bitset_log_histogram_print(FILE * file,const char * name,const char * msg,unsigned n_bins,unsigned * bins)129 bitset_log_histogram_print (FILE *file, const char *name, const char *msg,
130                             unsigned n_bins, unsigned *bins)
131 {
132   unsigned total = 0;
133   for (unsigned i = 0; i < n_bins; i++)
134     total += bins[i];
135 
136   if (!total)
137     return;
138 
139   /* Determine number of useful bins.  */
140   {
141     unsigned i;
142     for (i = n_bins; i > 3 && ! bins[i - 1]; i--)
143       continue;
144     n_bins = i;
145   }
146 
147   /* 2 * ceil (log10 (2) * (N - 1)) + 1.  */
148   unsigned max_width = 2 * (unsigned) (0.30103 * (n_bins - 1) + 0.9999) + 1;
149 
150   fprintf (file, "%s %s", name, msg);
151   {
152     unsigned i;
153     for (i = 0; i < 2; i++)
154       fprintf (file, "%*d\t%8u (%5.1f%%)\n",
155                max_width, i, bins[i], 100.0 * bins[i] / total);
156 
157     for (; i < n_bins; i++)
158       fprintf (file, "%*lu-%lu\t%8u (%5.1f%%)\n",
159                max_width - ((unsigned) (0.30103 * (i) + 0.9999) + 1),
160                1UL << (i - 1),
161                (1UL << i) - 1,
162                bins[i],
163                (100.0 * bins[i]) / total);
164   }
165 }
166 
167 
168 /* Print bitset statistics to FILE.  */
169 static void
bitset_stats_print_1(FILE * file,const char * name,struct bitset_type_info_struct * stats)170 bitset_stats_print_1 (FILE *file, const char *name,
171                       struct bitset_type_info_struct *stats)
172 {
173   if (!stats)
174     return;
175 
176   fprintf (file, "%s:\n", name);
177   fprintf (file, _("%u bitset_allocs, %u freed (%.2f%%).\n"),
178            stats->allocs, stats->frees,
179            stats->allocs ? 100.0 * stats->frees / stats->allocs : 0);
180   fprintf (file, _("%u bitset_sets, %u cached (%.2f%%)\n"),
181            stats->sets, stats->cache_sets,
182            stats->sets ? 100.0 * stats->cache_sets / stats->sets : 0);
183   fprintf (file, _("%u bitset_resets, %u cached (%.2f%%)\n"),
184            stats->resets, stats->cache_resets,
185            stats->resets ? 100.0 * stats->cache_resets / stats->resets : 0);
186   fprintf (file, _("%u bitset_tests, %u cached (%.2f%%)\n"),
187            stats->tests, stats->cache_tests,
188            stats->tests ? 100.0 * stats->cache_tests / stats->tests : 0);
189 
190   fprintf (file, _("%u bitset_lists\n"), stats->lists);
191 
192   bitset_log_histogram_print (file, name, _("count log histogram\n"),
193                               BITSET_LOG_COUNT_BINS, stats->list_counts);
194 
195   bitset_log_histogram_print (file, name, _("size log histogram\n"),
196                               BITSET_LOG_SIZE_BINS, stats->list_sizes);
197 
198   bitset_percent_histogram_print (file, name, _("density histogram\n"),
199                                   BITSET_DENSITY_BINS, stats->list_density);
200 }
201 
202 
203 /* Print all bitset statistics to FILE.  */
204 static void
bitset_stats_print(FILE * file,bool verbose MAYBE_UNUSED)205 bitset_stats_print (FILE *file, bool verbose MAYBE_UNUSED)
206 {
207   if (!bitset_stats_info)
208     return;
209 
210   fprintf (file, _("Bitset statistics:\n\n"));
211 
212   if (bitset_stats_info->runs > 1)
213     fprintf (file, _("Accumulated runs = %u\n"), bitset_stats_info->runs);
214 
215   for (int i = 0; i < BITSET_TYPE_NUM; i++)
216     bitset_stats_print_1 (file, bitset_type_names[i],
217                           &bitset_stats_info->types[i]);
218 }
219 
220 
221 /* Initialise bitset statistics logging.  */
222 void
bitset_stats_enable(void)223 bitset_stats_enable (void)
224 {
225   if (!bitset_stats_info)
226     bitset_stats_info = &bitset_stats_info_data;
227   bitset_stats_enabled = true;
228 }
229 
230 
231 void
bitset_stats_disable(void)232 bitset_stats_disable (void)
233 {
234   bitset_stats_enabled = false;
235 }
236 
237 
238 /* Read bitset statistics file.  */
239 void
bitset_stats_read(const char * file_name)240 bitset_stats_read (const char *file_name)
241 {
242   if (!bitset_stats_info)
243     return;
244 
245   if (!file_name)
246     file_name = BITSET_STATS_FILE;
247 
248   FILE *file = fopen (file_name, "re");
249   if (file)
250     {
251       if (fread (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
252                  1, file) != 1)
253         {
254           if (ferror (file))
255             perror (_("cannot read stats file"));
256           else
257             fprintf (stderr, _("bad stats file size\n"));
258         }
259       if (fclose (file) != 0)
260         perror (_("cannot read stats file"));
261     }
262   bitset_stats_info_data.runs++;
263 }
264 
265 
266 /* Write bitset statistics file.  */
267 void
bitset_stats_write(const char * file_name)268 bitset_stats_write (const char *file_name)
269 {
270   if (!bitset_stats_info)
271     return;
272 
273   if (!file_name)
274     file_name = BITSET_STATS_FILE;
275 
276   FILE *file = fopen (file_name, "we");
277   if (file)
278     {
279       if (fwrite (&bitset_stats_info_data, sizeof (bitset_stats_info_data),
280                   1, file) != 1)
281         perror (_("cannot write stats file"));
282       if (fclose (file) != 0)
283         perror (_("cannot write stats file"));
284     }
285   else
286     perror (_("cannot open stats file for writing"));
287 }
288 
289 
290 /* Dump bitset statistics to FILE.  */
291 void
bitset_stats_dump(FILE * file)292 bitset_stats_dump (FILE *file)
293 {
294   bitset_stats_print (file, false);
295 }
296 
297 
298 /* Function to be called from debugger to print bitset stats.  */
299 void
debug_bitset_stats(void)300 debug_bitset_stats (void)
301 {
302   bitset_stats_print (stderr, true);
303 }
304 
305 
306 static void
bitset_stats_set(bitset dst,bitset_bindex bitno)307 bitset_stats_set (bitset dst, bitset_bindex bitno)
308 {
309   bitset bset = dst->s.bset;
310   bitset_windex wordno = bitno / BITSET_WORD_BITS;
311   bitset_windex offset = wordno - bset->b.cindex;
312 
313   BITSET_STATS_SETS_INC (bset);
314 
315   if (offset < bset->b.csize)
316     {
317       bset->b.cdata[offset] |= (bitset_word) 1 << (bitno % BITSET_WORD_BITS);
318       BITSET_STATS_CACHE_SETS_INC (bset);
319     }
320   else
321     BITSET_SET_ (bset, bitno);
322 }
323 
324 
325 static void
bitset_stats_reset(bitset dst,bitset_bindex bitno)326 bitset_stats_reset (bitset dst, bitset_bindex bitno)
327 {
328   bitset bset = dst->s.bset;
329   bitset_windex wordno = bitno / BITSET_WORD_BITS;
330   bitset_windex offset = wordno - bset->b.cindex;
331 
332   BITSET_STATS_RESETS_INC (bset);
333 
334   if (offset < bset->b.csize)
335     {
336       bset->b.cdata[offset] &=
337         ~((bitset_word) 1 << (bitno % BITSET_WORD_BITS));
338       BITSET_STATS_CACHE_RESETS_INC (bset);
339     }
340   else
341     BITSET_RESET_ (bset, bitno);
342 }
343 
344 
345 static bool
bitset_stats_toggle(bitset src,bitset_bindex bitno)346 bitset_stats_toggle (bitset src, bitset_bindex bitno)
347 {
348   return BITSET_TOGGLE_ (src->s.bset, bitno);
349 }
350 
351 
352 static bool
bitset_stats_test(bitset src,bitset_bindex bitno)353 bitset_stats_test (bitset src, bitset_bindex bitno)
354 {
355   bitset bset = src->s.bset;
356   bitset_windex wordno = bitno / BITSET_WORD_BITS;
357   bitset_windex offset = wordno - bset->b.cindex;
358 
359   BITSET_STATS_TESTS_INC (bset);
360 
361   if (offset < bset->b.csize)
362     {
363       BITSET_STATS_CACHE_TESTS_INC (bset);
364       return (bset->b.cdata[offset] >> (bitno % BITSET_WORD_BITS)) & 1;
365     }
366   else
367     return BITSET_TEST_ (bset, bitno);
368 }
369 
370 
371 static bitset_bindex
bitset_stats_resize(bitset src,bitset_bindex size)372 bitset_stats_resize (bitset src, bitset_bindex size)
373 {
374   return BITSET_RESIZE_ (src->s.bset, size);
375 }
376 
377 
378 static bitset_bindex
bitset_stats_size(bitset src)379 bitset_stats_size (bitset src)
380 {
381   return BITSET_SIZE_ (src->s.bset);
382 }
383 
384 
385 static bitset_bindex
bitset_stats_count(bitset src)386 bitset_stats_count (bitset src)
387 {
388   return BITSET_COUNT_ (src->s.bset);
389 }
390 
391 
392 static bool
bitset_stats_empty_p(bitset dst)393 bitset_stats_empty_p (bitset dst)
394 {
395   return BITSET_EMPTY_P_ (dst->s.bset);
396 }
397 
398 
399 static void
bitset_stats_ones(bitset dst)400 bitset_stats_ones (bitset dst)
401 {
402   BITSET_ONES_ (dst->s.bset);
403 }
404 
405 
406 static void
bitset_stats_zero(bitset dst)407 bitset_stats_zero (bitset dst)
408 {
409   BITSET_ZERO_ (dst->s.bset);
410 }
411 
412 
413 static void
bitset_stats_copy(bitset dst,bitset src)414 bitset_stats_copy (bitset dst, bitset src)
415 {
416   BITSET_CHECK2_ (dst, src);
417   BITSET_COPY_ (dst->s.bset, src->s.bset);
418 }
419 
420 
421 static bool
bitset_stats_disjoint_p(bitset dst,bitset src)422 bitset_stats_disjoint_p (bitset dst, bitset src)
423 {
424   BITSET_CHECK2_ (dst, src);
425   return BITSET_DISJOINT_P_ (dst->s.bset, src->s.bset);
426 }
427 
428 
429 static bool
bitset_stats_equal_p(bitset dst,bitset src)430 bitset_stats_equal_p (bitset dst, bitset src)
431 {
432   BITSET_CHECK2_ (dst, src);
433   return BITSET_EQUAL_P_ (dst->s.bset, src->s.bset);
434 }
435 
436 
437 static void
bitset_stats_not(bitset dst,bitset src)438 bitset_stats_not (bitset dst, bitset src)
439 {
440   BITSET_CHECK2_ (dst, src);
441   BITSET_NOT_ (dst->s.bset, src->s.bset);
442 }
443 
444 
445 static bool
bitset_stats_subset_p(bitset dst,bitset src)446 bitset_stats_subset_p (bitset dst, bitset src)
447 {
448   BITSET_CHECK2_ (dst, src);
449   return BITSET_SUBSET_P_ (dst->s.bset, src->s.bset);
450 }
451 
452 
453 static void
bitset_stats_and(bitset dst,bitset src1,bitset src2)454 bitset_stats_and (bitset dst, bitset src1, bitset src2)
455 {
456   BITSET_CHECK3_ (dst, src1, src2);
457   BITSET_AND_ (dst->s.bset, src1->s.bset, src2->s.bset);
458 }
459 
460 
461 static bool
bitset_stats_and_cmp(bitset dst,bitset src1,bitset src2)462 bitset_stats_and_cmp (bitset dst, bitset src1, bitset src2)
463 {
464   BITSET_CHECK3_ (dst, src1, src2);
465   return BITSET_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
466 }
467 
468 
469 static void
bitset_stats_andn(bitset dst,bitset src1,bitset src2)470 bitset_stats_andn (bitset dst, bitset src1, bitset src2)
471 {
472   BITSET_CHECK3_ (dst, src1, src2);
473   BITSET_ANDN_ (dst->s.bset, src1->s.bset, src2->s.bset);
474 }
475 
476 
477 static bool
bitset_stats_andn_cmp(bitset dst,bitset src1,bitset src2)478 bitset_stats_andn_cmp (bitset dst, bitset src1, bitset src2)
479 {
480   BITSET_CHECK3_ (dst, src1, src2);
481   return BITSET_ANDN_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
482 }
483 
484 
485 static void
bitset_stats_or(bitset dst,bitset src1,bitset src2)486 bitset_stats_or (bitset dst, bitset src1, bitset src2)
487 {
488   BITSET_CHECK3_ (dst, src1, src2);
489   BITSET_OR_ (dst->s.bset, src1->s.bset, src2->s.bset);
490 }
491 
492 
493 static bool
bitset_stats_or_cmp(bitset dst,bitset src1,bitset src2)494 bitset_stats_or_cmp (bitset dst, bitset src1, bitset src2)
495 {
496   BITSET_CHECK3_ (dst, src1, src2);
497   return BITSET_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
498 }
499 
500 
501 static void
bitset_stats_xor(bitset dst,bitset src1,bitset src2)502 bitset_stats_xor (bitset dst, bitset src1, bitset src2)
503 {
504   BITSET_CHECK3_ (dst, src1, src2);
505   BITSET_XOR_ (dst->s.bset, src1->s.bset, src2->s.bset);
506 }
507 
508 
509 static bool
bitset_stats_xor_cmp(bitset dst,bitset src1,bitset src2)510 bitset_stats_xor_cmp (bitset dst, bitset src1, bitset src2)
511 {
512   BITSET_CHECK3_ (dst, src1, src2);
513   return BITSET_XOR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset);
514 }
515 
516 
517 static void
bitset_stats_and_or(bitset dst,bitset src1,bitset src2,bitset src3)518 bitset_stats_and_or (bitset dst, bitset src1, bitset src2, bitset src3)
519 {
520   BITSET_CHECK4_ (dst, src1, src2, src3);
521   BITSET_AND_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
522 }
523 
524 
525 static bool
bitset_stats_and_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)526 bitset_stats_and_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
527 {
528   BITSET_CHECK4_ (dst, src1, src2, src3);
529   return BITSET_AND_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
530 }
531 
532 
533 static void
bitset_stats_andn_or(bitset dst,bitset src1,bitset src2,bitset src3)534 bitset_stats_andn_or (bitset dst, bitset src1, bitset src2, bitset src3)
535 {
536   BITSET_CHECK4_ (dst, src1, src2, src3);
537   BITSET_ANDN_OR_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
538 }
539 
540 
541 static bool
bitset_stats_andn_or_cmp(bitset dst,bitset src1,bitset src2,bitset src3)542 bitset_stats_andn_or_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
543 {
544   BITSET_CHECK4_ (dst, src1, src2, src3);
545   return BITSET_ANDN_OR_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
546 }
547 
548 
549 static void
bitset_stats_or_and(bitset dst,bitset src1,bitset src2,bitset src3)550 bitset_stats_or_and (bitset dst, bitset src1, bitset src2, bitset src3)
551 {
552   BITSET_CHECK4_ (dst, src1, src2, src3);
553   BITSET_OR_AND_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
554 }
555 
556 
557 static bool
bitset_stats_or_and_cmp(bitset dst,bitset src1,bitset src2,bitset src3)558 bitset_stats_or_and_cmp (bitset dst, bitset src1, bitset src2, bitset src3)
559 {
560   BITSET_CHECK4_ (dst, src1, src2, src3);
561   return BITSET_OR_AND_CMP_ (dst->s.bset, src1->s.bset, src2->s.bset, src3->s.bset);
562 }
563 
564 
565 static bitset_bindex
bitset_stats_list(bitset bset,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)566 bitset_stats_list (bitset bset, bitset_bindex *list,
567                    bitset_bindex num, bitset_bindex *next)
568 {
569   bitset_bindex count = BITSET_LIST_ (bset->s.bset, list, num, next);
570 
571   BITSET_STATS_LISTS_INC (bset->s.bset);
572 
573   /* Log histogram of number of set bits.  */
574   {
575     bitset_bindex i;
576     bitset_bindex tmp;
577     for (i = 0, tmp = count; tmp; tmp >>= 1, i++)
578       continue;
579     if (i >= BITSET_LOG_COUNT_BINS)
580       i = BITSET_LOG_COUNT_BINS - 1;
581     BITSET_STATS_LIST_COUNTS_INC (bset->s.bset, i);
582   }
583 
584   /* Log histogram of number of bits in set.  */
585   bitset_bindex size = BITSET_SIZE_ (bset->s.bset);
586   {
587     bitset_bindex i;
588     bitset_bindex tmp;
589     for (i = 0, tmp = size; tmp; tmp >>= 1, i++)
590       continue;
591     if (i >= BITSET_LOG_SIZE_BINS)
592       i = BITSET_LOG_SIZE_BINS - 1;
593     BITSET_STATS_LIST_SIZES_INC (bset->s.bset, i);
594   }
595 
596   /* Histogram of fraction of bits set.  */
597   {
598     bitset_bindex i = size ? (count * BITSET_DENSITY_BINS) / size : 0;
599     if (i >= BITSET_DENSITY_BINS)
600       i = BITSET_DENSITY_BINS - 1;
601     BITSET_STATS_LIST_DENSITY_INC (bset->s.bset, i);
602   }
603   return count;
604 }
605 
606 
607 static bitset_bindex
bitset_stats_list_reverse(bitset bset,bitset_bindex * list,bitset_bindex num,bitset_bindex * next)608 bitset_stats_list_reverse (bitset bset, bitset_bindex *list,
609                            bitset_bindex num, bitset_bindex *next)
610 {
611   return BITSET_LIST_REVERSE_ (bset->s.bset, list, num, next);
612 }
613 
614 
615 static void
bitset_stats_free(bitset bset)616 bitset_stats_free (bitset bset)
617 {
618   BITSET_STATS_FREES_INC (bset->s.bset);
619   BITSET_FREE_ (bset->s.bset);
620 }
621 
622 
623 struct bitset_vtable bitset_stats_vtable = {
624   bitset_stats_set,
625   bitset_stats_reset,
626   bitset_stats_toggle,
627   bitset_stats_test,
628   bitset_stats_resize,
629   bitset_stats_size,
630   bitset_stats_count,
631   bitset_stats_empty_p,
632   bitset_stats_ones,
633   bitset_stats_zero,
634   bitset_stats_copy,
635   bitset_stats_disjoint_p,
636   bitset_stats_equal_p,
637   bitset_stats_not,
638   bitset_stats_subset_p,
639   bitset_stats_and,
640   bitset_stats_and_cmp,
641   bitset_stats_andn,
642   bitset_stats_andn_cmp,
643   bitset_stats_or,
644   bitset_stats_or_cmp,
645   bitset_stats_xor,
646   bitset_stats_xor_cmp,
647   bitset_stats_and_or,
648   bitset_stats_and_or_cmp,
649   bitset_stats_andn_or,
650   bitset_stats_andn_or_cmp,
651   bitset_stats_or_and,
652   bitset_stats_or_and_cmp,
653   bitset_stats_list,
654   bitset_stats_list_reverse,
655   bitset_stats_free,
656   BITSET_STATS
657 };
658 
659 
660 /* Return enclosed bitset type.  */
661 enum bitset_type
bitset_stats_type_get(bitset bset)662 bitset_stats_type_get (bitset bset)
663 {
664   return BITSET_TYPE_ (bset->s.bset);
665 }
666 
667 
668 size_t
bitset_stats_bytes(void)669 bitset_stats_bytes (void)
670 {
671   return sizeof (struct bitset_stats_struct);
672 }
673 
674 
675 bitset
bitset_stats_init(bitset bset,bitset_bindex n_bits,enum bitset_type type)676 bitset_stats_init (bitset bset, bitset_bindex n_bits, enum bitset_type type)
677 {
678   bset->b.vtable = &bitset_stats_vtable;
679 
680   /* Disable cache.  */
681   bset->b.cindex = 0;
682   bset->b.csize = 0;
683   bset->b.cdata = 0;
684 
685   BITSET_NBITS_ (bset) = n_bits;
686 
687   /* Set up the actual bitset implementation that
688      we are a wrapper over.  */
689   switch (type)
690     {
691     default:
692       abort ();
693 
694     case BITSET_ARRAY:
695       {
696         size_t bytes = abitset_bytes (n_bits);
697         bset->s.bset = xzalloc (bytes);
698         abitset_init (bset->s.bset, n_bits);
699       }
700       break;
701 
702     case BITSET_LIST:
703       {
704         size_t bytes = lbitset_bytes (n_bits);
705         bset->s.bset = xzalloc (bytes);
706         lbitset_init (bset->s.bset, n_bits);
707       }
708       break;
709 
710     case BITSET_TABLE:
711       {
712         size_t bytes = tbitset_bytes (n_bits);
713         bset->s.bset = xzalloc (bytes);
714         tbitset_init (bset->s.bset, n_bits);
715       }
716       break;
717 
718     case BITSET_VECTOR:
719       {
720         size_t bytes = vbitset_bytes (n_bits);
721         bset->s.bset = xzalloc (bytes);
722         vbitset_init (bset->s.bset, n_bits);
723       }
724       break;
725     }
726 
727   BITSET_STATS_ALLOCS_INC (type);
728 
729   return bset;
730 }
731