1.NH 1 2TEMPLATE PROCESSING 3.LP 4In some code generation applications, pieces of the target 5numerical program are known in advance. A "template" file 6containing a program outline is supplied by the user, and 7formulas are derived in VAXIMA, converted to numerical code, 8and inserted in the corresponding places in the program outline 9to form a complete numerical program. A template processor is 10provided by GENTRAN for use in these applications. 11.NH 2 12The Template Processing Command 13.SH 14User Level Syntax: 15.RS 16.DS L 17.ft CR 18\fIgentranin(\fRf1,f2,...,fn {,[f1,f2,...,fm]}); 19.ft 20.DE 21.RE 22where f1,f2,...,fn is an argument list containing one or more 23f's, each of which is one of the following: 24.RS 25.DS L 26.ft CR 27a string = a template (input) file 28\fItrue\fR = the terminal 29.ft 30.DE 31.RE 32and [f1,f2,...,fm] is an optional argument list which, if 33supplied, contains one or more f's, each of which is one 34of the following: 35.RS 36.DS L 37.ft CR 38a string = an output file 39\fItrue\fR = the terminal 40\fIfalse\fR = the current output file(s) 41\fIall\fR = all files currently open for output by GENTRAN 42 (see section 4) 43.ft 44.DE 45.RE 46.SH 47LISP Level Syntax: 48.RS 49.DS L 50.ft CR 51\fI(gentranin '(\fRf1 f2 ... fn) '(f1 f2 ... fm)) 52.ft 53.DE 54.RE 55where f1 f2 ... fn is an argument list containing one or 56more f's, each of which is one of the following: 57.RS 58.DS L 59.ft CR 60a string = a template (input) file 61\fIt\fR = the terminal 62.ft 63.DE 64.RE 65and (f1 f2 ... fm) is an argument list which 66contains zero or more f's, each of which is one of the 67following: 68.RS 69.DS L 70.ft CR 71a string = an output file 72\fIt\fR = the terminal 73\fInil\fR = the current output file(s) 74\fI$all\fR = all files currently open for output by GENTRAN 75 (see section 4) 76.ft 77.DE 78.RE 79.SH 80Side Effects: 81.LP 82\fIgentranin\fR processes each template file f1,f2,...,fn 83sequentially. 84.LP 85A template file may contain any number of parts, each of which 86is either an "active" or an "inactive" part. Each active 87part starts with the delimiter << and ends with >>. 88.LP 89Inactive parts of template files are assumed to 90contain code in the target language, FORTRAN, RATFOR, or C, depending on the 91value of the global variable \fI*gentranlang\fR. Each inactive 92part is copied to the output. Each comment delimited by the 93appropriate characters, 94.RS 95.DS L 96.ft CR 97C ... <cr> for FORTRAN (beginning in column 1) or 98* ... <cr> for FORTRAN (beginning in column 1), 99# ... <cr> for RATFOR, and 100/* ... */ for C 101.ft 102.DE 103.RE 104is also copied in its entirety to the output. Thus the character 105sequences << and >> have no special meanings within 106comments. 107.LP 108Active parts may contain any number of VAXIMA expressions and 109statements. They are not copied directly to the output. Instead, 110they are given to VAXIMA for evaluation \fIat the user level\fR. All 111output generated by each evaluation is sent to the output 112file(s). Returned values are only printed on the terminal. 113.LP 114Active parts will most likely contain calls to \fIgentran\fR 115to generate code. This means that the result of processing a template 116file will be the original template file with all active 117parts replaced by generated code. 118.LP 119If [f1,f2,...,fm] ((f1 f2 ... fn)) is empty, then 120generated code is simply written to the current output file(s). 121.LP 122However, if it is given, then the current output file is 123temporarily overridden. Generated code is written to each file 124represented by f1,f2,...,fn for this command 125only. Files which were open prior to the call to \fIgentranin\fR 126will remain open after the call, and files which did not exist 127prior to the call will be created, opened, written to, and 128closed. The output file stack will be exactly the same both 129before and after the call. 130.SH 131Return Value: 132.LP 133\fIgentranin\fR returns the names of all files written to by this 134command. 135.SH 136Diagnostic Messages: 137.LP 138Nonexistent Input File 139.sp 140Template File Already Open for Input 141.sp 142Wrong Type of Arg 143.SH 144Example: 145.LP 146Suppose we wish to generate a FORTRAN subprogram to compute the determinant 147of a 3 x 3 matrix. We can construct a template file with an outline of the 148FORTRAN subprogram and VAXIMA and GENTRAN commands to fill it in: 149.DS L 150.ft CR 151Contents of file det.tem: 152+----------------------------------------------+ 153| real*8 function det(m) | 154| real*8 m(3,3) | 155|<< | 156| m : genmatrix(m, 3,3, 1,1)$ | 157| gentran( rsetq( det, determinant(m) ) )$| 158|>> | 159| return | 160| end | 161+----------------------------------------------+ 162.ft 163.DE 164.LP 165Now we can generate a FORTRAN subprogram with the following VAXIMA session: 166.DS L 167.ft CR 168(c1) gentranlang(fortran)$ 169.ft 170.DE 171.DS L 172.ft CR 173(c2) gentranin("det.tem", ["det.f"]); 174 175(d2) det.f 176.ft 177.DE 178.DS L 179.ft CR 180Contents of file det.f: 181+------------------------------------------------------------------------+ 182| real*8 function det(m) | 183| real*8 m(3,3) | 184| det=m(1,3)*(-m(2,2)*m(3,1)+m(2,1)*m(3,2))-m(1,2)*(-m(2,3)*m(3,1)+m| 185| . (2,1)*m(3,3))+m(1,1)*(-m(2,3)*m(3,2)+m(2,2)*m(3,3)) | 186| return | 187| end | 188+------------------------------------------------------------------------+ 189.ft 190.DE 191.NH 3 192Copying Files into Template Files 193.LP 194Template files can be copied into other template files with recursive 195calls to \fIgentranin\fR; i.e., by calling \fIgentranin\fR from the 196active part of a template file. 197.LP 198For example, suppose we wish to copy the contents of the file det.f, 199generated in the previous section, into a file containing a main 200program. The template file for the main program, main.tem, will 201contain an active part to copy the contents of det.f: 202.DS L 203.ft CR 204Contents of file main.tem: 205+----------------------------------------+ 206|c | 207|c --- Main Program --- | 208|c | 209| real*8 m(3,3),det | 210| write(6,*) 'Enter 3 x 3 Matrix:' | 211| do 100 i=1,3 | 212| read(5,*) (m(i,j),j=1,3) | 213|100 continue | 214| write(6,*) 'Determinant = ',det(m)| 215| stop | 216| end | 217|c | 218|c --- Determinant Calculation --- | 219|c | 220|<< | 221| gentranin("det.f")$ | 222|>> | 223+----------------------------------------+ 224.ft 225.DE 226.LP 227The following VAXIMA session will create the file main.f: 228.DS L 229.ft CR 230(c1) gentranin("main.tem", ["main.f"]); 231 232(d1) main.f 233.ft 234.DE 235.DS L 236.ft CR 237Contents of file main.f: 238+------------------------------------------------------------------------+ 239|c | 240|c --- Main Program --- | 241|c | 242| real*8 m(3,3),det | 243| write(6,*) 'Enter 3 x 3 Matrix:' | 244| do 100 i=1,3 | 245| read(5,*) (m(i,j),j=1,3) | 246|100 continue | 247| write(6,*) 'Determinant = ',det(m) | 248| stop | 249| end | 250.ft 251.DE 252.DS L 253.ft CR 254|c | 255|c --- Determinant Calculation --- | 256|c | 257| real*8 function det(m) | 258| real*8 m(3,3) | 259| det=m(1,3)*(-m(2,2)*m(3,1)+m(2,1)*m(3,2))-m(1,2)*(-m(2,3)*m(3,1)+m| 260| . (2,1)*m(3,3))+m(1,1)*(-m(2,3)*m(3,2)+m(2,2)*m(3,3)) | 261| return | 262| end | 263+------------------------------------------------------------------------+ 264.ft 265.DE 266.NH 3 267The Template File Stack 268.LP 269The VAXIMA \fIbatch\fR command takes one file name as its argument. VAXIMA 270reads in the file and executes all statements and commands, any of which 271may be another \fIbatch\fR command. A stack of input file names is 272maintained by VAXIMA to allow recursive invocation of the \fIbatch\fR 273command. Similarly, a stack of template file names is maintained by 274GENTRAN to facilitate recursive invocation of the template 275processor. Section 3.2 showed that the \fIgentranin\fR command can be 276called recursively to copy files into other files. This section shows that 277template files which are copied into other template files can also contain 278active parts, and thus, the whole code generation process can be 279invoked recursively. 280.LP 281We can generalize the example of section 3.2 by generating code 282recursively. We can extend it to generate code which will compute 283entries of the inverse matrix, also. Suppose we have created the 284file init.in, which contains a VAXIMA command to create an 285n x n matrix, m, and initialize its entries to 286m(1,1), m(1,2), ..., m(n,n), for some user-entered value 287n: 288.DS L 289.ft CR 290Contents of file init.in: 291+---------------------------+ 292|m : genmatrix(m, n,n, 1,1)$| 293+---------------------------+ 294.ft 295.DE 296.LP 297We have also created template files det.tem and inv.tem 298which contain outlines of FORTRAN subprograms to compute the 299determinant and inverse of an n x n matrix, m, 300respectively: 301.DS L 302.ft CR 303Contents of file det.tem: 304+-------------------------------------------------------+ 305| real*8 function det(m) | 306|<< | 307| gentran( type("real*8", m(eval(n),eval(n)) ), | 308| rsetq( det, determinant(m) ) )$ | 309|>> | 310| return | 311| end | 312+-------------------------------------------------------+ 313.ft 314.DE 315.DS L 316.ft CR 317Contents of file inv.tem: 318+-------------------------------------------------------+ 319| subroutine inv(m,minv) | 320|<< | 321| gentran( type("real*8", m(eval(n),eval(n)), | 322| minv(eval(n),eval(n))), | 323| rsetq( minv, m^^(-1) ) )$| 324|>> | 325| return | 326| end | 327+-------------------------------------------------------+ 328.ft 329.DE 330.LP 331Now we can construct a template file with a generalized version of 332the main program given in section 3.2 and can place \fIgentranin\fR 333commands in this file to generate code recursively from the template 334files det.tem and inv.tem: 335.DS L 336.ft CR 337Contents of file main.tem: 338+-------------------------------------------------------------------+ 339|c | 340|c Main Program | 341|c | 342|<< | 343| gentran( type("real*8", m(eval(n),eval(n)), | 344| det, | 345| minv(eval(n),eval(n)) ), | 346| type("integer", n), | 347| literal(tab, "data n/", eval(n), "/", cr) )$ | 348|>> | 349| write(6,*) 'Enter ',n,' x ',n,' Matrix:' | 350| do 100 i=1,n | 351| read(5,*) (m(i,j),j=1,n) | 352|100 continue | 353| write(6,*) 'Determinant = ',det(m) | 354| write(6,*) 'Inverse Matrix:' | 355| call inv(m,minv) | 356| do 200 i=1,n | 357| write(6,*) (minv(i,j),j=1,n) | 358|200 continue | 359| stop | 360| end | 361.ft 362.DE 363.DS L 364.ft CR 365|c | 366|c Determinant Calculation | 367|c | 368|<< | 369| gentranin("det.tem")$ | 370|>> | 371|c | 372|c Inverse Calculation | 373|c | 374|<< | 375| gentranin("inv.tem")$ | 376|>> | 377+-------------------------------------------------------------------+ 378.ft 379.DE 380.LP 381The following VAXIMA session will create the file main.f: 382.DS L 383.ft CR 384(c1) n : 3$ 385.ft 386.DE 387.DS L 388.ft CR 389(c2) batch("init.in"); 390 391(c3) m : genmatrix(m, n,n, 1,1)$ 392 393(d4) BATCH DONE 394.ft 395.DE 396.DS L 397.ft CR 398(c5) gentranlang(fortran)$ 399.ft 400.DE 401.DS L 402.ft CR 403(c6) gentranin("main.tem", ["main.f"]); 404 405(d6) main.f 406.ft 407.DE 408.DS L 409.ft CR 410Contents of file main.f: 411+------------------------------------------------------------------------+ 412|c | 413|c Main Program | 414|c | 415.ft 416.DE 417.DS L 418.ft CR 419| real*8 m(3,3),det,minv(3,3) | 420| integer n | 421| data n/3/ | 422| write(6,*) 'Enter ',n,' x ',n,' Matrix:' | 423| do 100 i=1,n | 424| read(5,*) (m(i,j),j=1,n) | 425|100 continue | 426| write(6,*) 'Determinant = ',det(m) | 427| write(6,*) 'Inverse Matrix:' | 428| call inv(m,minv) | 429| do 200 i=1,n | 430| write(6,*) (minv(i,j),j=1,n) | 431|200 continue | 432| stop | 433| end | 434|c | 435|c Determinant Calculation | 436|c | 437| real*8 function det(m) | 438| real*8 m(3,3) | 439| det=m(1,3)*(-m(2,2)*m(3,1)+m(2,1)*m(3,2))-m(1,2)*(-m(2,3)*m(3,1)+m| 440| . (2,1)*m(3,3))+m(1,1)*(-m(2,3)*m(3,2)+m(2,2)*m(3,3)) | 441| return | 442| end | 443|c | 444|c Inverse Calculation | 445|c | 446| subroutine inv(m,minv) | 447| real*8 m(3,3),minv(3,3) | 448| minv(1,1)=(-m(2,3)*m(3,2)+m(2,2)*m(3,3))/((-m(1,3)*m(2,2)+m(1,2)*m| 449| . (2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,1| 450| . )+m(1,1)*m(2,2))*m(3,3)) | 451| minv(1,2)=-(-m(1,3)*m(3,2)+m(1,2)*m(3,3))/((-m(1,3)*m(2,2)+m(1,2)*| 452| . m(2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,| 453| . 1)+m(1,1)*m(2,2))*m(3,3)) | 454| minv(1,3)=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))/((-m(1,3)*m(2,2)+m(1,2)*m| 455| . (2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,1| 456| . )+m(1,1)*m(2,2))*m(3,3)) | 457| minv(2,1)=-(-m(2,3)*m(3,1)+m(2,1)*m(3,3))/((-m(1,3)*m(2,2)+m(1,2)*| 458| . m(2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,| 459| . 1)+m(1,1)*m(2,2))*m(3,3)) | 460| minv(2,2)=(-m(1,3)*m(3,1)+m(1,1)*m(3,3))/((-m(1,3)*m(2,2)+m(1,2)*m| 461| . (2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,1| 462| . )+m(1,1)*m(2,2))*m(3,3)) | 463| minv(2,3)=-(-m(1,3)*m(2,1)+m(1,1)*m(2,3))/((-m(1,3)*m(2,2)+m(1,2)*| 464| . m(2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,| 465| . 1)+m(1,1)*m(2,2))*m(3,3)) | 466| minv(3,1)=(-m(2,2)*m(3,1)+m(2,1)*m(3,2))/((-m(1,3)*m(2,2)+m(1,2)*m| 467| . (2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,1| 468| . )+m(1,1)*m(2,2))*m(3,3)) | 469| minv(3,2)=-(-m(1,2)*m(3,1)+m(1,1)*m(3,2))/((-m(1,3)*m(2,2)+m(1,2)*| 470| . m(2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,| 471| . 1)+m(1,1)*m(2,2))*m(3,3)) | 472| minv(3,3)=(-m(1,2)*m(2,1)+m(1,1)*m(2,2))/((-m(1,3)*m(2,2)+m(1,2)*m| 473| . (2,3))*m(3,1)+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2)+(-m(1,2)*m(2,1| 474| . )+m(1,1)*m(2,2))*m(3,3)) | 475| return | 476| end | 477+------------------------------------------------------------------------+ 478.ft 479.DE 480.LP 481This is an example of a modular approach to code generation; 482separate subprogram templates are given in separate 483files. Furthermore, the template files are general; they can be 484used for matrices of any predetermined size. Therefore, we 485can easily generate different subprograms to handle matrices 486of different sizes from the same template files simply by 487assigning different values to n, and reloading the file 488init.in. 489.NH 2 490Insertion of Generated Type Declarations 491.LP 492The \fIgendecs\fR flag makes it possible to generate declarations 493for variables generated from within active parts of template files. 494.SH 495Example: 496.LP 497Suppose we wish to process a template file which will cause GENTRAN 498to generate one or more temporary variables in an active part. We can 499tell GENTRAN to generate declarations in the correct location by 500processing the template file twice as follows: 501.LP 502Construct the template file as usual, but with two additions: 503.IP 1) 504Insert an active part at the beginning of the file to turn the 505\fIgendecs\fR flag off: 506.DS L 507.ft CR 508<< off(gendecs)$ >> 509.ft 510.DE 511.IP 2) 512Insert an active part immediately after the subprogram heading to write 513an active part to the output file. This active part will cause the 514\fIgendecs\fR flag to be switched back on during the second pass over 515the template file: 516.DS L 517.ft CR 518<< gentran( literal("<< on(gendecs)\e$ \e>\e>", cr) )$ >> 519.ft 520.DE 521.LP 522For example, suppose the original template file contains the following: 523.DS L 524.ft CR 525Contents of file detinv.tem: 526+------------------------------------------------------------+ 527| subroutine detinv(m,det,inv) | 528|<< | 529| off(gendecs)$ | 530| gentran( literal("<< on(gendecs)\e$ \e>\e>", cr) )$| 531|>> | 532|<< | 533| m : genmatrix(m, n,n, 1,1)$ | 534| gentran( type("real*8", m(eval(n),eval(n))) )$ | 535|>> | 536|<< | 537| gentran( type("real*8", det), | 538| rsetq( det, determinant(m) ) )$ | 539|>> | 540|<< | 541| gentran( type("real*8", inv(eval(n),eval(n))), | 542| rsetq( inv, m^^(-1) ) )$ | 543|>> | 544| return | 545| end | 546+------------------------------------------------------------+ 547.ft 548.DE 549Now we are ready to invoke the template processor. Since it must make 550two passes over the template file, we will invoke it twice and have it 551write to a temporary file as follows: 552.DS L 553.ft CR 554(c1) n : 3$ 555.ft 556.DE 557.DS L 558.ft CR 559(c2) ?maxexpprintlen\* : 60$ 560.ft 561.DE 562.DS L 563.ft CR 564(c3) gentranin("detinv.tem", ["##detinv"]); 565 566(d3) ##detinv 567.ft 568.DE 569.DS L 570.ft CR 571(c4) gentranin("##detinv", ["detinv.f"]); 572 573(d4) detinv.f 574.ft 575.DE 576.LP 577After the first template processing command has been executed, ##detinv 578contains the following: 579.DS L 580.ft CR 581Contents of file ##detinv: 582+------------------------------------------------------------+ 583| subroutine detinv(m,det,inv) | 584|<< on(gendecs)$ >> | 585| t0=m(1,3)*(-m(2,2)*m(3,1)+m(2,1)*m(3,2)) | 586| t0=t0-m(1,2)*(-m(2,3)*m(3,1)+m(2,1)*m(3,3)) | 587| det=t0+m(1,1)*(-m(2,3)*m(3,2)+m(2,2)*m(3,3)) | 588| t1=-m(2,3)*m(3,2)+m(2,2)*m(3,3) | 589| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 590| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 591| inv(1,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 592| t1=-(-m(1,3)*m(3,2)+m(1,2)*m(3,3)) | 593| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 594| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 595| inv(1,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 596| t1=-m(1,3)*m(2,2)+m(1,2)*m(2,3) | 597| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 598| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 599| inv(1,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 600| t1=-(-m(2,3)*m(3,1)+m(2,1)*m(3,3)) | 601| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 602| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 603| inv(2,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 604| t1=-m(1,3)*m(3,1)+m(1,1)*m(3,3) | 605| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 606| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 607| inv(2,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 608| t1=-(-m(1,3)*m(2,1)+m(1,1)*m(2,3)) | 609| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 610| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 611| inv(2,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 612| t1=-m(2,2)*m(3,1)+m(2,1)*m(3,2) | 613| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 614| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 615| inv(3,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 616| t1=-(-m(1,2)*m(3,1)+m(1,1)*m(3,2)) | 617| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 618| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 619| inv(3,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 620| t1=-m(1,2)*m(2,1)+m(1,1)*m(2,2) | 621| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 622| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 623| inv(3,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 624| return | 625| end | 626+------------------------------------------------------------+ 627.ft 628.DE 629This is a temporary file. It can be removed after the second \fIgentranin\fR 630command has been executed. 631.LP 632The final output file will contain the following: 633.DS L 634.ft CR 635Contents of file detinv.f: 636+------------------------------------------------------------+ 637| subroutine detinv(m,det,inv) | 638| real*8 m(3,3),det,inv(3,3),t0,t1 | 639| t0=m(1,3)*(-m(2,2)*m(3,1)+m(2,1)*m(3,2)) | 640| t0=t0-m(1,2)*(-m(2,3)*m(3,1)+m(2,1)*m(3,3)) | 641| det=t0+m(1,1)*(-m(2,3)*m(3,2)+m(2,2)*m(3,3)) | 642| t1=-m(2,3)*m(3,2)+m(2,2)*m(3,3) | 643| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 644| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 645| inv(1,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 646| t1=-(-m(1,3)*m(3,2)+m(1,2)*m(3,3)) | 647| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 648| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 649| inv(1,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 650| t1=-m(1,3)*m(2,2)+m(1,2)*m(2,3) | 651| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 652| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 653| inv(1,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 654| t1=-(-m(2,3)*m(3,1)+m(2,1)*m(3,3)) | 655| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 656| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 657| inv(2,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 658| t1=-m(1,3)*m(3,1)+m(1,1)*m(3,3) | 659| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 660| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 661| inv(2,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 662| t1=-(-m(1,3)*m(2,1)+m(1,1)*m(2,3)) | 663| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 664| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 665| inv(2,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 666| t1=-m(2,2)*m(3,1)+m(2,1)*m(3,2) | 667| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 668| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 669| inv(3,1)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 670| t1=-(-m(1,2)*m(3,1)+m(1,1)*m(3,2)) | 671| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 672| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 673| inv(3,2)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 674| t1=-m(1,2)*m(2,1)+m(1,1)*m(2,2) | 675| t0=(-m(1,3)*m(2,2)+m(1,2)*m(2,3))*m(3,1) | 676| t0=t0+(m(1,3)*m(2,1)-m(1,1)*m(2,3))*m(3,2) | 677| inv(3,3)=t1/(t0+(-m(1,2)*m(2,1)+m(1,1)*m(2,2))*m(3,3))| 678| return | 679| end | 680+------------------------------------------------------------+ 681.ft 682.DE 683.NH 2 684Special Template Variables 685.LP 686 687 ** Not Implemented Yet ** 688