2019-06-26 15:26:19 +03:00

230 lines
6.3 KiB
Python

from bitset import bitset
from range import *
import math
# Define the number of trits, quints and bits used for an encoded range, this
# table is indexed by N-1 where N is the number of elements in a range.
TRITS_QUINTS_BITS_TABLE = \
[
(0, 0, 1), # RANGE_2
(1, 0, 0), # RANGE_3
(0, 0, 2), # RANGE_4
(0, 1, 0), # RANGE_5
(1, 0, 1), # RANGE_6
(0, 0, 3), # RANGE_8
(0, 1, 1), # RANGE_10
(1, 0, 2), # RANGE_12
(0, 0, 4), # RANGE_16
(0, 1, 2), # RANGE_20
(1, 0, 3), # RANGE_24
(0, 0, 5), # RANGE_32
(0, 1, 3), # RANGE_40
(1, 0, 4), # RANGE_48
(0, 0, 6), # RANGE_64
(0, 1, 4), # RANGE_80
(1, 0, 5), # RANGE_96
(0, 0, 7), # RANGE_128
(0, 1, 5), # RANGE_160
(1, 0, 6), # RANGE_192
(0, 0, 8) # RANGE_256
]
def bits_bise_bitcount(items, bits):
"""
Compute the number of bits needed for regular binary encoding.
"""
assert items > 0 and bits > 0
return items * bits
def trits_bise_bitcount(items, bits):
"""
Compute the number of bits needed for trit-based encoding.
"""
assert items > 0 and bits >= 0
#return math.ceil((8.0 + 5.0*bits) * items / 5.0)
return math.ceil(8.0*items / 5.0 + bits*items)
def quints_bise_bitcount(items, bits):
"""
Compute the number of bits needed for quint-based encoding.
"""
assert items > 0 and bits >= 0
#return math.ceil((7.0 + 3.0*bits) * items / 3.0)
return math.ceil(7.0*items / 3.0 + bits*items)
def compute_bise_bitcount(items, quant):
"""
Compute the number of bits needed for the BISE stream.
"""
assert type(items) is int
assert type(quant) is int
assert items > 0
assert quant >= RANGE_2 and quant <= RANGE_256
trits, quints, bits = TRITS_QUINTS_BITS_TABLE[quant]
if trits == 0 and quints == 0:
return bits_bise_bitcount(items, bits)
elif trits != 0:
return trits_bise_bitcount(items, bits)
elif quints != 0:
return quints_bise_bitcount(items, bits)
else:
assert False
def last_index(lst, a):
last = -1
for i in range(len(lst)):
if a == lst[i]:
last = i
if last == -1:
raise ValueError("%s is not in the list" % repr(a))
return last
# From ASTC specification, decode the a encoded set of 5 trits.
def decode_trits(T):
assert isinstance(T, bitset)
assert T.size() == 8
t4 = -1
t3 = -1
t2 = -1
t1 = -1
C = bitset(5, 0)
if T.substr(4, 2) == bitset(3, 0b111):
C.set(4, T.get(7))
C.set(3, T.get(6))
C.set(2, T.get(5))
C.set(1, T.get(1))
C.set(0, T.get(0))
t4 = 2
t3 = 2
else:
C = T.substr(4, 0)
if T.substr(6, 5) == bitset(2, 0b11):
t4 = 2
t3 = T.get(7)
else:
t4 = T.get(7)
t3 = T.substr(6, 5).number()
if C.substr(1, 0) == bitset(2, 0b11):
t2 = 2
t1 = C.get(4)
t0 = bitset.from_args(C.get(3), C.get(2) & (not C.get(3))).number()
elif C.substr(3, 2) == bitset(2, 0b11):
t2 = 2
t1 = 2
t0 = C.substr(1, 0).number()
else:
t2 = C.get(4)
t1 = C.substr(3, 2).number()
t0 = bitset.from_args(C.get(1), C.get(0) & (not C.get(1))).number()
assert t4 >= 0 and t4 <= 2, t4
assert t3 >= 0 and t3 <= 2, t3
assert t2 >= 0 and t2 <= 2, t2
assert t1 >= 0 and t1 <= 2, t1
assert t0 >= 0 and t0 <= 2, t0
return (t0, t1, t2, t3, t4)
# From ASTC specification, decode a encoded set of 3 quints.
def decode_quints(Q):
assert Q.size() == 7
q2 = -1
q1 = -1
q0 = -1
if Q.substr(2, 1) == bitset(2, 0b11) and Q.substr(6, 5) == bitset(2, 0b00):
q2 = bitset.from_args(
Q.get(0), Q.get(4) & (not Q.get(0)), Q.get(3) & (not Q.get(0))).number()
q1 = 4
q0 = 4
else:
C = None
if Q.substr(2, 1) == bitset(2, 0b11):
q2 = 4
C = bitset.from_args(
Q.get(4),
Q.get(3),
not Q.get(6),
not Q.get(5),
Q.get(0))
else:
q2 = Q.substr(6, 5).number()
C = Q.substr(4, 0)
if C.substr(2, 0) == bitset(3, 0b101):
q1 = 4
q0 = C.substr(4, 3).number()
else:
q1 = C.substr(4, 3).number()
q0 = C.substr(2, 0).number()
assert q2 >= 0 and q2 <= 4, q2
assert q1 >= 0 and q1 <= 4, q1
assert q0 >= 0 and q0 <= 4, q0
return (q0, q1, q2)
# Generate table for trit decoding for all possible 8 bit numbers, [0, 255].
def trits_from_integer_table():
return [decode_trits(bitset(8, i)) for i in range(256)]
# Generate table for trit decoding by brute force searching the encoding table.
# Exhaustive search solution works because the search space is small.
def integer_from_trits_table(trits):
return \
[
[
[
[
[
last_index(trits, (t0, t1, t2, t3, t4))
for t0 in range(3)
]
for t1 in range(3)
]
for t2 in range(3)
]
for t3 in range(3)
]
for t4 in range(3)
]
# Generate table for quint encoding for all possible 7 bit numbers, [0, 127].
def quints_from_integer_table():
return [decode_quints(bitset(7, i)) for i in range(128)]
# Generate table for quint decoding by brute force searching the encoding
# table. Exhaustive search solution works because the search space is small.
def integer_from_quints_table(quints):
return \
[
[
[
last_index(quints, (q0, q1, q2))
for q0 in range(5)
]
for q1 in range(5)
]
for q2 in range(5)
]
if __name__ == "__main__":
trits_from_integer = trits_from_integer_table()
integer_from_trits = integer_from_trits_table(trits_from_integer)
quints_from_integer = quints_from_integer_table()
integer_from_quints = integer_from_quints_table(quints_from_integer)
print(trits_from_integer)
print(integer_from_trits)
print(quints_from_integer)
print(integer_from_quints)