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)
|
Download
Copy to clipboard
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.