library to store n bits data (n > 0) in a python array
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 | class nBitArray() :
m = 32
f = 'I'
_default_type = None
def __init__(self, n_bit) :
if not (isinstance(n_bit, int) and n_bit > 0) :
raise ValueError
self.n_bit = n_bit
self.n_item = 0
self.b_mask = (2 ** self.n_bit) - 1
self.i_mask = ((0x1 << self.m) - 1)
def _normalize_index(self, index) :
if (-1 * self.n_item) <= index < 0 :
index += self.n_item
if 0 <= index < self.n_item :
return index
raise IndexError
def __getitem__(self, index):
if isinstance(index, int) :
return self._get_at(self._normalize_index(index))
elif isinstance(index, slice) :
return (self._get_at(i) for i in range(* index.indices(self.n_item)))
else:
raise TypeError("index must be int or slice")
def __str__(self) :
u = io.StringIO()
for n, i in enumerate(self._data) :
u.write("{0:08X}".format(i))
u.write('\n' if (n + 1) % 6 == 0 else ' ')
return u.getvalue()
def load_data(self, value_lst) :
""" load a list of n_bit words """
w_curs = 0 # position in the word
word = 0
stack = list()
for n, value in enumerate(value_lst) :
value = value & self.b_mask
v_curs = 0 # position in the value
v_count = self.n_bit - v_curs # number of remaining bits to be written
w_count = self.m - w_curs # number of bits available in the word
while v_count > 0 :
if w_count <= v_count :
p = value >> (v_count - w_count)
word |= p & self.i_mask
v_curs += w_count
w_curs += w_count
else :
p = value << (w_count - v_count)
word |= p & self.i_mask
v_curs += v_count
w_curs += v_count
if w_curs == self.m :
stack.append(word)
word = 0
w_curs = 0
v_count = self.n_bit - v_curs
w_count = self.m - w_curs
if word :
stack.append(word)
self.n_item = len(value_lst)
self._data = array.array(self.f, stack)
return self
def _get_at(self, v_index) :
if not 0 <= v_index < self.n_item :
raise IndexError
b = v_index * self.n_bit
i_index = b // self.m # index of the word
#print(v_index, b, i_index)
v_curs = 0 # position in the value
w_curs = b % self.m # position in the word
v_count = self.n_bit - v_curs # number of remaining bits to append to the value
w_count = self.m - w_curs # number of remaining bits to be read from the word
value = 0
while v_count > 0 :
#print("v curs={0}, count={1} - w curs={2}, count={3}".format(v_curs, v_count, w_curs, w_count))
if w_count <= v_count :
value = (value << self.m) | self._data[i_index]
#print("IF -> value = {0:05X}".format(value & self.b_mask))
v_curs += w_count
w_curs += w_count
else :
value = (value << v_count) | (self._data[i_index] >> (w_count - v_count))
#print("ELSE -> value = {0:05X}".format(value & self.b_mask))
v_curs += v_count
w_curs += v_count
if w_curs == self.m :
i_index += 1
w_curs = 0
v_count = self.n_bit - v_curs
w_count = self.m - w_curs
return value & self.b_mask
if __name__ == '__main__' :
high_res_sinus = [int(math.sin(i) * 0x3FFFFF) & 0x3FFFFF for i in range(10000)]
low_res_sinus = [int(math.sin(i) * 0x3) & 0x3FFFFF for i in range(10000)]
def do(array, name, size) :
data = nBitArray(size).load_data(array)._data.tobytes()
compressed = gzip.compress(data)
print("{3}:{4} bits: {0} -> {1} ({2:0.1f} %)".format(
len(data), len(compressed), 100 * len(compressed) / len(data), name, size)
)
do(high_res_sinus, "high_res_sinus", 22)
do(high_res_sinus, "high_res_sinus", 24)
do(low_res_sinus, "low_res_sinus", 22)
do(low_res_sinus, "low_res_sinus", 24)
|
Your code is indented with tab characters which is interpreted as every eight columns on many systems. For this reason it better to always use space characters and tab by 4 as PEP 8 - Style Guide for Python Code recommends.
So I suggest you edit your recipe and fix the indenting.