1.NH 1 2CODE GENERATION 3.LP 4GENTRAN generates numerical programs based on algorithmic specifications 5in the VAXIMA programming language and derived symbolic expressions 6produced by VAXIMA evaluations. FORTRAN, RATFOR, or C code can 7be produced. Type declarations can be generated, and comments and 8other literal strings can be inserted into the generated code. In 9addition, large arithmetic expressions can be optimized and segmented 10into a sequence of subexpressions of manageable size. 11.LP 12This section explains how to select the target language, generate 13code, control expression optimization and segmentation, and how to 14generate temporary variable names. 15.NH 2 16Target Language Selection 17.LP 18Before generating code, the target numerical language must be 19selected. GENTRAN is currently able to generate FORTRAN, RATFOR, 20and C code. The global lisp variable \fI*gentranlang\fR determines 21which type of code is produced. \fI*gentranlang\fR can be 22set at the user and LISP levels. 23It can be set to any value, but 24only three atoms have special meaning: \fIfortran\fR, \fIratfor\fR, and 25\fIc\fR. Any other value is assumed to mean 26\fIfortran\fR. \fI*gentranlang\fR is always initialized to \fIfortran\fR. 27At the Macsyma user level, 28.DS 29.ft CR 30gentranlang(ratfor); 31.ft 32.DE 33for example, sets \fI*gentranlang\fR to \fIratfor\fR. 34.NH 2 35Translation 36.LP 37The \fIgentran\fR (\fIgen\fRerate/\fItran\fRslate) command is used to generate 38numerical code and also to translate code from algorithmic 39specifications in the VAXIMA programming language to code in 40the target numerical language. Section 2.3 explains code 41\fIgeneration\fR. This section explains code \fItranslation\fR. 42.LP 43A substantial subset of all expressions and statements in the 44VAXIMA programming language can be translated directly into 45numerical code. The \fIgentran\fR command takes VAXIMA 46statements or procedure definitions, and translates them 47into code in the target language. 48.SH 49User-Level Syntax: 50.RS 51.DS L 52.ft CR 53\fIgentran(\fRstmt1,stmt2,...,stmtn {,[f1,f2,...,fm]}); 54.ft 55.DE 56.RE 57where stmt1,stmt2,...,stmtn is a sequence of 58one or more stmt's, each of which is any VAXIMA user level 59expression, (simple, group, or block) statement, or procedure definition 60that can be translated by GENTRAN into the target language[1]. Each 61.FS 62[1] See Appendix A for a complete list of VAXIMA user-level expression 63and statement types that can be translated. 64.FE 65stmt may contain calls to the special functions described in 66sections 2.2.1 - 2.2.5 and 2.3.1 - 2.3.4. 67.LP 68[f1,f2,...,fm] is an optional argument list containing one or 69more f's, where each f is one of: 70.RS 71.DS L 72.ft CR 73a string = an output file 74\fItrue\fR = the terminal 75\fIfalse\fR = the current output file(s) 76\fIall\fR = all files currently open for output by GENTRAN 77 (see sect. 4) 78.ft 79.DE 80.RE 81.SH 82LISP Level Syntax: 83.RS 84.DS L 85.ft CR 86\fI(gentran '(\fRstmt1 stmt2 ... stmtn) '(f1 f2 ... fm)) 87.ft 88.DE 89.RE 90where stmt1 stmt2 ... stmtn is a sequence of one or more 91stmt's, each of which is any VAXIMA LISP level expression, 92(simple, group, or block) statement, or procedure definition that 93can be translated by GENTRAN into the target language[2]. Each 94.FS 95[2] See Appendix A for a complete list of VAXIMA LISP level 96expression and statement types that can be translated. 97.FE 98stmt may contain calls to the special functions described in 99sections 2.2.1 - 2.2.5 and 2.3.1 - 2.3.4. 100.LP 101(f1 f2 ... fm) is an argument list containing any number 102of f's, where each f is one of: 103.RS 104.DS L 105.ft CR 106a string = an output file 107\fIt\fR = the terminal 108\fInil\fR = the current output file(s) 109\fI$all\fR = all files currently open for output by GENTRAN 110 (see sect. 4) 111.ft 112.DE 113.RE 114.SH 115Side Effects: 116.LP 117\fIgentran\fR translates each stmt into formatted code in the 118target language. 119.LP 120If the file list is empty, generated 121code is simply written to the current output file. However, 122if it contains one or more file arguments, 123then the current output file is temporarily 124overridden. Generated code is written to each file represented 125by f1,f2,...,fm for this command only. Files which were open 126prior to the call to \fIgentran\fR will remain open after the call, 127and files which did not exist or were not open prior 128to the call will be created (if necessary), opened, written 129to (or appended onto), and closed. The output file stack 130will be exactly the same both before and after the call. 131.SH 132Return Value: 133.LP 134\fIgentran\fR returns (a list of) the name(s) of the file(s) to 135which code was written. 136.SH 137Diagnostic Messages: 138.LP 139wrong type of arg 140.LP 141exp 142.br 143cannot be translated 144.SH 145User Level Examples: 146.DS L 147.ft CR 148(c1) gentranlang(fortran)$ 149.ft 150.DE 151.DS L 152.ft CR 153(c2) gentran( for i:1 thru n do v[i]:0.0 ); 154 do 25001 i=1,n 155 v(i)=0.0 15625001 continue 157 158(d2) true 159.ft 160.DE 161.DS L 162.ft CR 163(c3) gentranlang(ratfor)$ 164.ft 165.DE 166.DS L 167.ft CR 168(c4) gentran( for i:1 thru n do 169 for j:i+1 thru n do 170 ( 171 x[j,i] : x[i,j], 172 y[j,i] : y[i,j] 173 ) ); 174do i=1,n 175 do j=i+1,n 176 { 177 x(j,i)=x(i,j) 178 y(j,i)=y(i,j) 179 } 180 181(d4) true 182.ft 183.DE 184.DS L 185.ft CR 186(c5) gentranlang(c)$ 187.ft 188.DE 189.DS L 190.ft CR 191(c6) gentran( p : a*x^2 + b*x + c ); 192p=a*power(x,2)+b*x+c; 193 194(d6) true 195.ft 196.DE 197.SH 198LISP Level Examples: 199.DS L 200.ft CR 201<1>: (setq *gentranlang 'fortran) 202fortran 203.ft 204.DE 205.DS L 206.ft CR 207<1>: (gentran '(((mdo) i 1 nil nil n nil ((msetq) ((v) i) 0.0))) ()) 208 do 25001 i=1,n 209 v(i)=0.0 21025001 continue 211t 212.ft 213.DE 214.DS L 215.ft CR 216<1>: (setq *gentranlang 'ratfor) 217ratfor 218.ft 219.DE 220.DS L 221.ft CR 222<1>: (gentran '(((mdo) i 1 nil nil n nil 223 ((mdo) j ((mplus) i 1) nil nil n nil 224 ((mprogn) 225 ((msetq) ((x) j i) ((x) i j)) 226 ((msetq) ((y) j i) ((y) i j)))))) ()) 227do i=1,n 228 do j=i+1,n 229 { 230 x(j,i)=x(i,j) 231 y(j,i)=y(i,j) 232 } 233t 234.ft 235.DE 236.DS L 237.ft CR 238<1>: (setq *gentranlang 'c) 239c 240.ft 241.DE 242.DS L 243.ft CR 244<1>: (gentran '(((msetq) p ((mplus) ((mtimes) a ((mexpt) x 2)) 245 ((mtimes) b x) 246 c))) ()) 247p=a*power(x,2)+b*x+c; 248t 249.ft 250.DE 251.NH 3 252Special Arguments 253.LP 254In addition to statements in the VAXIMA programming language, the 255\fIgentran\fR function can also translate special arguments 256into numerical code. Several of these arguments are described 257in this section. 258.SH 259Subprogram Headings & Bodies 260.LP 261FORTRAN and RATFOR function and subroutine headings, and C procedure 262headings can be generated separately from their corresponding bodies 263of code with the arguments given in this section. 264.SH 265User Level Syntax: 266.RS 267.DS L 268.ft CR 269\fIsubroutine(\fRname(p1,p2,...,pn)) 270.sp 271\fIfunction({\fRtype,} name(p1,p2,...,pn)) 272.sp 273\fIcprocedure(\fR{type,} name(p1,p2,...,pn)) 274.sp 275\fIbody(\fRstmt1,stmt2,...,stmtn) 276.ft 277.DE 278.RE 279where name is an atom, and p1,p2,...,pn is a sequence 280of zero or more atoms, representing a subroutine, function or 281procedure name, and a list of parameter names, respectively; type 282is an optional argument which, if supplied to either 283\fIfunction\fR or \fIcprocedure\fR, is a string representing the 284function's or procedure's return value type (e.g., "real*8", 285"double", etc.); and stmt1,stmt2,...,stmtn is a sequence of zero or 286more user level translatable VAXIMA statements representing the 287body of a subprogram. 288.SH 289LISP Level Syntax: 290.RS 291.DS L 292.ft CR 293\fI(($subroutine) \fR((name) p1 p2 ... pn)) 294.sp 295\fI(($function) \fR{type} ((name) p1 p2 ... pn)) 296.sp 297\fI(($cprocedure) \fR{type} ((name) p1 p2 ... pn)) 298.sp 299\fI(($body) \fRstmt1 stmt2 ... stmtn) 300.ft 301.DE 302.RE 303where name is an atom, and p1 p2 ... pn is a sequence 304of zero or more atoms, representing a subroutine function or 305procedure name, and a list of parameter names, respectively; 306type is an optional argument which, if supplied to either 307\fI$function\fR or \fI$cprocedure\fR, is an atom representing the 308function's or procedure's return value type (e.g., real*8, double, etc.); 309and stmt1 stmt2 ... stmtn is a sequence of zero or more LISP 310level translatable VAXIMA statements representing the body of a 311subprogram. 312.SH 313User Level Examples: 314.DS L 315.ft CR 316(c1) gentranlang(fortran)$ 317.ft 318.DE 319.DS L 320.ft CR 321(c2) gentran( function("real", f(x,y)), 322 body( x:x^2, y:y^2, f:abs(x-y) ) )$ 323 real function f(x,y) 324 x=x**2 325 y=y**2 326 f=abs(x-y) 327 return 328 end 329.ft 330.DE 331.DS L 332.ft CR 333(c3) gentranlang(ratfor)$ 334.ft 335.DE 336.DS L 337.ft CR 338(c4) gentran( subroutine(f(x,y)), 339 body( y:abs(x^2-y^2) ) )$ 340subroutine f(x,y) 341y=abs(x**2-y**2) 342return 343end 344.ft 345.DE 346.DS L 347.ft CR 348(c5) gentranlang(c)$ 349.ft 350.DE 351.DS L 352.ft CR 353(c6) gentran( cprocedure("float", f(x,y)) )$ 354float f(x,y) 355.ft 356.DE 357.SH 358LISP Level Examples: 359.DS L 360.ft CR 361<1>: (setq *gentranlang 'fortran) 362fortran 363.ft 364.DE 365.DS L 366.ft CR 367<1>: (gentran '( (($function) real ((f) x y)) 368 (($body) ((msetq) x ((mexpt) x 2)) 369 ((msetq) y ((mexpt) y 2)) 370 ((msetq) f ((mabs) 371 ((mplus) x ((mminus) y)))))) 372 ()) 373 real function f(x,y) 374 x=x**2 375 y=y**2 376 f=abs(x-y) 377 return 378 end 379t 380.ft 381.DE 382.DS L 383.ft CR 384<1>: (setq *gentranlang 'ratfor) 385ratfor 386.ft 387.DE 388.DS L 389.ft CR 390<1>: (gentran '( (($subroutine) ((f) x y)) 391 (($body) ((msetq) y 392 ((mabs) 393 ((mplus) ((mexpt) x 2) 394 ((mminus) ((mexpt) y 2))))))) 395 ()) 396subroutine f(x,y) 397y=abs(x**2-y**2) 398return 399end 400t 401.ft 402.DE 403.DS L 404.ft CR 405<1>: (setq *gentranlang 'c) 406c 407.ft 408.DE 409.DS L 410.ft CR 411<1>: (gentran '( (($cprocedure) float ((f) x y)) ) ()) 412float f(x,y) 413t 414.ft 415.DE 416.SH 417Other Special Arguments 418.LP 419The arguments described in this section allow numerical language statements 420to be generated which do not have semantically equivalent statements in 421the VAXIMA programming language. 422.SH 423User Level Syntax: 424.RS 425.DS L 426.ft CR 427\fIbreak()\fR 428.ft 429.DE 430.DS L 431.ft CR 432\fIstop()\fR 433.ft 434.DE 435.DS L 436.ft CR 437\fIend()\fR 438.ft 439.DE 440.DS L 441.ft CR 442\fIbegin_group\fR 443.ft 444.DE 445.DS L 446.ft CR 447\fIend_group\fR 448.ft 449.DE 450.RE 451.SH 452LISP Level Syntax: 453.RS 454.DS L 455.ft CR 456\fI(($break))\fR 457.ft 458.DE 459.DS L 460.ft CR 461\fI(($stop))\fR 462.ft 463.DE 464.DS L 465.ft CR 466\fI(($end))\fR 467.ft 468.DE 469.DS L 470.ft CR 471\fI$begin_group\fR 472.ft 473.DE 474.DS L 475.ft CR 476\fI$end_group\fR 477.ft 478.DE 479.RE 480.SH 481User Level Examples: 482.DS L 483.ft CR 484(c1) gentranlang(fortran)$ 485.ft 486.DE 487.DS L 488.ft CR 489(c2) gentran( for n:1 thru 100 do 490 if f(n)<0 then break() )$ 491 do 25001 n=1,100 492 if (.not.f(n).lt.0.0) goto 25002 493 goto 25003 49425002 continue 49525001 continue 49625003 continue 497.ft 498.DE 499.DS L 500.ft CR 501(c3) gentran( stop(), end() )$ 502 stop 503 end 504.ft 505.DE 506.DS L 507.ft CR 508(c4) gentranlang(ratfor)$ 509.ft 510.DE 511.DS L 512.ft CR 513(c5) gentran( for n:1 thru 100 do 514 if f(n)<0 then break() )$ 515do n=1,100 516 if (f(n)<0.0) 517 break 518.ft 519.DE 520.DS L 521.ft CR 522(c6) gentranlang(c)$ 523.ft 524.DE 525.DS L 526.ft CR 527(c7) gentran( begin_group, 528 for n:1 thru 100 do 529 if f(n)<0 then break() )$ 530{ 531 for (n=1;!(n>100);n=n+1) 532 fi(f(n)<0.0) 533 break; 534.ft 535.DE 536.DS L 537.ft CR 538(c8) gentran( if n>100 then stop(), 539 end_group )$ 540 if (n>100.0) 541 exit(0); 542} 543.ft 544.DE 545.SH 546LISP Level Examples: 547.DS L 548.ft CR 549<1>: (setq *gentranlang 'fortran) 550fortran 551.ft 552.DE 553.DS L 554.ft CR 555<1>: (gentran '( ((mdo) n 1 nil nil 100 nil 556 ((mcond) ((mlessp) ((f) n) 0) 557 (($break)) 558 t 559 $false)) ) ()) 560 do 25001 n=1,100 561 if (.not.f(n).lt.0.0) goto 25002 562 goto 25003 56325002 continue 56425001 continue 56525003 continue 566t 567.ft 568.DE 569.DS L 570.ft CR 571<1>: (gentran '( (($stop)) (($end)) ) ()) 572 stop 573 end 574t 575.ft 576.DE 577.DS L 578.ft CR 579<1>: (setq *gentranlang 'ratfor) 580ratfor 581.ft 582.DE 583.DS L 584.ft CR 585<1>: (gentran '( ((mdo) n 1 nil nil 100 nil 586 ((mcond) ((mlessp) ((f) n) 0) 587 (($break)) 588 t 589 (($false)))) ) ()) 590do n=1,100 591 if (f(n)<0.0) 592 break 593t 594.ft 595.DE 596.DS L 597.ft CR 598<1>: (setq *gentranlang 'c) 599c 600.ft 601.DE 602.DS L 603.ft CR 604<1>: (gentran '( $begin_group 605 ((mdo) n 1 nil nil 100 nil 606 ((mcond) ((mlessp) ((f) n) 0) 607 (($break)) 608 t 609 $false)) ) ()) 610{ 611 for (n=1;!(n>100);n=n+1) 612 if (f(n)<0.0) 613 break; 614t 615.ft 616.DE 617.DS L 618.ft CR 619<1>: (gentran '( ((mcond) ((mgreaterp) n 100) 620 (($stop)) 621 t 622 $false) 623 $end_group ) ()) 624 if (n>100.0) 625 exit(0); 626} 627t 628.ft 629.DE 630.LP 631Translation is a convenient method of producing numerical code 632when the exact behavior of the resultant code is known. It gives 633the VAXIMA user who is familiar with the syntax of 634statements in the VAXIMA programming language the ability to 635write code in a numerical programming language without knowing 636the exact syntactical requirements of the language. However, 637the \fIreal\fR power of the \fIgentran\fR command lies in its ability to 638generate code: it can produce numerical code from symbolic 639expressions derived in VAXIMA in addition to translating 640statements directly. This aspect is described in the next section. 641.NH 2 642Code Generation: Evaluation Prior to Translation 643.LP 644Section 2.2 showed how VAXIMA statements and expressions can 645be translated directly into the target language. This section 646shows how to indicate that parts of those statements and expressions 647are to be handed to VAXIMA to be evaluated before being 648translated. In other words, this section explains how to generate 649numerical code from algorithmic specifications (in the VAXIMA 650programming language) and symbolic expressions. 651.LP 652Each of the following four subsections describes a special 653function that can be used to request partial or 654full evaluation of expressions prior to translation. Note that 655these functions have the described effects \fIonly\fR when used 656as arguments to the \fIgentran\fR function. 657.NH 3 658The eval Function 659.SH 660User Level Syntax: 661.RS 662.DS L 663.ft CR 664\fIeval(\fRexp) 665.ft 666.DE 667.RE 668where exp is any VAXIMA user level expression or statement which, 669after evaluation by VAXIMA, results in an expression that can 670be translated by \fIgentran\fR into the target language. 671.SH 672LISP Level Syntax: 673.RS 674.DS L 675.ft CR 676\fI(($eval) \fRexp) 677.ft 678.DE 679.RE 680where exp is any VAXIMA LISP level expression or statement 681which, after evaluation by VAXIMA, results in an expression 682that can be translated by \fIgentran\fR into the target language. 683.SH 684Side Effects: 685.LP 686When \fIeval\fR is called on an argument which is to be translated, 687it tells \fIgentran\fR to give the expression to VAXIMA for evaluation 688first, and then to translate the result of that evaluation. 689.SH 690User Level Example: 691.LP 692The following formula, f, has been derived symbolically: 693.RS 694.DS L 695.ft CR 696 2 6972 x - 5 x + 6 698.ft 699.DE 700.RE 701We wish to generate an assignment statement for the quotient 702of f and its derivative. 703.DS L 704.ft CR 705(c1) gentran( q : eval(f)/eval(diff(f,x)) ); 706 q=(6.0-5.0*x+2.0*x**2)/(-5.0+4.0*x) 707 708(d1) true 709.ft 710.DE 711.SH 712LISP Level Example: 713.LP 714The following formula, f, has been derived symbolically: 715.RS 716.DS L 717.ft CR 718((mplus) ((mtimes) 2 ((mexpt) x 2)) 719 ((mtimes) -5 x) 720 6) 721.ft 722.DE 723.RE 724We wish to generate an assignment statement for the quotient of 725f and its derivative. 726.DS L 727.ft CR 728<1>: (gentran '(((msetq) q ((mquotient) (($eval) f) 729 (($eval) (($diff) f x))))) ()) 730 q=(6.0-5.0*x+2.0*x**2)/(-5.0+4.0*x) 731t 732.ft 733.DE 734.NH 3 735The rsetq Function 736.LP 737In many applications, assignments must be generated in which the 738left-hand side is some known variable name, but the 739right-hand side is an expression that must be evaluated. For 740this reason, a special function is provided to 741indicate that the expression on the right-hand side is to be 742evaluated prior to translation. This special function is \fIrsetq\fR. 743.SH 744User Level Syntax: 745.RS 746.DS L 747.ft CR 748\fIrsetq(\fRvar, exp) 749.ft 750.DE 751.RE 752where var is any VAXIMA user level variable, matrix or array 753element, and exp is any VAXIMA user level expression which, 754after evaluation by VAXIMA, results in an expression that can 755be translated by \fIgentran\fR into the target language. 756.SH 757LISP Level Syntax: 758.RS 759.DS L 760.ft CR 761\fI(($rsetq) \fRvar exp) 762.ft 763.DE 764.RE 765where var is any VAXIMA LISP level variable, matrix or array 766element, and exp is any VAXIMA LISP level expression which, 767after evaluation by VAXIMA, results in an expression that can 768be translated by \fIgentran\fR into the target language. 769.SH 770User Level Example: 771.DS L 772.ft CR 773(c1) gentran( rsetq( deriv, diff(x^4-x^3+2*x^2-1,x) ) ); 774 deriv=4.0*x-3.0*x**2+4.0*x**3 775 776(d1) true 777.ft 778.DE 779Note: This is equivalent to a call of the form 780.RS 781.DS L 782.ft CR 783gentran( deriv : eval(diff(x^4-x^3+2*x^2-1,x)) ); 784.ft 785.DE 786.RE 787.SH 788LISP Level Example: 789.DS L 790.ft CR 791<1>: (gentran '((($rsetq) deriv 792 (($diff) ((mplus) ((mexpt) x 4) 793 ((mminus) ((mexpt) x 3)) 794 ((mtimes) 2 ((mexpt) x 2)) 795 -1) 796 x))) ()) 797 deriv=4.0*x-3.0*x**2+4.0*x**3 798t 799.ft 800.DE 801.NH 3 802The lsetq Function 803.LP 804When assignments to matrix or array elements must be generated, 805many times the indices of the element must be evaluated first. The 806special function \fIlsetq\fR can be used within a call to \fIgentran\fR 807to indicate that the indices of the matrix or array element on 808the left-hand side of the assignment are to be evaluated prior to 809translation. 810.SH 811User Level Syntax: 812.RS 813.DS L 814.ft CR 815\fIlsetq(\fRvar, exp) 816.ft 817.DE 818.RE 819where var is any VAXIMA user level matrix or array element 820with indices which, after evaluation by VAXIMA, will result in 821expressions that can be translated by \fIgentran\fR, and exp is any 822VAXIMA user level expression that can be translated into the 823target language. 824.SH 825LISP Level Syntax: 826.RS 827.DS L 828.ft CR 829\fI(($lsetq) \fRvar exp) 830.ft 831.DE 832.RE 833where var is any VAXIMA LISP level matrix or array element with 834indices which, after evaluation by VAXIMA, result in expressions 835that can be translated by \fIgentran\fR, and exp is any VAXIMA 836LISP level expression that can be translated into the target language. 837.SH 838User Level Example: 839.LP 840We wish to generate assignments which assign zeros to all 841elements on the main diagonal of m, an n x n matrix. 842.DS L 843.ft CR 844(c1) for j:1 thru n do 845 gentran( lsetq( m[j,j], 0.0 ) ); 846 m(1,1)=0.0 847 m(2,2)=0.0 848 . 849 . 850 . 851 m(\fIn\fR,\fIn\fR)=0.0 852 853(d1) done 854.ft 855.DE 856Note: This is equivalent to a call of the form 857.DS L 858.ft CR 859for j:1 thru n do 860 gentran( m[eval(j),eval(j)] : 0.0 ); 861.ft 862.DE 863.SH 864LISP Level Example: 865.LP 866We wish to generate assignments which assign zeros to all 867elements on the main diagonal of m, an n x n matrix. 868.DS L 869.ft CR 870<1>: (do ((j 1 (1+ j))) 871 ((> j n)) 872 (gentran '((($lsetq) ((m) j j) 0.0)) ())) 873 m(1,1)=0.0 874 m(2,2)=0.0 875 . 876 . 877 . 878 m(\fIn\fR,\fIn\fR)=0.0 879nil 880.ft 881.DE 882.NH 3 883The lrsetq Function 884.LP 885In applications in which evaluated expressions are to be assigned to 886matrix or array elements with evaluated subscripts, the \fIlrsetq\fR 887function can be used. It is a combination of the \fIlsetq\fR and 888\fIrsetq\fR functions described in sections 2.3.2 and 2.3.3. 889.SH 890User Level Syntax: 891.RS 892.DS L 893.ft CR 894\fIlrsetq(\fRvar, exp) 895.ft 896.DE 897.RE 898where var is any VAXIMA user level matrix or array 899element with indices which, after evaluation by VAXIMA, 900will result in expressions that can be translated by \fIgentran\fR; 901and exp is any user level expression which, after evaluation, 902will result in an expression that can be translated by 903\fIgentran\fR into the target language. 904.SH 905LISP Level Syntax: 906.RS 907.DS L 908.ft CR 909\fI(($lrsetq) \fRvar exp) 910.ft 911.DE 912.RE 913where var is any VAXIMA LISP level matrix or array element 914with indices which, after evaluation by VAXIMA, will result in 915expressions that can be translated by \fIgentran\fR; and exp is any 916LISP level expression which, after evaluation, will result in an 917expression that can be translated by \fIgentran\fR into the target 918language. 919.SH 920User Level Example: 921.LP 922The following matrix, m, has been derived symbolically: 923.RS 924.DS L 925.ft CR 926[ a 0 - 1 1 ] 927[ ] 928[ 0 b 0 0 ] 929[ ] 930[ - 1 0 c - 1 ] 931[ ] 932[ 1 0 - 1 d ] 933.ft 934.DE 935.RE 936We wish to generate assignment statements for those elements 937on the main diagonal of the matrix. 938.DS L 939.ft CR 940(c1) for j:1 thru 4 do 941 gentran( lrsetq( m[j,j], m[j,j] ) ); 942 m(1,1)=a 943 m(2,2)=b 944 m(3,3)=c 945 m(4,4)=d 946 947(d1) done 948.ft 949.DE 950Note: This is equivalent to a call of the form 951.DS L 952.ft CR 953for j:1 thru 4 do 954 gentran( m[eval(j),eval(j)] : eval(m[j,j]) ); 955.ft 956.DE 957.SH 958LISP Level Example: 959.LP 960The following matrix, m, has been derived symbolically: 961.RS 962.DS L 963.ft CR 964[ a 0 1 1 ] 965[ ] 966[ 0 b 0 0 ] 967[ ] 968[ - 1 0 c - 1 ] 969[ ] 970[ 1 0 - 1 d ] 971.ft 972.DE 973.RE 974We wish to generate assignment statements for those elements on the main 975diagonal of the matrix. 976.DS L 977.ft CR 978<1>: (do ((j 1 (1+ j))) 979 ((> j 4)) 980 (gentran '((($lrsetq) ((m array) j j) 981 ((m array) j j))) ())) 982 m(1,1)=a 983 m(2,2)=b 984 m(3,3)=c 985 m(4,4)=d 986nil 987.ft 988.DE 989.NH 2 990Type Declarations 991.LP 992Type declarations are automatically generated each time a 993subprogram heading is generated. Type declarations are 994constructed from information stored in the GENTRAN symbol 995table. The user can place entries into the symbol table 996explicitly through calls to the special GENTRAN function \fItype\fR. 997.SH 998User Level Syntax: 999.RS 1000.DS L 1001.ft CR 1002\fItype(\fRtype, v1,v2,...,vn); 1003.ft 1004.DE 1005.RE 1006where v1,v2,...,vn is one or more variables (optionally 1007subscripted to indicate array dimensions), or variable ranges 1008(two letters separated by "-" and enclosed in double 1009quotes). v's are not evaluated unless given as arguments to 1010\fIeval\fR. type is a variable type in the target language. It 1011should be a string or an atom. type is not evaluated unless given as an 1012argument to \fIeval\fR. 1013.SH 1014LISP Level Syntax: 1015.RS 1016.DS L 1017.ft CR 1018\fI(($type) \fRtype v1 v2 ... vn) 1019.ft 1020.DE 1021.RE 1022where v1 v2 ... vn is one or more variables (optionally in 1023lists with array dimensions), or variable ranges (two letters 1024separated by "-"). v's are not evaluated unless given as 1025arguments to \fI$eval\fR. type is a variable type in the target 1026language. It must be an atom. type is not evaluated 1027unless given as an argument to \fI$eval\fR. 1028.SH 1029Side Effects: 1030.LP 1031Entries are placed in the symbol table for each variable or 1032variable range declared in the call to this function. The 1033function call itself is removed from the statement group being 1034translated. Then after translation, type declarations are generated 1035from these symbol table entries before the resulting executable 1036statements are printed. 1037.SH 1038User Level Example: 1039.DS L 1040.ft CR 1041(c1) gentran( type("implicit real*8", "a-h","o-z"), 1042 type("real*8", m(4,4)), 1043 for i:1 thru 4 do 1044 for j:1 thru 4 do 1045 if i=j 1046 then m[i,j] : 1.0 1047 else m[i,j] : 0.0, 1048 type("integer", i,j), 1049 . 1050 . 1051 . 1052 ); 1053.ft 1054.DE 1055.DS L 1056.ft CR 1057 implicit real*8 (a-h,o-z) 1058 real*8 m(4,4) 1059 integer i,j 1060 do 25001 i=1,4 1061 do 25002 j=1,4 1062 if (.not.i.eq.j) goto 25003 1063 m(i,j)=1.0 1064 goto 25004 106525003 continue 1066 m(i,j)=0.0 106725004 continue 106825002 continue 106925001 continue 1070 . 1071 . 1072 . 1073.ft 1074.DE 1075.DS L 1076.ft CR 1077(d1) true 1078.ft 1079.DE 1080.SH 1081LISP Level Example: 1082.DS L 1083.ft CR 1084<1>: (gentran '((($type) |implicit real*8| a-h o-z) 1085 (($type) real*8 ((m) 4 4)) 1086 ((mdo) i 1 nil nil 4 nil 1087 ((mdo) j 1 nil nil 4 nil 1088 ((mcond) ((mequal) i j) 1089 ((msetq) ((m) i j) 1.0) 1090 t 1091 ((msetq) ((m) i j) 0.0)))) 1092 (($type) integer i j) 1093 . 1094 . 1095 . 1096 ) ()) 1097 implicit real*8 (a-h,o-z) 1098 real*8 m(4,4) 1099 integer i,j 1100 do 25001 i=1,4 1101 do 25002 j=1,4 1102 if (.not.i.eq.j) goto 25003 1103 m(i,j)=1.0 1104 goto 25004 110525003 continue 1106 m(i,j)=0.0 110725004 continue 110825002 continue 110925001 continue 1110 . 1111 . 1112 . 1113t 1114.ft 1115.DE 1116.NH 3 1117Subprogram Type Declarations 1118.LP 1119The \fItype\fR function can also be used to declare subprogram 1120types (i.e., subroutine or function) for FORTRAN and RATFOR 1121code, and function types for FORTRAN, RATFOR, and C code. 1122.SH 1123User Level Examples: 1124.DS L 1125.ft CR 1126(c1) gentranlang(ratfor)$ 1127.ft 1128.DE 1129.DS L 1130.ft CR 1131(c2) gentran( fac(n) := block( type(function, fac), 1132 type(integer, fac,n), 1133 f : 1, 1134 for i:2 thru n do 1135 f : f*i, 1136 type(integer, f,i), 1137 return(f) ) ); 1138integer function fac(n) 1139integer n,f,i 1140f=1 1141do i=2,n 1142 f=f*i 1143return(f) 1144end 1145 1146(d2) true 1147.ft 1148.DE 1149.DS L 1150.ft CR 1151(c3) gentranlang(c)$ 1152.ft 1153.DE 1154.DS L 1155.ft CR 1156(c4) gentran( fac(n) := block( type(int, fac,n,i,f), 1157 f : 1, 1158 for i:2 thru n do 1159 f : f*i, 1160 return(f) ) ); 1161int fac(n) 1162int n; 1163{ 1164 int i,f; 1165 f=1; 1166 for (i=2;!(i>n);i=i+1) 1167 f=f*i; 1168 return(f); 1169} 1170 1171(d4) done 1172.ft 1173.DE 1174.SH 1175LISP Level Examples: 1176.DS L 1177.ft CR 1178<1>: (setq *gentranlang 'ratfor) 1179ratfor 1180.ft 1181.DE 1182.DS L 1183.ft CR 1184<1>: (gentran '(((mdefine) ((fac) n) 1185 ((mprog) 1186 (($type) function fac) 1187 (($type) integer fac n) 1188 ((msetq) f 1) 1189 ((mdo) i 2 nil nil n nil 1190 ((msetq) f ((mtimes) f i))) 1191 (($type) integer f i) 1192 ((mreturn) f)))) ()) 1193integer function fac(n) 1194integer n,f,i 1195f=1 1196do i=2,n 1197 f=f*i 1198return(f) 1199end 1200t 1201.ft 1202.DE 1203.DS L 1204.ft CR 1205<1>: (setq *gentranlang 'c) 1206c 1207.ft 1208.DE 1209.DS L 1210.ft CR 1211<1>: (gentran '(((mdefine) ((fac) n) 1212 ((mprog) 1213 (($type) int fac n i f) 1214 ((msetq) f 1) 1215 ((mdo) i 2 nil nil n nil 1216 ((msetq) f ((mtimes) f i))) 1217 ((mreturn) f)))) ()) 1218int fac(n) 1219int n; 1220{ 1221 int i,f; 1222 f=1; 1223 for (i=2;!(i>2);i=i+1) 1224 f=f*i; 1225 return(f); 1226} 1227t 1228.ft 1229.DE 1230.NH 3 1231A Note on Subscripted Variables 1232.LP 1233When generating code for subscripted variables (i.e., matrix and 1234array elements), it is important to keep several things in 1235mind. First of all, when a VAXIMA array is declared with a declaration 1236such as 1237.RS 1238.DS L 1239.ft CR 1240array(a, \fIn\fR); 1241.ft 1242.DE 1243.RE 1244where \fIn\fR is a positive integer, a is actually being declared to 1245be of size \fIn\fR+1. Each of the elements a[0], a[1], ..., a[\fIn\fR] 1246can be used. However, a FORTRAN or RATFOR declaration such as 1247.RS 1248.DS L 1249.ft CR 1250dimension a(\fIn\fR) 1251.ft 1252.DE 1253.RE 1254only declares a to be of size \fIn\fR. Only the elements a(1), 1255a(2), ..., a(\fIn\fR) can be used. Furthermore, a C declaration such as 1256.RS 1257.DS L 1258.ft CR 1259float a[\fIn\fR]; 1260.ft 1261.DE 1262.RE 1263declares a to be of size \fIn\fR with elements referred to as 1264a[0], a[1], ..., a[\fIn\fR-1]. 1265.LP 1266To resolve these array size and subscripting conflicts, the user 1267should remember the following: 1268.IP - 1269All VAXIMA array subscripts are translated literally. Therefore 1270it is the user's responsibility to be sure that 1271array elements with subscript 0 are not translated into FORTRAN or 1272RATFOR. 1273.IP - 1274Since C arrays allow elements with a subscript of 0, when an array is 1275declared to be of size \fIn\fR by the user, the actual generated C type 1276declaration will be of size n+1 so that the user can translate elements with 1277subscripts from 0, up to and including \fIn\fR. 1278.NH 2 1279Comments and Literal Strings 1280.LP 1281Comments and other strings of characters can be inserted directly 1282into the stream of generated code through a call to the special function 1283\fIliteral\fR. 1284.SH 1285User Level Syntax: 1286.RS 1287.DS L 1288.ft CR 1289\fIliteral(\fRarg1,arg2,...,argn) 1290.ft 1291.DE 1292.RE 1293where arg1,arg2,...,argn is an argument list containing one or 1294more arg's, each of which either is, or evaluates to, an 1295atom. The atoms tab and cr have special meanings. arg's 1296are not evaluated unless given as arguments to \fIeval\fR. 1297.SH 1298LISP Level Syntax: 1299.RS 1300.DS L 1301.ft CR 1302\fI(($literal) \fRarg1 arg2 ... argn) 1303.ft 1304.DE 1305.RE 1306where arg1 arg2 ... argn is an argument list containing one or 1307more arg's, each of which either is, or evaluates to, an 1308atom. The atoms $tab and $cr have special meanings. arg's 1309are not evaluated unless given as arguments to \fI$eval\fR. 1310.SH 1311Side Effect: 1312.LP 1313This function call is replaced by the character sequence resulting 1314from concatenation of the given atoms. Double quotes are 1315stripped from all string type arg's, and each occurrence of 1316the reserved atom tab or cr ($tab or $cr at 1317the LISP level) is replaced by a tab to the current level of 1318indentation, or an end-of-line character. 1319.SH 1320User Level Examples: 1321.DS L 1322.ft CR 1323(c1) gentranlang(fortran)$ 1324.ft 1325.DE 1326Suppose \fBn\fR has value 10. 1327.DS L 1328.ft CR 1329(c2) gentran( literal( "c", tab, "--This is a FORTRAN Comment--", cr, 1330 "c", cr ), 1331 literal( tab, "data ", "n/", eval(n), "/", cr ) ); 1332c --This is a FORTRAN Comment-- 1333c 1334 data n/10/ 1335 1336(d2) true 1337.ft 1338.DE 1339.DS L 1340.ft CR 1341(c3) gentranlang(ratfor)$ 1342.ft 1343.DE 1344.DS L 1345.ft CR 1346(c4) gentran( for i:1 thru n do 1347 ( 1348 literal( tab, "# --This is a RATFOR Comment--", cr ), 1349 literal( tab, "write(6,10) (m(i,j),j=1,n)", cr ), 1350 literal( 10, tab, "format(1x,10(i5,3x))", cr ) 1351 ) ); 1352do i=1,n 1353 { 1354 # --This is a RATFOR Comment-- 1355 write(6,10) (m(i,j),j=1,n) 135610 format(1x,10(i5,3x)) 1357 } 1358 1359(d4) true 1360.ft 1361.DE 1362.DS L 1363.ft CR 1364(c5) gentranlang(c)$ 1365.ft 1366.DE 1367.DS L 1368.ft CR 1369(c6) gentran( x : 0.0, 1370 literal( tab, "/*", cr, 1371 tab, " * This is a C Comment", cr, 1372 tab, " */", cr ) ); 1373x=0.0; 1374/* 1375 * This is a C Comment 1376 */ 1377 1378(d6) true 1379.ft 1380.DE 1381.SH 1382LISP Level Examples: 1383.DS L 1384.ft CR 1385<1>: (setq *gentranlang 'fortran) 1386fortran 1387.ft 1388.DE 1389Suppose \fBn\fR has value 10. 1390.DS L 1391.ft CR 1392<1>: (gentran '((($literal) |c| $tab |--This is a FORTRAN Comment--| $cr 1393 |c| $cr) 1394 (($literal) $tab |data | |n//| (($eval) n) |//| $cr)) ()) 1395c --This is a FORTRAN Comment-- 1396c 1397 data n/10/ 1398t 1399.ft 1400.DE 1401.DS L 1402.ft CR 1403<1>: (setq *gentranlang 'ratfor) 1404ratfor 1405.ft 1406.DE 1407.DS L 1408.ft CR 1409<1>: (gentran '(((mdo) i 1 nil nil n nil 1410 ((mprogn) 1411 (($literal) $tab |# --This is a RATFOR Comment--| $cr) 1412 (($literal) $tab |write(6,10) (m(i,j),j=1,n)| $cr) 1413 (($literal) 10 $tab |format(1x,10(i5,3x))| $cr)))) ()) 1414do i=1,n 1415 { 1416 # --This is a RATFOR Comment-- 1417 write(6,10) (m(i,j),j=1,n) 141810 format(1x,10(i5,3x)) 1419 } 1420t 1421.ft 1422.DE 1423.DS L 1424.ft CR 1425<1>: (setq *gentranlang 'c) 1426c 1427.ft 1428.DE 1429.DS L 1430.ft CR 1431<1>: (gentran '(((msetq) x 0.0) 1432 (($literal) $tab |//*| $cr 1433 $tab | * This is a C Comment| $cr 1434 $tab | *//| $cr)) ()) 1435x=0.0; 1436/* 1437 * This is a C Comment 1438 */ 1439t 1440.ft 1441.DE 1442.NH 2 1443The fortran, ratfor, and c Mode Switches 1444.LP 1445Sections 2.1 - 2.5 have shown how to produce numerical code 1446from derived expressions and algorithmic specifications. First 1447the variable \fI*gentranlang\fR is set to \fIfortran\fR, \fIratfor\fR, 1448or \fIc\fR, and then the \fIgentran\fR function is called. Any of the 1449special functions \fIeval\fR, \fIlsetq\fR, \fIrsetq\fR, \fIlrsetq\fR, 1450\fItype\fR, and \fIliteral\fR can be called from within a call to 1451\fIgentran\fR. This section describes an alternative method of code 1452generation. 1453.LP 1454Three mode switches are provided in GENTRAN to change the default mode 1455of VAXIMA from evaluation to translation. These switches are \fIfortran\fR, 1456\fIratfor\fR, and \fIc\fR, and can be turned on and off with the 1457special functions \fIon\fR and \fIoff\fR. Each time a fresh VAXIMA 1458session is started up, the system is in evaluation mode. It prints a prompt 1459on the user's terminal screen and waits for an expression or statement 1460to be entered. When it reads in a ; or $, the preceding 1461expression is evaluated, a new prompt is printed, and the system waits 1462for the user to enter another expression or statement. This mode can be 1463changed to translation mode by turning on one of the following 1464switches: \fIfortran\fR, \fIratfor\fR, or \fIc\fR. After one of 1465these switches is turned on, and until it is turned off, every 1466expression or statement entered by the user is translated into the 1467corresponding language just as if it had been given as an argument 1468to the \fIgentran\fR function. Each of the special functions which 1469can be used from within a call to \fIgentran\fR can be used at the 1470top level until the switch is turned off. Thus, the \fIfortran\fR, 1471\fIratfor\fR, and \fIc\fR mode switches are an alternative method of 1472code generation. 1473.SH 1474User Level Examples: 1475.DS L 1476.ft CR 1477(c1) m : genmatrix(m, 2,2, 1,1)$ 1478.ft 1479.DE 1480.DS L 1481.ft CR 1482(c2) on(fortran); 1483 1484 rsetq( minv, m^^(-1) ); 1485 minv(1,1)=m(2,2)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1486 minv(1,2)=-m(1,2)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1487 minv(2,1)=-m(2,1)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1488 minv(2,2)=m(1,1)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1489 1490 rsetq( d, determinant(m) ); 1491 d=-m(1,2)*m(2,1)+m(1,1)*m(2,2) 1492 1493 off(fortran); 1494 1495(d2) done 1496.ft 1497.DE 1498.SH 1499LISP Level Examples: 1500.DS L 1501.ft CR 1502<1>: (meval '((msetq) m (($genmatrix) m 2 2 1 1)) ) 1503(($matrix simp) ((mlist simp) ((m simp array) 1 1) ((m simp array 1504) 1 2)) ((mlist simp) ((m simp array) 2 1) ((m simp array) 2 2))) 1505.ft 1506.DE 1507.DS L 1508.ft CR 1509<1>: (on '(fortran)) 1510 1511 rsetq( minv, ?m^^(-1) ); 1512 minv(1,1)=m(2,2)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1513 minv(1,2)=-m(1,2)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1514 minv(2,1)=-m(2,1)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1515 minv(2,2)=m(1,1)/(-m(1,2)*m(2,1)+m(1,1)*m(2,2)) 1516 1517 rsetq( d, determinant(?m) ); 1518 d=-m(1,2)*m(2,1)+m(1,1)*m(2,2) 1519 1520 off(fortran); 1521$done 1522.ft 1523.DE 1524.NH 2 1525Code Optimization 1526.LP 1527VAXIMA contains an \fIoptimize\fR command which takes one expression 1528as its argument. It searches for common subexpressions, replaces 1529them by temporary variable names, and returns the resulting expression 1530preceded by a sequence of assignment statements which assign the common 1531subexpressions to the temporary variable names. GENTRAN has been 1532interfaced with this command to make it possible to generate code 1533in which the numerical expressions have been optimized. This interface 1534is activated when the \fIgentranopt\fR flag is on. (\fIgentranopt\fR is 1535off initially.) The following command will turn the \fIgentranopt\fR flag 1536on: 1537.RS 1538.DS L 1539.ft CR 1540\fIon(gentranopt);\fR 1541.ft 1542.DE 1543.RE 1544and 1545.RS 1546.DS L 1547.ft CR 1548\fIoff(gentranopt);\fR 1549.ft 1550.DE 1551.RE 1552will turn it back off again. 1553.SH 1554Example: 1555.LP 1556Suppose the following expression, ans, has been derived: 1557.DS L 1558.ft CR 1559(c10) ans; 1560 1561 2 7 4 8 2 6 3 8 3 7 4 6 3 6 3 6 1562(d10) - 36 w x y z + 3 w x y z - 24 w x y z + 2 w x y z 1563 1564 2 8 6 5 4 7 6 5 2 7 6 5 2 10 5 5 1565 + 96 w x y z - 168 w x y z + 12 w x y z - 216 w x y z 1566 1567 2 7 5 5 7 5 5 4 6 5 5 2 6 5 5 2 9 4 5 1568 - 8 w x y z + 9 x y z + 14 w x y z - w x y z + 18 w x y z 1569 1570 7 3 5 2 6 3 5 7 5 3 7 3 3 3 6 3 3 1571 + 87 x y z - 3 w x y z + 6 w x y z + 58 w x y z - 2 w x y z 1572 1573 8 7 2 2 7 7 2 7 7 2 10 6 2 8 5 2 1574 - 24 x y z + 42 w x y z - 3 x y z + 54 x y z - 232 x y z 1575 1576 2 7 5 2 7 5 2 4 6 5 2 2 6 5 2 10 4 2 1577 + 414 w x y z - 29 x y z - 14 w x y z + w x y z + 522 x y z 1578 1579 2 9 4 2 1580 - 18 w x y z 1581.ft 1582.DE 1583We wish to generate optimized FORTRAN code to compute this value. 1584.LP 1585The following VAXIMA session will generate the code: 1586.DS L 1587.ft CR 1588(c11) on(gentranopt); 1589 1590(d11) done 1591.ft 1592.DE 1593.DS L 1594.ft CR 1595(c12) gentran( rsetq(ans,ans) ); 1596.ft 1597.DE 1598.DS L 1599.ft CR 1600 t0=w**2 1601 t1=x**9 1602 t2=y**4 1603 t3=z**2 1604 t4=x**10 1605 t5=x**6 1606 t6=y**5 1607 t7=w**4 1608 t8=x**7 1609 t9=x**8 1610 t10=y**6 1611 t11=y**7 1612 t12=w**3 1613 t13=y**3 1614 t14=z**3 1615 t15=z**5 1616 t16=z**6 1617 t17=z**8 1618.ft 1619.DE 1620.DS L 1621.ft CR 1622 ans=-18.0*t0*t1*t2*t3+522.0*t4*t2*t3+t0*t5*t6*t3-14.0*t7*t5*t6*t3 1623 . -29.0*t8*t6*t3+414.0*t0*t8*t6*t3-232.0*t9*t6*t3+54.0*t4*t10*t3 1624 . -3.0*t8*t11*t3+42.0*t0*t8*t11*t3-24.0*t9*t11*t3-2.0*t12*t5*t13* 1625 . t14+58.0*w*t8*t13*t14+6.0*w*t8*t6*t14-3.0*t0*t5*t13*t15+87.0*t8* 1626 . t13*t15+18.0*t0*t1*t2*t15-t0*t5*t6*t15+14.0*t7*t5*t6*t15+9.0*t8* 1627 . t6*t15-8.0*t0*t8*t6*t15-216.0*t0*t4*t6*t15+12.0*t0*t8*t10*t15 1628 . -168.0*t7*t8*t10*t15+96.0*t0*t9*t10*t15+2.0*t12*t5*t13*t16-24.0* 1629 . t12*t8*t2*t16+3.0*t0*t5*t13*t17-36.0*t0*t8*t2*t17 1630.ft 1631.DE 1632.DS L 1633.ft CR 1634(d12) true 1635.ft 1636.DE 1637.LP 1638Unfortunately, VAXIMA's \fIoptimize\fR facility is not as powerful 1639as it could be. It does not produce an absolutely 1640optimal sequence of assignments to calculate an 1641expression's value. For example, in the code above, 1642.RS 1643.DS L 1644.ft CR 1645 t3=z**2 1646 . 1647 . 1648 . 1649 t14=z**3 1650 t15=z**5 1651 t16=z**6 1652 t17=z**8 1653.ft 1654.DE 1655.RE 1656could be calculated more efficiently with 1657.RS 1658.DS L 1659.ft CR 1660 t3=z*z 1661 . 1662 . 1663 . 1664 t14=t3*z 1665 t15=t3*t14 1666 t16=t15*z 1667 t17=t16*t3 1668.ft 1669.DE 1670.RE 1671In addition, the \fIoptimize\fR facility does not detect all possible 1672common subexpressions. For example, in the above, 1673t2*t3 appears in each of the first two terms of the final 1674assignment statement. That expression should have been replaced by 1675another temporary variable name, and 1676another assignment statement should have been generated for it. 1677.LP 1678A code optimizer, designed by J. A. van Hulzen /14/ of Twente University of 1679Technology in The Netherlands, has been implemented in RLISP to run under 1680REDUCE. It utilizes an optimization technique in which one or more expressions 1681are mapped onto matrices of coefficients and exponents. These matrices are 1682searched for patterns corresponding to common subexpressions, all of which 1683are replaced by temporary variable names. This optimization technique is 1684much more powerful than the one used in VAXIMA's \fIoptimize\fR command. A 1685comparison of code generated using each of the two optimization facilities 1686is given in sections 6.3.3 - 6.3.6. 1687.NH 2 1688Expression Segmentation 1689.LP 1690Symbolic derivations can easily produce formulas that can be 1691anywhere from a few lines to several pages in length. Such 1692formulas can be translated into numerical assignment statements, 1693but unless they are broken into smaller pieces, they 1694may be too long for a compiler to handle. (The maximum 1695number of continuation lines for one statement allowed by most 1696FORTRAN compilers is only 19.) Therefore GENTRAN contains 1697a segmentation facility which automatically "segments", or 1698breaks down, unreasonably large expressions. 1699.LP 1700The segmentation facility generates a sequence of assignment 1701statements, each of which assigns a subexpression to an 1702automatically generated temporary variable. This sequence 1703is generated in such a way that temporary variables are re-used 1704as soon as possible, thereby keeping the number of 1705automatically generated variables to a minimum. The facility 1706can be turned on or off by setting the mode switch 1707\fIgentranseg\fR accordingly (i.e., by calling the function 1708\fIon\fR or \fIoff\fR on it). The user can control the maximum allowable 1709expression size by setting the variable 1710\fI?maxexpprintlen\e*\fR to the maximum number of characters allowed 1711in an expression printed in the target language (excluding 1712spaces automatically printed by the formatter). The 1713\fIgentranseg\fR switch is on initially, and \fI?maxexpprintlen\e*\fR is 1714initialized to 800. 1715.SH 1716User Level Examples: 1717.DS L 1718.ft CR 1719(c1) on(gentranseg)$ 1720.ft 1721.DE 1722.DS L 1723.ft CR 1724(c2) ?maxexpprintlen\e* : 120$ 1725.ft 1726.DE 1727.DS L 1728.ft CR 1729(c3) ( poly : 0, 1730 for i:0 thru 20 do 1731 poly : poly + c(i+1)*x^i )$ 1732.ft 1733.DE 1734.DS L 1735.ft CR 1736(c4) gentran( rsetq( poly, poly ) ); 1737 t0=c(1)+c(2)*x+c(3)*x**2+c(4)*x**3+c(5)*x**4+c(6)*x**5+c(7)*x**6+c 1738 . (8)*x**7+c(9)*x**8+c(10)*x**9 1739 t0=t0+c(11)*x**10+c(12)*x**11+c(13)*x**12+c(14)*x**13+c(15)*x**14+ 1740 . c(16)*x**15+c(17)*x**16+c(18)*x**17 1741 poly=t0+c(19)*x**18+c(20)*x**19+c(21)*x**20 1742 1743(d4) true 1744.ft 1745.DE 1746.SH 1747LISP Level Examples: 1748.DS L 1749.ft CR 1750<1>: (on '(gentranseg)) 1751$done 1752.ft 1753.DE 1754.DS L 1755.ft CR 1756<1>: (setq maxexpprintlen* 120) 1757120 1758.ft 1759.DE 1760.DS L 1761.ft CR 1762<1>: (meval '((mprogn) 1763 ((msetq) poly 0) 1764 ((mdo) i 0 nil nil 20 nil 1765 ((msetq) poly ((mplus) poly 1766 ((mtimes) ((c) ((mplus) i 1)) 1767 ((mexpt) x i)))) ) ) ) 1768$done 1769.ft 1770.DE 1771.DS L 1772.ft CR 1773<1>: (gentran '((($rsetq) poly poly)) ()) 1774 t0=c(1)+c(2)*x+c(3)*x**2+c(4)*x**3+c(5)*x**4+c(6)*x**5+c(7)*x**6+c 1775 . (8)*x**7+c(9)*x**8+c(10)*x**9 1776 t0=t0+c(11)*x**10+c(12)*x**11+c(13)*x**12+c(14)*x**13+c(15)*x**14+ 1777 . c(16)*x**15+c(17)*x**16+c(18)*x**17 1778 poly=t0+c(19)*x**18+c(20)*x**19+c(21)*x**20 1779t 1780.ft 1781.DE 1782.NH 3 1783Implicit Type Declarations 1784.LP 1785When the segmentation routine generates temporary variables, 1786it places type declarations in the symbol table for those 1787variables if possible. It uses the following rules to 1788determine their type: 1789.IP 1) 1790If the type of the variable to which the large expression 1791is being assigned is already known (i.e., has been 1792declared by the user), then the temporary variables will be 1793declared to be of that same type. 1794.IP 2) 1795If the global variable \fI?tempvartype\e*\fR (\fI$tempvartype\fR at the LISP 1796level) has a non-nil value, then the temporary variables are declared to 1797be of that type. 1798.IP 3) 1799Otherwise, the variables are not declared. 1800.SH 1801Example: 1802.DS L 1803.ft CR 1804(c1) on(gentranseg)$ 1805.ft 1806.DE 1807.DS L 1808.ft CR 1809(c2) ?maxexpprintlen\e* : 20$ 1810.ft 1811.DE 1812.DS L 1813.ft CR 1814(c3) ?tempvartype\e* : real$ 1815.ft 1816.DE 1817.DS L 1818.ft CR 1819(c4) gentran( type(integer, isum), 1820 . 1821 . 1822 isum : i(1)+i(2)+i(3)+i(4)+i(5), 1823 pprod : p(1)*p(2)*p(3)*p(4)*p(5), 1824 . 1825 . 1826 ); 1827 integer isum,t0 1828 real t1 1829 . 1830 . 1831 t0=i(1)+i(2)+i(3)+i(4) 1832 isum=t0+i(5) 1833 t1=p(1)*p(2)*p(3)*p(4) 1834 pprod=t1*p(5) 1835 . 1836 . 1837 1838(d4) true 1839.ft 1840.DE 1841.NH 3 1842Controlling Generation of Declarations 1843.LP 1844In some applications, it may not be convenient to have type declarations 1845generated automatically. The \fIgendecs\fR flag has been provided for 1846this reason. 1847.LP 1848\fIgendecs\fR is on initially. As long as it stays on, all type 1849declarations will be generated whenever possible. However, when 1850\fIgendecs\fR is off, type declarations will not be generated. Instead, 1851type information will be stored in GENTRAN's Symbol Table but will not 1852be retrieved in the form of declarations unless and until either the 1853\fIgendecs\fR function is called or the \fIgendecs\fR flag is turned back 1854on. 1855.LP 1856The \fIgendecs\fR function can be called any time the \fIgendecs\fR flag 1857is turned off to retrieve all type declarations from the Symbol Table 1858for the given subprogram name (or the "current" subprogram if \fIfalse\fR or 1859\fInil\fR is given as its argument). The syntax for calls to this function 1860is: 1861.SH 1862User Level Syntax: 1863.RS 1864.DS L 1865.ft CR 1866\fIgendecs(\fRname); 1867.ft 1868.DE 1869.RE 1870where name is an atom. 1871.SH 1872LISP Level Syntax: 1873.RS 1874.DS L 1875.ft CR 1876\fI(gendecs '\fRname) 1877.ft 1878.DE 1879.RE 1880where name is an atom. 1881.LP 1882The \fIgendecs\fR flag can be turned on and off with the \fIon\fR and 1883\fIoff\fR functions: 1884.SH 1885User Level Syntax: 1886.RS 1887.DS L 1888.ft CR 1889\fIon(gendecs);\fR 1890.ft 1891.DE 1892.DS L 1893.ft CR 1894\fIoff(gendecs);\fR 1895.ft 1896.DE 1897.RE 1898.SH 1899LISP Level Syntax: 1900.RS 1901.DS L 1902.ft CR 1903\fI(on '(gendecs))\fR 1904.ft 1905.DE 1906.DS L 1907.ft CR 1908\fI(off '(gendecs))\fR 1909.ft 1910.DE 1911.RE 1912.LP 1913The \fIgendecs\fR flag will is discussed in connection with template 1914processing in section 3.2. 1915.NH 2 1916Generation of Temporary Variable Names 1917.LP 1918As we have just seen, GENTRAN's segmentation module generates 1919temporary variables and places type declarations in 1920the symbol table for them whenever possible. Various other 1921modules also generate variables and corresponding declarations. All 1922of these modules call one special GENTRAN function each 1923time they need a temporary variable name. This 1924function is \fItempvar\fR. There are situations in which it may 1925be convenient for the user to be able to generate temporary 1926variable names directly[3]. Therefore 1927.FS 1928[3] One such example is suppression of the simplification process to 1929generate numerical code which is more efficient. See 1930the example in section 6.3.4. 1931.FE 1932\fItempvar\fR is a user-accessible function. 1933.SH 1934User Level Syntax: 1935.RS 1936.DS L 1937.ft CR 1938\fItempvar(\fRtype); 1939.ft 1940.DE 1941.RE 1942where type is either a string which indicates the variable 1943type in the target language (e.g., "integer", "real*8", etc.), or 1944is \fIfalse\fR if the variable type is unknown. 1945.SH 1946LISP Level Syntax: 1947.RS 1948.DS L 1949.ft CR 1950\fI(tempvar '\fRtype) 1951.ft 1952.DE 1953.RE 1954where type is either an atom which indicates the variable 1955type in the target language (e.g., integer, real*8, etc.), or 1956is \fInil\fR if the variable type is unknown. 1957.SH 1958Side Effects 1959.LP 1960\fItempvar\fR creates temporary variable names by repeatedly 1961concatenating the values of the global variables 1962\fI?tempvarname\e*\fR (\fItempvarname*\fR), which has a default value 1963of '\fIt\fR, 1964and \fI?tempvarnum\e*\fR (\fItempvarnum*\fR), which is initially set to 0, 1965and incrementing \fI?tempvarnum\e*\fR 1966until a variable name is created which satisfies 1967one of the following conditions: 1968.IP 1) 1969It had not been generated previously, and it has not been declared 1970by the user. 1971.IP 2) 1972It had previously been generated to hold the same type 1973of value that it must hold this time (e.g., integer, real, etc.), 1974and the value assigned to it previously is no longer needed. 1975.LP 1976If type is a non-\fIfalse\fR (non-\fInil\fR) argument, or if 1977type is \fIfalse\fR (\fInil\fR) and the global variable 1978\fI?tempvartype\e*\fR (\fItempvartype*\fR), which is initially \fIfalse\fR 1979(\fInil\fR), has been set to a non-\fIfalse\fR (non-\fInil\fR) value, 1980then a type entry for the generated variable name is placed in the 1981symbol table. 1982.SH 1983Returned Value: 1984.LP 1985\fItempvar\fR returns an atom which can be used as a variable. 1986.SH 1987Note: 1988.LP 1989It is the user's responsibility to set \fI?tempvarname\e*\fR 1990and \fI?tempvarnum\e*\fR (\fItempvarnum*\fR) to 1991values such that generated variable names will not clash with variables 1992used elsewhere in the program unless those variables have been 1993declared. 1994.NH 3 1995Marking Temporary Variables 1996.LP 1997In section 2.9 we saw that a temporary variable name (of a 1998certain type) can be regenerated when the value previously 1999assigned to it is no longer needed. This section describes 2000a function which "marks" a variable to indicate that it 2001currently holds a significant value, and the next section 2002describes functions which "unmark" variables to indicate 2003that the values they hold are no longer significant. 2004.SH 2005User Level Syntax: 2006.RS 2007.DS L 2008.ft CR 2009\fImarkvar(\fRvar); 2010.ft 2011.DE 2012.RE 2013where var is an atom. 2014.SH 2015LISP Level Syntax: 2016.RS 2017.DS L 2018.ft CR 2019\fI(markvar \fRvar) 2020.ft 2021.DE 2022.RE 2023where var is an atom. 2024.SH 2025Side Effect: 2026.LP 2027\fImarkvar\fR sets a flag on var's property list to 2028indicate that var currently holds a significant value. 2029.SH 2030Return Value: 2031.LP 2032\fImarkvar\fR returns var. 2033.SH 2034User Level Example: 2035.LP 2036The following matrix, m, has been derived symbolically: 2037.RS 2038.DS L 2039.ft CR 2040[ x (z + y) 0 x z ] 2041[ ] 2042[ - x y + x 0 ] 2043[ ] 2044[ 2 ] 2045[ x z 0 z ] 2046.ft 2047.DE 2048.RE 2049We wish to replace each non-zero element by a generated variable name 2050to prevent these expressions from being resubstituted into further 2051calculations. (We will also record these substitutions in the numerical 2052program we are constructing by generating assignment statements.) 2053.DS L 2054.ft CR 2055(c1) for i:1 thru 3 do 2056 for j:1 thru 3 do 2057 if m[i,j]#0 then 2058 ( 2059 var : tempvar(false), 2060 markvar(var), 2061 gentran( eval(var) : eval(m[i,j]) ), 2062 m[i,j] : var 2063 ); 2064.ft 2065.DE 2066.DS L 2067.ft CR 2068 t0=x*(y+z) 2069 t1=x*z 2070 t2=-x 2071 t3=x+y 2072 t4=x*z 2073 t5=z**2 2074.ft 2075.DE 2076.DS L 2077.ft CR 2078(d1) done 2079.ft 2080.DE 2081Now matrix m contains the following entries: 2082.RS 2083.DS L 2084.ft CR 2085[ t0 0 t1 ] 2086[ ] 2087[ t2 t3 0 ] 2088[ ] 2089[ t4 0 t5 ] 2090.ft 2091.DE 2092.RE 2093.SH 2094LISP Level Example: 2095.LP 2096The following matrix, m, has been derived symbolically: 2097.RS 2098.DS L 2099.ft CR 2100[ x (z + y) 0 x z ] 2101[ ] 2102[ - x y + x 0 ] 2103[ ] 2104[ 2 ] 2105[ x z 0 z ] 2106.ft 2107.DE 2108.RE 2109We wish to replace each non-zero element by a generated variable 2110name to prevent these expressions from being resubstituted into further 2111calculations. (We will also record these substitutions in the 2112numerical program we are constructing by generating assignment 2113statements.) 2114.DS L 2115.ft CR 2116<1>: (meval '((mdo) i 1 nil nil 3 nil 2117 ((mdo) j 1 nil nil 3 nil 2118 ((mcond) ((mnotequal) ((m array) i j) 0) 2119 ((mprogn) 2120 ((msetq) var ((tempvar) nil)) 2121 ((markvar) var) 2122 ((gentran) 2123 '(((msetq) (($eval) var) 2124 (($eval) ((m array) i j)))) ()) 2125 ((msetq) ((m array) i j) var)) 2126 t 2127 $false)))) 2128.ft 2129.DE 2130.DS L 2131.ft CR 2132 t0=x*(y+z) 2133 t1=x*z 2134 t2=-x 2135 t3=x+y 2136 t4=x*z 2137 t5=z**2 2138.ft 2139.DE 2140.DS L 2141.ft CR 2142$done 2143.ft 2144.DE 2145.NH 3 2146Unmarking Temporary Variables 2147.LP 2148After the value assigned to a temporary variable has been 2149used in the numerical program and is no longer needed, the 2150variable name can be "unmarked" with the \fIunmarkvar\fR 2151function. 2152.SH 2153User Level Syntax: 2154.RS 2155.DS L 2156.ft CR 2157\fIunmarkvar(\fRvar); 2158.ft 2159.DE 2160.RE 2161where var is an atom. 2162.SH 2163LISP Level Syntax: 2164.RS 2165.DS L 2166.ft CR 2167\fI(unmarkvar \fRvar) 2168.ft 2169.DE 2170.RE 2171where var is an atom. 2172.SH 2173Side Effect: 2174.LP 2175\fIunmarkvar\fR resets a flag on var's property list to indicate 2176that var does not hold a significant value. 2177.LP 2178.LP 2179The \fIrecurunmark\fR function unmarks all variable names in an 2180expression. 2181.SH 2182User Level Syntax: 2183.RS 2184.DS L 2185.ft CR 2186\fIrecurunmark(\fRexp); 2187.ft 2188.DE 2189.RE 2190where exp is an expression containing one or more variable 2191names. 2192.SH 2193LISP Level Syntax: 2194.RS 2195.DS L 2196.ft CR 2197\fI(recurunmark \fRexp) 2198.ft 2199.DE 2200.RE 2201where exp is an expression containing one or more variable 2202names. 2203.SH 2204Side Effect: 2205.LP 2206\fIrecurunmark\fR resets flags on the property lists of all 2207variable names in exp to indicate that they do not hold 2208significant values any longer. 2209.NH 3 2210The Marked Variable Predicate 2211.LP 2212A variable name can be tested to see if it is currently marked 2213with the marked variable predicate. 2214.SH 2215User Level Syntax: 2216.RS 2217.DS L 2218.ft CR 2219\fImarkedvarp(\fRvar); 2220.ft 2221.DE 2222.RE 2223where var is an atom. 2224.SH 2225LISP Level Syntax: 2226.RS 2227.DS L 2228.ft CR 2229\fI(markedvarp '\fRvar) 2230.ft 2231.DE 2232.RE 2233where var is an atom. 2234.SH 2235Return Value: 2236.LP 2237\fImarkedvarp\fR returns \fItrue\fR or \fIfalse\fR (\fIt\fR 2238or \fInil\fR at the LISP level), depending 2239on whether or not var is currently marked. 2240.NH 2 2241Generation of Statement Numbers 2242.LP 2243The \fIgenstmtno\fR function is called by GENTRAN whenever a new 2244statement number must be generated. The syntax is as follows: 2245.SH 2246User Level Syntax: 2247.RS 2248.DS L 2249.ft CR 2250\fIgenstmtno();\fR 2251.ft 2252.DE 2253.RE 2254.SH 2255LISP Level Syntax: 2256.RS 2257.DS L 2258.ft CR 2259\fI(genstmtno)\fR 2260.ft 2261.DE 2262.RE 2263.SH 2264Side Effects: 2265.LP 2266\fIgenstmtno\fR increases the value of global variable 2267\fI?genstmtno\e*\fR (\fIgenstmtno*\fR) by \fI?genstmtincr\e*\fR 2268(\fIgenstmtincr*\fR) when it is called. (\fI?genstmtno\e*\fR is 2269initialized to 25000, and \fI?genstmtincr\e*\fR is initialized to 1.) 2270.SH 2271Return Value: 2272\fIgenstmtno\fR returns the new value of \fI?genstmtno\e*\fR 2273(\fIgenstmtno*\fR). 2274