Re: Compile&Which
- To: mathgroup at smc.vnet.net
- Subject: [mg66065] Re: Compile&Which
- From: Maxim <m.r at inbox.ru>
- Date: Fri, 28 Apr 2006 06:33:04 -0400 (EDT)
- References: <e2ne3s$3b7$1@smc.vnet.net>
- Sender: owner-wri-mathgroup at wolfram.com
On Wed, 26 Apr 2006 09:22:04 +0000 (UTC), gregorc
<gregor.cernivec at fe.uni-lj.si> wrote:
> Hello,
>
> I have trouble to understand how does the Compile function handle the
> Which statement. Following there are two examples (just as
> ilustration), both are compiled OK, but the second one does not evaluate
> as a compiled expression. Can someone explain the evaluation error? It
> is probably because the Which statement, but I do not know how to do
> this correctly. Much thanks!
>
> 1st example:
>
> f = Compile[{{x, _Real, 1}}, {x[[1]]}];
> g = Compile[{{x, _Real, 1}}, {x[[2]]}];
> r = Compile[{{x, _Real, 1}}, f[x] + g[x], {{f[x], _Real, 1}, {g[x],
> _Real, 1}}]
> CompiledFunction[{x}, f[x] + g[x], -CompiledCode-]
> r[{3, 4}]
> {7.}
>
> 2nd example:
>
> f = Compile[{{x, _Real, 1}}, {x[[1]]}];
> g = Compile[{{x, _Real, 1}}, {x[[2]]}];
> r = Compile[{{x, _Real, 1}}, Which[x[[1]] ? x[[2]], f[x] +g[x], x[[1]] <
> x[[2]], f[x] -g[x]], {{f[x], _Real, 1}, {g[x], _Real, 1}}]
> CompiledFunction[{x}, Which[x?1? ? x?2?, f[x] + g[x], x?1? < x?2?, f[x]
> - g[x]], -CompiledCode-]
> r[{3, 4}]
> CompiledFunction::cfse: Compiled expression {-1.} should be a
> machine-size \real number.
> CompiledFunction::cfex: External evaluation error at instruction 2;
> \proceeding with uncompiled evaluation.
> {-1.}
>
> Thanks,
>
> Cernivec Gregor
>
>
The reason seems to be that Compile modifies Which statements by appending
the True case if it is not already present. Then if Which[1 == 1, {1, 2}]
is converted to something like Which[1 == 1, {1, 2}, True, Null] it won't
be possible to use this expression in assignments, because return types
are different. Adding the True case fixes that:
f = Compile[{{x, _Real, 1}}, {x[[1]]}];
g = Compile[{{x, _Real, 1}}, {x[[2]]}];
r = Compile[{{x, _Real, 1}},
Which[x[[1]] >= x[[2]], f[x] + g[x],
x[[1]] < x[[2]], f[x] - g[x],
True, f[x] - g[x]],
{{(f|g)[x], _Real, 1}}];
r[{3,4}]
Here are a couple more curious examples:
In[1]:= break = Break; Compile[{}, While[True, break[]]; 0][]
Out[1]= Hold[Break[]]
Here Break cannot find the enclosing While, because While is compiled and
Break isn't.
In[2]:= i = 0; f := ++i; Compile[{}, f; i][]
Out[2]= 0.
Here it seems that Compile fails to recognize an external call when it's
just a symbol (expressions like f[] or {f} would work).
Also Compile converts Switch to Which:
In[3]:= Compile[{}, Switch[1, 1., 0, 1, 1]][]
Out[3]= 0
The result is different from what we would get from uncompiled code,
because instead of MatchQ[1, 1.] we're evaluating (1 == 1.).
Maxim Rytin
m.r at inbox.ru