from ctypes import c_float, c_int32, cast, byref, POINTER import sys from random import randint import time import struct ''' from: https://github.com/ajcr/ajcr.github.io/blob/master/_posts/2016-04-01-fast-inverse-square-root-python.md Using ctypes, not the fastest version. ''' def ctypes_isqrt(number): threehalfs = 1.5 x2 = number * 0.5 y = c_float(number) i = cast(byref(y), POINTER(c_int32)).contents.value i = c_int32(0x5f3759df - (i >> 1)) y = cast(byref(i), POINTER(c_float)).contents.value y = y * (1.5 - (x2 * y * y)) return y def struct_isqrt(number): threehalfs = 1.5 x2 = number * 0.5 y = number packed_y = struct.pack('f', y) i = struct.unpack('i', packed_y)[0] # treat float's bytes as int i = 0x5f3759df - (i >> 1) # arithmetic with magic number packed_i = struct.pack('i', i) y = struct.unpack('f', packed_i)[0] # treat int's bytes as float y = y * (threehalfs - (x2 * y * y)) # Newton's method return y def norm_isq(number): return 1.0/(number**0.5) def main(argv): numSamples = long(argv[0]) samples = [randint(1,10000) for i in range(0, numSamples)] startTime = time.time() [norm_isq(n) for n in samples] print("normal functions ran by python: %.6f seconds." % (time.time() - startTime)) startTime = time.time() # calling fast inverse square root: [struct_isqrt(n) for n in samples] print("fast inverse square root struct: %.6f seconds." % (time.time() - startTime)) # calling fast inverse square root: [ctypes_isqrt(n) for n in samples] print("fast inverse square root ctypes: %.6f seconds." % (time.time() - startTime)) if __name__ == "__main__": main(sys.argv[1:])