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