2    Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 
   3    Contributed by Michael Hayes (m.hayes@elec.canterbury.ac.nz). 
   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 3 of the License, or 
   8    (at your option) any later version. 
  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. 
  15    You should have received a copy of the GNU General Public License 
  16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ 
  18 /* This file is a wrapper bitset implementation for the other bitset 
  19    implementations.  It provides bitset compatibility checking and 
  20    statistics gathering without having to instrument the bitset 
  21    implementations.  When statistics gathering is enabled, the bitset 
  22    operations get vectored through here and we then call the appropriate 
  27 #include "bitset_stats.h" 
  39 #define _(Msgid)  gettext (Msgid) 
  41 /* Configuration macros.  */ 
  42 #define BITSET_STATS_FILE "bitset.dat" 
  43 #define BITSET_LOG_COUNT_BINS 10 
  44 #define BITSET_LOG_SIZE_BINS  16 
  45 #define BITSET_DENSITY_BINS  20 
  48 /* Accessor macros.  */ 
  49 #define BITSET_STATS_ALLOCS_INC(TYPE)                   \ 
  50     bitset_stats_info->types[(TYPE)].allocs++ 
  51 #define BITSET_STATS_FREES_INC(BSET)                    \ 
  52     bitset_stats_info->types[BITSET_TYPE_ (BSET)].frees++ 
  53 #define BITSET_STATS_SETS_INC(BSET)                     \ 
  54     bitset_stats_info->types[BITSET_TYPE_ (BSET)].sets++ 
  55 #define BITSET_STATS_CACHE_SETS_INC(BSET)               \ 
  56     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_sets++ 
  57 #define BITSET_STATS_RESETS_INC(BSET)                   \ 
  58     bitset_stats_info->types[BITSET_TYPE_ (BSET)].resets++ 
  59 #define BITSET_STATS_CACHE_RESETS_INC(BSET)             \ 
  60     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_resets++ 
  61 #define BITSET_STATS_TESTS_INC(BSET)                    \ 
  62     bitset_stats_info->types[BITSET_TYPE_ (BSET)].tests++ 
  63 #define BITSET_STATS_CACHE_TESTS_INC(BSET)              \ 
  64     bitset_stats_info->types[BITSET_TYPE_ (BSET)].cache_tests++ 
  65 #define BITSET_STATS_LISTS_INC(BSET)                    \ 
  66     bitset_stats_info->types[BITSET_TYPE_ (BSET)].lists++ 
  67 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I)           \ 
  68     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++ 
  69 #define BITSET_STATS_LIST_SIZES_INC(BSET, I)            \ 
  70     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++ 
  71 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I)          \ 
  72     bitset_stats_info->types[BITSET_TYPE_ (BSET)].list_density[(I)]++ 
  75 struct bitset_type_info_struct
 
  81   unsigned int cache_sets
; 
  83   unsigned int cache_resets
; 
  85   unsigned int cache_tests
; 
  86   unsigned int list_counts
[BITSET_LOG_COUNT_BINS
]; 
  87   unsigned int list_sizes
[BITSET_LOG_SIZE_BINS
]; 
  88   unsigned int list_density
[BITSET_DENSITY_BINS
]; 
  91 struct bitset_stats_info_struct
 
  94   struct bitset_type_info_struct types
[BITSET_TYPE_NUM
]; 
  98 struct bitset_stats_info_struct bitset_stats_info_data
; 
  99 struct bitset_stats_info_struct 
*bitset_stats_info
; 
 100 bool bitset_stats_enabled 
= false; 
 103 /* Print a percentage histogram with message MSG to FILE.  */ 
 105 bitset_percent_histogram_print (FILE *file
, const char *name
, const char *msg
, 
 106                                 unsigned int n_bins
, unsigned int *bins
) 
 112   for (i 
= 0; i 
< n_bins
; i
++) 
 118   fprintf (file
, "%s %s", name
, msg
); 
 119   for (i 
= 0; i 
< n_bins
; i
++) 
 120     fprintf (file
, "%.0f-%.0f%%\t%8u (%5.1f%%)\n", 
 122              (i 
+ 1) * 100.0 / n_bins
, bins
[i
], 
 123              (100.0 * bins
[i
]) / total
); 
 127 /* Print a log histogram with message MSG to FILE.  */ 
 129 bitset_log_histogram_print (FILE *file
, const char *name
, const char *msg
, 
 130                             unsigned int n_bins
, unsigned int *bins
) 
 134   unsigned int max_width
; 
 137   for (i 
= 0; i 
< n_bins
; i
++) 
 143   /* Determine number of useful bins.  */ 
 144   for (i 
= n_bins
; i 
> 3 && ! bins
[i 
- 1]; i
--) 
 148   /* 2 * ceil (log10 (2) * (N - 1)) + 1.  */ 
 149   max_width 
= 2 * (unsigned int) (0.30103 * (n_bins 
- 1) + 0.9999) + 1; 
 151   fprintf (file
, "%s %s", name
, msg
); 
 152   for (i 
= 0; i 
< 2; i
++) 
 153     fprintf (file
, "%*d\t%8u (%5.1f%%)\n", 
 154              max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
); 
 156   for (; i 
< n_bins
; i
++) 
 157     fprintf (file
, "%*lu-%lu\t%8u (%5.1f%%)\n", 
 158              max_width 
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1), 
 162              (100.0 * bins
[i
]) / total
); 
 166 /* Print bitset statistics to FILE.  */ 
 168 bitset_stats_print_1 (FILE *file
, const char *name
, 
 169                       struct bitset_type_info_struct 
*stats
) 
 174   fprintf (file
, "%s:\n", name
); 
 175   fprintf (file
, _("%u bitset_allocs, %u freed (%.2f%%).\n"), 
 176            stats
->allocs
, stats
->frees
, 
 177            stats
->allocs 
? 100.0 * stats
->frees 
/ stats
->allocs 
: 0); 
 178   fprintf (file
, _("%u bitset_sets, %u cached (%.2f%%)\n"), 
 179            stats
->sets
, stats
->cache_sets
, 
 180            stats
->sets 
? 100.0 * stats
->cache_sets 
/ stats
->sets 
: 0); 
 181   fprintf (file
, _("%u bitset_resets, %u cached (%.2f%%)\n"), 
 182            stats
->resets
, stats
->cache_resets
, 
 183            stats
->resets 
? 100.0 * stats
->cache_resets 
/ stats
->resets 
: 0); 
 184   fprintf (file
, _("%u bitset_tests, %u cached (%.2f%%)\n"), 
 185            stats
->tests
, stats
->cache_tests
, 
 186            stats
->tests 
? 100.0 * stats
->cache_tests 
/ stats
->tests 
: 0); 
 188   fprintf (file
, _("%u bitset_lists\n"), stats
->lists
); 
 190   bitset_log_histogram_print (file
, name
, _("count log histogram\n"), 
 191                               BITSET_LOG_COUNT_BINS
, stats
->list_counts
); 
 193   bitset_log_histogram_print (file
, name
, _("size log histogram\n"), 
 194                               BITSET_LOG_SIZE_BINS
, stats
->list_sizes
); 
 196   bitset_percent_histogram_print (file
, name
, _("density histogram\n"), 
 197                                   BITSET_DENSITY_BINS
, stats
->list_density
); 
 201 /* Print all bitset statistics to FILE.  */ 
 203 bitset_stats_print (FILE *file
, bool verbose ATTRIBUTE_UNUSED
) 
 207   if (!bitset_stats_info
) 
 210   fprintf (file
, _("Bitset statistics:\n\n")); 
 212   if (bitset_stats_info
->runs 
> 1) 
 213     fprintf (file
, _("Accumulated runs = %u\n"), bitset_stats_info
->runs
); 
 215   for (i 
= 0; i 
< BITSET_TYPE_NUM
; i
++) 
 216     bitset_stats_print_1 (file
, bitset_type_names
[i
], 
 217                           &bitset_stats_info
->types
[i
]); 
 221 /* Initialise bitset statistics logging.  */ 
 223 bitset_stats_enable (void) 
 225   if (!bitset_stats_info
) 
 226     bitset_stats_info 
= &bitset_stats_info_data
; 
 227   bitset_stats_enabled 
= true; 
 232 bitset_stats_disable (void) 
 234   bitset_stats_enabled 
= false; 
 238 /* Read bitset statistics file.  */ 
 240 bitset_stats_read (const char *file_name
) 
 244   if (!bitset_stats_info
) 
 248     file_name 
= BITSET_STATS_FILE
; 
 250   file 
= fopen (file_name
, "r"); 
 253       if (fread (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
), 
 257             perror (_("Could not read stats file.")); 
 259             fprintf (stderr
, _("Bad stats file size.\n")); 
 261       if (fclose (file
) != 0) 
 262         perror (_("Could not read stats file.")); 
 264   bitset_stats_info_data
.runs
++; 
 268 /* Write bitset statistics file.  */ 
 270 bitset_stats_write (const char *file_name
) 
 274   if (!bitset_stats_info
) 
 278     file_name 
= BITSET_STATS_FILE
; 
 280   file 
= fopen (file_name
, "w"); 
 283       if (fwrite (&bitset_stats_info_data
, sizeof (bitset_stats_info_data
), 
 285         perror (_("Could not write stats file.")); 
 286       if (fclose (file
) != 0) 
 287         perror (_("Could not write stats file.")); 
 290     perror (_("Could not open stats file for writing.")); 
 294 /* Dump bitset statistics to FILE.  */ 
 296 bitset_stats_dump (FILE *file
) 
 298   bitset_stats_print (file
, false); 
 302 /* Function to be called from debugger to print bitset stats.  */ 
 304 debug_bitset_stats (void) 
 306   bitset_stats_print (stderr
, true); 
 311 bitset_stats_set (bitset dst
, bitset_bindex bitno
) 
 313   bitset bset 
= dst
->s
.bset
; 
 314   bitset_windex wordno 
= bitno 
/ BITSET_WORD_BITS
; 
 315   bitset_windex offset 
= wordno 
- bset
->b
.cindex
; 
 317   BITSET_STATS_SETS_INC (bset
); 
 319   if (offset 
< bset
->b
.csize
) 
 321       bset
->b
.cdata
[offset
] |= (bitset_word
) 1 << (bitno 
% BITSET_WORD_BITS
); 
 322       BITSET_STATS_CACHE_SETS_INC (bset
); 
 325     BITSET_SET_ (bset
, bitno
); 
 330 bitset_stats_reset (bitset dst
, bitset_bindex bitno
) 
 332   bitset bset 
= dst
->s
.bset
; 
 333   bitset_windex wordno 
= bitno 
/ BITSET_WORD_BITS
; 
 334   bitset_windex offset 
= wordno 
- bset
->b
.cindex
; 
 336   BITSET_STATS_RESETS_INC (bset
); 
 338   if (offset 
< bset
->b
.csize
) 
 340       bset
->b
.cdata
[offset
] &= 
 341         ~((bitset_word
) 1 << (bitno 
% BITSET_WORD_BITS
)); 
 342       BITSET_STATS_CACHE_RESETS_INC (bset
); 
 345     BITSET_RESET_ (bset
, bitno
); 
 350 bitset_stats_toggle (bitset src
, bitset_bindex bitno
) 
 352     return BITSET_TOGGLE_ (src
->s
.bset
, bitno
); 
 357 bitset_stats_test (bitset src
, bitset_bindex bitno
) 
 359   bitset bset 
= src
->s
.bset
; 
 360   bitset_windex wordno 
= bitno 
/ BITSET_WORD_BITS
; 
 361   bitset_windex offset 
= wordno 
- bset
->b
.cindex
; 
 363   BITSET_STATS_TESTS_INC (bset
); 
 365   if (offset 
< bset
->b
.csize
) 
 367       BITSET_STATS_CACHE_TESTS_INC (bset
); 
 368       return (bset
->b
.cdata
[offset
] >> (bitno 
% BITSET_WORD_BITS
)) & 1; 
 371     return BITSET_TEST_ (bset
, bitno
); 
 376 bitset_stats_resize (bitset src
, bitset_bindex size
) 
 378     return BITSET_RESIZE_ (src
->s
.bset
, size
); 
 383 bitset_stats_size (bitset src
) 
 385   return BITSET_SIZE_ (src
->s
.bset
); 
 390 bitset_stats_count (bitset src
) 
 392   return BITSET_COUNT_ (src
->s
.bset
); 
 397 bitset_stats_empty_p (bitset dst
) 
 399   return BITSET_EMPTY_P_ (dst
->s
.bset
); 
 404 bitset_stats_ones (bitset dst
) 
 406   BITSET_ONES_ (dst
->s
.bset
); 
 411 bitset_stats_zero (bitset dst
) 
 413   BITSET_ZERO_ (dst
->s
.bset
); 
 418 bitset_stats_copy (bitset dst
, bitset src
) 
 420   BITSET_CHECK2_ (dst
, src
); 
 421   BITSET_COPY_ (dst
->s
.bset
, src
->s
.bset
); 
 426 bitset_stats_disjoint_p (bitset dst
, bitset src
) 
 428   BITSET_CHECK2_ (dst
, src
); 
 429   return BITSET_DISJOINT_P_ (dst
->s
.bset
, src
->s
.bset
); 
 434 bitset_stats_equal_p (bitset dst
, bitset src
) 
 436   BITSET_CHECK2_ (dst
, src
); 
 437   return BITSET_EQUAL_P_ (dst
->s
.bset
, src
->s
.bset
); 
 442 bitset_stats_not (bitset dst
, bitset src
) 
 444   BITSET_CHECK2_ (dst
, src
); 
 445   BITSET_NOT_ (dst
->s
.bset
, src
->s
.bset
); 
 450 bitset_stats_subset_p (bitset dst
, bitset src
) 
 452   BITSET_CHECK2_ (dst
, src
); 
 453   return BITSET_SUBSET_P_ (dst
->s
.bset
, src
->s
.bset
); 
 458 bitset_stats_and (bitset dst
, bitset src1
, bitset src2
) 
 460   BITSET_CHECK3_ (dst
, src1
, src2
); 
 461   BITSET_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 466 bitset_stats_and_cmp (bitset dst
, bitset src1
, bitset src2
) 
 468   BITSET_CHECK3_ (dst
, src1
, src2
); 
 469   return BITSET_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 474 bitset_stats_andn (bitset dst
, bitset src1
, bitset src2
) 
 476   BITSET_CHECK3_ (dst
, src1
, src2
); 
 477   BITSET_ANDN_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 482 bitset_stats_andn_cmp (bitset dst
, bitset src1
, bitset src2
) 
 484   BITSET_CHECK3_ (dst
, src1
, src2
); 
 485   return BITSET_ANDN_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 490 bitset_stats_or (bitset dst
, bitset src1
, bitset src2
) 
 492   BITSET_CHECK3_ (dst
, src1
, src2
); 
 493   BITSET_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 498 bitset_stats_or_cmp (bitset dst
, bitset src1
, bitset src2
) 
 500   BITSET_CHECK3_ (dst
, src1
, src2
); 
 501   return BITSET_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 506 bitset_stats_xor (bitset dst
, bitset src1
, bitset src2
) 
 508   BITSET_CHECK3_ (dst
, src1
, src2
); 
 509   BITSET_XOR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 514 bitset_stats_xor_cmp (bitset dst
, bitset src1
, bitset src2
) 
 516   BITSET_CHECK3_ (dst
, src1
, src2
); 
 517   return BITSET_XOR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
); 
 522 bitset_stats_and_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 524   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 525   BITSET_AND_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 530 bitset_stats_and_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 532   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 533   return BITSET_AND_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 538 bitset_stats_andn_or (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 540   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 541   BITSET_ANDN_OR_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 546 bitset_stats_andn_or_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 548   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 549   return BITSET_ANDN_OR_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 554 bitset_stats_or_and (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 556   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 557   BITSET_OR_AND_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 562 bitset_stats_or_and_cmp (bitset dst
, bitset src1
, bitset src2
, bitset src3
) 
 564   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 565   return BITSET_OR_AND_CMP_ (dst
->s
.bset
, src1
->s
.bset
, src2
->s
.bset
, src3
->s
.bset
); 
 570 bitset_stats_list (bitset bset
, bitset_bindex 
*list
, 
 571                    bitset_bindex num
, bitset_bindex 
*next
) 
 577   enum bitset_type type
; 
 579   count 
= BITSET_LIST_ (bset
->s
.bset
, list
, num
, next
); 
 581   type 
= BITSET_TYPE_ (bset
->s
.bset
); 
 582   BITSET_STATS_LISTS_INC (bset
->s
.bset
); 
 584   /* Log histogram of number of set bits.  */ 
 585   for (i 
= 0, tmp 
= count
; tmp
; tmp 
>>= 1, i
++) 
 587   if (i 
>= BITSET_LOG_COUNT_BINS
) 
 588      i 
= BITSET_LOG_COUNT_BINS 
- 1; 
 589   BITSET_STATS_LIST_COUNTS_INC (bset
->s
.bset
, i
); 
 591   /* Log histogram of number of bits in set.  */ 
 592   size 
= BITSET_SIZE_ (bset
->s
.bset
); 
 593   for (i 
= 0, tmp 
= size
; tmp
; tmp 
>>= 1, i
++) 
 595   if (i 
>= BITSET_LOG_SIZE_BINS
) 
 596      i 
= BITSET_LOG_SIZE_BINS 
- 1; 
 597   BITSET_STATS_LIST_SIZES_INC (bset
->s
.bset
, i
); 
 599   /* Histogram of fraction of bits set.  */ 
 600   i 
= size 
? (count 
* BITSET_DENSITY_BINS
) / size 
: 0; 
 601   if (i 
>= BITSET_DENSITY_BINS
) 
 602      i 
= BITSET_DENSITY_BINS 
- 1; 
 603   BITSET_STATS_LIST_DENSITY_INC (bset
->s
.bset
, i
); 
 609 bitset_stats_list_reverse (bitset bset
, bitset_bindex 
*list
, 
 610                            bitset_bindex num
, bitset_bindex 
*next
) 
 612   return BITSET_LIST_REVERSE_ (bset
->s
.bset
, list
, num
, next
); 
 617 bitset_stats_free (bitset bset
) 
 619   BITSET_STATS_FREES_INC (bset
->s
.bset
); 
 620   BITSET_FREE_ (bset
->s
.bset
); 
 624 struct bitset_vtable bitset_stats_vtable 
= { 
 632   bitset_stats_empty_p
, 
 636   bitset_stats_disjoint_p
, 
 637   bitset_stats_equal_p
, 
 639   bitset_stats_subset_p
, 
 641   bitset_stats_and_cmp
, 
 643   bitset_stats_andn_cmp
, 
 647   bitset_stats_xor_cmp
, 
 649   bitset_stats_and_or_cmp
, 
 650   bitset_stats_andn_or
, 
 651   bitset_stats_andn_or_cmp
, 
 653   bitset_stats_or_and_cmp
, 
 655   bitset_stats_list_reverse
, 
 661 /* Return enclosed bitset type.  */ 
 663 bitset_stats_type_get (bitset bset
) 
 665    return BITSET_TYPE_ (bset
->s
.bset
); 
 670 bitset_stats_bytes (void) 
 672   return sizeof (struct bitset_stats_struct
); 
 677 bitset_stats_init (bitset bset
, bitset_bindex n_bits
, enum bitset_type type
) 
 682   bset
->b
.vtable 
= &bitset_stats_vtable
; 
 689   BITSET_NBITS_ (bset
) = n_bits
; 
 691   /* Set up the actual bitset implementation that 
 692      we are a wrapper over.  */ 
 699       bytes 
= abitset_bytes (n_bits
); 
 700       sbset 
= xcalloc (1, bytes
); 
 701       abitset_init (sbset
, n_bits
); 
 705       bytes 
= lbitset_bytes (n_bits
); 
 706       sbset 
= xcalloc (1, bytes
); 
 707       lbitset_init (sbset
, n_bits
); 
 711       bytes 
= ebitset_bytes (n_bits
); 
 712       sbset 
= xcalloc (1, bytes
); 
 713       ebitset_init (sbset
, n_bits
); 
 717       bytes 
= vbitset_bytes (n_bits
); 
 718       sbset 
= xcalloc (1, bytes
); 
 719       vbitset_init (sbset
, n_bits
); 
 723   bset
->s
.bset 
= sbset
; 
 725   BITSET_STATS_ALLOCS_INC (type
);