Overview of the codegen Package
Calling Sequence
Description
List of codegen Package Commands
Examples
codegen:-command(arguments)
The code generation (codegen) package contains tools for creating, manipulating, and translating Maple procedures into other languages. This includes tools for automatic differentiation of Maple procedures, code optimization, translation into C, Fortran and MathML, and an operation count of a Maple procedure.
Each command in the codegen package can be accessed by using either the long form or the short form of the command name in the command calling sequence.
Important: The newer CodeGeneration package also offers translation of Maple code to other languages. The codegen[C] and codegen[fortran] commands have been deprecated, and the superseding commands CodeGeneration:-C and CodeGeneration:-Fortran should be used instead. Additionally, codegen[maple2intrep] and codegen[intrep2maple] have been superseded by ToInert and FromInert.
The following is a list of available commands.
C(deprecated)
cost
declare
dontreturn
eqn
fortran(deprecated)
GRADIENT
HESSIAN
horner
intrep2maple(deprecated)
JACOBIAN
joinprocs
makeglobal
makeparam
makeproc
makevoid
maple2intrep(deprecated)
MathML
optimize
packargs
packlocals
packparams
prep2trans
renamevar
split
swapargs
To display the help page for a particular codegen command, see Getting Help with a Command in a Package.
with⁡codegen:
The first example shows how the package can be used to create a Fortran subroutine to compute a vector valued function.
f≔1−exp⁡−t⁢x⁢y:
g≔x−y⁢exp⁡−t⁢x2:
v≔vector⁡f,g
v≔1−ⅇ−t⁢x⁢yx−y⁢ⅇ−t⁢x2
fg := makeproc(v,parameters=[t,x,y]);
fg ≔ proct,x,ylocalv;v ≔ array⁡1..2;v[1] ≔ 1 − exp⁡−t*x*y;v[2] ≔ x − y*exp⁡−t*x^2;vend proc
fortran⁡fg,optimized
subroutine fg(t,x,y,crea_par) doubleprecision t doubleprecision x doubleprecision y doubleprecision crea_par(2) doubleprecision t1 doubleprecision t5 doubleprecision v(2) t1 = exp(-t) v(1) = -y*x*t1+1 t5 = x**2 v(2) = -t5*t1*y+x crea_par(1) = v(1) crea_par(2) = v(2) return return end
The function f below computes the square of the distance from a point (x,y) to a circle of radius r with centre (h,k) under translation by (C,D) followed by rotation of theta radians. We use automatic differentiation to compute the gradient of the function f with respect to C,D,theta and generate C code for the result. Finally we output the computational cost of the optimized code.
f := proc(C,D,theta,x,y,h,k,r) local s,c,xbar,ybar,d1,d2,d; s := sin(theta); c := cos(theta); xbar := (x+C)*c + (y+D)*s; ybar := (y+D)*c - (x+C)*s; d1 := (h-xbar)^2; d2 := (k-ybar)^2; d := sqrt( d1+d2 ) - r; d^2 end proc:
G≔GRADIENT⁡f,C,D,θ,result_type=array
G ≔ procC,D,θ,x,y,h,k,rlocalc,d,d1,d2,dfr0,grd,s,xbar,ybar;s ≔ sin⁡θ;c ≔ cos⁡θ;xbar ≔ x+C*c+y+D*s;ybar ≔ y+D*c − x+C*s;d1 ≔ h − xbar^2;d2 ≔ k − ybar^2;d ≔ sqrt⁡d1+d2 − r;dfr0 ≔ array⁡1..7;dfr0[7] ≔ 2*d;dfr0[6] ≔ 1/2*dfr0[7]/d1+d2^1/2;dfr0[5] ≔ 1/2*dfr0[7]/d1+d2^1/2;dfr0[4] ≔ dfr0[6]*−2*k+2*ybar;dfr0[3] ≔ dfr0[5]*−2*h+2*xbar;dfr0[2] ≔ dfr0[4]*y+D+dfr0[3]*x+C;dfr0[1] ≔ dfr0[4]*−x − C+dfr0[3]*y+D;grd ≔ array⁡1..3;grd[1] ≔ 0;grd[2] ≔ c*dfr0[4]+s*dfr0[3];grd[3] ≔ −dfr0[2]*sin⁡θ+dfr0[1]*cos⁡θ;returngrdend proc
C⁡G,optimized,precision=single
#include <math.h> void G(C,D,theta,x,y,h,k,r,grd) float C; float D; float theta; float x; float y; float h; float k; float r; float grd[3]; { float c; float d1; float d2; float dfr0[7]; float s; float t1; float t10; float t12; float t20; float t22; float t3; float t7; float t8; float t9; { s = sin(theta); c = cos(theta); t1 = x+C; t3 = y+D; t7 = -c*t1-s*t3+h; d1 = t7*t7; t8 = -c*t3+s*t1+k; d2 = t8*t8; t9 = d1+d2; t10 = sqrt(t9); dfr0[6] = 2.0*t10-2.0*r; t12 = sqrt(t9); dfr0[5] = 1/t12*dfr0[6]/2.0; dfr0[4] = dfr0[5]; dfr0[3] = -2.0*t8*dfr0[4]; dfr0[2] = -2.0*t7*dfr0[4]; t20 = dfr0[3]; t22 = dfr0[2]; dfr0[1] = t1*t22+t3*t20; dfr0[0] = -t1*t20+t3*t22; grd[0] = 0.0; grd[1] = c*t20+s*t22; grd[2] = c*dfr0[0]-s*dfr0[1]; return; } }
cost⁡optimize⁡G
23⁢storage+25⁢assignments+5⁢functions+12⁢additions+22⁢multiplications+18⁢subscripts+divisions
In this example, we compute 1+x+x^2/2+x^3/6+...+x^n/n! We do this in two ways. Firstly, we use a symbolic sum. To obtain C code we explicitly convert the symbolic sum to a for loop.
f≔Sum⁡xii!,i=0..n
f≔∑i=0n⁡xii!
F := makeproc(f,parameters=[n,x],locals=[i]);
F ≔ procn,xlocali;Sum⁡x^i/factorial⁡i,i=0..nend proc
F≔prep2trans⁡F
F ≔ procn,xlocali,i1,s1,t1;if0<−nthens1 ≔ 0elset1 ≔ 1;s1 ≔ 1;fori1tondot1 ≔ x*t1/i1;s1 ≔ s1+t1end doend if;s1end proc
F≔declare⁡n::integer,F
F ≔ procn::integer,xlocali,i1,s1,t1;if0<−nthens1 ≔ 0elset1 ≔ 1;s1 ≔ 1;fori1tondot1 ≔ x*t1/i1;s1 ≔ s1+t1end doend if;s1end proc
C⁡F
double F(n,x) int n; double x; { double i; int i1; double s1; double t1; { if( 0.0 < -n ) s1 = 0.0; else { t1 = 1.0; s1 = 1.0; for(i1 = 1;i1 <= n;i1++) { t1 = x/i1*t1; s1 += t1; } } return(s1); } }
In the second approach, our program uses a loop to compute the finite sum. We use the intermediate representation for programs provided by the codegen package. This representation is an expression tree. It can be converted into a Maple procedure using the intrep2maple command which can then be converted into Fortran or C code if desired.
f≔Proc⁡Parameters⁡n::integer,x::float,Locals⁡i,s,t,StatSeq⁡Assign⁡s,1.0,Assign⁡t,1.0,For⁡i,1,1,n,true,StatSeq⁡Assign⁡t,x⁢ti,Assign⁡s,s+t,false,s
f≔Proc⁡Parameters⁡n::ℤ,x::float,Locals⁡i,s,t,StatSeq⁡Assign⁡s,1.0,Assign⁡t,1.0,For⁡i,1,1,n,true,StatSeq⁡Assign⁡t,x⁢ti,Assign⁡s,s+t,false,s
F≔intrep2maple⁡f
F ≔ procn::integer,x::floatlocali,s,t;s ≔ 1.0;t ≔ 1.0;foritondot ≔ x*t/i;s ≔ s+tend do;send proc
In this example, we compute the gradient and hessian of a simple function, manipulate the procedures then join the two together.
f≔1−exp⁡−t⁢x⁢y
f≔1−ⅇ−t⁢x⁢y
F := makeproc(f,[x,y,t]);
F ≔ procx,y,t1 − exp⁡−t*x*yend proc
G≔GRADIENT⁡F,x,y,result_type=array
G ≔ procx,y,tlocalgrd;grd ≔ array⁡1..2;grd[1] ≔ −exp⁡−t*y;grd[2] ≔ −exp⁡−t*x;returngrdend proc
G≔dontreturn⁡grd,makeparam⁡grd,G
G ≔ procx,y,t,grd::array⁡1..2grd[1] ≔ −exp⁡−t*y;grd[2] ≔ −exp⁡−t*x;returnend proc
H≔HESSIAN⁡F,x,y,result_type=array:
H≔renamevar⁡grd=hes,dontreturn⁡grd,makeparam⁡grd,H
H ≔ procx,y,t,hes::array⁡1..2,1..2localdf,dfr0,grd1,grd2,t1;t1 ≔ exp⁡−t;grd1 ≔ −y*t1;grd2 ≔ −x*t1;df ≔ array⁡1..2;dfr0 ≔ array⁡1..2;df[1] ≔ 1;dfr0[2] ≔ 1;hes[1,1] ≔ 0;hes[1,2] ≔ −df[1]*t1;hes[2,1] ≔ −dfr0[2]*t1;hes[2,2] ≔ 0;returnend proc
GH≔optimize⁡joinprocs⁡G,H
GH ≔ procx,y,t,grd,hes::array⁡1..2,1..2localt1,t2;t2 ≔ exp⁡−t;grd[1] ≔ −y*t2;grd[2] ≔ −x*t2;t1 ≔ t2;hes[1,1] ≔ 0;hes[1,2] ≔ −t1;hes[2,1] ≔ hes[1,2];hes[2,2] ≔ 0;returnend proc
This final example shows the functionality of the maple2intrep and intrep2maple commands. The maple2intrep command converts a Maple procedure into an intermediate representation which is suitable for manipulation. One must be careful about how one evaluates this representation because the functions in the code will evaluate.
f := proc(x,n) local A,i; A := Array(0..n); A[0] := 1; for i to n do A[i] := x*A[i-1] end do; A end proc:
IR≔maple2intrep⁡f
IR≔Proc⁡Name⁡f..List⁡0..n,float,Parameters⁡x..float,n..integer,Options⁡,Description⁡,Locals⁡A..List⁡0..n,float,i..integer,Globals⁡,StatSeq⁡Assign⁡A,Array⁡0..n,Assign⁡A0,1,For⁡i,1,1,n,true,StatSeq⁡Assign⁡Ai,x⁢A−1+i,false,A
intrep2maple⁡IR
Error, integer dimensions required
intrep2maple⁡eval⁡IR,1
procx,nlocalA,i;A ≔ Array⁡0..n;A[0] ≔ 1;foritondoA[i] ≔ x*A[i − 1]end do;Aend proc
See Also
codegen:-optimize
codegen[C(deprecated)]
codegen[fortran(deprecated)]
CodeGeneration
CodeGeneration:-C
CodeGeneration:-Fortran
examples/codegen
UsingPackages
Download Help Document