Skip to content

Instantly share code, notes, and snippets.

@protolambda
Created May 25, 2019 13:39
Show Gist options
  • Save protolambda/9ad3f46665cb9bdfdb38599cbc626c30 to your computer and use it in GitHub Desktop.
Save protolambda/9ad3f46665cb9bdfdb38599cbc626c30 to your computer and use it in GitHub Desktop.
# status-quo, readability
def a_next_power_of_2(x):
    if x == 0: return 0
    return 1 if x == 1 else 2 * a_next_power_of_2((x+1)//2)

# faster version, cross-language
def b_next_power_of_2(v: int) -> int:
    """
    Get the next power of 2. (for 64 bit range ints)
    Examples:
    0 -> 0, 1 -> 1, 2 -> 2, 3 -> 4, 32 -> 32, 33 -> 64
    """
    # effectively fill the bitstring (1 less, do not want to  with ones, then increment for next power of 2.
    v -= 1
    v |= v >> (1 << 0)
    v |= v >> (1 << 1)
    v |= v >> (1 << 2)
    v |= v >> (1 << 3)
    v |= v >> (1 << 4)
    v |= v >> (1 << 5)
    v += 1
    return v

# iteration on readability, fast in python
def c_next_power_of_2(v: int) -> int:
    if v == 0: return 0
    return 1 << (v-1).bit_length()

funcs = {'a': a_next_power_of_2, 'b': b_next_power_of_2, 'c': c_next_power_of_2}
tests = [
    (0,0), (1,1), (2,2), (3,4), (31,32), (32,32), (33,64)
]
for (inp, out) in tests:
  for name, fn in funcs.items():
    res = fn(inp)
    if res != out:
      print("bad run, test: (%d, %d), got: %d, func: %s" %(inp, out, res, name))


# Far from perfect benchmarking code, but good enough to show relative performance
import time

for name, fn in funcs.items():
  print("benching ", name)
  start = time.time()
  for i in range(0, 1000000, 33):
    res = fn(i)
  end = time.time()
  print("bench", name, " took ", end - start)

No bad runs (after I added a case for 0, and adjusted the bit-length approach with -1 to match behavior).

Bench results:

benching  a
bench a  took  0.17035603523254395
benching  b
bench b  took  0.02341461181640625
benching  c
bench c  took  0.011197090148925781
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment