1993-10-27 06:27:13 -03:00
|
|
|
#
|
|
|
|
# this is a rather strict implementation of a bit vector class
|
|
|
|
# it is accessed the same way as an array of python-ints, except
|
|
|
|
# the value must be 0 or 1
|
|
|
|
#
|
|
|
|
|
|
|
|
import sys; rprt = sys.stderr.write #for debugging
|
|
|
|
|
Merged revisions 66394,66404,66412,66414,66424-66436 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r66394 | benjamin.peterson | 2008-09-11 17:04:02 -0500 (Thu, 11 Sep 2008) | 1 line
fix typo
........
r66404 | gerhard.haering | 2008-09-12 08:54:06 -0500 (Fri, 12 Sep 2008) | 2 lines
sqlite3 module: Mark iterdump() method as "Non-standard" like all the other methods not found in DB-API.
........
r66412 | gerhard.haering | 2008-09-12 13:58:57 -0500 (Fri, 12 Sep 2008) | 2 lines
Fixes issue #3103. In the sqlite3 module, made one more function static. All renaming public symbos now have the pysqlite prefix to avoid name clashes. This at least once created problems where the same symbol name appeared somewhere in Apache and the sqlite3 module was used from mod_python.
........
r66414 | gerhard.haering | 2008-09-12 17:33:22 -0500 (Fri, 12 Sep 2008) | 2 lines
Issue #3846: Release GIL during calls to sqlite3_prepare. This improves concurrent access to the same database file from multiple threads/processes.
........
r66424 | andrew.kuchling | 2008-09-12 20:22:08 -0500 (Fri, 12 Sep 2008) | 1 line
#687648 from Robert Schuppenies: use classic division. (RM Barry gave permission to update the demos.)
........
r66425 | andrew.kuchling | 2008-09-12 20:27:33 -0500 (Fri, 12 Sep 2008) | 1 line
#687648 from Robert Schuppenies: use classic division. From me: don't use string exception; flush stdout after printing
........
r66426 | andrew.kuchling | 2008-09-12 20:34:41 -0500 (Fri, 12 Sep 2008) | 1 line
#687648 from Robert Schuppenies: use classic division. From me: don't use string exception; add __main__ section
........
r66427 | andrew.kuchling | 2008-09-12 20:42:55 -0500 (Fri, 12 Sep 2008) | 1 line
#687648 from Robert Schuppenies: use classic division. From me: remove two stray semicolons
........
r66428 | andrew.kuchling | 2008-09-12 20:43:28 -0500 (Fri, 12 Sep 2008) | 1 line
#687648 from Robert Schuppenies: use classic division.
........
r66429 | andrew.kuchling | 2008-09-12 20:47:02 -0500 (Fri, 12 Sep 2008) | 1 line
Remove semicolon
........
r66430 | andrew.kuchling | 2008-09-12 20:48:36 -0500 (Fri, 12 Sep 2008) | 1 line
Subclass exception
........
r66431 | andrew.kuchling | 2008-09-12 20:56:56 -0500 (Fri, 12 Sep 2008) | 1 line
Fix SyntaxError
........
r66432 | andrew.kuchling | 2008-09-12 20:57:25 -0500 (Fri, 12 Sep 2008) | 1 line
Update uses of string exceptions
........
r66433 | andrew.kuchling | 2008-09-12 21:08:30 -0500 (Fri, 12 Sep 2008) | 1 line
Use title case
........
r66434 | andrew.kuchling | 2008-09-12 21:09:15 -0500 (Fri, 12 Sep 2008) | 1 line
Remove extra 'the'; the following title includes it
........
r66435 | andrew.kuchling | 2008-09-12 21:11:51 -0500 (Fri, 12 Sep 2008) | 1 line
#3288: Document as_integer_ratio
........
r66436 | andrew.kuchling | 2008-09-12 21:14:15 -0500 (Fri, 12 Sep 2008) | 1 line
Use title case
........
2008-09-13 12:58:53 -03:00
|
|
|
class error(Exception):
|
|
|
|
pass
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
|
|
|
|
def _check_value(value):
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(value) != type(0) or not 0 <= value < 2:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec() items must have int value 0 or 1')
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
|
|
|
|
import math
|
|
|
|
|
|
|
|
def _compute_len(param):
|
2003-04-24 14:13:18 -03:00
|
|
|
mant, l = math.frexp(float(param))
|
2007-07-17 17:59:35 -03:00
|
|
|
bitmask = 1 << l
|
2003-04-24 14:13:18 -03:00
|
|
|
if bitmask <= param:
|
2007-08-30 14:37:22 -03:00
|
|
|
raise ValueError('(param, l) = %r' % ((param, l),))
|
2003-04-24 14:13:18 -03:00
|
|
|
while l:
|
|
|
|
bitmask = bitmask >> 1
|
|
|
|
if param & bitmask:
|
|
|
|
break
|
|
|
|
l = l - 1
|
|
|
|
return l
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
|
|
|
|
def _check_key(len, key):
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(key) != type(0):
|
2007-07-17 17:59:35 -03:00
|
|
|
raise TypeError('sequence subscript not int')
|
2003-04-24 14:13:18 -03:00
|
|
|
if key < 0:
|
|
|
|
key = key + len
|
|
|
|
if not 0 <= key < len:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise IndexError('list index out of range')
|
2003-04-24 14:13:18 -03:00
|
|
|
return key
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
def _check_slice(len, i, j):
|
2003-04-24 14:13:18 -03:00
|
|
|
#the type is ok, Python already checked that
|
|
|
|
i, j = max(i, 0), min(len, j)
|
|
|
|
if i > j:
|
|
|
|
i = j
|
|
|
|
return i, j
|
|
|
|
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
class BitVec:
|
|
|
|
|
2003-04-24 14:13:18 -03:00
|
|
|
def __init__(self, *params):
|
2007-07-17 17:59:35 -03:00
|
|
|
self._data = 0
|
2003-04-24 14:13:18 -03:00
|
|
|
self._len = 0
|
|
|
|
if not len(params):
|
|
|
|
pass
|
|
|
|
elif len(params) == 1:
|
|
|
|
param, = params
|
|
|
|
if type(param) == type([]):
|
2007-07-17 17:59:35 -03:00
|
|
|
value = 0
|
|
|
|
bit_mask = 1
|
2003-04-24 14:13:18 -03:00
|
|
|
for item in param:
|
|
|
|
# strict check
|
|
|
|
#_check_value(item)
|
|
|
|
if item:
|
|
|
|
value = value | bit_mask
|
|
|
|
bit_mask = bit_mask << 1
|
|
|
|
self._data = value
|
|
|
|
self._len = len(param)
|
2007-07-17 17:59:35 -03:00
|
|
|
elif type(param) == type(0):
|
2003-04-24 14:13:18 -03:00
|
|
|
if param < 0:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec() can\'t handle negative longs')
|
2003-04-24 14:13:18 -03:00
|
|
|
self._data = param
|
|
|
|
self._len = _compute_len(param)
|
|
|
|
else:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec() requires array or long parameter')
|
2003-04-24 14:13:18 -03:00
|
|
|
elif len(params) == 2:
|
|
|
|
param, length = params
|
2007-07-17 17:59:35 -03:00
|
|
|
if type(param) == type(0):
|
2003-04-24 14:13:18 -03:00
|
|
|
if param < 0:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('can\'t handle negative longs')
|
2003-04-24 14:13:18 -03:00
|
|
|
self._data = param
|
|
|
|
if type(length) != type(0):
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec()\'s 2nd parameter must be int')
|
2003-04-24 14:13:18 -03:00
|
|
|
computed_length = _compute_len(param)
|
|
|
|
if computed_length > length:
|
2007-07-17 17:59:35 -03:00
|
|
|
print('warning: bitvec() value is longer than the length indicates, truncating value')
|
2003-04-24 14:13:18 -03:00
|
|
|
self._data = self._data & \
|
2007-07-17 17:59:35 -03:00
|
|
|
((1 << length) - 1)
|
2003-04-24 14:13:18 -03:00
|
|
|
self._len = length
|
|
|
|
else:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec() requires array or long parameter')
|
2003-04-24 14:13:18 -03:00
|
|
|
else:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise error('bitvec() requires 0 -- 2 parameter(s)')
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
|
|
|
|
def append(self, item):
|
|
|
|
#_check_value(item)
|
|
|
|
#self[self._len:self._len] = [item]
|
|
|
|
self[self._len:self._len] = \
|
2007-07-17 17:59:35 -03:00
|
|
|
BitVec(int(not not item), 1)
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
|
|
|
|
def count(self, value):
|
|
|
|
#_check_value(value)
|
|
|
|
if value:
|
|
|
|
data = self._data
|
|
|
|
else:
|
|
|
|
data = (~self)._data
|
|
|
|
count = 0
|
|
|
|
while data:
|
|
|
|
data, count = data >> 1, count + (data & 1 != 0)
|
|
|
|
return count
|
|
|
|
|
|
|
|
|
|
|
|
def index(self, value):
|
|
|
|
#_check_value(value):
|
|
|
|
if value:
|
|
|
|
data = self._data
|
|
|
|
else:
|
|
|
|
data = (~self)._data
|
|
|
|
index = 0
|
|
|
|
if not data:
|
2007-07-17 17:59:35 -03:00
|
|
|
raise ValueError('list.index(x): x not in list')
|
2003-04-24 14:13:18 -03:00
|
|
|
while not (data & 1):
|
|
|
|
data, index = data >> 1, index + 1
|
|
|
|
return index
|
|
|
|
|
|
|
|
|
|
|
|
def insert(self, index, item):
|
|
|
|
#_check_value(item)
|
|
|
|
#self[index:index] = [item]
|
2007-07-17 17:59:35 -03:00
|
|
|
self[index:index] = BitVec(int(not not item), 1)
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
|
|
|
|
def remove(self, value):
|
|
|
|
del self[self.index(value)]
|
|
|
|
|
|
|
|
|
|
|
|
def reverse(self):
|
|
|
|
#ouch, this one is expensive!
|
|
|
|
#for i in self._len>>1: self[i], self[l-i] = self[l-i], self[i]
|
2007-07-17 17:59:35 -03:00
|
|
|
data, result = self._data, 0
|
2003-04-24 14:13:18 -03:00
|
|
|
for i in range(self._len):
|
|
|
|
if not data:
|
|
|
|
result = result << (self._len - i)
|
|
|
|
break
|
|
|
|
result, data = (result << 1) | (data & 1), data >> 1
|
|
|
|
self._data = result
|
|
|
|
|
|
|
|
|
|
|
|
def sort(self):
|
|
|
|
c = self.count(1)
|
2007-07-17 17:59:35 -03:00
|
|
|
self._data = ((1 << c) - 1) << (self._len - c)
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
|
|
|
|
def copy(self):
|
|
|
|
return BitVec(self._data, self._len)
|
|
|
|
|
|
|
|
|
|
|
|
def seq(self):
|
|
|
|
result = []
|
|
|
|
for i in self:
|
|
|
|
result.append(i)
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
##rprt('<bitvec class instance object>.' + '__repr__()\n')
|
2004-02-12 13:35:32 -04:00
|
|
|
return 'bitvec(%r, %r)' % (self._data, self._len)
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
def __cmp__(self, other, *rest):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__cmp__%r\n' % (self, (other,) + rest))
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(other) != type(self):
|
2006-03-17 04:00:19 -04:00
|
|
|
other = bitvec(other, *rest)
|
2003-04-24 14:13:18 -03:00
|
|
|
#expensive solution... recursive binary, with slicing
|
|
|
|
length = self._len
|
|
|
|
if length == 0 or other._len == 0:
|
|
|
|
return cmp(length, other._len)
|
|
|
|
if length != other._len:
|
|
|
|
min_length = min(length, other._len)
|
|
|
|
return cmp(self[:min_length], other[:min_length]) or \
|
|
|
|
cmp(self[min_length:], other[min_length:])
|
|
|
|
#the lengths are the same now...
|
|
|
|
if self._data == other._data:
|
|
|
|
return 0
|
|
|
|
if length == 1:
|
|
|
|
return cmp(self[0], other[0])
|
|
|
|
else:
|
|
|
|
length = length >> 1
|
|
|
|
return cmp(self[:length], other[:length]) or \
|
|
|
|
cmp(self[length:], other[length:])
|
|
|
|
|
|
|
|
|
|
|
|
def __len__(self):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__len__()\n' % (self,))
|
2003-04-24 14:13:18 -03:00
|
|
|
return self._len
|
|
|
|
|
|
|
|
def __getitem__(self, key):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__getitem__(%r)\n' % (self, key))
|
2003-04-24 14:13:18 -03:00
|
|
|
key = _check_key(self._len, key)
|
2007-07-17 17:59:35 -03:00
|
|
|
return self._data & (1 << key) != 0
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
def __setitem__(self, key, value):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__setitem__(%r, %r)\n' % (self, key, value))
|
2003-04-24 14:13:18 -03:00
|
|
|
key = _check_key(self._len, key)
|
|
|
|
#_check_value(value)
|
|
|
|
if value:
|
2007-07-17 17:59:35 -03:00
|
|
|
self._data = self._data | (1 << key)
|
2003-04-24 14:13:18 -03:00
|
|
|
else:
|
2007-07-17 17:59:35 -03:00
|
|
|
self._data = self._data & ~(1 << key)
|
2003-04-24 14:13:18 -03:00
|
|
|
|
|
|
|
def __delitem__(self, key):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__delitem__(%r)\n' % (self, key))
|
2003-04-24 14:13:18 -03:00
|
|
|
key = _check_key(self._len, key)
|
|
|
|
#el cheapo solution...
|
|
|
|
self._data = self[:key]._data | self[key+1:]._data >> key
|
|
|
|
self._len = self._len - 1
|
|
|
|
|
|
|
|
def __getslice__(self, i, j):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__getslice__(%r, %r)\n' % (self, i, j))
|
2003-04-24 14:13:18 -03:00
|
|
|
i, j = _check_slice(self._len, i, j)
|
|
|
|
if i >= j:
|
2007-07-17 17:59:35 -03:00
|
|
|
return BitVec(0, 0)
|
2003-04-24 14:13:18 -03:00
|
|
|
if i:
|
|
|
|
ndata = self._data >> i
|
|
|
|
else:
|
|
|
|
ndata = self._data
|
|
|
|
nlength = j - i
|
|
|
|
if j != self._len:
|
|
|
|
#we'll have to invent faster variants here
|
|
|
|
#e.g. mod_2exp
|
2007-07-17 17:59:35 -03:00
|
|
|
ndata = ndata & ((1 << nlength) - 1)
|
2003-04-24 14:13:18 -03:00
|
|
|
return BitVec(ndata, nlength)
|
|
|
|
|
|
|
|
def __setslice__(self, i, j, sequence, *rest):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%s.__setslice__%r\n' % (self, (i, j, sequence) + rest))
|
2003-04-24 14:13:18 -03:00
|
|
|
i, j = _check_slice(self._len, i, j)
|
|
|
|
if type(sequence) != type(self):
|
2006-03-17 04:00:19 -04:00
|
|
|
sequence = bitvec(sequence, *rest)
|
2003-04-24 14:13:18 -03:00
|
|
|
#sequence is now of our own type
|
|
|
|
ls_part = self[:i]
|
|
|
|
ms_part = self[j:]
|
|
|
|
self._data = ls_part._data | \
|
|
|
|
((sequence._data | \
|
|
|
|
(ms_part._data << sequence._len)) << ls_part._len)
|
|
|
|
self._len = self._len - j + i + sequence._len
|
|
|
|
|
|
|
|
def __delslice__(self, i, j):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__delslice__(%r, %r)\n' % (self, i, j))
|
2003-04-24 14:13:18 -03:00
|
|
|
i, j = _check_slice(self._len, i, j)
|
|
|
|
if i == 0 and j == self._len:
|
2007-07-17 17:59:35 -03:00
|
|
|
self._data, self._len = 0, 0
|
2003-04-24 14:13:18 -03:00
|
|
|
elif i < j:
|
|
|
|
self._data = self[:i]._data | (self[j:]._data >> i)
|
|
|
|
self._len = self._len - j + i
|
|
|
|
|
|
|
|
def __add__(self, other):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__add__(%r)\n' % (self, other))
|
2003-04-24 14:13:18 -03:00
|
|
|
retval = self.copy()
|
|
|
|
retval[self._len:self._len] = other
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def __mul__(self, multiplier):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__mul__(%r)\n' % (self, multiplier))
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(multiplier) != type(0):
|
2007-07-17 17:59:35 -03:00
|
|
|
raise TypeError('sequence subscript not int')
|
2003-04-24 14:13:18 -03:00
|
|
|
if multiplier <= 0:
|
2007-07-17 17:59:35 -03:00
|
|
|
return BitVec(0, 0)
|
2003-04-24 14:13:18 -03:00
|
|
|
elif multiplier == 1:
|
|
|
|
return self.copy()
|
|
|
|
#handle special cases all 0 or all 1...
|
2007-07-17 17:59:35 -03:00
|
|
|
if self._data == 0:
|
|
|
|
return BitVec(0, self._len * multiplier)
|
|
|
|
elif (~self)._data == 0:
|
|
|
|
return ~BitVec(0, self._len * multiplier)
|
2003-04-24 14:13:18 -03:00
|
|
|
#otherwise el cheapo again...
|
2007-07-17 17:59:35 -03:00
|
|
|
retval = BitVec(0, 0)
|
2003-04-24 14:13:18 -03:00
|
|
|
while multiplier:
|
|
|
|
retval, multiplier = retval + self, multiplier - 1
|
|
|
|
return retval
|
|
|
|
|
|
|
|
def __and__(self, otherseq, *rest):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__and__%r\n' % (self, (otherseq,) + rest))
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(otherseq) != type(self):
|
2006-03-17 04:00:19 -04:00
|
|
|
otherseq = bitvec(otherseq, *rest)
|
2003-04-24 14:13:18 -03:00
|
|
|
#sequence is now of our own type
|
|
|
|
return BitVec(self._data & otherseq._data, \
|
|
|
|
min(self._len, otherseq._len))
|
|
|
|
|
|
|
|
|
|
|
|
def __xor__(self, otherseq, *rest):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__xor__%r\n' % (self, (otherseq,) + rest))
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(otherseq) != type(self):
|
2006-03-17 04:00:19 -04:00
|
|
|
otherseq = bitvec(otherseq, *rest)
|
2003-04-24 14:13:18 -03:00
|
|
|
#sequence is now of our own type
|
|
|
|
return BitVec(self._data ^ otherseq._data, \
|
|
|
|
max(self._len, otherseq._len))
|
|
|
|
|
|
|
|
|
|
|
|
def __or__(self, otherseq, *rest):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__or__%r\n' % (self, (otherseq,) + rest))
|
2003-04-24 14:13:18 -03:00
|
|
|
if type(otherseq) != type(self):
|
2006-03-17 04:00:19 -04:00
|
|
|
otherseq = bitvec(otherseq, *rest)
|
2003-04-24 14:13:18 -03:00
|
|
|
#sequence is now of our own type
|
|
|
|
return BitVec(self._data | otherseq._data, \
|
|
|
|
max(self._len, otherseq._len))
|
|
|
|
|
|
|
|
|
|
|
|
def __invert__(self):
|
2004-02-12 13:35:32 -04:00
|
|
|
#rprt('%r.__invert__()\n' % (self,))
|
2007-07-17 17:59:35 -03:00
|
|
|
return BitVec(~self._data & ((1 << self._len) - 1), \
|
2003-04-24 14:13:18 -03:00
|
|
|
self._len)
|
|
|
|
|
|
|
|
def __int__(self):
|
|
|
|
return int(self._data)
|
|
|
|
|
|
|
|
def __float__(self):
|
|
|
|
return float(self._data)
|
1993-10-27 06:27:13 -03:00
|
|
|
|
|
|
|
|
1993-12-17 10:23:52 -04:00
|
|
|
bitvec = BitVec
|