41 lines
1.1 KiB
Python
41 lines
1.1 KiB
Python
import math
|
|
|
|
class BhashException(Exception): pass
|
|
|
|
class Bhash:
|
|
"""
|
|
Hash manipulation class.
|
|
|
|
The hash is internally treated as a big-endinan integer. This allows for
|
|
easy implementation of operations such as modulo.
|
|
|
|
Note: The consumed bits are calculated using math.log() so the exact number
|
|
may be inprecise.
|
|
"""
|
|
def __init__(self):
|
|
self.bhash = None
|
|
self.bits_avail = 0
|
|
self.bits_used = 0.0
|
|
|
|
def from_bytes(self, buf: bytes):
|
|
"""
|
|
Initialize a Bhash from a bytes object
|
|
"""
|
|
self.bhash = int.from_bytes(buf, byteorder='big')
|
|
self.bits_avail = len(buf) * 8
|
|
self.bits_used = 0.0
|
|
|
|
def modulo(self, mod: int) -> int:
|
|
"""
|
|
Treat the hash as a bigint and divide it by mod. The hash is updated
|
|
with the division result while the module value is returned.
|
|
"""
|
|
self.bits_used += math.log(mod) / math.log(2)
|
|
if self.bits_used > self.bits_avail:
|
|
raise BhashException("Consumed all bits in hash")
|
|
|
|
r = self.bhash % mod
|
|
self.bhash //= mod
|
|
|
|
return r
|