codegen/C/procedure
generating C code for Maple procedures
Calling Sequence
Parameters
Description
Examples
C(s);
C(s, options);
s
-
named Maple procedure
Important: The codegen[C] command has been deprecated. Use the superseding command CodeGeneration[C] instead. See CodeGeneration for information on translation to other languages.
The codegen[C] command can generate a complete C subroutine or function from a Maple procedure. This will normally include all necessary declarations and include headers required for compilation. The first input argument s must be a named Maple procedure. The remaining input arguments are optional. Those options pertaining to Maple procedures are described below. For help on other options see ?codegen[C].
The ansi option: by default the syntax for parameter declarations follows the older Kernighan and Ritchie syntax. If the optional argument ansi is specified, ANSI C syntax is followed.
The precision option: the optional argument precision=single, or precision=double specifies whether single precision or double precision is to be used in the generation of floating-point variables and constants. The default is single precision if the mode=single option is provided and double precision otherwise.
The mode option: the optional argument mode=single or mode=double specifies whether single precision or double precision math function names are generated. The default is double precision (resulting in the standard math library names), even if the precision=single option is provided.
The declarations option: a limited type deduction algorithm has been implemented to determine the types of the parameters, local variables, and global variables appearing in the Maple procedure. If no type can be deduced from the context then a floating point type is declared. The optional argument declarations = x::t tells the C translator that the type of the variable x is t where t may be one of integer, float, numeric, or an array of these. More than one declaration is specified as a list of declarations. For example declarations = [n::integer, x::'array'(1..n, numeric)].
Generally speaking, the C translator can translate Maple numerical programs only. These are programs whose variables (parameters, local variables, and global variables) are of type integer or floating point, and arrays of integer and floating point numbers. The programs may contain mathematical formulae, array subscripts, Maple programming language statements, and certain Maple commands, like array(1..n), print(x, y), and error "message", which are understood by the C translator. The only error statements that can be translated are those with a single string argument. The C translator will inform the user if it does not know about a mathematical function or Maple command, for example coeff. A few Maple statements and expressions that appear inside the Maple procedure cannot be translated. The most important are
quotes
sets
for var in ...
args[i]
package[function](...)
tables
nargs
f(...) := ...
series
procname
'...' (unevaluation quotes)
read
save
All array references in the generated C code are shifted to begin at 0. For higher dimensional arrays, row-major ordering is assumed and one-dimensional array references are generated for arrays with non-constant array bounds. For example, given the array A::array(1..m, 1..n) the Maple array subscript A[i, j] generates the C code A[(i-1)*n+j-1].
The handling of array parameters is as follows. Normally, both the array dimension and bounds must be given. This may be done in the parameter type declaration or with the declarations option.
Examples are f := proc( a::array(1..5, 1..5) ) for a two-dimensional array with constant bounds, g := proc(n::integer, A::array(1..n)) for a one-dimensional array with length n. The latter example could also be done by C(g, declarations='[n::integer, A::array(1..n, numeric)]'.
For one-dimensional arrays, if only the array dimension is specified, for example proc(a::array(1)), the Maple array will be assumed to be indexed from 1, thus the Maple subscript A[i] will generate the C array reference A[i-1].
The handling of local arrays is as follows. If the variable A is a local variable, the Maple statement A := array(1..n, 1..n) will be used to determine the dimension and bounds of the array. If the array bounds are constants, the C runtime stack will be used for the array, otherwise storage for the array will be allocated dynamically using malloc.
The handling of procedures which return local arrays is as follows. If a local variable is an array and it is also the return value of the Maple procedure, then if the array bounds are either constant or they are parameters, e.g. proc(n, x) local A; A := array(1..2, 1..n); ... return A end, then the array will be moved to the last parameter of the C subroutine.
Procedures returning sequences are handled. A new parameter called crea_par, an array, is added as the last parameter and the corresponding assignments are generated.
Maple procedures which contain symbolic sums represented either by the sum command or the add command, piecewise commands, are not translated by the C translator. The user may first run the code through the codegen[prep2trans] command to convert these symbolic forms into for loops and if statements.
The command with(codegen,C) allows the use of the abbreviated form of this command.
with⁡codegen,C:
Compute sin(x)/x accurately for all x to double precision
f := proc(x) if abs(x) < 1.0e-8 then 1-x^2/6; else sin(x)/x; end if; end proc:
C⁡f
#include <math.h> double f(x) double x; { { if( fabs(x) < 0.1E-7 ) return(1.0-x*x/6.0); else return(sin(x)/x); } }
C⁡f,ansi,precision=single
#include <math.h> float f(float x) { { if( fabs(x) < 0.1E-7 ) return(1.0-x*x/6.0); else return(sin(x)/x); } }
Compute 1+x+x^2/2+...+x^n/n! in a for loop
f := proc(x,n) local i,s,t; s := 1; t := 1; for i to n do t := t*x/i; s := s+t end do; s end proc:
double f(x,n) double x; double n; { int i; double s; double t; { s = 1.0; t = 1.0; for(i = 1;i <= n;i++) { t = t*x/i; s += t; } return(s); } }
Compute 1+y+y^2/2+...+y^n/n! as a symbolic sum where y = (1-x)^2. The C translator does not know about the sum command.
g := proc(x,n) local i,t; t := (1-x)^2; sum(t^i/i!,i=0..n); end proc:
C⁡g
#include <math.h> double g(x,n) double x; double n; { double i; double t; { t = pow(1.0-x,2.0); codegen/C/expression: Unknown function: sum will be left as is. codegen/C/expression: Unable to translate i = 0 .. n into C codegen/C/expression: Replacing value with three parameters i, 0, n return(sum(pow(t,1.0*i)/exp(lgamma(1.0+i)),i,0.0,n)); } }
with⁡codegen,prep2trans:
g≔prep2trans⁡g,language=C
g ≔ procx,nlocali,i2,s2,t,t1,t2;t1 ≔ 1 − x;t ≔ t1^2;if0<−nthens2 ≔ 0elset2 ≔ 1;s2 ≔ 1;fori2tondot2 ≔ t*t2/i2;s2 ≔ s2+t2end doend if;s2end proc
double g(x,n) double x; double n; { double i; int i2; double s2; double t; double t1; double t2; { t1 = 1.0-x; t = t1*t1; if( 0.0 < -n ) s2 = 0.0; else { t2 = 1.0; s2 = 1.0; for(i2 = 1;i2 <= n;i2++) { t2 = t/i2*t2; s2 += t2; } } return(s2); } }
An example showing shifting of arrays, printed output, and error handling
f := proc(x::numeric) local i, M; global test; M := array(-2..3, sparse, [(1)=sin(x), (2)=x^3]); for i from -2 to 3 do if test then print(M[i]) else error "Error message"; end if; end do; M; end proc:
#include <math.h> void f(x,M) double x; double M[6]; { int i; extern int test; { M[0] = 0.0; M[1] = 0.0; M[2] = 0.0; M[3] = sin(x); M[4] = x*x*x; M[5] = 0.0; for(i = -2;i <= 3.0;i++) if( (test) ) printf( "%e\n" ,M[i+2]); else { fprintf(stderr, "Error message" ); exit(1); } return; } }
A Maple procedure which takes as input a one-dimensional array. In the first case, the translator does not know the bounds for the array. In the second case, we tell it using the declarations option.
h := proc(n,a::array,x) local i,s; s := a[n]; for i from n-1 by -1 to 0 do s := a[i]+x*s; end do; s end proc:
C⁡h
codegen/C/pretreatment: WARNING: Unable to determine array bounds in a[n] codegen/C/pretreatment: WARNING: Unable to determine array bounds in a[i] double h(n,a,x) int n; double *a; double x; { int i; double s; { s = a[-1+n]; for(i = -1+n;0.0 <= i;i--) s = x*s+a[i-1]; return(s); } }
C⁡h,declarations=a::array⁡1..n
double h(n,a,x) int n; double *a; double x; { int i; double s; { s = a[-1+n]; for(i = -1+n;0.0 <= i;i--) s = x*s+a[i-1]; return(s); } }
A Maple procedure which creates and returns an array of constant dimension. The procedure g was created by the codegen[GRADIENT] command.
g := proc(x,y,z) local dt,grd,t; grd := array(1 .. 3); dt := array(1 .. 3); dt[3] := 2*z; t := z^2; grd[1] := cos(x)*z-sin(x)*t; grd[2] := 0; grd[3] := sin(x)+cos(x)*dt[3]-1/t^2*dt[3]; grd end proc:
#include <math.h> void g(x,y,z,grd) double x; double y; double z; double grd[3]; { double dt[3]; double t; { dt[2] = 2.0*z; t = z*z; grd[0] = cos(x)*z-sin(x)*t; grd[1] = 0.0; grd[2] = sin(x)+cos(x)*dt[2]-1/(t*t)*dt[2]; return; } }
C⁡g,ansi,mode=single,optimized
#include <math.h> void g(float x,float y,float z,float grd[3]) { float dt[3]; float t; float t1; float t3; float t5; float t7; { dt[2] = 2.0*z; t = z*z; t1 = cosf(x); t3 = sinf(x); grd[0] = -t3*t+t1*z; grd[1] = 0.0; t5 = dt[2]; t7 = t*t; grd[2] = t3+t1*t5-1/t7*t5; return; } }
A Maple procedure which has a matrix A and vector x for inputs, updates the input vector b with the result, and returns no value.
m := proc(n,A,x,b) local i,j,s; for i to n do s := 0; for j to n do s := s+A[i,j]*x[j] end do; b[i] := s; end do; NULL end proc:
C⁡m,declarations=A::array⁡1..n,1..n,x::array⁡1..n,b::array⁡1..n
void m(n,A,x,b) double n; double *A; double *x; double *b; { int i; int j; double s; { for(i = 1;i <= n;i++) { s = 0.0; for(j = 1;j <= n;j++) s += A[(i-1)*n+j-1]*x[j-1]; b[i-1] = s; } return; } }
A Maple procedure which creates and returns a matrix. The C code generated from this example dynamically allocates storage for A.
z := proc(m::integer,n::integer) local r, A, i, j; r := min(m,n); A := array(1..r,1..r); for i to r do for j to r do A[i,j] := 0 end do end do; return A; end proc:
C⁡z
#include <math.h> #include <stdlib.h> double *z(m,n) int m; int n; { double *A; int i; int j; int r; { r = (m<n ? m : n); A = (double *) malloc(sizeof(double)*(r*r)); for(i = 1;i <= r;i++) for(j = 1;j <= r;j++) A[(i-1)*r+j-1] = 0.0; return(A); } }
See Also
codegen
codegen[C](deprecated)
CodeGeneration
CodeGeneration[C]
Writing Efficient Maple Code
Download Help Document