![]()
Code Generation
" From equations to source code
¨C General application development (software to software)
¨C Real-time simulation (software to hardware via RT platform)
![]()
" Automate the model derivation and programming process
¨C More target languages
¨C Optimized code generation and equation simplification
4.3 ´úÂëÉú³É
Code generation ÊÇMapleÖг£ÓõÄÒ»¸ö¹¤¾ß£¬Ä¿µÄÊǽ«MapleµÄÓ¦Óõ½ÆäËûϵͳ¡£Maple¿ÉÒÔת»»¹«Ê½¡¢ÊýÖµ³ÌÐò¡¢Êý¾Ý¼¯¡¢¾ØÕóµÈµ½±àÒëÓïÑÔ¡£MapleÖ§³ÖµÄת»»ÓïÑÔ°üÀ¨C¡¢Java¡¢Visual Basic¡¢Matlab¡¢Fortran¡£
restart; with(CodeGeneration);
[C, Fortran, IntermediateCode, Java, LanguageDefinition, Matlab,
Names, Save, Translate, VisualBasic]
4.3.1 ת»» Maple ¹«Ê½
Àý×Ó£º¼ÆËãÒ»¸ö 3x3 ¾ØÕ󣨰üº¬·ûºÅÏµÄÄæ¾ØÕ󣬲¢½«½á¹ûת»»ÎªC´úÂë¡£
ÀûÓÃ×ó²àµÄÃæ°å£¬ÊäÈëÒ»¸ö 3x3 ¾ØÕ󣬾ØÕóÈçÏ£º
M := Matrix(3, 3, [[a, 3, c], [1, b, 2], [-1, 0, -1]]);
ʹÓÃÓÒ¼ü²Ëµ¥»òÃüÁî¼ÆËãMµÄÄæ¾ØÕó¡£
Minv := 1/M;
Minv:=Matrix(%id = 18446744074328686894)
Êä³öÄæ¾ØÕó½á¹ûµ½C´úÂë¡£
C(Minv);
cg0[0][0] = b / (3 - c * b + a * b);
cg0[0][1] = -3 / (3 - c * b + a * b);
cg0[0][2] = (-6 + c * b) / (3 - c * b + a * b);
cg0[1][0] = 1 / (3 - c * b + a * b);
cg0[1][1] = (a - c) / (3 - c * b + a * b);
cg0[1][2] = (2 * a - c) / (3 - c * b + a * b);
cg0[2][0] = -b / (3 - c * b + a * b);
cg0[2][1] = 3 / (3 - c * b + a * b);
cg0[2][2] = -(-3 + a * b) / (3 - c * b + a * b);
ÉÏÃæµÄ´úÂë¿ÉÒÔÕý³£¹¤×÷£¬µ«ÊÇЧÂʲ»¸ß£¬ÒòΪËü¶à´ÎÖØ¸´¼ÆËãÁ˱í´ïʽ(-3 + b * c - a * b) ¡£Õâ¸ö±í´ïʽӦ¸Ã¼ÆËãÒ»´Î£¬²¢´æ´¢Îª±äÁ¿£¬ÒÔ±ãÒÔËû±í´ïʽµ÷Óá£ÎÒÃÇ¿ÉÒÔͨ¹ýÔÚCÊä³öÃüÁîÖмÓÈë optimize Ñ¡ÏîʵÏÖÕâÒ»µã¡£
ͨ³££¬optimizeÑ¡Ïî»á×îС»¯Êä³ö´úÂëÖÐËãÊõ¼ÆËãµÄ´ÎÊý¡£
C(Minv, optimize);
t1 = (int) ((double) c * (double) b);
t2 = (int) ((double) a * (double) b);
t4 = 1 / (3 - t1 + t2);
t5 = b * t4;
t6 = 3 * t4;
cg1[0][0] = t5;
cg1[0][1] = -t6;
cg1[0][2] = (-6 + t1) * t4;
cg1[1][0] = t4;
cg1[1][1] = (a - c) * t4;
cg1[1][2] = (2 * a - c) * t4;
cg1[2][0] = -t5;
cg1[2][1] = t6;
cg1[2][2] = -(-3 + t2) * t4;
ÏÖÔÚÊä³ö´úÂëµÄЧÂʵõ½ÁËÌá¸ß¡£
4.3.2 ת»»Maple³ÌÐò
Àý×Ó£º½« Maple µÄÅ£¶Ù·½·¨³ÌÐòת»»Îª C£¬Java£¬Matlab£¬Fortran ºÍ VB¡£
ÏÂÃæµÄ Maple ³ÌÐòʹÓÃÅ£¶Ù·½·¨¸ø¶¨³õʼµã¼ÆËãÁË
cos(a x + b)
µÄ¸ù¡£Óû§ÊäÈëÕûÊý a ºÍ b£¬ÒÔ¼°³õʼµã¡£
f := proc(a::integer, b::integer, x::float)
local x0, x1, v, vp;
x1 := x;
x0 := x+1;
while abs(x1-x0)>10^(-3) do
v := cos(a*x1+b);
vp := -a*sin(a*x1+b);
x0 := x1;
x1 := x1-v/vp;
end do;
x1;
end proc:
f(2, 3, .3);
0.8561944904
cos(2*%+3);
-10
6.153101422 10
ת»»³ÌÐòΪ C¡£×¢Òâµ½ Maple °üº¬ÁË C's math.h ¿âÎļþ£¬Í¬Ê±ËµÃ÷ÁËÊäÈë±äÁ¿ÊÇ int ºÍ double£¬¶ÔÓ¦µÄ Maple Êý¾ÝÀàÐÍÊÇ integer ºÍ float.
C(f);
#include <math.h>
double f (int a, int b, double x)
{
double x0;
double x1;
double v;
double vp;
x1 = x;
x0 = x + 0.1e1;
while (0.1e1 / 0.1000e4 < fabs(x1 - x0))
{
v = cos((double) a * x1 + (double) b);
vp = -(double) a * sin((double) a * x1 + (double) b);
x0 = x1;
x1 = x1 - v / vp;
}
return(x1);
}
ת»»³ÌÐòµ½ Fortran
Fortran(f);
doubleprecision function f (a, b, x)
integer a
integer b
doubleprecision x
doubleprecision x0
doubleprecision x1
doubleprecision v
doubleprecision vp
x1 = x
x0 = x + 0.1D1
100 continue
if (0.1D1 / 0.1000D4 .lt. abs(x1 - x0)) then
v = cos(dble(a) * x1 + dble(b))
vp = -dble(a) * sin(dble(a) * x1 + dble(b))
x0 = x1
x1 = x1 - v / vp
goto 100
end if
f = x1
return
end
ת»»³ÌÐòµ½ Java£¬×¢Òâµ½Êä³öµÄ´úÂë°üº¬ÁË java.lang.Math Àà¡£
Java(f);
import java.lang.Math;
class CodeGenerationClass {
public static double f (int a, int b, double x)
{
double x0;
double x1;
double v;
double vp;
x1 = x;
x0 = x + 0.1e1;
while (0.1e1 / 0.1000e4 < Math.abs(x1 - x0))
{
v = Math.cos((double) a * x1 + (double) b);
vp = -(double) a * Math.sin((double) a * x1 + (double) b);
x0 = x1;
x1 = x1 - v / vp;
}
return(x1);
}
}
ת»»³ÌÐòµ½ VB¡£
VisualBasic(f);
Imports System.Math
Public Module CodeGenerationModule
Public Function f( _
ByVal a As Integer, _
ByVal b As Integer, _
ByVal x As Double) As Double
Dim x0 As Double
Dim x1 As Double
Dim v As Double
Dim vp As Double
x1 = x
x0 = x + 0.1E1
Do While (0.1E1 / 0.1000E4 < Abs(x1 - x0))
v = Cos(CDbl(a) * x1 + CDbl(b))
vp = -CDbl(a) * Sin(CDbl(a) * x1 + CDbl(b))
x0 = x1
x1 = x1 - v / vp
Loop
Return x1
End Function
End Module
ת»»³ÌÐòµ½ MATLAB
Matlab(f);
function freturn = f(a, b, x)
x1 = x;
x0 = x + 0.1e1;
while (0.1e1 / 0.1000e4 < abs(x1 - x0))
v = cos(a * x1 + b);
vp = -a * sin(a * x1 + b);
x0 = x1;
x1 = x1 - v / vp;
end
freturn = x1;
4.3.3 ת»»µ½ÐµÄÄ¿±êÓïÑÔ£¨¿ÉÑ¡£©
ʹÓà LanguageDefinition ×Ó³ÌÐò°ü£¬Äã¿ÉÒÔÌí¼ÓÓïÑÔÉèÖã¬ÒÔ±ã CodeGeneration ¿ÉÒÔת»»¡£ Äã¿ÉÒÔͨ¹ý´´½¨Ò»¸öеÄÓïÑÔ¶¨Ò壬»ò¼Ì³ÐÏÖÓÐÓïÑÔ¶¨ÒåµÄͬʱ¸²¸ÇÏ£Íû¸Ä±äµÄ²¿·Ö£¬ÊµÏÖÕâ¸öÄ¿µÄ¡£
with(LanguageDefinition);
[Add, DefaultPrinter, Define, GenericPrinter, Get, GetInstance,
IsDefined, ListLanguages]
£¨ÎÒÃǽ«ÔÚAdvanced Maple ProgrammingµÚ4²¿·ÖmodulesÖÐѧϰÕâЩ֪ʶ¡££©
m := 'module()
export PrintTarget, Printer;
PrintTarget := proc()
Printer:-PrintTarget(args):
end proc:
Printer := eval(LanguageDefinition:-Get("default")):-Printer;
Printer:-AddFunction("Pi", [anything]::anything, "pi");
Printer:-AddOperator(Names:-Assignment = " := ");
end module':
Add º¯ÊýÔö¼Ó module µÄ¶¨Ò壬¶¨Òå CodeGeneration ±í¸ñÖпÉʶ±ðµÄÓïÑÔ¡£Õâ¸öÓïÑÔ¿ÉÒÔͨ¹ý Translate ºÍ Get ʹÓá£
Add("MyLanguage", m);
Translate ÃüÁîת»» Maple ´úÂëµ½¶¨ÒåµÄÄ¿±êÓïÑÔ¡£
Translate(Pi, language = "MyLanguage");
cg2 := pi;
m := 'module() export PrintTarget, Printer;
Printer := eval(LanguageDefinition:-Get("C")):-Printer;
PrintTarget := proc(ic, digits::posint, prec::name, func_prec, namelist)::string;
Printer:-PrintTarget(args);
end proc:
# set precedence of addition higher than that of multiplication
Printer:-SetPrecedence(
Names:-Addition = Printer:-GetPrecedence(Names:-Multiplication)+5);
end module':
LanguageDefinition:-Add("MyLanguage", m);
Translate(x*y+z, language="MyLanguage");
cg3 = x * y + z;
4.3.4 Options for tailoring the generated code
There are fundamental differences between the Maple language and the target languages supported by CodeGeneration that make direct translation difficult in some cases. For example, Maple is an interpreted language, has a rich set of data types, and allows implicit returns. The target languages support a more limited set of basic types and require variable and return types to be known at compile time.
So the CodeGeneration functions often must choose the most suitable translation in cases when more than one result is possible. Occasionally, the choices Maple makes in generating the code made may not be the ones you expect. However, Maple provides a number of options to customize the output. Options common to all the CodeGeneration functions are described on the CodeGenerationOptions help page.
In the following example, all the parameters are assigned a floating-point type by default.
f := proc (x, y, z) return y*x-y*z+x*z end proc; C(f);
double f (double x, double y, double z)
{
return(x * y - y * z + x * z);
}
Change the default type given to untyped variables by using the defaulttype option.
C(f, defaulttype = integer);
int f (int x, int y, int z)
{
return(x * y - y * z + x * z);
}
Maple tries to deduce the types of untyped variables. The default type is given only to those variables left untyped after the automatic type deduction process. In the following example, the parameters y and z are given a floating-point type because they are in an expression involving the float variable x. Thus, the default type, integer, is not assigned.
f := proc (x::float, y, z) y*x-y*z+x*z end proc; C(f, defaulttype = integer);
double f (double x, double y, double z)
{
return(x * y - y * z + x * z);
}
You can turn off the automatic type deduction system by using the deducetypes=false option. In the following example, parameters y and z are now given the default type.
C(f, defaulttype = integer, deducetypes = false);
double f (double x, int y, int z)
{
return(x * (double) y - (double) (y * z) + x * (double) z);
}
You can turn off explicit type coercion using the coercetypes=false option.
C(f, defaulttype = integer, deducetypes = false, coercetypes = false);
double f (double x, int y, int z)
{
return(x * y - y * z + x * z);
}
You can obtain more control over how types are assigned by declaring the parameter, local variable, and return types explicitly in procedures or by using the declare option with expressions.
C(1+x+y, declare = [x::float, y::integer]);
cg0 = 0.1e1 + x + (double) y;