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?


3 Answers 3


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


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]
  • $\begingroup$ Rojo, please see my answer above, especially the last part. Do you think my understanding of the question is correct? $\endgroup$
    – Mr.Wizard
    Feb 7, 2012 at 4:41
  • $\begingroup$ @Spartacus I think you probably got it. But perhaps he needs that ppost function for something. He'll probably tell us soon $\endgroup$
    – Rojo
    Feb 7, 2012 at 4:52
  • $\begingroup$ please see this post, then try Map[f, step[l], {2}] $\endgroup$
    – Mr.Wizard
    Feb 7, 2012 at 12:40
  • $\begingroup$ I need the ppost1 function as it is supposed to be used in another function that expects the signature of ppost1, i.e., an argument arg, and a context. $\endgroup$
    – asim
    Feb 7, 2012 at 13:53
  • $\begingroup$ @asim, read my edit then $\endgroup$
    – Rojo
    Feb 7, 2012 at 16:32

A possible solution it to use the Listable attribute of compile.

fc2 = Compile[{{arg, _Real, 1}, {c1, _Real, 
    1}, {c2, _Real}, {c3, _Real}}, c3*arg + c2*c1, 
  RuntimeAttributes -> Listable]

Then call like this:

fc2[nargList, nmList, {50, 50}, {55, 55}]

What you really want is:

(* fc2[nargList, nmList, 50, 55] *)

Unfortunately, this crashes my V8.0.4 Kernel, but it's fixed in the development version. Hope this helps.


Your syntax between the two functions is different. In terms of Thread I think you mean to use:

nargList = {{1, 2}, {3, 4, 5}} // N;

nmList = {{6, 7}, {8, 9, 10}} // N;

ncontextList = {nmList, 50, 55} // N;

Thread[ppost1[nargList, Sequence @@ ncontextList]]

{ppost1[{1., 2.}, {6., 7.}, 50., 55.], ppost1[{3., 4., 5.}, {8., 9., 10.}, 50., 55.]}

But there seems to me to be another problem: your function is applied before the threading takes place. I am finding it difficult to divine your ultimate intent but I suspect this is not working the way you think it is.

Reading the question a second time you appear to be confused regarding the way Thread works. Only elements that appear at the first level of func are distributed among lists. Further, any lists over which the function is threaded must be of the same length. Please consider these examples:

Thread[func[{1, 2, 3}, {4, 5, 6}, 7]]
{func[1, 4, 7], func[2, 5, 7], func[3, 6, 7]}
Thread[func[{1, 2, 3}, {4, 5, 6}, {7}]]

During evaluation of In[2]:= Thread::tdlen: Objects of unequal length in func[{1,2,3},{4,5,6},{7}] cannot be combined. >>

Thread[func[{1, 2, 3}, {4, 5, 6, 7}]]

During evaluation of In[3]:= Thread::tdlen: Objects of unequal length in func[{1,2,3},{4,5,6,7}] cannot be combined. >>

Thread[func[{1, 2, 3}, {{4, 5, 6}, 7}]]

During evaluation of In[4]:= Thread::tdlen: Objects of unequal length in func[{1,2,3},{{4,5,6},7}] cannot be combined. >>

Finally, I believe that this is probably what you are trying to do:

(EDIT: Since you need ppost1 then I should have written:)

 Thread[ppost1[nargList, ncontextList]]
{{355., 460.}, {565., 670., 775.}}
  • $\begingroup$ Thanks for the above, but I need to us the compiled function via the ppost1 function. The ppost1 function will be used in another general function that needs to be called with different functions across different programs. $\endgroup$
    – asim
    Feb 7, 2012 at 13:57
  • $\begingroup$ @asim please see the edit at the bottom of my post for an alternative to modifying fc. I am sorry that I did not understand the heart of your question sooner. $\endgroup$
    – Mr.Wizard
    Feb 7, 2012 at 22:05
  • $\begingroup$ @Spartacus, +1 for your last edit, hehe $\endgroup$
    – Rojo
    Feb 7, 2012 at 22:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.