0

do block state unpacking with numpy slices, not loops

For posterity, my testbench used to make sure this implementation
yields identical results:

https://gist.github.com/agrif/a34efb8e0b534f0309415c9af4872a69
This commit is contained in:
Aaron Griffith
2019-02-21 19:52:23 -05:00
parent b70f1a012f
commit 28f924621b

View File

@@ -961,91 +961,66 @@ class RegionSet(object):
if bits_per_value < 4 or 12 < bits_per_value: if bits_per_value < 4 or 12 < bits_per_value:
raise nbt.CorruptChunkError() raise nbt.CorruptChunkError()
b = numpy.frombuffer(numpy.asarray(long_array, dtype=numpy.uint64), dtype=numpy.uint8) b = numpy.frombuffer(numpy.asarray(long_array, dtype=numpy.uint64), dtype=numpy.uint8)
# give room for work, later
b = b.astype(numpy.uint16)
if bits_per_value == 8: if bits_per_value == 8:
result = b.astype(numpy.uint16) return b
else:
result = [] result = numpy.zeros((n,), dtype=numpy.uint16)
i = 0 if bits_per_value == 4:
# We will consume the byte array in chunks equal to bits_per_value. result[0::2] = b & 0x0f
while i < len(b): result[1::2] = (b & 0xf0) >> 4
if bits_per_value == 4: elif bits_per_value == 5:
for k in range(0, 4): result[0::8] = b[0::5] & 0x1f
result.extend([ result[1::8] = ((b[1::5] & 0x03) << 3) | ((b[0::5] & 0xe0) >> 5)
b[i + k] & 0x0f, result[2::8] = (b[1::5] & 0x7c) >> 2
(b[i + k] & 0xf0) >> 4, result[3::8] = ((b[2::5] & 0x0f) << 1) | ((b[1::5] & 0x80) >> 7)
]) result[4::8] = ((b[3::5] & 0x01) << 4) | ((b[2::5] & 0xf0) >> 4)
i += 4 result[5::8] = (b[3::5] & 0x3e) >> 1
elif bits_per_value == 5: result[6::8] = ((b[4::5] & 0x07) << 2) | ((b[3::5] & 0xc0) >> 6)
result.extend([ result[7::8] = (b[4::5] & 0xf8) >> 3
b[i] & 0x1f, elif bits_per_value == 6:
((b[i+1] & 0x03) << 3) | ((b[i] & 0xe0) >> 5), result[0::4] = b[0::3] & 0x3f
(b[i+1] & 0x7c) >> 2, result[1::4] = ((b[1::3] & 0x0f) << 2) | ((b[0::3] & 0xc0) >> 6)
((b[i+2] & 0x0f) << 1) | ((b[i+1] & 0x80) >> 7), result[2::4] = ((b[2::3] & 0x03) << 4) | ((b[1::3] & 0xf0) >> 4)
((b[i+3] & 0x01) << 4) | ((b[i+2] & 0xf0) >> 4), result[3::4] = (b[2::3] & 0xfc) >> 2
(b[i+3] & 0x3e) >> 1, elif bits_per_value == 7:
((b[i+4] & 0x07) << 2) | ((b[i+3] & 0xc0) >> 6), result[0::8] = b[0::7] & 0x7f
(b[i+4] & 0xf8) >> 3, result[1::8] = ((b[1::7] & 0x3f) << 1) | ((b[0::7] & 0x80) >> 7)
]) result[2::8] = ((b[2::7] & 0x1f) << 2) | ((b[1::7] & 0xc0) >> 6)
i += 5 result[3::8] = ((b[3::7] & 0x0f) << 3) | ((b[2::7] & 0xe0) >> 5)
elif bits_per_value == 6: result[4::8] = ((b[4::7] & 0x07) << 4) | ((b[3::7] & 0xf0) >> 4)
result.extend([ result[5::8] = ((b[5::7] & 0x03) << 5) | ((b[4::7] & 0xf8) >> 3)
b[i] & 0x3f, result[6::8] = ((b[6::7] & 0x01) << 6) | ((b[5::7] & 0xfc) >> 2)
((b[i+1] & 0x0f) << 2) | ((b[i] & 0xc0) >> 6), result[7::8] = (b[6::7] & 0xfc) >> 1
((b[i+2] & 0x03) << 4) | ((b[i+1] & 0xf0) >> 4), # bits_per_value == 8 is handled above
(b[i+2] & 0xfc) >> 2, elif bits_per_value == 9:
]) result[0::8] = ((b[1::9] & 0x01) << 8) | b[0::9]
i += 3 result[1::8] = ((b[2::9] & 0x03) << 7) | ((b[1::9] & 0xfe) >> 1)
elif bits_per_value == 7: result[2::8] = ((b[3::9] & 0x07) << 6) | ((b[2::9] & 0xfc) >> 2)
result.extend([ result[3::8] = ((b[4::9] & 0x0f) << 5) | ((b[3::9] & 0xf8) >> 3)
b[i] & 0x7f, result[4::8] = ((b[5::9] & 0x1f) << 4) | ((b[4::9] & 0xf0) >> 4)
((b[i+1] & 0x3f) << 1) | ((b[i] & 0x80) >> 7), result[5::8] = ((b[6::9] & 0x3f) << 3) | ((b[5::9] & 0xe0) >> 5)
((b[i+2] & 0x1f) << 2) | ((b[i+1] & 0xc0) >> 6), result[6::8] = ((b[7::9] & 0x7f) << 2) | ((b[6::9] & 0xc0) >> 6)
((b[i+3] & 0x0f) << 3) | ((b[i+2] & 0xe0) >> 5), result[7::8] = ( b[8::9] << 1) | ((b[7::9] & 0x80) >> 7)
((b[i+4] & 0x07) << 4) | ((b[i+3] & 0xf0) >> 4), elif bits_per_value == 10:
((b[i+5] & 0x03) << 5) | ((b[i+4] & 0xf8) >> 3), result[0::4] = ((b[1::5] & 0x03) << 8) | b[0::5]
((b[i+6] & 0x01) << 6) | ((b[i+5] & 0xfc) >> 2), result[1::4] = ((b[2::5] & 0x0f) << 6) | ((b[1::5] & 0xfc) >> 2)
(b[i+6] & 0xfc) >> 1, result[2::4] = ((b[3::5] & 0x3f) << 4) | ((b[2::5] & 0xf0) >> 4)
]) result[3::4] = ( b[4::5] << 2) | ((b[3::5] & 0xc0) >> 6)
i += 7 elif bits_per_value == 11:
elif bits_per_value == 9: result[0::8] = ((b[ 1::11] & 0x07) << 8 ) | b[ 0::11]
result.extend([ result[1::8] = ((b[ 2::11] & 0x3f) << 5 ) | ((b[ 1::11] & 0xf8) >> 3 )
((b[i+1] & 0x01) << 8) | b[i], result[2::8] = ((b[ 4::11] & 0x01) << 10) | ( b[ 3::11] << 2 ) | ((b[ 2::11] & 0xc0) >> 6 )
((b[i+2] & 0x03) << 7) | ((b[i+1] & 0xfe) >> 1), result[3::8] = ((b[ 5::11] & 0x0f) << 7 ) | ((b[ 4::11] & 0xfe) >> 1 )
((b[i+3] & 0x07) << 6) | ((b[i+2] & 0xfc) >> 2), result[4::8] = ((b[ 6::11] & 0x7f) << 4 ) | ((b[ 5::11] & 0xf0) >> 4 )
((b[i+4] & 0x0f) << 5) | ((b[i+3] & 0xf8) >> 3), result[5::8] = ((b[ 8::11] & 0x03) << 9 ) | ( b[ 7::11] << 1 ) | ((b[ 6::11] & 0x80) >> 7 )
((b[i+5] & 0x1f) << 4) | ((b[i+4] & 0xf0) >> 4), result[6::8] = ((b[ 9::11] & 0x1f) << 2 ) | ((b[ 8::11] & 0xfc) >> 2 )
((b[i+6] & 0x3f) << 3) | ((b[i+5] & 0xe0) >> 5), result[7::8] = ( b[10::11] << 3 ) | ((b[ 9::11] & 0xe0) >> 5 )
((b[i+7] & 0x7f) << 2) | ((b[i+6] & 0xc0) >> 6), elif bits_per_value == 12:
(b[i+8] << 1) | ((b[i+7] & 0x80) >> 7), result[0::2] = ((b[1::3] & 0x0f) << 8) | b[0::3]
]) result[1::2] = ( b[2::3] << 4) | ((b[1::3] & 0xf0) >> 4)
i += 9
elif bits_per_value == 10:
result.extend([
((b[i+1] & 0x03) << 8) | b[i],
((b[i+2] & 0x0f) << 6) | ((b[i+1] & 0xfc) >> 2),
((b[i+3] & 0x3f) << 4) | ((b[i+2] & 0xf0) >> 4),
(b[i+4] << 2) | ((b[i+3] & 0xc0) >> 6),
])
i += 5
elif bits_per_value == 11:
result.extend([
((b[i+1] & 0x07) << 8) | b[i],
((b[i+2] & 0x3f) << 5) | ((b[i+1] & 0xf8) >> 3),
((b[i+4] & 0x01) << 10)| (b[i+3] << 2) | ((b[i+2] & 0xc0) >> 6),
((b[i+5] & 0x0f) << 7) | ((b[i+4] & 0xfe) >> 1),
((b[i+6] & 0x7f) << 4) | ((b[i+5] & 0xf0) >> 4),
((b[i+8] & 0x03) << 9) | (b[i+7] << 1) | ((b[i+6] & 0x80) >> 7),
((b[i+9] & 0x1f) << 2) | ((b[i+8] & 0xfc) >> 2),
(b[i+10] << 3) | ((b[i+9] & 0xe0) >> 5),
])
i += 11
elif bits_per_value == 12:
result.extend([
((b[i+1] & 0x0f) << 8) | b[i],
(b[i+2] << 4) | ((b[i+1] & 0xf0) >> 4),
])
i += 3
result = numpy.asarray(result, numpy.uint16)
return result return result
def _get_blockdata_v113(self, section, unrecognized_block_types): def _get_blockdata_v113(self, section, unrecognized_block_types):