blob: 62b26ccf3f51e794aadd70319a9929d455ba7fb3 [file] [log] [blame]
Guido van Rossumb6957e41993-10-27 09:27:13 +00001#
2# this is a rather strict implementation of a bit vector class
3# it is accessed the same way as an array of python-ints, except
4# the value must be 0 or 1
5#
6
7import sys; rprt = sys.stderr.write #for debugging
8
Benjamin Petersond7b03282008-09-13 15:58:53 +00009class error(Exception):
10 pass
Guido van Rossumb6957e41993-10-27 09:27:13 +000011
12
13def _check_value(value):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000014 if type(value) != type(0) or not 0 <= value < 2:
Collin Winter6f2df4d2007-07-17 20:59:35 +000015 raise error('bitvec() items must have int value 0 or 1')
Guido van Rossumb6957e41993-10-27 09:27:13 +000016
17
18import math
19
20def _compute_len(param):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000021 mant, l = math.frexp(float(param))
Collin Winter6f2df4d2007-07-17 20:59:35 +000022 bitmask = 1 << l
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000023 if bitmask <= param:
Collin Winter3cd65372007-08-30 17:37:22 +000024 raise ValueError('(param, l) = %r' % ((param, l),))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000025 while l:
26 bitmask = bitmask >> 1
27 if param & bitmask:
28 break
29 l = l - 1
30 return l
Guido van Rossumb6957e41993-10-27 09:27:13 +000031
32
33def _check_key(len, key):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000034 if type(key) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +000035 raise TypeError('sequence subscript not int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000036 if key < 0:
37 key = key + len
38 if not 0 <= key < len:
Collin Winter6f2df4d2007-07-17 20:59:35 +000039 raise IndexError('list index out of range')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000040 return key
Guido van Rossumb6957e41993-10-27 09:27:13 +000041
42def _check_slice(len, i, j):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000043 #the type is ok, Python already checked that
44 i, j = max(i, 0), min(len, j)
45 if i > j:
46 i = j
47 return i, j
48
Guido van Rossumb6957e41993-10-27 09:27:13 +000049
50class BitVec:
51
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000052 def __init__(self, *params):
Collin Winter6f2df4d2007-07-17 20:59:35 +000053 self._data = 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000054 self._len = 0
55 if not len(params):
56 pass
57 elif len(params) == 1:
58 param, = params
59 if type(param) == type([]):
Collin Winter6f2df4d2007-07-17 20:59:35 +000060 value = 0
61 bit_mask = 1
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000062 for item in param:
63 # strict check
64 #_check_value(item)
65 if item:
66 value = value | bit_mask
67 bit_mask = bit_mask << 1
68 self._data = value
69 self._len = len(param)
Collin Winter6f2df4d2007-07-17 20:59:35 +000070 elif type(param) == type(0):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000071 if param < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000072 raise error('bitvec() can\'t handle negative longs')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000073 self._data = param
74 self._len = _compute_len(param)
75 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000076 raise error('bitvec() requires array or long parameter')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000077 elif len(params) == 2:
78 param, length = params
Collin Winter6f2df4d2007-07-17 20:59:35 +000079 if type(param) == type(0):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000080 if param < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000081 raise error('can\'t handle negative longs')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000082 self._data = param
83 if type(length) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +000084 raise error('bitvec()\'s 2nd parameter must be int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000085 computed_length = _compute_len(param)
86 if computed_length > length:
Collin Winter6f2df4d2007-07-17 20:59:35 +000087 print('warning: bitvec() value is longer than the length indicates, truncating value')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000088 self._data = self._data & \
Collin Winter6f2df4d2007-07-17 20:59:35 +000089 ((1 << length) - 1)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000090 self._len = length
91 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000092 raise error('bitvec() requires array or long parameter')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000093 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000094 raise error('bitvec() requires 0 -- 2 parameter(s)')
Guido van Rossumb6957e41993-10-27 09:27:13 +000095
96
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000097 def append(self, item):
98 #_check_value(item)
99 #self[self._len:self._len] = [item]
100 self[self._len:self._len] = \
Collin Winter6f2df4d2007-07-17 20:59:35 +0000101 BitVec(int(not not item), 1)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000102
103
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000104 def count(self, value):
105 #_check_value(value)
106 if value:
107 data = self._data
108 else:
109 data = (~self)._data
110 count = 0
111 while data:
112 data, count = data >> 1, count + (data & 1 != 0)
113 return count
Guido van Rossumb6957e41993-10-27 09:27:13 +0000114
115
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000116 def index(self, value):
117 #_check_value(value):
118 if value:
119 data = self._data
120 else:
121 data = (~self)._data
122 index = 0
123 if not data:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000124 raise ValueError('list.index(x): x not in list')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000125 while not (data & 1):
126 data, index = data >> 1, index + 1
127 return index
Guido van Rossumb6957e41993-10-27 09:27:13 +0000128
129
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000130 def insert(self, index, item):
131 #_check_value(item)
132 #self[index:index] = [item]
Collin Winter6f2df4d2007-07-17 20:59:35 +0000133 self[index:index] = BitVec(int(not not item), 1)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000134
135
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000136 def remove(self, value):
137 del self[self.index(value)]
Guido van Rossumb6957e41993-10-27 09:27:13 +0000138
139
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000140 def reverse(self):
141 #ouch, this one is expensive!
142 #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
Collin Winter6f2df4d2007-07-17 20:59:35 +0000143 data, result = self._data, 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000144 for i in range(self._len):
145 if not data:
146 result = result << (self._len - i)
147 break
148 result, data = (result << 1) | (data & 1), data >> 1
149 self._data = result
Guido van Rossumb6957e41993-10-27 09:27:13 +0000150
151
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000152 def sort(self):
153 c = self.count(1)
Collin Winter6f2df4d2007-07-17 20:59:35 +0000154 self._data = ((1 << c) - 1) << (self._len - c)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000155
156
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000157 def copy(self):
158 return BitVec(self._data, self._len)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000159
160
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000161 def seq(self):
162 result = []
163 for i in self:
164 result.append(i)
165 return result
Guido van Rossumb6957e41993-10-27 09:27:13 +0000166
Guido van Rossumb6957e41993-10-27 09:27:13 +0000167
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000168 def __repr__(self):
169 ##rprt('<bitvec class instance object>.' + '__repr__()\n')
Walter Dörwald70a6b492004-02-12 17:35:32 +0000170 return 'bitvec(%r, %r)' % (self._data, self._len)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000171
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000172 def __cmp__(self, other, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000173 #rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000174 if type(other) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000175 other = bitvec(other, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000176 #expensive solution... recursive binary, with slicing
177 length = self._len
178 if length == 0 or other._len == 0:
179 return cmp(length, other._len)
180 if length != other._len:
181 min_length = min(length, other._len)
182 return cmp(self[:min_length], other[:min_length]) or \
183 cmp(self[min_length:], other[min_length:])
184 #the lengths are the same now...
185 if self._data == other._data:
186 return 0
187 if length == 1:
188 return cmp(self[0], other[0])
189 else:
190 length = length >> 1
191 return cmp(self[:length], other[:length]) or \
192 cmp(self[length:], other[length:])
Guido van Rossumb6957e41993-10-27 09:27:13 +0000193
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000194
195 def __len__(self):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000196 #rprt('%r.__len__()\n' % (self,))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000197 return self._len
198
199 def __getitem__(self, key):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000200 #rprt('%r.__getitem__(%r)\n' % (self, key))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000201 key = _check_key(self._len, key)
Collin Winter6f2df4d2007-07-17 20:59:35 +0000202 return self._data & (1 << key) != 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000203
204 def __setitem__(self, key, value):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000205 #rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000206 key = _check_key(self._len, key)
207 #_check_value(value)
208 if value:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000209 self._data = self._data | (1 << key)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000210 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000211 self._data = self._data & ~(1 << key)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000212
213 def __delitem__(self, key):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000214 #rprt('%r.__delitem__(%r)\n' % (self, key))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000215 key = _check_key(self._len, key)
216 #el cheapo solution...
217 self._data = self[:key]._data | self[key+1:]._data >> key
218 self._len = self._len - 1
219
220 def __getslice__(self, i, j):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000221 #rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000222 i, j = _check_slice(self._len, i, j)
223 if i >= j:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000224 return BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000225 if i:
226 ndata = self._data >> i
227 else:
228 ndata = self._data
229 nlength = j - i
230 if j != self._len:
231 #we'll have to invent faster variants here
232 #e.g. mod_2exp
Collin Winter6f2df4d2007-07-17 20:59:35 +0000233 ndata = ndata & ((1 << nlength) - 1)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000234 return BitVec(ndata, nlength)
235
236 def __setslice__(self, i, j, sequence, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000237 #rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000238 i, j = _check_slice(self._len, i, j)
239 if type(sequence) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000240 sequence = bitvec(sequence, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000241 #sequence is now of our own type
242 ls_part = self[:i]
243 ms_part = self[j:]
244 self._data = ls_part._data | \
245 ((sequence._data | \
246 (ms_part._data << sequence._len)) << ls_part._len)
247 self._len = self._len - j + i + sequence._len
248
249 def __delslice__(self, i, j):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000250 #rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000251 i, j = _check_slice(self._len, i, j)
252 if i == 0 and j == self._len:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000253 self._data, self._len = 0, 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000254 elif i < j:
255 self._data = self[:i]._data | (self[j:]._data >> i)
256 self._len = self._len - j + i
257
258 def __add__(self, other):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000259 #rprt('%r.__add__(%r)\n' % (self, other))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000260 retval = self.copy()
261 retval[self._len:self._len] = other
262 return retval
263
264 def __mul__(self, multiplier):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000265 #rprt('%r.__mul__(%r)\n' % (self, multiplier))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000266 if type(multiplier) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000267 raise TypeError('sequence subscript not int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000268 if multiplier <= 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000269 return BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000270 elif multiplier == 1:
271 return self.copy()
272 #handle special cases all 0 or all 1...
Collin Winter6f2df4d2007-07-17 20:59:35 +0000273 if self._data == 0:
274 return BitVec(0, self._len * multiplier)
275 elif (~self)._data == 0:
276 return ~BitVec(0, self._len * multiplier)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000277 #otherwise el cheapo again...
Collin Winter6f2df4d2007-07-17 20:59:35 +0000278 retval = BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000279 while multiplier:
280 retval, multiplier = retval + self, multiplier - 1
281 return retval
282
283 def __and__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000284 #rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000285 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000286 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000287 #sequence is now of our own type
288 return BitVec(self._data & otherseq._data, \
289 min(self._len, otherseq._len))
290
291
292 def __xor__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000293 #rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000294 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000295 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000296 #sequence is now of our own type
297 return BitVec(self._data ^ otherseq._data, \
298 max(self._len, otherseq._len))
299
300
301 def __or__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000302 #rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000303 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000304 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000305 #sequence is now of our own type
306 return BitVec(self._data | otherseq._data, \
307 max(self._len, otherseq._len))
308
309
310 def __invert__(self):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000311 #rprt('%r.__invert__()\n' % (self,))
Collin Winter6f2df4d2007-07-17 20:59:35 +0000312 return BitVec(~self._data & ((1 << self._len) - 1), \
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000313 self._len)
314
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000315 def __int__(self):
316 return int(self._data)
317
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000318 def __float__(self):
319 return float(self._data)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000320
321
Guido van Rossum7565b931993-12-17 14:23:52 +0000322bitvec = BitVec