11ビット整数のパックされたストリームを表すbytesオブジェクトまたはbytearrayオブジェクトがあります。 (編集:ストリームはパディングなしの11ビットビッグエンディアン整数です)11ビット整数を含むbytearrayを16ビット整数の配列にキャストする
これを16ビット整数のストリームにコピーする方法はありますか?または他の整数型?
私はctypesがビットフィールドをサポートしていることを知っていますが、これが私にはまったく役立つかどうかはわかりません。
他の目的のために既にこのようなビットバイディングを行っている標準ライブラリの一部を "乱用"できますか?
私はcythonに頼らなければならない場合は、可変ビット長に対応できる良い実装がありますか?私。 11ビット入力だけでなく、12,13などの入力も可能です。
編集:PM2リングの回答に基づいてピュアPythonのソリューション
def unpackIntegers(data, num_points, bit_len):
"""Unpacks an array of integers of arbitrary bit-length into a
system-word aligned array of integers"""
# TODO: deal with native integer types separately for speedups
mask = (1 << bit_len) - 1
unpacked_bit_len = 2 ** ceil(log(bit_len, 2))
unpacked_byte_len = ceil(unpacked_bit_len/8)
unpacked_array = bytearray(num_points * unpacked_byte_len)
unpacked = memoryview(unpacked_array).cast(
FORMAT_CODES[unpacked_byte_len])
num_blocks = num_points // 8
# Note: zipping generators is faster than calculating offsets
# from a block count
for idx1_start, idx1_stop, idx2_start, idx2_stop in zip(
range(0, num_blocks*bit_len, bit_len),
range(bit_len, (num_blocks+1)*bit_len, bit_len),
range(7, num_points, 8),
range(-1, num_points-8, 8),
):
n = int.from_bytes(data[idx1_start:idx1_stop], 'big')
for i in range(idx2_start, idx2_stop, -1):
unpacked[i] = n & mask
n >>= bit_len
# process left-over part (missing from PM2 Ring's answer)
else:
points_left = num_points % 8
bits_left = points_left * bit_len
bytes_left = len(data)-num_blocks*bit_len
num_unused_bits = bytes_left * 8 - bits_left
n = int.from_bytes(data[num_blocks*bit_len:], 'big')
n >>= num_unused_bits
for i in range(num_points-1, num_points-points_left-1, -1):
unpacked[i] = n & mask
n >>= bit_len
return unpacked