This had been piquing my curiosity for a few days, but I finally found why!
The reason is a tiny sentence hidden in the documentation of Compile
, which has drastic consequences I had not realized before:
Ordinary Mathematica code can be called from within compiled code. Results obtained from the Mathematica code are assumed to be approximate real numbers, unless specified otherwise by the third argument of Compile.
So, there you have it: if you use
Compile[{{m, _Real, 2}}, Fourier[m]]
then compilation assumes that Fourier
returns a real values. When you evaluate this, and the returned values turn out to be complex, you get your error message:
CompiledFunction::cfex:
Could not complete external evaluation at instruction 1; proceeding with uncompiled evaluation.
When you specify that Fourier
returns complex values, using the third argument to Compile
,
things work better as you found out.
Also, you can fully confirm that the issue here is with the number type (i.e. real vs. complex) rather than the rank, by trying your first code with FourierDST
, which returns real numbers and does not emit the error:
Compile[{{m, _Real, 2}}, FourierDST[m]] @ Table[N[i - j], {i, 4}, {j, 4}]
Fourier
) does not in fact get compiled. Even though you get a usable "compiled function", it will just call back to the main evaluator. This function will not be faster than a plainFourier
. It may actually be a tiny bit slower, theoretically. $\endgroup$