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