There's a serious mismatch between the question and accepted answer. fun is not an arbitrary function of the coordinates. It is a fully 'vectorized' one, one that accepts broadcastable arrays.
In [195]: def fun(i,j): return i*j-j**2
In [196]:
In [196]: np.fromfunction(fun, (4,4))
Out[196]:
array([[ 0., -1., -4., -9.],
[ 0., 0., -2., -6.],
[ 0., 1., 0., -3.],
[ 0., 2., 2., 0.]])
In [197]: fun(np.arange(4)[:,None], np.arange(4))
Out[197]:
array([[ 0, -1, -4, -9],
[ 0, 0, -2, -6],
[ 0, 1, 0, -3],
[ 0, 2, 2, 0]])
All fromfunction does is generate a full set of coordinates, and pass the resulting array(s) to your function:
In [199]: np.indices((4,4))
Out[199]:
array([[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]],
[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]]])
np.meshgrid and np.mgrid could also be used to generate these coordinates. A function that works with 2d arrays like this is not arbitrary. It is, though, a highly desirable trait when working with numpy.
Your question, or maybe it's the lack of response to our questions, implies that i and j have to be scalar, and hence requiring that each i,j pair gets passed individually to the function. For example j might be used in math.sin(j), or the function has some if test on the i or j value. In that case the fromfunction approach will fail.
iandj? So it has to be called one for each combination of values? There are minor tweaks that might give a 2x speedup, but not much better.f, so you'll have to post whatfis to get any help..