54 lines
1.3 KiB
Python
54 lines
1.3 KiB
Python
import operator
|
|
|
|
from ._utils import deprecated
|
|
|
|
|
|
__all__ = ["ceil_log2", "exact_log2", "log2_int", "bits_for"]
|
|
|
|
|
|
def ceil_log2(n):
|
|
"""Returns the integer log2 of the smallest power-of-2 greater than or equal to ``n``.
|
|
|
|
Raises a ``ValueError`` for negative inputs.
|
|
"""
|
|
n = operator.index(n)
|
|
if n < 0:
|
|
raise ValueError(f"{n} is negative")
|
|
if n == 0:
|
|
return 0
|
|
return (n - 1).bit_length()
|
|
|
|
|
|
def exact_log2(n):
|
|
"""Returns the integer log2 of ``n``, which must be an exact power of two.
|
|
|
|
Raises a ``ValueError`` if ``n`` is not a power of two.
|
|
"""
|
|
n = operator.index(n)
|
|
if n <= 0 or (n & (n - 1)):
|
|
raise ValueError(f"{n} is not a power of 2")
|
|
return (n - 1).bit_length()
|
|
|
|
|
|
@deprecated("instead of `log2_int(n, True)`, use `exact_log2(n)`; instead of `log2_int(n, False)` use `ceil_log2(n)`")
|
|
def log2_int(n, need_pow2=True):
|
|
n = operator.index(n)
|
|
if n == 0:
|
|
return 0
|
|
r = (n - 1).bit_length()
|
|
if need_pow2 and (1 << r) != n:
|
|
raise ValueError(f"{n} is not a power of 2")
|
|
return r
|
|
|
|
|
|
def bits_for(n, require_sign_bit=False):
|
|
n = operator.index(n)
|
|
if n > 0:
|
|
r = ceil_log2(n + 1)
|
|
else:
|
|
require_sign_bit = True
|
|
r = ceil_log2(-n)
|
|
if require_sign_bit:
|
|
r += 1
|
|
return r
|