File: BitVector.h

package info (click to toggle)
lbt 1.2.2-7
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 188 kB
  • sloc: cpp: 910; ansic: 102; makefile: 46; sh: 2
file content (191 lines) | stat: -rw-r--r-- 5,551 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// -*- c++ -*-
/// @file BitVector.h
/*
 *  Copyright  2001 Marko Mkel <msmakela@tcs.hut.fi>
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#ifndef BITVECTOR_H_
# define BITVECTOR_H_
# ifdef __GNUC__
#  pragma interface
# endif // __GNUC__

# include <limits.h>
# include <string.h>

/** Binary digit (bit) vector */
class BitVector
{
public:
  /** machine word */
  typedef unsigned long word_t;

  /** Constructor
   * @param size	number of elements in the vector
   */
  explicit BitVector (unsigned size = 0) :
    m_size (0), m_allocated (1), m_bits (new word_t[1]) {
    *m_bits = 0;
    setSize (size);
  }
  /** Copy constructor */
  explicit BitVector (const class BitVector& old) :
    m_size (old.m_size), m_allocated (old.m_allocated), m_bits (0) {
    memcpy (m_bits = new word_t[m_allocated], old.m_bits,
	    m_allocated * sizeof (word_t));
  }
private:
  /** Assignment operator */
  class BitVector& operator= (const class BitVector& old);
public:
  /** Destructor */
  ~BitVector () { delete[] m_bits; }

  /** Equality comparison
   * @param other	other bit vector to compare this against
   * @return		true if the bit vectors are identical,
   *			treating missing bits as unset
   */
  bool operator== (const class BitVector& other) const {
    unsigned tsize = getNumWords (m_size), osize = getNumWords (other.m_size);
    if (tsize < osize) {
      if (memcmp (m_bits, other.m_bits, tsize * sizeof (word_t)))
	return false;
      for (register const word_t* bits = other.m_bits + osize;
	   bits-- > other.m_bits + tsize; )
	if (*bits)
	  return false;
    }
    else {
      if (memcmp (m_bits, other.m_bits, osize * sizeof (word_t)))
	return false;
      for (register const word_t* bits = m_bits + tsize;
	   bits-- > m_bits + osize; )
	if (*bits)
	  return false;
    }
    return true;
  }

  /** Determine the number of words the specified amount of bits occupy */
  static unsigned getNumWords (unsigned bits) {
    const unsigned bitsPerWord = CHAR_BIT * sizeof (word_t);
    return (bits + bitsPerWord - 1) / bitsPerWord;
  }

  /** Set the size of the vector
   * @param size	the new size of the vector
   */
  void setSize (unsigned size) {
    const unsigned numWords = getNumWords (size);
    if (m_allocated < numWords) {
      while (m_allocated < numWords)
	m_allocated <<= 1;
      word_t* bits = new word_t[m_allocated];
      const unsigned init = getNumWords (m_size);
      memcpy (bits, m_bits, init * sizeof *m_bits);
      memset (bits + init, 0, (m_allocated - init) * sizeof *m_bits);
      delete[] m_bits;
      m_bits = bits;
    }
    m_size = size;
  }
  /** Determine the size of the vector
   * @return	the size of the vector
   */
  unsigned getSize () const { return m_size; }

  /** Read a binary digit
   * @param i	zero-based index of the element
   * @return	value of the ternary digit
   */
  bool operator[] (unsigned i) const {
    return i < m_size &&
      m_bits[i / (CHAR_BIT * sizeof (word_t))] &
      (word_t (1) << (i % (CHAR_BIT * sizeof (word_t))));
  }

  /** Set a binary digit
   * @param i	zero-based index of the element
   */
  void assign_true (unsigned i) {
    if (i >= m_size)
      setSize (i + 1);
    m_bits[i / (CHAR_BIT * sizeof (word_t))] |=
      word_t (1) << (i % (CHAR_BIT * sizeof (word_t)));
  }

  /** Clear a binary digit
   * @param i	zero-based index of the element
   */
  void assign_false (unsigned i) {
    m_bits[i / (CHAR_BIT * sizeof (word_t))] &=
      ~(word_t (1) << (i % (CHAR_BIT * sizeof (word_t))));
  }

  /** Determine whether the whole vector is filled with zero bits
   * @return	0 if all bits in the vector are clear;
   *		index of a nonzero entry + 1 otherwise
   */
  unsigned nonzero () const {
    if (!m_size)
      return 0;
    return findNext (0);
  }

  /** Find the next index at which there is a set bit
   * @param i	the starting index (counting forward)
   * @return	0 if all following bits in the vector are clear;
   *		index of the next nonzero entry + 1 otherwise
   */
  unsigned findNext (unsigned i) const {
    if (i >= m_size)
      return 0;

    register const word_t* w = &m_bits[i / (CHAR_BIT * sizeof (word_t))];
    register word_t bit = 1 << (i % (CHAR_BIT * sizeof (word_t)));

    if (*w >= bit) {
      // found in the same word
      do
	if (*w & bit)
	  return i + 1;
      while (i++, bit <<= 1);
    }

    const word_t* const w_end = m_bits + getNumWords (m_size);

    // search in the remaining words
    while (++w < w_end) {
      if (!*w) continue;
      for (i = 1, bit = 1; !(*w & bit); bit <<= 1, i++);
      return i + (w - m_bits) * CHAR_BIT * sizeof (word_t);
    }

    return 0;
  }

private:
  /** Number of elements in the vector */
  unsigned m_size;
  /** Size of the allocated vector in words */
  unsigned m_allocated;
  /** The vector */
  word_t* m_bits;
};

#endif // BITVECTOR_H_