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