I converted this code into Python.
For the following tests, I used Python 64-bit because it uses more than 1 GB of RAM.
mobius(10**6) takes 2.5 seconds with pure Python + numpy.
mobius(10**6) takes 0.7 seconds with Python + numpy + numba (just-in-time compiler).
mobius(10**9) takes 39 seconds with Python + numpy + numba.
import numpy as np
from numba import jit # comment this line if you don't have numba installed
@jit # idem
def mobius(N):
SQRT = int(np.sqrt(N))
mu = np.ones(N+1, dtype=np.int32)
mu[0] = 0
for i in range(2, SQRT+1):
if mu[i] == 1:
for j in range(1, int(N / i)+1):
mu[i*j] *= -i
for j in range(1, int(N / i / i)+1):
mu[i*i*j] = 0
for i in range(2, N+1):
if mu[i] == i:
mu[i] = 1
elif mu[i] == -i:
mu[i] = -1
elif mu[i] < 0:
mu[i] = 1
elif mu[i] > 0:
mu[i] = -1
return mu
print mobius(10**6)
# Test that shows that it works, see https://oeis.org/A008683
OEISmobius = [0,1,-1,-1,0,-1,1,-1,0,0,1,-1,0,-1,1,1,0,-1,0,-1,0,1,1,-1,0,0,1,0,0,-1,-1,-1,0,1,1,1,0,-1,1,1,0,-1,-1,-1,0,0,1,-1,0,0,0,1,0,-1,0,1,0,1,1,-1,0,-1,1,0,0,1,-1,-1,0,1,-1,-1,0,-1,1,0,0,1,-1]
assert (mobius(78) == OEISmobius).all()
Edit: I also translated this code in Python:
import numpy as np
from numba import jit
@jit
def mobius2(N):
mu = -np.ones(N+1, dtype=np.int8)
mu[0] = 0
mu[1] = 1
for n in range(2, N+1):
for m in range(n+n, N, n):
mu[m] -= mu[n]
return mu
print mobius2(10**9)
mobius2(10**9) takes ? seconds with Python + numpy + numba.