RE: compiling problem
- To: mathgroup at smc.vnet.net
- Subject: [mg18956] RE: [mg18933] compiling problem
- From: "Ersek, Ted R" <ErsekTR at navair.navy.mil>
- Date: Fri, 30 Jul 1999 01:33:46 -0400
- Sender: owner-wri-mathgroup at wolfram.com
Kiran Shrestha wrote:
--------------------------------------
Can anybody teach me how to compile a function of several variables which
are values of other functions. For example, I have a function
f[x_, y_]:= alpha[x] + alpha[y] - beta[x]/beta[y].
The alpha and beta function values are known.
---------------------------------------
I think you need to include the calculation of alpha and beta in the
CompiledFunction. For example suppose alpah and beta are defined as:
alpha[a_]:=x Exp[-x];
beta[b_]:=2+Sin[b];
f[x_, y_]:= alpha[x] + alpha[y] - beta[x]/beta[y]
-------------
Then I would use Compiled as below.
Note:
It's a good idea to make sure the Compiled function is translated into
"op-code" by evaluating f[[-2]]. If f[[-2]] returns a list of lists where
each sublist is a list of integers all is well. Any portions represented
otherwise probably couldn't be converted to op-code, and the compiled
function will probably not run very fast.
In[1]:=
f=Compile[{x,y},x Exp[-x]+y Exp[y]-(2+Sin[x])/(2+Sin[y])];
In[6]:=
f[[-2]]
Out[6]=
{{1,3},{38,0,2},{95,34,3,0,2,3,0,3},{34,0,3,2},{95,34,3,0,1,3,0,3},{34,1,3,3
},{9,2,0},{95,1,3,0,0,3,0,4},{19,0,0,5},{30,5,4,4},{9,2,0},{95,1,3,0,1,3,0,5
},{19,0,0,6},{30,6,5,5},{41,5,5},{34,4,5,4},{38,4,5},{30,2,3,5,2},{4,2}}
Keep in mind that not all math functions in the Mathematica kernel can be
converted to op-code. A list of functions that can is available at:
http://support.wolfram.com/Kernel/Symbols/System/Compile.html
Note:
Factorial can't be converted to opcode, so the function below doesn't run
very fast. Instead one should replace Factorial[n] with (Times@@Range[n]).
In[20]:=
f1=Compile[{{x,_Real},{n,_Integer}},x^n/Factorial[n]];
When you evaluate the line above you don't get a message indicating
Factorial[n] couldn't be converted to op-code. In version 4 one can use the
following line to set a system option to cause posting of such messages (as
demonstrated below).
In[21]:=
Developer`SetSystemOptions["CompileReportExternal"->True];
In[22]:=
f2=Compile[{{x,_Real},{n,_Integer}},x^n/ Factorial[n]];
Compile::extscalar: n! can not be compiled and will be evaluated externally.
The result is assumed to be of type integer.
-----------------------------
The Compile messages are listed in the Help Browser under
Other Information > Warning Messages > Compile
I read over these messages, and came up with the
following requirements for Compile to work:
- All variables must have numeric or True/False values.
- Compiled evaluation has no speed advantage if some
numeric values encountered are not machine numbers.
- The type of expression returned from each subexpression
in the compiled function must be known.
- If Apply is used the first argument must have the head
Plus, Times, or List.
- If Outer is used the first argument must have the head
Plus, Times, or List.
- (Tr) can be used with two arguments only when the second
argument is Plus, Times, or List.
- If an expression returns a tensor, the compiled function
interpreter needs to be able to determine the rank of the tensor.
- Empty tensors such as {},or {{},{},{}},or {{{}},{{}}} can't be
used in a compiled function.
- The second argument of Compile can't include Patterns.
- The only types compiled functions can work with are
(_Integer,_Real,_Complex,True|False)
- The only list structures compiled functions can work with
are vectors, matrices, and (other tensors with rank<101).
- A variable in a compiled function has to keep the same type.
- Local variables used in compiled evaluation must have a
numeric value when they are used.
- Certain functions supported by Compile don't work in situations
as general as they do in uncompiled evaluation.
e.g. In compiled evaluation Floor can't take a complex argument.
-----------------------------------------
Here is an example where Compile has trouble.
A global variable can't be represented using op-code.
The compiled function(f2) below isn't converted to op-code because the
global variable (w) issued in the function. The best way around this known
to me, is to provide the global variable to the function as an argument.
f1=Compile
In[7]:=
w = 0.25;
f2 = Compile[{x}, (x^2 + Sqrt[Exp[x]]+w)];
f2[[-2]]
Out[9]=
{{1,3},{15,0,1},{34,1,1,2},{95,34,3,0,0,3,0,3},{95,54,3,0,3,3,0,4},{26,Funct
ion[{x},w],3,0,0,3,0,5},{30,2,4,5,6},{4,6}}
-----------------------------------------
Here is another example where Compile has trouble.
You can't use opcode to change the value of a function's argument. The
CompiledFunction below doesn't convert to op-code because the function
changes the value of (x) (one of the function's arguments).
In[10]:=
f3=Compile[{x,y},
x=Floor[y];
x+y
];
f3[[-2]]
Out[11]=
{{1,3},{26,Function[{x,y},x=Floor[y]],3,0,0,3,0,1,6,0,17},{30,0,1,2},{4,2}}
---------------------------------
This next feature is only available in versions 3.0 and later.
Using Compile[{{x1,t1,n1}, ...},expr] (x1) is a rank (n1) tensor where each
element has the type (t1). A vector is a rank 1 tensor, and a matrix is a
rank 2 tensor.
In[23]:=
magnitude =
Compile[{{vector, _Real, 1}}, Sqrt[Plus @@ vector^2] ];
In[24]:=
magnitude[{2.3,4.5,1.6,6.7,8.9}]
Out[24]=
12.3369
--------------------------
This next example uses the same feature as the last and
is only available in versions 3.0 and later.
Compile[{{x, _Real, 2}}, ...] takes an argument that is a matrix of real
numbers. The matrix can have any dimensions. As an example a
CompiledFunction (func) is defined below. The function (func) takes two
matrices of real numbers named (a) and (p) and computes
(p)(a)(Inverse[p])
In[25]:=
func=Compile[{{a,_Real,2},{p,_Real,2}},(p.a.Inverse[p])];
A demonstration of (func) is given below.
In[32]:=
x={{1.2,4.3,0.1},{0.2,1.4,0.2},{0.1,0.3,0.4}};
y={{1.2,0.2,0.},{0.3,1.5,2.3},{0.2,2.2,0.7}};
result=func[x,y]
Out[34]=
{{0.948593,-0.828727,2.95153},{0.44076,-0.0110458,1.82201},{0.357749,-0.3059
64,2.06245}}
------------------------------
Regards,
Ted Ersek