2    Copyright (C) 2002 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 2 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, write to the Free Software 
  17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */ 
  30 static void bitset_print 
PARAMS ((FILE *, bitset
, int)); 
  33 #define BITSET_STATS_FILE "bitset.dat" 
  35 #define BITSET_LOG_COUNT_BINS 10 
  36 #define BITSET_LOG_SIZE_BINS  16 
  37 #define BITSET_DENSITY_BINS  20 
  39 struct bitset_type_stats_struct
 
  41   unsigned int xmallocs
; 
  43   unsigned int oballocs
; 
  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
]; 
  51 struct bitset_stats_struct
 
  54   struct bitset_type_stats_struct types
[BITSET_TYPE_NUM
]; 
  57 struct bitset_stats_struct bitset_stats_data
; 
  58 struct bitset_stats_struct 
*bitset_stats
; 
  60 static void bitset_percent_histogram_print 
PARAMS ((FILE *, const char *, 
  64 static void bitset_log_histogram_print 
PARAMS ((FILE *, const char *, 
  68 static void bitset_stats_print_1
 
  69 PARAMS ((FILE *, const char *, struct bitset_type_stats_struct 
*)); 
  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)); 
  74 #define BITSET_STATS_XMALLOCS_INC(TYPE)                 \ 
  76     bitset_stats->types[(TYPE)].xmallocs++ 
  78 #define BITSET_STATS_XFREES_INC(BSET)                   \ 
  80     bitset_stats->types[BITSET_TYPE_ (BSET)].xfrees++ 
  82 #define BITSET_STATS_OBALLOCS_INC(TYPE)                 \ 
  84     bitset_stats->types[(TYPE)].oballocs++ 
  86 #define BITSET_STATS_OBFREES_INC(BSET)                  \ 
  88     bitset_stats->types[BITSET_TYPE_ (BSET)].obfrees++ 
  90 #define BITSET_STATS_LISTS_INC(BSET)                    \ 
  92     bitset_stats->types[BITSET_TYPE_ (BSET)].lists++ 
  94 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I)           \ 
  96     bitset_stats->types[BITSET_TYPE_ (BSET)].list_counts[(I)]++ 
  98 #define BITSET_STATS_LIST_SIZES_INC(BSET, I)            \ 
 100     bitset_stats->types[BITSET_TYPE_ (BSET)].list_sizes[(I)]++ 
 102 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I)          \ 
 104     bitset_stats->types[BITSET_TYPE_ (BSET)].list_density[(I)]++ 
 107 #define BITSET_STATS_XMALLOCS_INC(TYPE) 
 109 #define BITSET_STATS_XFREES_INC(BSET) 
 111 #define BITSET_STATS_OBALLOCS_INC(TYPE) 
 113 #define BITSET_STATS_OBFREES_INC(BSET) 
 115 #define BITSET_STATS_LISTS_INC(BSET) 
 117 #define BITSET_STATS_LIST_COUNTS_INC(BSET, I) 
 119 #define BITSET_STATS_LIST_SIZES_INC(BSET, I) 
 121 #define BITSET_STATS_LIST_DENSITY_INC(BSET, I) 
 122 #endif /* BITSET_STATS  */ 
 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.  */ 
 128 bitset_bytes (type
, n_bits
) 
 129      enum bitset_type type
; 
 130      bitset_bindex n_bits
; 
 137       bytes 
= sbitset_bytes (n_bits
); 
 141       bytes 
= lbitset_bytes (n_bits
); 
 145       bytes 
= ebitset_bytes (n_bits
); 
 156 /* Initialise bitset BSET of TYPE for N_BITS.  */ 
 158 bitset_init (bset
, n_bits
, type
) 
 160      bitset_bindex n_bits
; 
 161      enum bitset_type type
; 
 166       return sbitset_init (bset
, n_bits
); 
 169       return lbitset_init (bset
, n_bits
); 
 172       return ebitset_init (bset
, n_bits
); 
 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.  */ 
 184 bitset_type_choose (n_bits
, attr
) 
 185      bitset_bindex n_bits ATTRIBUTE_UNUSED
; 
 188   enum bitset_type type
; 
 191   /* Check attributes.  */ 
 192   if (attr 
& BITSET_FIXED 
&& attr 
& BITSET_VARIABLE
) 
 194   if (attr 
& BITSET_SPARSE 
&& attr 
& BITSET_DENSE
) 
 197   /* Note that sometimes we will be asked for a zero length 
 198      fixed size bitset.  */ 
 201   /* Choose the type of bitset.  */ 
 204   /* Currently, the simple bitsets do not support a variable size.  */ 
 205   if (attr 
& BITSET_VARIABLE 
|| attr 
& BITSET_SPARSE
) 
 208       if (attr 
& BITSET_DENSE 
|| attr 
& BITSET_GREEDY
) 
 216 /* Create a bitset of N_BITS of type TYPE.  */ 
 218 bitset_alloc (n_bits
, type
) 
 219      bitset_bindex n_bits
; 
 220      enum bitset_type type
; 
 225   BITSET_STATS_XMALLOCS_INC (type
); 
 227   bytes 
= bitset_bytes (type
, n_bits
); 
 229   bset 
= (bitset
) xcalloc (1, bytes
); 
 231   /* The cache is disabled until some elements are allocated.  If we 
 232      have variable length arrays, then we may need to allocate dummy 
 235   return bitset_init (bset
, n_bits
, type
); 
 239 /* Create a bitset of N_BITS of type TYPE.  */ 
 241 bitset_obstack_alloc (bobstack
, n_bits
, type
) 
 242      struct obstack 
*bobstack
; 
 243      bitset_bindex n_bits
; 
 244      enum bitset_type type
; 
 249   BITSET_STATS_OBALLOCS_INC (type
); 
 251   bytes 
= bitset_bytes (type
, n_bits
); 
 253   bset 
= obstack_alloc (bobstack
, bytes
); 
 254   memset (bset
, 0, bytes
); 
 256   return bitset_init (bset
, n_bits
, type
); 
 260 /* Create a bitset of N_BITS and with attribute hints specified by 
 263 bitset_create (n_bits
, attr
) 
 264      bitset_bindex n_bits
; 
 267   enum bitset_type type
; 
 269   type 
= bitset_type_choose (n_bits
, attr
); 
 271   return bitset_alloc (n_bits
, type
); 
 275 /* Free bitset BSET.  */ 
 280   BITSET_STATS_XFREES_INC (bset
); 
 287 /* Free bitset BSET allocated on obstack.  */ 
 289 bitset_obstack_free (bset
) 
 292   BITSET_STATS_OBFREES_INC (bset
); 
 298 /* Find next bit set in SRC starting from and including BITNO. 
 299    Return -1 if SRC empty.  */ 
 301 bitset_next (src
, bitno
) 
 306   bitset_bindex next 
= bitno
; 
 308   if (!bitset_list (src
, &val
, 1, &next
)) 
 314 /* Find previous bit set in SRC starting from and including BITNO. 
 315    Return -1 if SRC empty.  */ 
 317 bitset_prev (src
, bitno
) 
 322   bitset_bindex next 
= bitno
; 
 324   if (!bitset_reverse_list (src
, &val
, 1, &next
)) 
 330 /* Find first set bit.   */ 
 335   return bitset_next (src
, 0); 
 339 /* Find last set bit.   */ 
 344   return bitset_prev (src
, 0); 
 348 /* Print contents of bitset BSET to FILE.   */ 
 350 bitset_print (file
, bset
, verbose
) 
 358     fprintf (file
, "n_bits = %d, set = {", bitset_size (bset
)); 
 361   BITSET_EXECUTE (bset
, 0, i
, 
 365         fprintf (file
, "\n"); 
 369     fprintf (file
, "%d ", i
); 
 370     pos 
+= 1 + (i 
>= 10) + (i 
>= 100); 
 374     fprintf (file
, "}\n"); 
 378 /* DST = SRC.  Return non-zero if DST != SRC.  */ 
 380 bitset_copy (dst
, src
) 
 386   if (BITSET_COMPATIBLE_ (dst
, src
)) 
 387     return BITSET_COPY_ (dst
, src
); 
 389   /* Convert bitset types.  We assume that the DST bitset 
 390      is large enough to hold the SRC bitset.  */ 
 392   BITSET_EXECUTE (src
, 0, i
, 
 401 /* Return size in bits of bitset SRC.  */ 
 406   return BITSET_SIZE_ (src
); 
 410 /* Return number of bits set in bitset SRC.  */ 
 415   bitset_bindex list
[BITSET_LIST_SIZE
]; 
 421   for (count 
= 0; (num 
= bitset_list (src
, list
, BITSET_LIST_SIZE
, &next
)); 
 434   return BITSET_ZERO_ (dst
); 
 443   return BITSET_ONES_ (dst
); 
 447 /* Return SRC == 0.  */ 
 452   return BITSET_EMPTY_P_ (src
); 
 456 /* Return DST == DST | SRC.  */ 
 458 bitset_subset_p (dst
, src
) 
 462   BITSET_CHECK2_ (dst
, src
); 
 463   return BITSET_SUBSET_P_ (dst
, src
); 
 467 /* Return DST == SRC.  */ 
 469 bitset_equal_p (dst
, src
) 
 473   BITSET_CHECK2_ (dst
, src
); 
 474   return BITSET_EQUAL_P_ (dst
, src
); 
 478 /* Return DST & SRC == 0.  */ 
 480 bitset_disjoint_p (dst
, src
) 
 484   BITSET_CHECK2_ (dst
, src
); 
 485   return BITSET_DISJOINT_P_ (dst
, src
); 
 491 bitset_not (dst
, src
) 
 495   BITSET_CHECK2_ (dst
, src
); 
 496   return BITSET_NOT_ (dst
, src
); 
 500 /* DST = SRC1 | SRC2.  Return non-zero if DST != SRC1 | SRC2.  */ 
 502 bitset_or (dst
, src1
, src2
) 
 507   BITSET_CHECK3_ (dst
, src1
, src2
); 
 508   return BITSET_OR_ (dst
, src1
, src2
); 
 512 /* DST = SRC1 & SRC2.  Return non-zero if DST != SRC1 & SRC2.  */ 
 514 bitset_and (dst
, src1
, src2
) 
 519   BITSET_CHECK3_ (dst
, src1
, src2
); 
 520   return BITSET_AND_ (dst
, src1
, src2
); 
 524 /* DST = SRC1 ^ SRC2.  Return non-zero if DST != SRC1 ^ SRC2.  */ 
 526 bitset_xor (dst
, src1
, src2
) 
 531   BITSET_CHECK3_ (dst
, src1
, src2
); 
 532   return BITSET_XOR_ (dst
, src1
, src2
); 
 536 /* DST = SRC1 & ~SRC2.  Return non-zero if DST != SRC1 & ~SRC2.  */ 
 538 bitset_andn (dst
, src1
, src2
) 
 543   BITSET_CHECK3_ (dst
, src1
, src2
); 
 544   return BITSET_ANDN_ (dst
, src1
, src2
); 
 548 /* DST = SRC1 | ~SRC2.  Return non-zero if DST != SRC1 | ~SRC2.  */ 
 550 bitset_orn (dst
, src1
, src2
) 
 555   BITSET_CHECK3_ (dst
, src1
, src2
); 
 556   return BITSET_ORN_ (dst
, src1
, src2
); 
 561 bitset_op4 (dst
, src1
, src2
, src3
, op
) 
 571   /* Create temporary bitset.  */ 
 572   tmp 
= bitset_alloc (BITSET_TYPE_ (dst
), 0); 
 576     case BITSET_OP_OR_AND
: 
 577       BITSET_OR_ (tmp
, src1
, src2
); 
 578       changed 
= BITSET_AND_ (dst
, src3
, tmp
); 
 581     case BITSET_OP_AND_OR
: 
 582       BITSET_AND_ (tmp
, src1
, src2
); 
 583       changed 
= BITSET_OR_ (dst
, src3
, tmp
); 
 586     case BITSET_OP_ANDN_OR
: 
 587       BITSET_ANDN_ (tmp
, src1
, src2
); 
 588       changed 
= BITSET_OR_ (dst
, src3
, tmp
); 
 600 /* DST = (SRC1 | SRC2) & SRC3.  Return non-zero if 
 601    DST != (SRC1 | SRC2) & SRC3.  */ 
 603 bitset_or_and (dst
, src1
, src2
, src3
) 
 609   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 610   return BITSET_OR_AND_ (dst
, src1
, src2
, src3
); 
 614 /* DST = (SRC1 & SRC2) | SRC3.  Return non-zero if 
 615    DST != (SRC1 & SRC2) | SRC3.  */ 
 617 bitset_and_or (dst
, src1
, src2
, src3
) 
 623   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 624   return BITSET_AND_OR_ (dst
, src1
, src2
, src3
); 
 628 /* DST = (SRC1 & ~SRC2) | SRC3.  Return non-zero if 
 629    DST != (SRC1 & ~SRC2) | SRC3.  */ 
 631 bitset_andn_or (dst
, src1
, src2
, src3
) 
 637   BITSET_CHECK4_ (dst
, src1
, src2
, src3
); 
 638   return BITSET_ANDN_OR_ (dst
, src1
, src2
, src3
); 
 642 /* Dump bitset BSET to FILE.  */ 
 644 bitset_dump (file
, bset
) 
 648   bitset_print (file
, bset
, 0); 
 652 /* Function to be called from debugger to print bitset.  */ 
 658     bitset_print (stderr
, bset
, 1); 
 662 /* Release memory associated with bitsets.  */ 
 664 bitset_release_memory () 
 666   lbitset_release_memory (); 
 667   ebitset_release_memory (); 
 673 bitset_list (bset
, list
, num
, next
) 
 681   count 
= BITSET_LIST_ (bset
, list
, num
, next
); 
 688       enum bitset_type type
; 
 690       type 
= BITSET_TYPE_ (bset
); 
 691       BITSET_STATS_LISTS_INC (bset
); 
 693       /* Log histogram of number of set bits.  */ 
 694       for (i 
= 0, tmp 
= count
; tmp
; tmp 
>>= 1, i
++) 
 696       if (i 
>= BITSET_LOG_COUNT_BINS
) 
 697         i 
= BITSET_LOG_COUNT_BINS 
- 1; 
 698       BITSET_STATS_LIST_COUNTS_INC (bset
, i
); 
 700       /* Log histogram of number of bits in set.  */ 
 701       size 
= bitset_size (bset
); 
 702       for (i 
= 0, tmp 
= size
; tmp
; tmp 
>>= 1, i
++) 
 704       if (i 
>= BITSET_LOG_SIZE_BINS
) 
 705         i 
= BITSET_LOG_SIZE_BINS 
- 1; 
 706       BITSET_STATS_LIST_SIZES_INC (bset
, i
); 
 708       /* Histogram of fraction of bits set.  */ 
 709       i 
= size 
? (count 
* BITSET_DENSITY_BINS
) / size 
: 0; 
 710       if (i 
>= BITSET_DENSITY_BINS
) 
 711         i 
= BITSET_DENSITY_BINS 
- 1; 
 712       BITSET_STATS_LIST_DENSITY_INC (bset
, i
); 
 718 /* Print a percentage histogram with message MSG to FILE.  */ 
 720 bitset_percent_histogram_print (file
, name
, msg
, n_bins
, bins
) 
 731   for (i 
= 0; i 
< n_bins
; i
++) 
 737   fprintf (file
, "%s %s", name
, msg
); 
 738   for (i 
= 0; i 
< n_bins
; i
++) 
 739     fprintf (file
, "%.0f-%.0f%%\t%8d (%5.1f%%)\n", 
 741              (i 
+ 1) * 100.0 / n_bins
, bins
[i
], 
 742              (100.0 * bins
[i
]) / total
); 
 746 /* Print a log histogram with message MSG to FILE.  */ 
 748 bitset_log_histogram_print (file
, name
, msg
, n_bins
, bins
) 
 757   unsigned int max_width
; 
 760   for (i 
= 0; i 
< n_bins
; i
++) 
 766   /* 2 * ceil (log10(2) * (N - 1)) + 1  */ 
 767   max_width 
= 2 * (unsigned int) (0.30103 * (n_bins 
- 1) + 0.9999) + 1; 
 769   fprintf (file
, "%s %s", name
, msg
); 
 770   for (i 
= 0; i 
< 2; i
++) 
 771     fprintf (file
, "%*d\t%8d (%5.1f%%)\n", 
 772              max_width
, i
, bins
[i
], 100.0 * bins
[i
] / total
); 
 774   /* Perhaps we should bail out once the histogram goes to zero.  */ 
 775   for (; i 
< n_bins
; i
++) 
 776     fprintf (file
, "%*d-%d\t%8d (%5.1f%%)\n", 
 777              max_width 
- ((unsigned int) (0.30103 * (i
) + 0.9999) + 1), 
 778              1 << (i 
- 1), (1 << i
) - 1, bins
[i
], 
 779              (100.0 * bins
[i
]) / total
); 
 783 /* Print bitset statistics to FILE.  */ 
 785 bitset_stats_print_1 (file
, name
, stats
) 
 788      struct bitset_type_stats_struct 
*stats
; 
 793   fprintf (file
, "%d %ss xmalloced, %d freed.\n", 
 794            stats
->xmallocs
, name
, stats
->xfrees
); 
 795   fprintf (file
, "%d %ss oballoced, %d freed.\n", 
 796            stats
->oballocs
, name
, stats
->obfrees
); 
 798   fprintf (file
, "%d bitset_lists\n", stats
->lists
); 
 800   bitset_log_histogram_print (file
, name
, "count log histogram\n", 
 801                               BITSET_LOG_COUNT_BINS
, stats
->list_counts
); 
 803   bitset_log_histogram_print (file
, name
, "size log histogram\n", 
 804                               BITSET_LOG_SIZE_BINS
, stats
->list_sizes
); 
 806   bitset_percent_histogram_print (file
, name
, "density histogram\n", 
 807                                   BITSET_DENSITY_BINS
, stats
->list_density
); 
 811 /* Print all bitset statistics to FILE.  */ 
 813 bitset_stats_print (file
, verbose
) 
 815      int verbose ATTRIBUTE_UNUSED
; 
 818   static const char *names
[] = BITSET_TYPE_NAMES
; 
 823   fprintf (file
, "Bitset statistics:\n\n"); 
 825   if (bitset_stats
->runs 
> 1) 
 826     fprintf (file
, "Accumulated runs = %d\n", bitset_stats
->runs
); 
 828   for (i 
= 0; i 
< BITSET_TYPE_NUM
; i
++) 
 829     bitset_stats_print_1 (file
, names
[i
], &bitset_stats
->types
[i
]); 
 831 #endif /* BITSET_STATS  */ 
 834 /* Initialise bitset statistics logging.  */ 
 839   bitset_stats 
= &bitset_stats_data
; 
 840   bitset_stats_read (); 
 841 #endif /* BITSET_STATS  */ 
 845 /* Read bitset statistics file.  */ 
 854   file 
= fopen (BITSET_STATS_FILE
, "r"); 
 857       if (fread (&bitset_stats_data
, sizeof (bitset_stats_data
), 
 861             perror ("Could not read stats file."); 
 863             fprintf (stderr
, "Bad stats file size.\n"); 
 867   bitset_stats_data
.runs
++; 
 871 /* Write bitset statistics file.  */ 
 873 bitset_stats_write () 
 880   file 
= fopen (BITSET_STATS_FILE
, "w"); 
 883       if (fwrite (&bitset_stats_data
, sizeof (bitset_stats_data
), 
 885         perror ("Could not write stats file."); 
 889     perror ("Could not open stats file for writing."); 
 893 /* Dump bitset statistics to FILE.  */ 
 895 bitset_stats_dump (file
) 
 899   bitset_stats_print (file
, 0); 
 900   bitset_stats_write (); 
 901 #endif /* BITSET_STATS  */ 
 905 /* Function to be called from debugger to print bitset stats.  */ 
 907 debug_bitset_stats (void) 
 910   bitset_stats_print (stderr
, 1); 
 911 #endif /* BITSET_STATS  */