def __init__(self, numbers: List[int]): """Initialize a new EliasFano data structure for given monotone sequence. numbers:List[int], sequence to convert into an EliasFano data structure. """ self._size = ceil(log2(max(numbers) / len(numbers))) superiors, inferiors = list( zip(*[divmod(n, 1 << self._size) for n in numbers])) self._inferiors = "".join( [f"{{0:0{self._size}b}}".format(n) for n in inferiors]) self._superiors = "".join([ inverted_unary(n - superiors[i - 1] if i else n) for i, n in enumerate(superiors) ])
def test_inverted_unary(): tests = { 0: "1", # 0 -> 0 1: "01", # 1 -> 10 2: "001", # 10 -> 110 3: "0001", # 11 -> 1110 4: "00001", # 100 -> 11110 5: "000001", # 101 -> 111110 11: "000000000001", # 1011 -> 111111111110 } for n, u in tests.items(): assert u == inverted_unary(n)
def test_is_prefix_code(): positive = [[unary(i) for i in range(100)], [inverted_unary(i) for i in range(100)], [minimal_binary_coding(i, 100) for i in range(100)], [gamma_coding(i) for i in range(100)], [delta_coding(i) for i in range(100)], [omega_coding(i) for i in range(1, 100)], [levenshtein_coding(i) for i in range(100)], [nibble_coding(i) for i in range(100)], [byte_coding(i) for i in range(100)], [golomb_coding(i, 5) for i in range(100)]] negative = [ interpolative_coding(list(range(0, 100)), 0, 100), [reduced_binary_coding(i) for i in range(100)] ] assert all([is_prefix_code(p) for p in positive]) assert not any([is_prefix_code(n) for n in negative])
def gamma_coding(n: int) -> str: """Return string representing given number in gamma coding. n:int, number to convert to unary. """ rbc = reduced_binary_coding(n) return inverted_unary(len(rbc)) + rbc
def golomb_coding(n: int, b: int) -> str: """Return string representing given number in golomb coding. n:int, number to convert to golomb coding. b:int, module. """ return inverted_unary(n // b) + minimal_binary_coding(n % b, b)