If your elements are in lists the fastest way is to use array operations. In the present case of an outer product one index, let's say "i", will not be expanded, on the other you want to thread.
To operate on a list the function needs the attribute Listable
. The Times
function, as many other internal ones, is already listable, that is
Times[{1,2,3},x] = {x, 2x, 3x}
You want to do the same with your function "f", e.g.
ClearAll[f]
SetAttributes[f, Listable]
f[{1,2,3},x] = {f[1, x], f[2, x], f[3, x]}
For the threading part you can use MapThread
to "slide" through the list, e.g.
MapThread[#1 f[#2] &, {{a,b,c},{1,2,3}}] = {a f[1], b f[2], c f[3]}
Finally your code will look like this
ClearAll[f]
SetAttributes[f, Listable]
f[x_, y_] := x y
{m, n, t, g} = RandomReal[1, {4, 1000}];
Total@Total@MapThread[m #1 f[t #2] &, {n, g}]
A note about speed: usually threaded operation are much faster than element ones
In[27]:=
Total@Total@MapThread[m #1 f[t, #2] &, {n, g}] // AbsoluteTiming
Total@Total[Outer[Times, m, n] Outer[f[#1, #2] &, t, g]] // AbsoluteTiming
Sum[m[[i]] n[[j]] f[t[[i]], g[[j]]], {i, 1, 1000}, {j, 1, 1000}] // AbsoluteTiming
ParallelSum[m[[i]] n[[j]] f[t[[i]], g[[j]]], {i, 1, 1000}, {j, 1, 1000}] // AbsoluteTiming
Out[27]= {0.797645, 62806.3}
Out[28]= {1.554886, 62806.3}
Out[29]= {2.933898, 62806.3}
Out[30]= {0.828527, 62806.3}
Thus always try to use them when possible.
Sum[m[[i]] n[[j]] f[tau[[i]], gamma[[j]]], {i, 1, n1}, {j, 1, n2}]
$\endgroup$f
is simple enough thenCompile
will likely give the best possible performance. But it's not "Mathematica-like". $\endgroup$Outer[Times,m,n]
and thenDot
that with your firstOuter
result. I don't know how that will be speedwise though. $\endgroup$Flatten
. This variant works.AbsoluteTiming[Flatten[Outer[Times, m, n]].Flatten[ Outer[f, t, gamma]]]
$\endgroup$