I have a code that I need to compile. The code contains a loop in which I need to gather data into a list. The question is how to best gather data so that the code works inside Compile. The following pieces of code illustrate the problem:
1. gathering just one list (tbl1) into the final list (result) - WORKS
Needs["CCompilerDriver`"];
dir = "c:\\temp";
$CCompilerInternalDirectory = dir;
func = Compile[{},
Module[{t, tmax, dt, n, eps, tbl1, tbl2, i, result},
n = 10;
t = 0.0;
tmax = 10.0;
eps = 10.0^-2;
tbl1 = Table[0.0, {n}];
tbl2 = Table[0.0, {n}];
result = {tbl1};
While[TrueQ[t <= tmax],
dt = RandomReal[{0.1, 0.5}];
t = t + dt;
For[i = 1, i <= n, i++,
tbl1[[i]] = t^0.5;
tbl2[[i]] = t^2;
];
result = Append[result, tbl1];
];
result
],
CompilationTarget -> "C",
CompilationOptions -> {"InlineExternalDefinitions" -> True}
];
2. gathering two lists (tbl1 and tbl1) - NOT Working:
Needs["CCompilerDriver`"];
dir = "c:\\temp";
$CCompilerInternalDirectory = dir;
func = Compile[{},
Module[{t, tmax, dt, n, eps, tbl1, tbl2, i, result},
n = 10;
t = 0.0;
tmax = 10.0;
eps = 10.0^-2;
tbl1 = Table[0.0, {n}];
tbl2 = Table[0.0, {n}];
result = {tbl1, tbl2};
While[TrueQ[t <= tmax],
dt = RandomReal[{0.1, 0.5}];
t = t + dt;
For[i = 1, i <= n, i++,
tbl1[[i]] = t^0.5;
tbl2[[i]] = t^2;
];
result = Append[result, {tbl1, tbl2}];
];
result
],
CompilationTarget -> "C",
CompilationOptions -> {"InlineExternalDefinitions" -> True}
];
Compile::cpts: The result after evaluating Insert[result,{tbl1,tbl2},-1] should be a tensor. Nontensor lists are not supported at present; evaluation will proceed with the uncompiled function. >>
Compile::cpts: The result after evaluating Insert[result,{tbl1,tbl2},-1] should be a tensor. Nontensor lists are not supported at present; evaluation will proceed with the uncompiled function. >>
3. And the same with linked lists - NOT working either:
Needs["CCompilerDriver`"];
dir = "c:\\temp";
$CCompilerInternalDirectory = dir;
func = Compile[{},
Module[{t, tmax, dt, n, eps, tbl1, tbl2, i, result},
n = 10;
t = 0.0;
tmax = 10.0;
eps = 10.0^-2;
tbl1 = Table[0.0, {n}];
tbl2 = Table[0.0, {n}];
result = {tbl1, tbl2};
While[TrueQ[t <= tmax],
dt = RandomReal[{0.1, 0.5}];
t = t + dt;
For[i = 1, i <= n, i++,
tbl1[[i]] = t^0.5;
tbl2[[i]] = t^2;
];
result = {result, {tbl1, tbl2}};
];
result
],
CompilationTarget -> "C",
CompilationOptions -> {"InlineExternalDefinitions" -> True}
];
Compile::cset: Variable result of type {_Real,2} encountered in assignment of type {_Real,3}. >>
Compile::cset: Variable result of type {_Real,2} encountered in assignment of type {_Real,3}. >>
4. Trying Sow and Reap with no effect either (although these functions are just a huge mystery for me):
Needs["CCompilerDriver`"];
dir = "c:\\temp";
$CCompilerInternalDirectory = dir;
func = Compile[{},
Module[{t, tmax, dt, n, eps, tbl1, tbl2, i, result},
n = 10;
t = 0.0;
tmax = 10.0;
eps = 10.0^-2;
tbl1 = Table[0.0, {n}];
tbl2 = Table[0.0, {n}];
result = {tbl1, tbl2};
result = Reap[
While[TrueQ[t <= tmax],
dt = RandomReal[{0.1, 0.5}];
t = t + dt;
For[i = 1, i <= n, i++,
tbl1[[i]] = t^0.5;
tbl2[[i]] = t^2;
];
Sow[tbl1];
Sow[tbl2];
];
];
result
],
CompilationTarget -> "C",
CompilationOptions -> {"InlineExternalDefinitions" -> True}
];
Compile::cset: Variable result of type {_Real,2} encountered in assignment of type {_Real,0}. >>
Compile::cset: Variable result of type {_Real,2} encountered in assignment of type {_Real,0}. >>
So what is he best and Compile safe approach of accumulating data to a list if one does not know the list size beforehand? (I can see that making a sufficiently large list to store the data would solve the problem, but I consider this as a last resort, and rather bad approach; Append is a compilable function after all.
Internal`Bag
insideCompile
" is a good start. $\endgroup$