blob: 97921f24f819b85ec0cf4a19b75b46ef53c849fd [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
9error = 'bitvec.error'
10
11
12def _check_value(value):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000013 if type(value) != type(0) or not 0 <= value < 2:
Collin Winter6f2df4d2007-07-17 20:59:35 +000014 raise error('bitvec() items must have int value 0 or 1')
Guido van Rossumb6957e41993-10-27 09:27:13 +000015
16
17import math
18
19def _compute_len(param):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000020 mant, l = math.frexp(float(param))
Collin Winter6f2df4d2007-07-17 20:59:35 +000021 bitmask = 1 << l
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000022 if bitmask <= param:
Walter Dörwald70a6b492004-02-12 17:35:32 +000023 raise 'FATAL', '(param, l) = %r' % ((param, l),)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000024 while l:
25 bitmask = bitmask >> 1
26 if param & bitmask:
27 break
28 l = l - 1
29 return l
Guido van Rossumb6957e41993-10-27 09:27:13 +000030
31
32def _check_key(len, key):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000033 if type(key) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +000034 raise TypeError('sequence subscript not int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000035 if key < 0:
36 key = key + len
37 if not 0 <= key < len:
Collin Winter6f2df4d2007-07-17 20:59:35 +000038 raise IndexError('list index out of range')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000039 return key
Guido van Rossumb6957e41993-10-27 09:27:13 +000040
41def _check_slice(len, i, j):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000042 #the type is ok, Python already checked that
43 i, j = max(i, 0), min(len, j)
44 if i > j:
45 i = j
46 return i, j
47
Guido van Rossumb6957e41993-10-27 09:27:13 +000048
49class BitVec:
50
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000051 def __init__(self, *params):
Collin Winter6f2df4d2007-07-17 20:59:35 +000052 self._data = 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000053 self._len = 0
54 if not len(params):
55 pass
56 elif len(params) == 1:
57 param, = params
58 if type(param) == type([]):
Collin Winter6f2df4d2007-07-17 20:59:35 +000059 value = 0
60 bit_mask = 1
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000061 for item in param:
62 # strict check
63 #_check_value(item)
64 if item:
65 value = value | bit_mask
66 bit_mask = bit_mask << 1
67 self._data = value
68 self._len = len(param)
Collin Winter6f2df4d2007-07-17 20:59:35 +000069 elif type(param) == type(0):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000070 if param < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000071 raise error('bitvec() can\'t handle negative longs')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000072 self._data = param
73 self._len = _compute_len(param)
74 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000075 raise error('bitvec() requires array or long parameter')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000076 elif len(params) == 2:
77 param, length = params
Collin Winter6f2df4d2007-07-17 20:59:35 +000078 if type(param) == type(0):
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000079 if param < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000080 raise error('can\'t handle negative longs')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000081 self._data = param
82 if type(length) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +000083 raise error('bitvec()\'s 2nd parameter must be int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000084 computed_length = _compute_len(param)
85 if computed_length > length:
Collin Winter6f2df4d2007-07-17 20:59:35 +000086 print('warning: bitvec() value is longer than the length indicates, truncating value')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000087 self._data = self._data & \
Collin Winter6f2df4d2007-07-17 20:59:35 +000088 ((1 << length) - 1)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000089 self._len = length
90 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000091 raise error('bitvec() requires array or long parameter')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000092 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +000093 raise error('bitvec() requires 0 -- 2 parameter(s)')
Guido van Rossumb6957e41993-10-27 09:27:13 +000094
95
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +000096 def append(self, item):
97 #_check_value(item)
98 #self[self._len:self._len] = [item]
99 self[self._len:self._len] = \
Collin Winter6f2df4d2007-07-17 20:59:35 +0000100 BitVec(int(not not item), 1)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000101
102
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000103 def count(self, value):
104 #_check_value(value)
105 if value:
106 data = self._data
107 else:
108 data = (~self)._data
109 count = 0
110 while data:
111 data, count = data >> 1, count + (data & 1 != 0)
112 return count
Guido van Rossumb6957e41993-10-27 09:27:13 +0000113
114
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000115 def index(self, value):
116 #_check_value(value):
117 if value:
118 data = self._data
119 else:
120 data = (~self)._data
121 index = 0
122 if not data:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000123 raise ValueError('list.index(x): x not in list')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000124 while not (data & 1):
125 data, index = data >> 1, index + 1
126 return index
Guido van Rossumb6957e41993-10-27 09:27:13 +0000127
128
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000129 def insert(self, index, item):
130 #_check_value(item)
131 #self[index:index] = [item]
Collin Winter6f2df4d2007-07-17 20:59:35 +0000132 self[index:index] = BitVec(int(not not item), 1)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000133
134
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000135 def remove(self, value):
136 del self[self.index(value)]
Guido van Rossumb6957e41993-10-27 09:27:13 +0000137
138
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000139 def reverse(self):
140 #ouch, this one is expensive!
141 #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
Collin Winter6f2df4d2007-07-17 20:59:35 +0000142 data, result = self._data, 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000143 for i in range(self._len):
144 if not data:
145 result = result << (self._len - i)
146 break
147 result, data = (result << 1) | (data & 1), data >> 1
148 self._data = result
Guido van Rossumb6957e41993-10-27 09:27:13 +0000149
150
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000151 def sort(self):
152 c = self.count(1)
Collin Winter6f2df4d2007-07-17 20:59:35 +0000153 self._data = ((1 << c) - 1) << (self._len - c)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000154
155
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000156 def copy(self):
157 return BitVec(self._data, self._len)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000158
159
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000160 def seq(self):
161 result = []
162 for i in self:
163 result.append(i)
164 return result
Guido van Rossumb6957e41993-10-27 09:27:13 +0000165
Guido van Rossumb6957e41993-10-27 09:27:13 +0000166
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000167 def __repr__(self):
168 ##rprt('<bitvec class instance object>.' + '__repr__()\n')
Walter Dörwald70a6b492004-02-12 17:35:32 +0000169 return 'bitvec(%r, %r)' % (self._data, self._len)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000170
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000171 def __cmp__(self, other, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000172 #rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000173 if type(other) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000174 other = bitvec(other, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000175 #expensive solution... recursive binary, with slicing
176 length = self._len
177 if length == 0 or other._len == 0:
178 return cmp(length, other._len)
179 if length != other._len:
180 min_length = min(length, other._len)
181 return cmp(self[:min_length], other[:min_length]) or \
182 cmp(self[min_length:], other[min_length:])
183 #the lengths are the same now...
184 if self._data == other._data:
185 return 0
186 if length == 1:
187 return cmp(self[0], other[0])
188 else:
189 length = length >> 1
190 return cmp(self[:length], other[:length]) or \
191 cmp(self[length:], other[length:])
Guido van Rossumb6957e41993-10-27 09:27:13 +0000192
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000193
194 def __len__(self):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000195 #rprt('%r.__len__()\n' % (self,))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000196 return self._len
197
198 def __getitem__(self, key):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000199 #rprt('%r.__getitem__(%r)\n' % (self, key))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000200 key = _check_key(self._len, key)
Collin Winter6f2df4d2007-07-17 20:59:35 +0000201 return self._data & (1 << key) != 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000202
203 def __setitem__(self, key, value):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000204 #rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000205 key = _check_key(self._len, key)
206 #_check_value(value)
207 if value:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000208 self._data = self._data | (1 << key)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000209 else:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000210 self._data = self._data & ~(1 << key)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000211
212 def __delitem__(self, key):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000213 #rprt('%r.__delitem__(%r)\n' % (self, key))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000214 key = _check_key(self._len, key)
215 #el cheapo solution...
216 self._data = self[:key]._data | self[key+1:]._data >> key
217 self._len = self._len - 1
218
219 def __getslice__(self, i, j):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000220 #rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000221 i, j = _check_slice(self._len, i, j)
222 if i >= j:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000223 return BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000224 if i:
225 ndata = self._data >> i
226 else:
227 ndata = self._data
228 nlength = j - i
229 if j != self._len:
230 #we'll have to invent faster variants here
231 #e.g. mod_2exp
Collin Winter6f2df4d2007-07-17 20:59:35 +0000232 ndata = ndata & ((1 << nlength) - 1)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000233 return BitVec(ndata, nlength)
234
235 def __setslice__(self, i, j, sequence, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000236 #rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000237 i, j = _check_slice(self._len, i, j)
238 if type(sequence) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000239 sequence = bitvec(sequence, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000240 #sequence is now of our own type
241 ls_part = self[:i]
242 ms_part = self[j:]
243 self._data = ls_part._data | \
244 ((sequence._data | \
245 (ms_part._data << sequence._len)) << ls_part._len)
246 self._len = self._len - j + i + sequence._len
247
248 def __delslice__(self, i, j):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000249 #rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000250 i, j = _check_slice(self._len, i, j)
251 if i == 0 and j == self._len:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000252 self._data, self._len = 0, 0
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000253 elif i < j:
254 self._data = self[:i]._data | (self[j:]._data >> i)
255 self._len = self._len - j + i
256
257 def __add__(self, other):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000258 #rprt('%r.__add__(%r)\n' % (self, other))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000259 retval = self.copy()
260 retval[self._len:self._len] = other
261 return retval
262
263 def __mul__(self, multiplier):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000264 #rprt('%r.__mul__(%r)\n' % (self, multiplier))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000265 if type(multiplier) != type(0):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000266 raise TypeError('sequence subscript not int')
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000267 if multiplier <= 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000268 return BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000269 elif multiplier == 1:
270 return self.copy()
271 #handle special cases all 0 or all 1...
Collin Winter6f2df4d2007-07-17 20:59:35 +0000272 if self._data == 0:
273 return BitVec(0, self._len * multiplier)
274 elif (~self)._data == 0:
275 return ~BitVec(0, self._len * multiplier)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000276 #otherwise el cheapo again...
Collin Winter6f2df4d2007-07-17 20:59:35 +0000277 retval = BitVec(0, 0)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000278 while multiplier:
279 retval, multiplier = retval + self, multiplier - 1
280 return retval
281
282 def __and__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000283 #rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000284 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000285 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000286 #sequence is now of our own type
287 return BitVec(self._data & otherseq._data, \
288 min(self._len, otherseq._len))
289
290
291 def __xor__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000292 #rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000293 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000294 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000295 #sequence is now of our own type
296 return BitVec(self._data ^ otherseq._data, \
297 max(self._len, otherseq._len))
298
299
300 def __or__(self, otherseq, *rest):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000301 #rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000302 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000303 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000304 #sequence is now of our own type
305 return BitVec(self._data | otherseq._data, \
306 max(self._len, otherseq._len))
307
308
309 def __invert__(self):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000310 #rprt('%r.__invert__()\n' % (self,))
Collin Winter6f2df4d2007-07-17 20:59:35 +0000311 return BitVec(~self._data & ((1 << self._len) - 1), \
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000312 self._len)
313
314 def __coerce__(self, otherseq, *rest):
315 #needed for *some* of the arithmetic operations
Walter Dörwald70a6b492004-02-12 17:35:32 +0000316 #rprt('%r.__coerce__%r\n' % (self, (otherseq,) + rest))
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000317 if type(otherseq) != type(self):
Neal Norwitzd9108552006-03-17 08:00:19 +0000318 otherseq = bitvec(otherseq, *rest)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000319 return self, otherseq
320
321 def __int__(self):
322 return int(self._data)
323
324 def __long__(self):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000325 return int(self._data)
Andrew M. Kuchling946c53e2003-04-24 17:13:18 +0000326
327 def __float__(self):
328 return float(self._data)
Guido van Rossumb6957e41993-10-27 09:27:13 +0000329
330
Guido van Rossum7565b931993-12-17 14:23:52 +0000331bitvec = BitVec