Using np.frexp(arr)[1]
comes in 4 to 6x faster than np.ceil(np.log2(x)).astype(int)
.
Note that, as pointed out by @GregoryMorse above, some additional work is needed to guarantee correct results for 64-bit inputs (bit_length3
below).
import numpy as np
def bit_length1(arr):
# assert arr.max() < (1<<53)
return np.ceil(np.log2(arr)).astype(int)
def bit_length2(arr):
# assert arr.max() < (1<<53)
return np.frexp(arr)[1]
def bit_length3(arr): # 64-bit safe
_, high_exp = np.frexp(arr >> 32)
_, low_exp = np.frexp(arr & 0xFFFFFFFF)
return np.where(high_exp, high_exp + 32, low_exp)
Performance results, 10 iterations on a 100,000-element array via https://perfpy.com/868.