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
7 import sys
; rprt
= sys
.stderr
.write
#for debugging
12 def _check_value(value
):
13 if type(value
) != type(0) or not 0 <= value
< 2:
14 raise error
, 'bitvec() items must have int value 0 or 1'
19 def _compute_len(param
):
20 mant
, l
= math
.frexp(float(param
))
23 raise 'FATAL', '(param, l) = ' + `param
, l`
25 bitmask
= bitmask
>> 1
32 def _check_key(len, key
):
33 if type(key
) != type(0):
34 raise TypeError, 'sequence subscript not int'
37 if not 0 <= key
< len:
38 raise IndexError, 'list index out of range'
41 def _check_slice(len, i
, j
):
42 #the type is ok, Python already checked that
43 i
, j
= max(i
, 0), min(len, j
)
51 def __init__(self
, *params
):
56 elif len(params
) == 1:
58 if type(param
) == type([]):
65 value
= value | bit_mask
66 bit_mask
= bit_mask
<< 1
68 self
._len
= len(param
)
69 elif type(param
) == type(0L):
71 raise error
, 'bitvec() can\'t handle negative longs'
73 self
._len
= _compute_len(param
)
75 raise error
, 'bitvec() requires array or long parameter'
76 elif len(params
) == 2:
77 param
, length
= params
78 if type(param
) == type(0L):
81 'can\'t handle negative longs'
83 if type(length
) != type(0):
84 raise error
, 'bitvec()\'s 2nd parameter must be int'
85 computed_length
= _compute_len(param
)
86 if computed_length
> length
:
87 print 'warning: bitvec() value is longer than the length indicates, truncating value'
88 self
._data
= self
._data
& \
92 raise error
, 'bitvec() requires array or long parameter'
94 raise error
, 'bitvec() requires 0 -- 2 parameter(s)'
97 def append(self
, item
):
99 #self[self._len:self._len] = [item]
100 self
[self
._len
:self
._len
] = \
101 BitVec(long(not not item
), 1)
104 def count(self
, value
):
112 data
, count
= data
>> 1, count
+ (data
& 1 != 0)
116 def index(self
, value
):
117 #_check_value(value):
124 raise ValueError, 'list.index(x): x not in list'
125 while not (data
& 1):
126 data
, index
= data
>> 1, index
+ 1
130 def insert(self
, index
, item
):
132 #self[index:index] = [item]
133 self
[index
:index
] = BitVec(long(not not item
), 1)
136 def remove(self
, value
):
137 del self
[self
.index(value
)]
141 #ouch, this one is expensive!
142 #for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
143 data
, result
= self
._data
, 0L
144 for i
in range(self
._len
):
146 result
= result
<< (self
._len
- i
)
148 result
, data
= (result
<< 1) |
(data
& 1), data
>> 1
154 self
._data
= ((1L << c
) - 1) << (self
._len
- c
)
158 return BitVec(self
._data
, self
._len
)
169 ##rprt('<bitvec class instance object>.' + '__repr__()\n')
170 return 'bitvec' + `self
._data
, self
._len`
172 def __cmp__(self
, other
, *rest
):
173 #rprt(`self`+'.__cmp__'+`(other, ) + rest`+'\n')
174 if type(other
) != type(self
):
175 other
= apply(bitvec
, (other
, ) + rest
)
176 #expensive solution... recursive binary, with slicing
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
:
188 return cmp(self
[0], other
[0])
191 return cmp(self
[:length
], other
[:length
]) or \
192 cmp(self
[length
:], other
[length
:])
196 #rprt(`self`+'.__len__()\n')
199 def __getitem__(self
, key
):
200 #rprt(`self`+'.__getitem__('+`key`+')\n')
201 key
= _check_key(self
._len
, key
)
202 return self
._data
& (1L << key
) != 0
204 def __setitem__(self
, key
, value
):
205 #rprt(`self`+'.__setitem__'+`key, value`+'\n')
206 key
= _check_key(self
._len
, key
)
209 self
._data
= self
._data |
(1L << key
)
211 self
._data
= self
._data
& ~
(1L << key
)
213 def __delitem__(self
, key
):
214 #rprt(`self`+'.__delitem__('+`key`+')\n')
215 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
220 def __getslice__(self
, i
, j
):
221 #rprt(`self`+'.__getslice__'+`i, j`+'\n')
222 i
, j
= _check_slice(self
._len
, i
, j
)
226 ndata
= self
._data
>> i
231 #we'll have to invent faster variants here
233 ndata
= ndata
& ((1L << nlength
) - 1)
234 return BitVec(ndata
, nlength
)
236 def __setslice__(self
, i
, j
, sequence
, *rest
):
237 #rprt(`self`+'.__setslice__'+`(i, j, sequence) + rest`+'\n')
238 i
, j
= _check_slice(self
._len
, i
, j
)
239 if type(sequence
) != type(self
):
240 sequence
= apply(bitvec
, (sequence
, ) + rest
)
241 #sequence is now of our own type
244 self
._data
= ls_part
._data | \
246 (ms_part
._data
<< sequence
._len
)) << ls_part
._len
)
247 self
._len
= self
._len
- j
+ i
+ sequence
._len
249 def __delslice__(self
, i
, j
):
250 #rprt(`self`+'.__delslice__'+`i, j`+'\n')
251 i
, j
= _check_slice(self
._len
, i
, j
)
252 if i
== 0 and j
== self
._len
:
253 self
._data
, self
._len
= 0L, 0
255 self
._data
= self
[:i
]._data |
(self
[j
:]._data
>> i
)
256 self
._len
= self
._len
- j
+ i
258 def __add__(self
, other
):
259 #rprt(`self`+'.__add__('+`other`+')\n')
261 retval
[self
._len
:self
._len
] = other
264 def __mul__(self
, multiplier
):
265 #rprt(`self`+'.__mul__('+`multiplier`+')\n')
266 if type(multiplier
) != type(0):
267 raise TypeError, 'sequence subscript not int'
270 elif multiplier
== 1:
272 #handle special cases all 0 or all 1...
274 return BitVec(0L, self
._len
* multiplier
)
275 elif (~self
)._data
== 0L:
276 return ~
BitVec(0L, self
._len
* multiplier
)
277 #otherwise el cheapo again...
278 retval
= BitVec(0L, 0)
280 retval
, multiplier
= retval
+ self
, multiplier
- 1
283 def __and__(self
, otherseq
, *rest
):
284 #rprt(`self`+'.__and__'+`(otherseq, ) + rest`+'\n')
285 if type(otherseq
) != type(self
):
286 otherseq
= apply(bitvec
, (otherseq
, ) + rest
)
287 #sequence is now of our own type
288 return BitVec(self
._data
& otherseq
._data
, \
289 min(self
._len
, otherseq
._len
))
292 def __xor__(self
, otherseq
, *rest
):
293 #rprt(`self`+'.__xor__'+`(otherseq, ) + rest`+'\n')
294 if type(otherseq
) != type(self
):
295 otherseq
= apply(bitvec
, (otherseq
, ) + rest
)
296 #sequence is now of our own type
297 return BitVec(self
._data ^ otherseq
._data
, \
298 max(self
._len
, otherseq
._len
))
301 def __or__(self
, otherseq
, *rest
):
302 #rprt(`self`+'.__or__'+`(otherseq, ) + rest`+'\n')
303 if type(otherseq
) != type(self
):
304 otherseq
= apply(bitvec
, (otherseq
, ) + rest
)
305 #sequence is now of our own type
306 return BitVec(self
._data | otherseq
._data
, \
307 max(self
._len
, otherseq
._len
))
310 def __invert__(self
):
311 #rprt(`self`+'.__invert__()\n')
312 return BitVec(~self
._data
& ((1L << self
._len
) - 1), \
315 def __coerce__(self
, otherseq
, *rest
):
316 #needed for *some* of the arithmetic operations
317 #rprt(`self`+'.__coerce__'+`(otherseq, ) + rest`+'\n')
318 if type(otherseq
) != type(self
):
319 otherseq
= apply(bitvec
, (otherseq
, ) + rest
)
320 return self
, otherseq
323 return int(self
._data
)
326 return long(self
._data
)
329 return float(self
._data
)