I am interested in threading a compiled function over multiple argument lists of different lengths.
I will explain this in two steps:
Suppose f is some function. Then one can define another function,
ppost[arg_, context_] := Apply[f[arg, ##] &, context]
which can be used as
In[2]:= ppost[a, {b, c}]
Out[2]= f[a, b, c]
or in a more complex scenario let,
In[3]:= argList = {{a1, b1}, {a2, b2, c2}};
In[4]:= mList = {{m1, n1}, {m2, n2, o2}};
In[5]:= contextList = {mList, y, z}
Out[5]= {{{m1, n1}, {m2, n2, o2}}, y, z}
We can thread the function over the argList and the contextList as follows:
In[6]:= Thread[ppost[argList, contextList]]
Out[6]= {f[{a1, b1}, {m1, n1}, y, z],
f[{a2, b2, c2}, {m2, n2, o2}, y, z]}
The above works, as needed.
Question: I need to do the same when f is a compiled function. As an example,
fc = Compile[{{arg, _Real, 1}, {c1, _Real, 1}, {c2, _Real}, {c3, _Real}},
c3*arg + c2*c1
]
ppost1[arg_, context_] := Apply[fc[arg, ##] &, context]
In[9]:= nargList = {{1, 2}, {3, 4, 5}} // N;
In[10]:= nmList = {{6, 7}, {8, 9, 10}} // N;
In[11]:= ncontextList = {nmList, 50, 55} // N
Out[11]= {{{6., 7.}, {8., 9., 10.}}, 50., 55.}
In[12]:= ppost1[nargList[[1]], {nmList[[1]], 50, 55}]
Out[12]= {355., 460.}
So far, so good, but then the following does not work properly, and uses the uncompiled version.
In[14]:= Thread[ppost1[nargList, ncontextList]]
During evaluation of
In[14]:= CompiledFunction::cfta: Argument {{1.,2.},{3.,4.,5.}} at position 1
should be a rank 1 tensor of machine-size real numbers. >>
During evaluation of
In[14]:= Thread::tdlen: Objects of unequal length in
{{355.,460.},{565.,670.,775.}} cannot be combined. >>`
Out[14]= {{355., 460.}, {565., 670., 775.}}
So, how can I thread the compiled function over the arguments nargList, ncontextList?
Answer
I think your problem is equivalent to trying to get something like this
l := Power[2, 2]
f /@ l
return f[2]^f[2]
instead of 4
You can control argument evaluation in MMA, for it to be either evaluated or not evaluated, but not half evaluated. If you wanted that you would have to either redesign your variables, or use things like replacement rules of OwnValues/DownValuess
In your case, you are expecting ppost1 to evaluate to fc, but fc not try to evaluate its arguments (until Thread had a chance to act)
If someone understood better than I did what your goal is, perhaps he can help you do it in some way
EDIT
Perhaps what you're looking for then can be achieved by masking the compiled function with a function that knows how to stay symbolically unevaluated
With[{cmp =
Compile[{{arg, _Real, 1}, {c1, _Real,
1}, {c2, _Real}, {c3, _Real}}, c3*arg + c2*c1]},
fc[arg : {___Real}, c1 : {___Real}, c2_Real, c3_Real] :=
cmp[arg, c1, c2, c3]
]
Comments
Post a Comment