This is an extension of my earlier questions Faster use of Condition for a large array (see the example) and How to use Compile to generate an $n\times n$ array using $n$ vectors . In this case each point is characterised by a pair of indices.
Consider this Array
.
n1 = n2 = 30;
n = 9;
data = Flatten[Table[{RandomInteger[{1, n}, 2], {1. i, 1. j}},
{i, n1}, {j, n2}],1];
So each element of data
is {{Integer
,Integer
},{Real
,Real
}}. Then I define 3 matrices.
P = RandomReal[{0, 1}, {n, n}];
Q = RandomReal[{0, 1}, {n, n}];
R = RandomReal[{0, 1}, {n, n}];
And I have to create another matrix from data
like this
m1 = Table[
{s1, t1} = x[[1]]; {s2, t2} = y[[1]];
dr = x[[2]] - y[[2]];
Which[
Abs[Norm[dr] - 0.] < 0.001, R[[s1, t1]],
Abs[Norm[dr] - 1.] < 0.001, Q[[Abs[s1 - s2] + 1, Abs[t1 - t2] + 1]],
Abs[Norm[dr] - Sqrt[2]] < 0.001, P[[Abs[s1 - s2] + 1, Abs[t1 - t2] + 1]],
True, 0],
{x, data}, {y, data}]; // AbsoluteTiming
{17.569614, Null}
That is, depending on what is distance between $i^{th}$ and $j^{th}$ point, the $ij^{th}$ element of m1
will be given by an element of P
,Q
or R
matrix.
As much I know, in such cases Compile
gives faster result. So I try in this way (based on the answer to a similar problem by Pickett)
TensorRank[data]
3
m = Compile[{{sys, _Real, 3}},
Table[
Assuming[{s1, t1, s2, t2} \[Element] Integers,
{{s1, t1} = IntegerPart@x[[1]], {s2, t2} = IntegerPart@y[[1]]}];
dr = x[[2]] - y[[2]];
Which[
Abs[Norm[dr] - 0.] < 0.001, R[[s1, t1]],
Abs[Norm[dr] - 1.] < 0.001, Q[[Abs[s1 - s2] + 1, Abs[t1 - t2] + 1]],
Abs[Norm[dr] - Sqrt[2]] < 0.001, P[[Abs[s1 - s2] + 1, Abs[t1 - t2] + 1]],
True, 0],
{x, sys}, {y, sys}],
CompilationTarget -> "C"];
m2 = m[data]; // AbsoluteTiming
{48.353723, Null}
It is almost same time with "RuntimeOptions" -> "Speed"
.
However if I remove Assuming
, so it treats s1,t1,s2,t2
as Reals
, it produces an error message
CompiledFunction::cfse: Compiled expression Compile`GetElement[{7,5},1] should be a machine-size integer. >>
CompiledFunction::cfexe: Could not complete external evaluation; proceeding with uncompiled evaluation. >>
and then it takes same time as the Table
(~18sec).
What would be the correct and faster way to do this?
Needs["CompiledFunctionTools`"]; CompilePrint[m]
. You will see many calls toMainEvaluate
in your generated code that indicate calls to the main Mathematica evaluator for functions / expressions that cannot be compiled. You will want to take a look at How to Compile effectively? as well. $\endgroup$Which
. Is it clear now? $\endgroup$