Consider the following function for calculating the number of steps for a given input to the 3 n + 1 problem:
def num_steps(b, steps):
e = b
d = 0
while True:
if e == 1:
d += steps[e]
return d
if e % 2 == 0:
e //= 2
else:
e = 3*e + 1
d += 1
Here, steps
exists to allow for memoization of the result, but for the sake of this question, we just note that as long as steps[1] == 0
, it should have no effect, since in that case, the effect of d += steps[e]
is to add 0 to d
. Indeed, the following example gives the expected result:
import numpy as np
steps = np.array([0, 0, 0, 0])
print(num_steps(3, steps)) # Prints 7
If, however, we JIT compile the method using numba.jit
(or njit
), we no longer get the right result:
import numpy as np
from numba import jit
steps = np.array([0, 0, 0, 0])
print(jit(num_steps)(3, steps)) # Prints 0
If we remove the seemingly-redundant d += steps[e]
before compiling the method, we do get the right result, though. We could even put in a print(steps[e])
prior to d += steps[e]
and see that the value is 0. I can also move the d += 1
to the top of the loop (and initialize d = -1
instead) to get something that also works in the Numba case.
This happens with Numba 0.48.0 (llvmlite 0.31.0) on Python 3.8 (the most recent versions available through the standard conda channel).