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