Artifact f61ed6a174b3ca4cb6a4f71352ff971d8a198341796937e8b952adcfcdbe8966:
- Executable file
r36/doc/TRI.TEX
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 85868) [annotate] [blame] [check-ins using] [more...]
- Executable file
r37/packages/tri/tri.tex
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 85868) [annotate] [blame] [check-ins using]
- Executable file
r38/packages/tri/tri.tex
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 85868) [annotate] [blame] [check-ins using]
\relax % ********************************************************************** % **** **** % **** DRAFT: The TeX-REDUCE-Interface **** % **** Werner Antweiler, University of Cologne, August 1, 1988 **** % **** **** % ********************************************************************** \magnification=1200 \hoffset=10truemm\hsize=16truecm\vsize=10truein \tolerance 1500 \hbadness=800 \parindent=12pt \parskip=0pt \displayindent=30pt \baselineskip=12pt plus0.1pt minus0.2pt \newdimen\narrowskip \narrowskip=10pt % Make Use of 12pt-Fonts Default % \font\caps=cmcsc10 \font\smallcaps=cmcsc10 at 10truept \font\small=cmr8 \font\smallit=cmti8 \font\smallbf=cmbx8 \font\smalltt=cmtt8 \font\big=cmbx10 at 15pt % \catcode`\"=\active \let"=\" \let\3=\ss \def\zB{z.B.\ } \def\D{\char'042} \def\B{\char'134} % ----------- % Hilfsmacros % ----------- \def\ttq{\par\vskip3.6135pt\begingroup\baselineskip=14.454pt \parindent=30pt\parskip=0pt\let\par=\endgraf\obeyspaces\obeylines\tt\ttf} {\obeylines\gdef\ttf^^M#1\endtt{\vbox{#1}\endgroup\par\noindent}} {\obeyspaces\gdef {\ }} \def\iq#1{{\it#1\/}} \def\quote{\par\begingroup\leftskip=\parindent \baselineskip=9.03pt\small\noindent} \def\endquote{\par\endgroup\par} \def\today{\ifcase\month\or January\or February\or March\or April\or May\or June\or July\or August\or September\or October\or November\or December\fi \space\number\day, \number\year} \def\endpage{\par\vfill\eject} \newcount\Defcount \Defcount=0 \def\Def#1\par{\global\advance\Defcount by1\par \vskip3.6135pt{\baselineskip=14.454pt \noindent\bf Definition \the\Defcount:\sl\enspace#1\par}} \let\YY=\let % now you can send the control sequence \YY \newcount\Figcount \Figcount=0 \def\VFig{\vFig\smalltt} \def\VVFig{\vFig\tt} \def\vFig#1{\midinsert\global\advance\Figcount by 1 \message{[Fig. \the\Figcount]} \vbox\bgroup \hrule height.6pt \hbox to\hsize\bgroup \vrule width.6pt \hskip 9.4pt \vbox\bgroup \advance\hsize by-20pt \line{} \vskip 9.4pt \nointerlineskip \let\vtt=#1\verbatim} \def\endVFig#1:#2\par{\vskip 9.4pt \egroup \hss \vrule width.6pt \egroup \hrule height.6pt \vskip3pt\baselineskip=\narrowskip \noindent\smallbf Fig. \the\Figcount: #1. \small #2\par \egroup\endinsert} % ------------------ % Fussnotensteuerung % ------------------ \newcount\notenumber\notenumber=0 \def\vfootnote#1{\insert\footins\bgroup \interlinepenalty=\interfootnotelinepenalty \splittopskip=\ht\strutbox \splitmaxdepth=\dp\strutbox \floatingpenalty=20000 \leftskip=0pt \rightskip=0pt \spaceskip=0pt \xspaceskip=0pt \item{#1}\footstrut\futurelet\next\fooot} \def\fooot{\ifcat\bgroup\noexpand\next\let\next\foooot \else\let\next\foot\fi\next} \def\foooot{\bgroup\aftergroup\oofoot\let\next} \def\foot#1{#1\oofoot} \def\oofoot{\strut\egroup} \def\note#1{\global\advance\notenumber by1 \begingroup\small\baselineskip=\narrowskip \setbox\strutbox=\hbox{\vrule height7.0pt depth3.0pt width0pt}% \footnote{$^{\the\notenumber}$}{\bgroup\small\baselineskip=\narrowskip #1\egroup}\endgroup} % ----------------------------------- % Seitenkopf und Fusszeilen-Steuerung % ----------------------------------- \pageno=1 \headline={\ifnum\pageno=1\hfill\else\hfill\rm---\ \folio\ ---\hfill\fi} \footline={\hfil} % ------------------ % Inhaltsverzeichnis % ------------------ \let\ZZ=\let % now you can send the control sequence \ZZ \newcount\seccount \seccount=0 \newcount\subseccount \subseccount=0 \newcount\subsubseccount \subsubseccount=0 \def\secnum{\number\seccount% \ifnum\subseccount=0\else.\number\subseccount\fi% \ifnum\subsubseccount=0\else.\number\subsubseccount\fi} % -------- % Textteil % -------- \newbox\secbox \def\secindent#1#2#3{\par\bigskip\begingroup \message{\secnum #1}\setbox\secbox=\hbox{#3\secnum\hskip1.5em} \hangafter=1\hangindent=\wd\secbox\baselineskip=\ht\secbox \advance\baselineskip by5pt \noindent #3\box\secbox#1 \par\endgroup\nobreak\smallskip \nobreak\smallskip\vskip-\parskip\noindent} \def\sec#1\par{\global\advance\seccount by1\global\subseccount=0 \global\subsubseccount=0\secindent{#1}{0}\bf} \def\subsec#1\par{\global\advance\subseccount by1 \global\subsubseccount=0\secindent{#1}{1}\bf} \def\subsubsec#1\par{\global\advance\subsubseccount by1 \secindent{#1}{2}\bf} % -------------- % Spezial Makros % -------------- \def\center{\vskip\parskip\begingroup \parindent=0pt \parskip=0pt plus 1pt \rightskip=0pt plus 1fill \leftskip=0pt plus 1fill \obeylines} \def\endcenter{\endgroup} \def\flushleft{\vskip\parskip\begingroup \parindent=0pt \parskip=0pt plus 1pt \rightskip=0pt plus 1fill \leftskip=0pt \obeylines} \def\endflushleft{\endgroup} \def\flushright{\vskip\parskip\begingroup \parindent=0pt \parskip=0pt plus 1pt \rightskip=0pt \leftskip=0pt plus 1fill \obeylines} \def\endflushright{\endgroup} \def\itemize#1{\par\begingroup\parindent=#1} \def\litem#1{\par\hang\noindent\hbox to \parindent{#1\hfil}} \def\ritem#1{\par\hang\noindent\hbox to \parindent{\hfil#1\enspace}} \def\sitemize#1{\par\begingroup\parindent=#1\baselineskip=\narrowskip\small} \def\enditemize{\par\endgroup\par} \def\bitem{\ritem{$\bullet$}} % ------------ % Mathe-Makros % ------------ \newcount\eqcount \eqcount=0 \newcount\eqoffcount \def\adveq{\global\advance\eqcount by1} \def\eqcon{\adveq(\number\eqcount)} \def\eqco{\eqno{\eqcon}} \def\ceqc#1{(\number\eqcount.#1)} \def\ceqalign{\adveq\eqalignno} \def\eqoff#1{\eqoffcount=\eqcount\advance\eqoffcount by-#1% (\the\eqoffcount)} \catcode`\*=\active \def*{\ifmmode\cdot\else\char'52\fi} % Spezialmakros \def\aut#1 \ttl#2 \pub#3 \ref#4 \dat#5 \inx#6 \^^M{\par {\baselineskip=\narrowskip \parindent=24pt\hang\noindent{\smallcaps#1}\small\ (#6) #2. #3, #5% \ifx\\#4\else, #4\fi.\par}\medskip\penalty0} \def\example{\par\vskip5pt\flushleft\tt\parindent=50pt} \def\endexample{\endflushleft\vskip5pt\noindent\ignorespaces} \def\i#1{{\it #1\/}} \def\t#1{{\tt #1}} \def\VAX{$\mu$VAX-I\kern-0.1em I} % ---------------------------------------------------------------------- % Verbatim Mode Macros % ---------------------------------------------------------------------- \def\uncatcodespecials{\def\do##1{\catcode`##1=12}\dospecials\do\"} \let\vtt=\tt \def\setupverbatim{\vtt\Obeylines\uncatcodespecials\obeyspaces} \def\newlinepar{~\par} {\catcode`\^^M=\active % these lines must end with `%' \gdef\Obeylines{\catcode`\^^M=\active\def^^M{\newlinepar}}}% {\obeyspaces\global\let =\ } \def\verbatim{\par\begingroup\parskip=0pt plus 1pt \ifx\vtt\smalltt\baselineskip=10pt\fi \setupverbatim\doverbatim} {\catcode`\|=0 \catcode`\\=12 |Obeylines|gdef|doverbatim^^M#1\endverbatim{#1|endgroup}} \def\verb{\begingroup\setupverbatim\doverb} \def\doverb#1{\def\next##1#1{##1\endgroup}\next} % ---------------------------------------------------------------------- % REDUCE-LISP Programming Language Documentation % ---------------------------------------------------------------------- \newdimen\xindent \dimen\xindent=15pt \catcode`\@=\active \def\@{\char'100} \def@{\hskip\dimen\xindent\ignorespaces} \def\gets{$\leftarrow$} \def\\#1/{{\it#1\/\kern.05em}} % italic type for identifiers \def\&{{\bf#1\/}} % boldface type for reserved words \def\.#1.{{\tt#1\/}} % typewriter type for strings \def\!#1!{{\rm$\langle$ #1 $\rangle$\/}} % roman for operations \def\[#1]{{\rm$\{$ #1 $\}$}} % comments in roman \def\DOC{\midinsert\global\advance\Figcount by 1 \message{[Fig. \the\Figcount]} \vbox\bgroup \hrule height.6pt \hbox to\hsize\bgroup \vrule width.6pt \hskip 9.4pt \vbox\bgroup \advance\hsize by-20pt \line{} \vskip 9.4pt \nointerlineskip \parindent=0pt \parskip=0pt plus 1pt \rightskip=0pt plus 1fill \leftskip=0pt \begingroup\obeylines} \def\endDOC{\endgroup\endDoc} \def\endDoc#1:#2\par{\vskip 9.4pt \egroup \hss \vrule width.6pt \egroup \hrule height.6pt \vskip3pt\baselineskip=\narrowskip \noindent\smallbf Fig. \the\Figcount: #1.\ \small#2\par \egroup\endinsert} % ---------------------------------------------------------------------- % Titel % ---------------------------------------------------------------------- \line{} \vskip10mm \center\big\baselineskip=24pt Typesetting REDUCE output with \TeX --- A REDUCE-\TeX-Interface --- \endcenter \vskip13mm \center\baselineskip=12pt \smallcaps Werner Antweiler \smallcaps Andreas Strotmann \smallcaps Volker Winkelmann \small University of Cologne Computer Center, West Germany{\parindent=12pt% \note{The authors are with: % Rechenzentrum der Universit"at zu K"oln (University of Cologne % Computer Center), % Abt. Anwendungssoftware (Application Software Department), % Robert-Koch-Stra\3e 10, 5000 K"oln 41, West Germany.}} \small\today \endcenter \vskip15mm \begingroup\narrower\narrower\baselineskip=\narrowskip \noindent\smallbf Abstract: \small REDUCE is a well known computer algebra system invented by Anthony C. Hearn. Although a pretty-printer is already incorporated in REDUCE, the output is produced only in line-printer quality. The simple idea to produce high quality output from REDUCE is to link REDUCE with Donald E. Knuth's famous \TeX\ typesetting language. This draft reviews our efforts in this direction. We introduce a program written in REDUCE-Lisp which is able to typeset REDUCE formulas using \TeX. Our REDUCE-\TeX-Interface incorporates three levels of \TeX\ output: without line breaking, with line breaking, and with line breaking plus indentation. This paper deals with some of the ideas we have put into LISP-code and it summarizes some of our experiments we have made with it yet. Furthermore, we compile a small user's manual introducing to the use of our REDUCE-\TeX-Interface. \par\bigskip \noindent\smallbf Keywords: \small Line-Breaking Algorithm, LISP, Prefix-to-Infix Conversion, REDUCE, \TeX, Typesetting \par\endgroup\vskip10mm \rm %begin(text) % ---------------------------------------------------------------------- \sec Introduction\par % ---------------------------------------------------------------------- REDUCE is a well known computer algebra system invented by Anthony C. Hearn. While every effort was made to improve the system's algebraic capabilities, the readability of the output remained poor by modern typesetting standards. Although a pretty-printer is already incorporated in REDUCE, the output is produced only in line-printer quality. The simple idea to produce high quality output from REDUCE is to link REDUCE with Donald E. Knuth's famous \TeX\ typesetting language. This draft reviews our efforts in this direction. We introduce a program written in REDUCE-Lisp to typeset REDUCE formulas with \TeX. Our REDUCE-\TeX-Interface incorporates three levels of \TeX\ output: without line breaking, with line breaking, and with line breaking plus indentation. While speed without line breaking is comparable to that achieved with REDUCE's pretty-printer, line breaking consumes much more CPU time. Nevertheless, we reckon with a cost increase due to line breaking which is almost linear in the length of the expression to be broken. This paper deals with some of the ideas and algorithms we have programmed and it summarizes some of the experiments we have made with our program. Furthermore, at the end of this paper we provide a small user's manual which gives a short introduction to the use of our REDUCE-\TeX-Interface. For simplicity's sake the name ``REDUCE-\TeX-Interface'' will be abbreviated to ``TRI'' in this paper.\note{The reason why it was called TRI and not RTI is simply due to the fact that TRI corresponds better to the three-level (``tri-level'') mode.} At this point we should mention major goals we pursue with TRI: \bitem We want to produce REDUCE-output in typesetting quality.\par \bitem The intermediate files (\TeX-input files) should be easy to edit. The reason is that it is likely that the proposed line-breaks are sub-optimal from the user's point of view.\par \bitem We apply a \TeX-like algorithm which ``optimizes'' the line-breaking over the whole expression. This differs fundamentally from the standard left-to-right, one-line look-ahead pretty-printers of REDUCE, LISP and the like.\par % ---------------------------------------------------------------------- \sec From REDUCE to \TeX: concepts\par % ---------------------------------------------------------------------- REDUCE uses the function \t{varpri} to decide how to output a REDUCE expression. The function gets three arguments: the expression to be printed, a list of variables to each of which the expression to be printed gets assigned, and a flag which determines if the expression to be printed is the first, last or only expression in the line. \t{varpri} may be called consecutively for preparing a line for output. So, our task is to assemble all expressions before finally printing them. When !*TeX is true, \t{varpri} redirects output to our function \t{TeXvarpri}, which receives a REDUCE expression, translates it into \TeX\ and pushes it onto a variable called \t{TeXStack*} before eventually printing it once the line is completed.\par The \t{TeXvarpri} function first calls a function named \t{makeprefix}. Its job is to change a REDUCE algebraic expression to a standard prefix list while retaining the tree structure of the whole expression. Generally, this is done using a call \t{prepsq*(simp(expression))}, but lists and matrices need some special treatment. After this has been done the new intermediate expression is passed to the most important module of the TRI: the \t{mktag/makefunc}-family.\note{The whole family currently has five members. The ``parents'' are the mktag and makefunc functions which do the most burdensome job. The ``children'' are \t{makearg, makemat and makeDF} which handle special cases such as list construnction or differentiation operators. We do not review the minor functions since they are easily understandable.} These functions recursively expand the structured list (or operator tree) into a flat list, translating each REDUCE symbol or expression into so-called \TeX-items on passing by. For that reason, this list is called the \TeX-item list. If the simple \TeX-mode (without line breaking) was chosen this list is then printed immediately without further considerations. Translation and printing this way is almost as fast as with the standard REDUCE pretty printer.\par When line-breaking has been enabled things get a bit more complicated. The greatest effort with TRI was to implement the line-breaking algorithm. More than half of the entire TRI code deals with this task. The ultimate goal is to add some ``break items'', i.e. \verb|\nl|-% \TeX-commands\note{This is not a \TeX-primitive but a TRI-specific \TeX-macro command which expands into a lot of stuff.}, marking --- in a certain way --- optimal line-breaks. Additionally, these break items can be followed immediately by ``indentation items'', i.e. \verb|\OFF{...}| \TeX-commands\note{see previous footnote}, specifying the amount of indentation applicable for the next new line. The problem is to choose the right points where to insert these special \TeX-items. Therefore, the \TeX-item list undergoes three further transformation steps.\par First, the \TeX-item list gets enlarged by so-called ``glue items''. Glue items are two-element lists, where the first element is a width info and the second element is a penalty info. The ``penalty'' is a value in the range $-10000\ldots+10000$ indicating a mark-up on a potential break-point, thus determining if this point is a fairly good (if negative) or bad (if positive) choice. The amount of penalty depends (a) on the kind of \TeX-items surrounding the glue item, (b) on the bracket nesting, and finally (c) on special characteristics.\note{For example, the plus- and the difference operator have special impact on the amount of penalty.} The function handling this job is named \t{insertglue} which implicitly calls the function \t{interglue}. The latter determines the glue item to insert between a left and a right \TeX-item.\par During the second level, the \TeX-item list becomes transformed into a so-called breaklist consisting of active and passive nodes. A passive node is simply a width info giving the total width of \TeX-items not interspersed by glue items. On the other hand, active nodes are glue items enlarged by a third element, the offset info, indicating an indentation level which is used later for computing the actual amount of indentation. Active nodes are used as potential breakpoints. Moreover, while creating the breaklist, the \TeX-item list will be modified if necessary according to the length of fractions and square roots which cannot be broken if retained in their ``classical'' form. Hence fractions look like \t{(...)/(...)} if they don't fit into a single line, especially in the case of large polynomial fractions. The major function for this job is named \t{breaklist} which calls \t{resolve} if necessary. \par The third and most important level is the line-breaking algorithm itself. This algorithm embedded in the function \t{trybreak} will be described below. The idea how to break lines is based on the article by Knuth/Plass(1981). Line-breaking can occur at active nodes only. So, you can loop through the breaklist considering all potential break-points. But in order to find a suitable way in a reasonable amount of time you have to limit the number of potential breakpoints considered. This is performed by associating a ``badness'' with each potential breakpoint, describing how good looking or bad looking a line turns out. If the badness is less than a given amount of ``tolerance'' --- as set by the user --- then an active node is considered to be feasible and becomes a delta node. A delta node is simply an active node enlarged by four further infos: an identification number for this node, a pointer to the best feasible break-point (i.e. delta-node) to come from% \note{If one were to break the formula at this delta-node, the best place to start this line is given by this pointer.} the total amount of demerits (i.e. a compound value derived from badness and penalty) accumulated so far, and a value indicating the amount of indentation applied to a new line beginning at this node. When \t{trybreak} has stepped through the list, the breakpoints will have been determined. Afterwards all glue items (i.e. active nodes) are deleted from the \TeX-item list while break- and indentation-% items for those nodes marked as break-points are inserted. \par Finally the \TeX-item list is printed with regular ASCII-characters. We didn't put much emphasis on the question on how to format the intermediate output since it will be input directly into \TeX. The best way to characterize the routine \t{texout} is to call it quick and dirty. The readabiltiy of the output is low, but it may be quite good enough for users to do some final editing work. Nevertheless, \t{texout} keeps the nesting structure of the term visible when printed, so it will be easy to distinguish between parenthesis levels simply by considering the amount of indentation. % ---------------------------------------------------------------------- \sec Creating a \TeX-item list\par % ---------------------------------------------------------------------- The first \TeX-specific step in preparing a typesettable equivalent of a REDUCE expression is to expand the operator tree generated by REDUCE into a so-called \TeX-item list. The operator tree is preprocessed by \t{makeprefix} in order to receive an operator tree in standard prefix notation. A \TeX-item is either a character (letter or digit or special character) or a \TeX-primitive or -macro (i.e. a LISP symbol), with properties \t{'CLASS}, \t{'TEXTAG}, \t{'TEXNAME} and (only if the item represents an operator) \t{'TEXPREC}, \t{'TEXPATT} and \t{'TEXUBY} bound to them, depending on what kind of \TeX-item it actually is. The latter three properties are used for operators only. \t{'TEXPREC} is the precedence of the operator, a number between 0 and 999. Here the value itself is less important than the position with respect to other operators' precedences. The remaining properties will be described later. \par First let's have a look at how a REDUCE expression arriving at TRI's main entry --- the function \t{TeXvarpri} --- is transformed through several levels of TRI-processing. For instance, let us consider the expression $(x-y)^{12}$, which expands into a polynomial $x^{12}-12*x^{11}*y+\cdots-12*x*y^{11}+y^{12}$ when evaluated. REDUCE uses a special form to store an expression. This form is called ``standard quotient'' because it in fact represents a quotient of two polynomials. The contents of the following figure 1 shows the ``standard quotient'' form of our example.\par % ---------------------------------------------------------------------- \VFig (*SQ ((((X . 12) . 1) ((X . 11) ((Y . 1) . -12)) ((X . 10) ((Y . 2) . 66)) ((X . 9) ((Y . 3) . -220)) ((X . 8) ((Y . 4) . 495)) ((X . 7) ((Y . 5) . -792)) ((X . 6) ((Y . 6) . 924)) ((X . 5) ((Y . 7) . -792)) ((X . 4) ((Y . 8) . 495)) ((X . 3) ((Y . 9) . -220)) ((X . 2) ((Y . 10) . 66)) ((X . 1) ((Y . 11) . -12)) ((Y . 12) . 1) ) . 1) T) \endverbatim \endVFig Standard Quotient Notation: This form is the way REDUCE represents terms.\par % ---------------------------------------------------------------------- \noindent The term has been indented by hand to retain the structure of this expression. Actually the denominator is 1 as you easily find out from the last line.\note{The ``T'' in the last line is an ``already-% simplified''-flag indicating that the term doesn't need to undergo any more processing.} Obviously the standard-quotient form is a bit complicated for further manipulations. It can be changed to a real prefix notation as displayed in figure 2. Here, too, the term was edited by hand to make it a bit more readable and comparable to the other forms.\note{``Edit'' only means we have provided some additional indentation. We have changed neither the expression nor its structure.} Note that \t{PLUS} is not a binary but a $n$-ary operator, i.e. it takes an arbitrary number of arguments, while \t{MINUS} is always a unary operator.\note{The same problem arises with the RECIP-operator which is the unary form of the binary QUOTIENT-% operator.} This causes a bit of trouble because real binary operators are much easier to handle. To tackle this problem we have introduced the \t{'TEXUBY} property, which is used to change a unary into a binary form if possible.\par % ---------------------------------------------------------------------- \VFig (PLUS (EXPT X 12) (MINUS (TIMES 12 (EXPT X 11) Y )) (TIMES 66 (EXPT X 10) (EXPT Y 2)) (MINUS (TIMES 220 (EXPT X 9) (EXPT Y 3))) (TIMES 495 (EXPT X 8) (EXPT Y 4)) (MINUS (TIMES 792 (EXPT X 7) (EXPT Y 5))) (TIMES 924 (EXPT X 6) (EXPT Y 6)) (MINUS (TIMES 792 (EXPT X 5) (EXPT Y 7))) (TIMES 495 (EXPT X 4) (EXPT Y 8)) (MINUS (TIMES 220 (EXPT X 3) (EXPT Y 9))) (TIMES 66 (EXPT X 2) (EXPT Y 10)) (MINUS (TIMES 12 X (EXPT Y 11))) (EXPT Y 12)) \endverbatim \endVFig Prefix Notation: This list represents the state after application of {\smalltt makeprefix}\par % ---------------------------------------------------------------------- A REDUCE expression is expanded using the two functions \t{mktag} and \t{makefunc}. Function \t{mktag} identifies the operator and is able to put some brackets around the expression if necessary. \t{makefunc} is a pattern oriented ``unification''\note{in the terminology of the programming language Prolog} function, which matches arguments of a REDUCE expression in order of appearance with so-called ``unification tags'', as explained below. Thus, \t{mktag} and \t{makefunc} are mutually dependent and highly recursive functions.\par A ``unification tag list'' is a list (or a pattern, if you like) which consists of single ``unfication tags''. Each REDUCE operator is associated with a unification pattern. While expanding the expression, each tag is replaced by the appropiate \TeX-item or partial \TeX-item list created subsequently. A tag is defined as either an atom declared as a \TeX-item or one of the following:\par\itemize{27mm}\smallskip \litem{(F)}insert operator \litem{(X)}insert non-associative argument \litem{(Y)}insert a left- or right-associative argument \litem{(Z)}insert superscript/subscript argument \litem{(R)}use tail recursion to unify remaining arguments (necessary with operators having more than two arguments, e.g. the plus operator; associativity depends on previous (X) or (Y) tag) \litem{(L \i{hs})}insert a list of arguments (eat up all arguments on passing by); put \i{hs} as a horizontal separator between the arguments (e.g., a separator could be a comma for simple argument lists.) \litem{(M \i{vs} \i{hs})}insert a matrix (and eat up all arguments on passing by); put \i{vs} as a vertical separator and \i{hs} as a horizontal separator between the rows and columns \litem{(APPLY \i{fun})}apply function \i{fun} to remaining argument list \par\enditemize\smallskip \noindent These ``tags'' are assembled to a tag-list or pattern, respectively. For each functor (i.e. the head of a prefix list, e.g. \t{PLUS}, \t{MINUS} or \t{SQRT}) such a list is bound to its property \t{'TEXPATT}. For instance, the functor \t{PLUS} has got the pattern \t{((X) (F) (R))} bound to it, and the functor \t{EXPT} possesses the pattern \verb|((X) ^{ (Z) })|. The following two boxes with pseudo-code (figures 3 and 4) survey the two major functions performing the expansion of a prefix REDUCE-expression into a TeX-item list.\par % ---------------------------------------------------------------------- \DOC \&function& \\mktag/(\\tag/,\\outer-precedence/,\\associative/); \&begin& @ \&if& \!tag is empty! \&then return nil& @ \&else if& \!tag is an atom! \&then return& \!get the \TeX-item for% \\tag/! @ \&else begin& \[the tag is a list] @ @ \\precedence/\gets\!precedence of this tag or 999! @ @ \[now expand the expression, the first element is the] @ @ \[functor, the following elements are the arguments] @ @ \\term/\gets\\makefunc/(\&car& \\tag/,\&cdr& \\tag/,\\precedence/); @ @ \[check for parentheses: term is surrounded by parentheses in order] @ @ \[to prevent it from overruling by precedence] @ @ \&if& (\\associative/ \&and& (\\precedence/ = \\outer-precedence/)) @ @ @ \&or& (\\precedence/ $<$ \\outer-precedence/) @ @ \&then& \\term/\gets\!put a pair of brackets around \\term/!; @ @ \&return& \\term/ @ \&end& \&end&; \endDOC The function {\smalltt mktag}: This function deals with the transformation from prefix notation to \TeX\ notation. One important task of it is to decide whether or not brackets should be placed around the term.\par % ---------------------------------------------------------------------- At this point, the way we use our LISP pseudo-code should be explained. Words typeset in boldface are reserved words, e.g. \&begin& and \&end&. We use a PASCAL-like syntax which is actually used by REDUCE-Lisp, too, but with a few differences: we use the word \&function& to indicate that a value is returned\note{REDUCE-Lisp uses the phrase ``symbolic procedure'' here.}, and we use \&return& to return the value of the function and therefore to exit the function. This is in contrast to the use of \t{return} in REDUCE-Lisp, where \t{return} is used only to return the value of a begin-end-block. Identifiers are printed in italics. Where identifiers are used as logical values, e.g. in conditions, they are either false if their value is \&nil& or true otherwise, regardless of their exact value. Pseudo-operations are printed in roman and are put in angle brackets. Comments, too, are printed in roman but they are put in curly brackets. Assignments are typeset by the assignment operator \gets, thus indicating the direction of assignment. Semicolons are used (as in PASCAL and REDUCE) as separators. In order to improve readability, mathematical expressions are given in mathematical form instead of real code. Finally, the operator {\tt ::=} is used to identify a pseudo-code-operation with its real code. We do not provide proper data type declarations for variables since this seems to be superfluous in LISP where you only deal with atoms and lists. % ---------------------------------------------------------------------- \DOC \&function& \\makefunc/(\\functor/,\\argument-list/,\\precedence/); \&begin& @ \\term/\gets\&nil&; @ \\pattern/\gets\!pattern of this functor or default pattern!; @ \&while& \\pattern/ \&do& \[as long as pattern isn't empty] @ \&begin& @ @ \\tag/\gets\&car& \\pattern/; @ @ \\pattern/\gets\&cdr& \\pattern/; @ @ \&if& \!\\tag/ is an atom! \&then& \\aux/\gets\&nil& @ @ \&else if& \!tag is (F)! \&then& \\aux/\gets\!get the \TeX-item for% \\functor/! @ @ \&else if& \!\\argument-list/ is empty! \&then& \\aux/\gets\&nil& @ @ \&else if& \!tag is (X)! \&then& @ @ \&begin& @ @ @ \\aux/\gets\\mktag/(\&car& \\argument-list/,\\precedence/,\&nil&); @ @ @ \\argument-list/\gets\&cdr& \\argument-list/ @ @ \&end& @ @ \&else if& \!tag is (Y)! \&then& @ @ \&begin& @ @ @ \\aux/\gets\\mktag/(\&car& \\argument-list/,\\precedence/,\&T&); @ @ @ \\argument-list/\gets\&cdr& \\argument-list/ @ @ \&end& @ @ \&else if& \!tag is (R)! \&then& \[tail recursive pattern] @ @ @ \&if cdr& \\argument-list/ \[more than one argument remaining?] @ @ @ \&then begin& @ @ @ @ \\pattern/\gets\!pattern for \\functor/!; @ @ @ @ \\argument-list/\gets\&nil& @ @ @ \&end& @ @ @ \&else begin& @ @ @ @ \\aux/\gets\\mktag/(\&car& \\argument-list/,\\precedence/,% \&nil&); @ @ @ @ \\argument-list/\gets\&cdr& \\argument-list/ @ @ @ \&end& @ @ \&else if& \!tag is (L \\hs/), (M \\vs hs/) or (APPLY xxx)! \&then& @ @ \&begin& @ @ @ \\aux/\gets\!result from call to a special routine!; @ @ @ \\argument-list/\gets\&nil& @ @ \&end& @ @ \&else& \\aux/\gets\&nil&; @ @ \&if& \\aux/ \&then& \!concatenate it to the end of term! @ \&end&; @ \&return& \\term/ \&end&; \endDOC The function {\smalltt makefunc}: As well as the function {\smalltt mktag} this function performs the prefix-to-\TeX\ notation. Its major task is to ``unify'' operators and their arguments with predefined patterns in order to build up lists of \TeX-items.\par % ---------------------------------------------------------------------- You can bind a \TeX-item to any REDUCE atom (except the operators) you like. This is supported by binding the \TeX-item to the specific atom by its property \t{'TEXNAME}. You can choose to have some default \t{'TEXNAME} properties for your variables. Function \t{makeset} defines a set of such default names. At the moment, two sets are provided for greek and for lowercase letters. Refer to the User's Guide for how you can use them.\par But now turn back to the state of modifications our example term has undergone. With our set of functions we have expanded the prefix form into a \TeX-item list consisting of single \TeX-items such as numbers, letters, \TeX-macros, \TeX-primitives and other \TeX\ symbols. The result is shown in figure 5. The \verb|\cdot| command is the multiplication sign, whereas \verb|^{| indicates the beginning of a superscript. (The term has been edited by hand to provide for proper indentation.)\par % ---------------------------------------------------------------------- \VFig ( x ^{ 1 2 } - 1 2 \cdot x ^{ 1 1 } \cdot y + 6 6 \cdot x ^{ 1 0 } \cdot y ^{ 2 } - 2 2 0 \cdot x ^{ 9 } \cdot y ^{ 3 } + 4 9 5 \cdot x ^{ 8 } \cdot y ^{ 4 } - 7 9 2 \cdot x ^{ 7 } \cdot y ^{ 5 } + 9 2 4 \cdot x ^{ 6 } \cdot y ^{ 6 } - 7 9 2 \cdot x ^{ 5 } \cdot y ^{ 7 } + 4 9 5 \cdot x ^{ 4 } \cdot y ^{ 8 } - 2 2 0 \cdot x ^{ 3 } \cdot y ^{ 9 } + 6 6 \cdot x ^{ 2 } \cdot y ^{ 1 0 } - 1 2 \cdot x \cdot y ^{ 1 1 } + y ^{ 1 2 } ) \endverbatim \endVFig A \TeX-item list: A \TeX-item is either a letter, a digit or another plain character, or it is a \TeX-command. Every \TeX-item belongs to one out of eight \TeX-item-classes.\par % ---------------------------------------------------------------------- The last box in this chapter (i.e. figure 6) is a verbatim copy of the output from TRI for our example. Because our example will be used to demonstrate line-breaking, too, some additional commands appear which won't occur in normal \TeX-mode. These additional commands you find at the beginning and ending of the output and as \verb|\nl|-commands within the output. Nevertheless, the structure of the output would be much the same with our normal \TeX-mode. % ---------------------------------------------------------------------- \VFig $$\displaylines{\qdd x^{12} -12\cdot x^{11}\cdot y +66\cdot x^{10}\cdot y^{2} -220\cdot x^{9}\cdot y^{3} +495\cdot x^{8}\cdot y^{4} -792\cdot x^{7}\cdot y^{5}\nl +924\cdot x^{6}\cdot y^{6} -792\cdot x^{5}\cdot y^{7} +495\cdot x^{4}\cdot y^{8} -220\cdot x^{3}\cdot y^{9} +66\cdot x^{2}\cdot y^{10} -12\cdot x\cdot y^{11} +y^{12} \Nl}$$ \endverbatim \endVFig Output produced by the TRI: This \TeX-code has to be postprocessed by \TeX. This example includes commands for line-breaking as produced with the second level of TRI.\par % ---------------------------------------------------------------------- The actual printing of TRI output in this example is easily readable since the expression is not deeply nested. Complications arise if expressions to be printed are deeply nested, use many subscripts and superscripts, have fractions and large operators and the like. Then output structure is worsened, especially if the whole expression extends over several lines. We provide a ``cheap'' way of indentation to retain some of the structure, but our solution is far from perfect. As the need for post-TRI-editing rises the output from TRI should be made better. However, our quick-and-dirty solution should suffice. % ---------------------------------------------------------------------- \sec Breaking REDUCE expressions into lines\par % ---------------------------------------------------------------------- As mentioned earlier, there are a few properties bound to each \TeX-item, two of them dealing with line-breaking. The following list gives you a survey of these two properties and the values they can take:\par \smallskip\itemize{17mm} \litem{\t{'CLASS}}one of the following class specifiers \itemitem{\t{'ORD\ }}ordinary symbols \itemitem{\t{'LOP\ }}large operators, such as integrals \itemitem{\t{'BIN\ }}binary operators \itemitem{\t{'REL\ }}relational operators \itemitem{\t{'OPN\ }}opening symbols (left parentheses) \itemitem{\t{'CLO\ }}closing symbols (right parentheses) \itemitem{\t{'PCT\ }}punctuation symbols \itemitem{\t{'INN\ }}inner \TeX\ group delimiters \litem{\t{'TEXTAG}}this is either an atom describing an \t{'INN} class or a list of widths defining the width of a \TeX-item, where succeeding elements of the list will be used depending on the \TeX\ inner group level (i.e. the nesting of subscripts or superscripts) \par\enditemize\smallskip\noindent Glue items are to be inserted between consecutive \TeX-items (similar to what \TeX\ does with its items). The following table specifies for each left and right class of a \TeX-item the corresponding glue measure. The glue item values have following meanings: 0 = no space, 1 = thin space, 2 = medium space, and 3 = thick space. An asterisk means that this case never arises, and values put in brackets indicate no space in the case of sub- or superscripts.\par % \midinsert \def\tablerule{\noalign{\hrule}} $$\vbox{\offinterlineskip \halign{&\vrule#&\quad\hfil\tt#\hfil\quad\cr \tablerule &\strut\rm Left&&\multispan{15}\hfil\rm Right Class\hfil&\cr &&&\multispan{15}\hrulefill&\cr &\strut\rm Class&&ORD&&LOP&&BIN&&REL&&OPN&&CLO&&PCT&&INN&\cr \tablerule &\strut ORD&&0&&1&&(2)&&(3)&&0&&0&&0&&0&\cr &\strut LOP&&1&&1&&*&&(3)&&0&&0&&0&&(1)&\cr &\strut BIN&&(2)&&(2)&&*&&*&&(2)&&*&&*&&(2)&\cr &\strut REL&&(3)&&(3)&&*&&0&&(3)&&0&&0&&(3)&\cr &\strut OPN&&0&&0&&*&&0&&0&&0&&0&&0&\cr &\strut CLO&&0&&1&&(2)&&(3)&&0&&0&&0&&0&\cr &\strut PCT&&(1)&&(1)&&*&&(1)&&(1)&&(1)&&(1)&&(1)&\cr &\strut INN&&0&&1&&(2)&&(3)&&(1)&&0&&(1)&&0&\cr \tablerule}}$$ \endinsert Actually, a glue item is a list consisting of two elements --- a width info characterizing the width of this item (in scaled points) and a ``penalty'' to be used if a line should be broken at this point. The algorithm for inserting glue items is easily described: for every consecutive pair of \TeX-items, get their classes and create a glue item according to the value found in the glue item table. For some special \TeX-items use special penalties instead of the default values. That's all.\par Let us return to our example from the last chapter. When the functions \t{insertglue} and \t{interglue} have finished, the \TeX-item list will be left (temporarily) extended with glue items. You can find them as the two-element lists in the example. All glue items there have (by chance) the same width 163840. But they have different penalties 0, 50 and -390. The latter therefore indicates a very good breaking point because it is a negative penalty, i.e. a bonus. See the following figure 7 for the changes made to the \TeX-item list. % ---------------------------------------------------------------------- \VFig ( x ^{ 1 2 } (163840 0) - 1 2 \cdot (163840 50) x ^{ 1 1 } \cdot (163840 50) y % (163840 -390) + 6 6 \cdot (163840 50) x ^{ 1 0 } \cdot (163840 50) y ^{ 2 } % (163840 0) - 2 2 0 \cdot (163840 50) x ^{ 9 } \cdot (163840 50) y ^{ 3 } % (163840 -390) + 4 9 5 \cdot (163840 50) x ^{ 8 } \cdot (163840 50) y ^{ 4 } % (163840 0) - 7 9 2 \cdot (163840 50) x ^{ 7 } \cdot (163840 50) y ^{ 5 } % (163840 -390) + 9 2 4 \cdot (163840 50) x ^{ 6 } \cdot (163840 50) y ^{ 6 } % (163840 0) - 7 9 2 \cdot (163840 50) x ^{ 5 } \cdot (163840 50) y ^{ 7 } % (163840 -390) + 4 9 5 \cdot (163840 50) x ^{ 4 } \cdot (163840 50) y ^{ 8 } % (163840 0) - 2 2 0 \cdot (163840 50) x ^{ 3 } \cdot (163840 50) y ^{ 9 } % (163840 -390) + 6 6 \cdot (163840 50) x ^{ 2 } \cdot (163840 50) y ^{ 1 0 } % (163840 0) - 1 2 \cdot (163840 50) x \cdot (163840 50) y ^{ 1 1 } % (163840 -390) + y ^{ 1 2 } ) \endverbatim \endVFig A \TeX-item list extended with glue items: \par % % Setting break points requires the creation of a ``breaklist''. A breaklist is a sequence of passive and active nodes, where each active node is followed by a passive node and vice versa. Active nodes represent glue items. Passive nodes are integer atoms which represent the width of a sequence of ordinary \TeX-items which must not be interspersed with glue items. Each breaklist consists of (at least one) passive nodes surrounded by delta nodes representing the beginning and ending of the list. \medskip \settabs\+\indent&passive-node\quad&\cr \+&\i{breaklist} &::= ( \i{delta-node} \i{inner-list} \i{delta-node} )\cr \+&\i{inner-list} &::= \i{passive-node} \i{active-node} \dots \i{passive-node}\cr \+&\i{active-node} &::= ( \i{width} \i{penalty} \i{offset} )\cr \+&\i{passive-node} &::= \i{width}\cr \+&\i{delta-node} &::= \i{active-node} $+$ \i{appendix}\cr \+&\i{appendix} &::= ( \i{id-number} \i{ptr} \i{demerits} \i{indentation} )\cr \medskip The breaklist will be created using the function \t{breaklist}. line breaking is performed with this list only; the \TeX-item list becomes modified only indirectly since the active nodes are shared. That means that the active nodes aren't copied while creating the breaklist. Instead, their memory addresses are put into the breaklist as a reference. This is both memory saving and necessary, since later we deal with the \TeX-item list itself again in order to insert \verb|\nl|-commands. So remember there exist two lists sharing all the active nodes (and hence all the delta nodes). Figure 8 contains the breaklist from our $(x-y)^{12}$ example. Bear in mind that passive nodes are sums of widths. The first line and the last line contain the beginning and ending delta nodes, respectively. By default, their \i{id-numbers} are 0 and -1, respectively. % % ---------------------------------------------------------------------- \VFig ((0 0 0 0 0 0 0) 915227 (163840 0 0) 1347128 (163840 50 0) 1097271 (163840 50 0) 321308 (163840 -390 0) 1347128 (163840 50 0) 1097271 (163840 50 0) 598015 (163840 0 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 -390 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 0 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 -390 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 0 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 -390 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 0 0) 1674808 (163840 50 0) 820564 (163840 50 0) 598015 (163840 -390 0) 1347128 (163840 50 0) 820564 (163840 50 0) 874722 (163840 0 0) 1347128 (163840 50 0) 543857 (163840 50 0) 874722 (163840 -390 0) 1384446 (0 0 41140184 -1 0 2147483647 0)) \endverbatim \endVFig A breaklist: Three types of objects are included in a breaklist. Active nodes are the lists with three elements. Delta nodes contain exactly seven elements. Passive nodes are integer atoms representing a width.\par % ---------------------------------------------------------------------- % The task of setting the break points (i.e. break items) in the breaklist is up to the function \t{trybreak}. During this phase, some active nodes are selected as ``feasible'' break points. Thus, they will be extended and called ``delta nodes'' furtheron. By default, the first and last node in a breaklist are delta nodes. When trybreak has finished, the \i{ptr}'s of the delta nodes point back to the best preceding delta node in terms of minimal total demerits. So, by stepping through this pointer list, it is easy to find the best path for breaking the whole breaklist apart. We use some terminology we'd like to explain: \itemize{27mm}\medskip \litem{\i{width}}width of this item (both active and passive nodes) \litem{\i{penalty}}a numeric value which prohibits line breaking (if negative, line breaking will be merited) \litem{\i{offset}}distance to the most recent opening bracket \litem{\i{id-number}}the identification number of this delta node (1,2,3,...) \litem{\i{ptr}}pointer to the best delta node to come from with respect to the minimal demerits path. (Note: a zero pointer indicates the very beginning of the breaklist) \litem{\i{demerits}}total demerits accumulated so far \litem{\i{indentation}}amount of indentation when breaking at this point \par\enditemize\medskip The algorithm itself will be described now. To determine the ``quality'' of a line we introduce a value called ``badness''. It simply is a heuristic describing how good-looking a line comes out. This concept is due to Knuth/Plass(1981) and is a major concept of \TeX. We use a slightly different heuristic here. We do not measure badness in terms of ``stretchability'' and ``shrinkability''. Instead we measure how ``full'' a line is, where ``full'' means that three quarters of the page width are optimal. Furthermore we add a surplus badness for the indentation: the less indentation the better. The badness is a value between 0 and 10000 and is calculated with the following code (displayed in figure 9). Surprisingly, we got a higher speed with floating point arithmetic here than with integer arithmetic. % ---------------------------------------------------------------------- \DOC \&function& \\badnessof/(\\length/,\\indentation/); \&begin& @ \\temp/\gets\&abs&(\\length/$-{3\over4}*$\\pagewidth/)/(${1\over6}*$% \\pagewidth/); @ \&return min&($10000,100*temp^3+2500*$\\indentation/$/$\\pagewidth/) \&end&; \endDOC The badness function: ``Badness'' is just a heuristic to compute a numerical value describing how ``good-looking'' a line comes out. A correction term is applied to provide for indentation.\par % ---------------------------------------------------------------------- Figure 10 summarizes the line breaking algorithm. The code is part of the function \t{trybreak} and describes the ``heart'' of our algorithm. Basically, it consists of two loops: the outer loop steps through the breaklist considering each delta node as a potential start of a new line while the inner loop looks ahead exactly one line (bounded by the \i{page-width} or by the rightmost delta-node) checking each active node if it is a feasible breakpoint, and if so, saving it as the best path of breaking. Or to put it in another way, simply imagine a window as wide as a page which moves over the unbroken expression from the very left to the very right. The left end of the window is put on every feasible breakpoint determined earlier. The right end of the window just defines the border of the search for feasible breakpoints within the window. % ---------------------------------------------------------------------- \DOC \\bottom/\gets\\breaklist/;\quad\\pagewidth/\gets\ % \!user defined page width!; \!set all variables not mentioned explicitly to zero or nil!; \&while& \\bottom/ \&do& \&begin& \[try a new line starting at this delta node] @ \\base/\gets\&car& \\bottom/; \\top/\gets\&cdr& \\bottom/; @ \\baseid/\gets\\idof/ \\base/; \\baseptr/\gets\\ptrof/ \\base/; @ \\basedemerits/\gets\\demeritsof/ \\base/; @ \\baseoffset/\gets\\offsetof/ \\base/; @ \\baseindent/\gets\\length/\gets\\indentof/ \\base/; @ \\total/\gets\\total/+\\widthof/ \\base/; @ \&while& \\top/ \&and& \\length$<$pagewidth/ \&do& @ \&begin& \[consider this node for end of the line] @ @ \\node/\gets\&car& \\top/; @ @ \\penalty/\gets\\penaltyof/ \\node/; @ @ \&if& \!node is a passive node! @ @ \&then& \\len/\gets\\len/+\\node/ @ @ \&else begin& \[node is an active node] @ @ @ \\badness/\gets\ \!compute current badness from \\length/ and% \\baseindent/! @ @ @ \\penalty/\gets\\penaltyof/ \\node/; \\offset/\gets\\offsetof/% \\node/; @ @ @ \&if& \\badness $<$ tolerance/ @ @ @ \&or& \\badness $< 1-$penalty/ @ @ @ \&or& \!this is the rightmost delta node! @ @ @ \&then begin& \[we have a feasible breakpoint] @ @ @ @ \\demerits/\gets\\basedemerits/+\\badness/$^2+$\\penalty/$*$% \&abs&(\\penalty/); @ @ @ @ \&if& \!node is a delta node! @ @ @ @ \&then begin& @ @ @ @ @ \&if& \\demerits$<$demeritsof node/ \[better path found?] @ @ @ @ @ \&then begin& @ @ @ @ @ @ \!save current \\demerits/ and \\baseid/ to \\node/!; @ @ @ @ @ @ \!compute amount of indentation! @ @ @ @ @ \&end& @ @ @ @ \&end& @ @ @ @ \&else begin& @ @ @ @ @ \\feasible/\gets\\feasible/+1; @ @ @ @ @ \!create new delta node with \\feasible, baseid, demerits/!; @ @ @ @ @ \!compute amount of indentation! @ @ @ @ \&end&; @ @ @ @ \&if& \\penalty/$=-10000$ \&then& \\top/\gets\&nil&% \[must break here] @ @ @ \&end;& @ @ @ \\length/\gets\\length/+\\wdithof node/ @ @ \&end&; @ @ \&if& \\top/ \&then& \\top/\gets\&cdr& \\top/ @ \&end&; @ \!save the total length so far to the delta node!; @ \!step ahead to next delta node and count total length! \&end&; \endDOC The code segment from {\smalltt trybreak} dealing with line-breaking: \par % ---------------------------------------------------------------------- Earlier we introduced the concept of ``badness'' derived from \TeX. But actually this is not the only measure answering the question whether a certain point in the breaklist is feasible or not. There are three conditions which decide whether a breakpoint is feasible or not. The first condition requires the badness to be smaller than the value of \i{tolerance} as specified by the user. This condition can be overridden if the active node under consideration has a negative penalty whose (absolute, i.e. positive) amount is greater than the badness. That means you can buy a breakpoint if you've got enough money (i.e. a bonus = negative penalty) to pay the price (i.e. the badness). The third condition just forces the rightmost delta node to be considered feasible anyway.\note{This is necessary since the end of the expression is naturally a breakpoint even if it is a bad one, and the last delta node is needed for accounting purposes as well as for storing the pointer to the preceding breakpoints.} At this point we introduce a second measure called ``demerits'' which is defined as the sum of the demerits so far (i.e. up to the beginning of the line currently under consideration), the squared badness and the sign-propagated square of the penalty.\note{The latter is evaluated as the product of the value (which can be positive or negative) and the absolute value (which can be positive only).} Now we have a measure which not only refers to the current line but to the previous lines, too. Therefore, our modified {\caps Knuth}-algorithm ``optimizes'' not only over \i{one} line but over \i{all} lines.\par Figure 11 should make clear what is happening to the breaklist and the \TeX-item list. For readability purposes we display the latter, but really it is the breaklist under consideration within \t{trybreak}. As in the previous display of our example, you can identify the active-nodes. These are the three element number lists. The third element which is zero here is used as an offset width to the last opening bracket. This information is used for indentation. The delta-nodes are remarkable. These are the number lists with seven elements. Count them by their fourth element. They run 0, 1, 2 through 8, 9, -1. The fifth element gives you the way back through the list. Start at the last delta-node. There the best way to come from is 1. So go to delta-node 1 where you find 0 as the best way to come from. Delta-node 0 is the beginning, so you're finished. The sixth element stands for the total demerits so far. The seventh element stands for the amount of indentation. Here it is a zero because the term isn't nested in our example. % ---------------------------------------------------------------------- \VFig ( ( 0 0 0 0 0 0 0) x ^{ 1 2 } (163840 0 0) - 1 2 \cdot (163840 50 0) x ^{ 1 1 } \cdot (163840 50 0) y (163840 -390 0) + 6 6 \cdot (163840 50 0) x ^{ 1 0 } \cdot (163840 50 0) y ^{ 2 } (163840 0 0) - 2 2 0 \cdot (163840 50 0) x ^{ 9 } \cdot (163840 50 0) y ^{ 3 } (163840 -390 0) + 4 9 5 \cdot (163840 50 0) x ^{ 8 } \cdot (163840 50 0) y ^{ 4 } (163840 0 0) - 7 9 2 \cdot (163840 50 0) x ^{ 7 } \cdot (163840 50 0) y ^{ 5 } (163840 18624949 0 1 0 -151875 0) + 9 2 4 \cdot (163840 20463597 0 2 0 2500 0) x ^{ 6 } \cdot (163840 21448001 0 3 0 2500 0) y ^{ 6 } (163840 22209856 0 4 0 1 0) - 7 9 2 \cdot (163840 50 0) x ^{ 5 } \cdot (163840 50 0) y ^{ 7 } (163840 25794763 0 5 0 -142299 0) + 4 9 5 \cdot (163840 50 0) x ^{ 4 } \cdot (163840 50 0) y ^{ 8 } (163840 0 0) - 2 2 0 \cdot (163840 50 0) x ^{ 3 } \cdot (163840 50 0) y ^{ 9 } (163840 32964577 0 6 1 -207875 0) + 6 6 \cdot (163840 50 0) x ^{ 2 } \cdot (163840 50 0) y ^{ 1 0 } (163840 0 0) - 1 2 \cdot (163840 38009479 0 7 1 -149350 0) x \cdot (163840 38717176 0 8 1 -149374 0) y ^{ 1 1 } (163840 39755738 0 9 1 -303975 0) + y ^{ 1 2 } ( 0 41140184 ?-1 1 -151866 ?) \endverbatim \endVFig A \TeX-item list extended with delta-nodes: From this list the line-breaking way can be derived. Start with node --1, go to node 1 and from there to node 0. That makes one break point at node 1.\par We haven't mentioned how we generate indentation yet. Generally speaking, indentation is entirely directed by brackets, either round, curly, or dummy brackets. But how do we compute the amount of indentation? First let's turn to the code segment which deals with this problem within the big line-braking algorithm shown before. The contents of figure 12 explains what happens to the amount of indentation. % ---------------------------------------------------------------------- \DOC \!compute amount of indentation! ::= \&begin& @ \&if& \\offset/$>$\\total/ @ \&then& \\indent/\gets\\offset$-$total$+$baseindent/ \ \ % \[opening bracket case] @ \&else if& \\offset$<$baseoffset/ @ @ \&then& \\indent/\gets\\findindent/() \ \ \ \ \ \ \ \ % \ \ \ \[closing bracket case] @ @ \&else& \\indent/\gets\\baseindent/; \ \ \ \ \ \ \ \ \ % \ \ \ \ \[no change case] @ \!save \\indent/ to delta-node! \&end&; \endDOC The code segment from {\smalltt trybreak} dealing with indentation: \par % ---------------------------------------------------------------------- The logic of this code segment is easily summarized. The \i{offset} is a measure of how distant the last opening bracket is from the beginning of the whole expression. So in the case where \i{offset} is greater than the total width accumulated until the very beginning of the line, the indentation is just the difference between \i{total} and the sum of \i{offset} and the amount of indentation \i{baseindent} for the currently line. That'll work if the line currently under consideration contains at least one opening bracket which hasn't become closed in the same line. This case may be labelled the ``opening bracket case''. But what shall we do in the other cases? We have to decide if we've got a ``closing bracket case'', i.e. if we have at least one more closing bracket than we have opening brackets, or if we've got a ``no change case'', i.e. the number of opening brackets in the current line matches the number of closing brackets in this line. This decision is made by comparing \i{offset}$<$\i{baseoffset}. If the \i{baseoffset}, i.e. the offset at the beginning of the line, is greater than \i{offset}, i.e. the offset at the current point, then we've got the ``closing bracket case'', otherwise we've got the ``no change case''. In the latter, the amount of indentation for the next line is just the amount of indentation for the current line. But the ``closing bracket case'' causes us much trouble. So we need an extra function dealing with this case, as displayed in figure 13. % ---------------------------------------------------------------------- \DOC \¯o function& \\findindent/; \[macro functions share all variables of outer code blocks] \&begin& \[first check if we can save search time for equal destination] @ \&if& \\offset/$=$\\lastoffset/ \&and& \\baseptr/$=$\\lastbaseptr/ @ \&then return& \\lastindent/ @ \&else begin& \[search the delta-node-stack for previous indentation] @ @ \\stack/\gets\\deltastack/; \\lastoffset/\gets\\offset/; @ @ \\p/\gets\\lastbaseptr/\gets\\baseptr/; @ @ \&while& \\stack/ \&do& \[as long as we have a delta-node ahead] @ @ \&begin& @ @ @ \\node/\gets\&car& \\stack/; \[current delta-node] @ @ @ \&if& \\p$=$idof node/ \&then begin& @ @ @ @ \\p/\gets\\ptrof node/; \\local/\gets\\totalof node/; @ @ @ @ \&if& \\local$<$offset/ \&then& \\stack/\gets\&nil& @ @ @ \&end&; @ @ @ \&if& \\stack/ \&then& \\stack/\gets\&cdr& \\stack/ @ @ \&end&; @ @ \\lastindent/\gets\\offset$-$local$+$indentof node/; @ @ \&return& \\lastindent/ @ \&end& \&end&; \endDOC The macro function findindent: This macro is used to compute the amount of indentation in the ``closing bracket case''. It causes some trouble since we have to travel back to previous delta nodes.\par % ---------------------------------------------------------------------- This macro\note{Macros become expanded where they are called and thus share all variable names defined in the code block where they are called. So, there is no need for argument passing if certain variable names in the code block don't differ from call to call.} searches the list of delta-nodes previously created until it reaches a delta-node (at least the very first delta-node in the breaklist) where the total width accumulated so far, i.e. the variable \i{local}, is less than \i{offset}, i.e. the offset at the end of the line under consideration, and computes the amount of indentation from the difference of \i{offset} and \i{local} plus the amount of indentation so far. Plainly speaking, we go back the lines until we find a line where we find the opening parenthesis matching the closing parenthesis in the current line. When we've found it, we compute the amount of indentation as described in the ``opening bracket case'', but with \i{local} instead of \i{total}. % ---------------------------------------------------------------------- \sec Postprocessing with the \TeX\ module ``tridefs.tex''\par % ---------------------------------------------------------------------- When a \TeX-output-file has been created with the TRI it has to be processed by \TeX\ itself. But before you run \TeX\ you should make sure the file looks the way you want it. Sometimes you will find it necessary to add some \TeX-code of your own or delete some other \TeX-code. This job is up to you before you finally run \TeX.\par During the \TeX-run the sizes of brackets are determined. This task is not done by the TRI. In order to produce proper sized brackets we put some \verb|\left(| and \verb|\right)| \TeX-commands where brackets are opened or closed. A new problem arises when an expression has been broken up into several lines. Since, for every line, the number of \verb|\left(| and \verb|\right)| \TeX-commands must match but bracketed expressions may start in one line and end in another, we have to insert the required number of ``dummy'' parentheses (i.e. \verb|\right.| and \verb|\left.| \TeX-commands) at the end of the current line and the beginning of the following line. Therefore, we have to keep track of the depth of bracketing. See the following figure 14 for the \TeX-code actually applied.\par There is a caveat against this method. Since opening and closing brackets needn't lie in the same line, it is possible that the height of the brackets can differ although they should correspond in height. That will happen if the height of the text in the opening line has a height different from the text in the closing line. We haven't found a way of tackling this problem yet, but we think it is possible to program a little \TeX-macro for this task. Furthermore, some macros deal with tricks we had to use in order to provide for indentation, fraction handling and the like. \VVFig \def\qdd{\quad\quad} % simply a double quad \def\frac#1#2{{#1\over#2}} % fractions from prefix notation \newcount\parenthesis % nesting of brackets \parenthesis=0 % intialize \newcount\n % a temporary variable % ---- round and curly brackets ---- \def\({\global\advance\parenthesis by1\left(} \def\){\global\advance\parenthesis by-1\right)} \def\{{\global\advance\parenthesis by1\left\lbrace} \def\}{\global\advance\parenthesis by-1\right\rbrace} \def\[{\relax} % dummy parenthesis \def\]{\relax} % dummy parenthesis % ---- provide for looping using tail recursion ---- % \loop ...what... \repeat \def\loop#1\repeat{\global\n=0\global\let\body=#1\iterate} \def\iterate{\body\let\next=\iterate\else\let\next=\relax\fi\next} % ---- conditions and statements for loop interior \def\ldd{\ifnum\n<\parenthesis\global\advance\n by1 \left.\nulldelimiterspace=0pt\mathsurround=0pt} \def\rdd{\ifnum\n<\parenthesis\global\advance\n by1 \right.\nulldelimiterspace=0pt\mathsurround=0pt} % ---- newline statement as issued by TRI ---- \def\nl{\loop\rdd\repeat\hfill\cr\quad\quad\loop\ldd\repeat{}} % ---- indentation statement as issued by TRI ---- \def\OFF#1{\hskip#1sp\relax} % ---- last newline statement before end of math group ---- \def\Nl{\hfill\cr} \endverbatim \endVFig The file ``tridefs.tex'': This is the code you have to use on the \TeX\ side in order to typeset output produced by our TRI.\par \noindent There is at least one more line of \TeX-code you have to insert by hand into the \TeX-input-file produced by TRI. This line runs \verbatim \input tridefs \endverbatim\noindent and inputs the module \t{tridefs.tex} into the file. This is necessary because otherwise \TeX\ won't know how to deal with our macro calls. If you use the \TeX-input-file as a ``stand-alone'' file, don't forget a final \verb|\bye| at the end of the text. If you use code produced by TRI as part of a larger text then simply put the input-line just once at the beginning of your text. % ---------------------------------------------------------------------- \sec Experiments\par % ---------------------------------------------------------------------- We measured performance using the TIME-facility of REDUCE, which can be switched on and off with the two commands \example ON TIME; OFF TIME; \endexample We have tested our TRI on a \VAX\ operating under VAX/VMS, with no other users operating during this phase in order to minimize interference with other processes, e.g. caused by paging. The TRI code has been compiled with the PSL~3.2a-Compiler. The following table presents results obtained with a small number of different terms. All data were measured in CPU-seconds as displayed by LISP's TIME-facility. For expressions where special packages such as \t{solve} and \t{int} were involved we have taken only effective output-time, i.e. the time consumption caused by producing the output and not by evaluating the algebraic result.\note{That means we assigned the result of an evaluation to an itermediate variable, and then we printed this intermediate variable. Thus we could eliminate the time overhead produced by ``pure'' evaluation. Nevertheless, in terms of effective interactive answering time, the sum of evaluation and printing time might be much more interesting than the ``pure'' printing time. In such a context the percentage overhead caused by printing is the critical point. But since we talk about printing we decided to document the ``pure'' printing time.}\par \def\strut{\vrule height8pt depth4pt width0pt} \def\tablerule{\noalign{\hrule}} \def\hdbox#1{\hbox to 12truemm{\small\hfil#1\hfil}} \def\[#1]{$\scriptstyle#1$\hfil} $$\vbox{ \offinterlineskip \halign{&\strut\vrule#&\quad\hfil\smalltt#\quad\cr \tablerule &{\smallbf REDUCE-}\hfil&&\hdbox{\small nor-}&& \hdbox{TeX}&&\hdbox{\small TeX-}&&\hdbox{\small TeX-}&\cr &{\smallbf Expression}\hfil&&\hdbox{\small mal}&& &&\hdbox{\small Break}&&\hdbox{\small Indent}&\cr \tablerule &\[(x+y)^{12}]&& 0.82&& 0.75&& 3.42&& 3.47&\cr &\[(x+y)^{24}]&& 2.00&& 2.22&&12.52&&12.41&\cr &\[(x+y)^{36}]&& 4.40&& 4.83&&21.48&&21.44&\cr &\[(x+y)^{16}/(v-w)^{16}]&& 2.27&& 2.38&&12.18&&12.19&\cr &\[solve((1+\xi)x^2-2\xi x+\xi,x)]&& 0.41&& 0.62&& 0.89&& 0.87&\cr &\[solve(x^3+x^2\mu+\nu,x)]&& 4.21&&20.84&&31.82&&40.43&\cr \tablerule }}$$\vskip5pt \noindent This short table should give you an impression of the performance of TRI. It goes without saying that on other machines results may turn out which are quite different from our results. But our intention is to show the relative and not the absolute performance. Note that printing times are a function of expression complexity, as shown by rows three and six. % ---------------------------------------------------------------------- \sec User's Guide to the REDUCE-\TeX-Interface\par % ---------------------------------------------------------------------- If you intend to use the TRI you are required to load the compiled code. This can be performed with the command \example load!-package 'tri; \endexample During the load, some default initializations are performed. The default page width is set to 15 centimeters, the tolerance for page breaking is set to 20 by default. Moreover, TRI is enabled to translate greek names, e.g. TAU or PSI, into equivalent \TeX\ symbols, e.g. $\tau$ or $\psi$, respectively. Letters are printed lowercase as defined through assertion of the set LOWERCASE. The whole operation produces the following lines of output \example *** Function TEXVARPRI redefined \% set GREEK asserted \% set LOWERCASE asserted \% \B hsize=150mm \% \B tolerance 20 \endexample Now you can switch on and off the three TRI modes as you like. You can use the switches alternatively and incrementally. That means you have to switch on TeX for receiving standard \TeX-output, or TeXBreak to receive broken \TeX-output, or TeXIndent to receive broken \TeX-output plus indentation. Thus, the three levels of TRI are enabled or disabled according to: \example On TeX; \% switch TeX is on On TeXBreak; \% switches TeX and TeXBreak are on On TeXIndent; \% switches TeX, TeXBreak and TeXIndent are on Off TeXIndent; \% switch TeXIndent is off Off TeXBreak; \% switches TeXBreak and TeXIndent are off Off TeX; \% all three switches are off \endexample More specifically, if you switch off {\tt TeXBreak} you implicitly quit {\tt TeXIndent}, too, or, if you switch off {\tt TeX} you implicitly quit {\tt TeXBreak} and, consequently, {\tt TeXIndent}.\par The most crucial point in defining how TRI breaks multiple lines of \TeX-code is your choice of the page width and the tolerance. As mentioned earlier, ``tolerance'' is related to \TeX's famous line-breaking algorithm. The value of ``tolerance'' determines which potential breakpoints are considered feasible and which not. The higher the tolerance, the more breakpoints become feasible as determined by the value of ``badness'' associated with each breakpoint. Breakpoints are considered feasible if the badness is less than the tolerance. You can easily set values for page width and tolerance using \example TeXsetbreak(\i{page-width},\i{tolerance}); \endexample where \i{page-width} is measured in millimeters\note{You can also specify page width in scaled points (sp). Note: 1~pt = 65536~sp = 1/72.27~inch. The function automatically chooses the appropiate dimension according to the size: all values greater than 400 are considered to be scaled points.} and the \i{tolerance} is a positive integer in the closed interval $[0\ldots10000]$. You should choose a page width according to your purposes, but allow a few centimeters for errors in TRI's metric. For example, specify 140 millimeters for an effective 150 or 160 millimeter wide page. That way you have a certain safety-margin to the borders of the page. Now let's turn to the tolerance. A tolerance of 0 means that actually no breakpoint will be considered feasible (except those carrying a negative penalty), while a value of 10000 allows any breakpoint to be considered feasible. Obviously, the choice of a tolerance has a great impact on the time consumption of our line-breaking algorithm since time consumption increases in proportion to the number of feasible breakpoints. So, the question is what values to choose. For line-breaking without indentation, suitable values for the tolerance lie between 10 and 100. As a rule of thumb, you should use higher values the deeper the term is nested --- if you can estimate. If you use indentation, you have to use much higher tolerance values. This is necessary because badness is worsened by indentation. So, TRI has to try harder to find suitable places where to break. Reasonable values for tolerance here lie between 700 and 1500. A value of 1000 should be your first guess. That'll work for most expressions in a reasonable amount of time.\par Sometimes you want to add your own REDUCE-symbol-to-\TeX-item translations. For such a task, TRI provides a function named \t{TeXlet} which binds any REDUCE-symbol to one of the predefined \TeX-items. A call to this function has the following syntax: \example TeXlet(\i{REDUCE-symbol},\i{\TeX-item}) \endexample Three examples show how to do it right: \example TeXlet('velocity,'!v); TeXlet('gamma,\verb|'!\!G!a!m!m!a! |); TeXlet('acceleration,\verb|'!\!v!a!r!t!h!e!t!a! |); \endexample Besides this method of single assertions you can choose to assert one of (currently) two standard sets providing substitutions for lowercase and greek letters. These sets are loaded by default. You can switch these sets on or off using the functions \example TeXassertset \i{setname}; TeXretractset \i{setname}; \endexample where the setnames currently defined are \t{'GREEK} and \t{'LOWERCASE}. So far you have learned only how to connect REDUCE-atoms with predefined \TeX-items but not how to create new \TeX-items itself. We provide a way for adding standard \TeX-items of any class \t{'ORD, 'BIN, 'REL, 'OPN, 'CLO, 'PCT} and \t{LOP} except for class \t{'INN} which is reserved for internal use by TRI only. You can call the function \example TeXitem(\i{item},\i{class},\i{list-of-widths}) \endexample e.g. together with a binding \example TeXitem(\verb|'!\!n!a!b!l!a! |,'ORD,'(655360 327680 163840)) TeXlet('NABLA,\verb|'!\!n!a!b!l!a! |); \endexample where \i{item} is a legal \TeX-code name\note{Please note that any \TeX-name ending with a letter must be followed by a blank to prevent from interference with letters of following \TeX-items. Note also that you can legalize a name by defining it as a \TeX-macro.}, \i{class} is one of seven classes (see above) and \i{list-of-width} is a non-empty list of elements each one representing the width of the item in successive super-/subscript depth levels. That means that the first entry is the breadth in display mode, the second stands for scriptstyle and the third stands for scriptscriptstyle in \TeX-% terminology. But how can you retrieve the width information required? For this purpose we provide the following small interactive \TeX\ facility called \t{redwidth.tex} documented in figure 15. Simply call \example tex redwidth \endexample on your local machine. Then you are prompted for the \TeX-item you want the width information for. Type ``end'' when you want to finish the session. \VVFig \newbox\testbox\newcount\xxx\newif\ifOK\def\endloop{end } \def\widthof#1{\message{width is: }\wwidthof{$\displaystyle#1$} \wwidthof{$\scriptstyle#1$}\wwidthof{$\scriptscriptstyle#1$}} \def\wwidthof#1{\setbox\testbox=\hbox{#1}\xxx=\wd\testbox \message{[\the\wd\testbox=\the\xxx sp]}} \loop\message{Type in TeX item or say 'end': }\read-1 to\answer \ifx\answer\endloop\OKfalse\else\OKtrue\fi \ifOK\widthof{\answer} \repeat \end \endverbatim \endVFig The file ``redwidth.tex'': This \TeX\ code you can use to determine the width of specific \TeX-items.\par Finally let us discuss how you can compile the TRI into a binary. (We refer to PSL, but other LISP versions work quite similar.) First of all start REDUCE. Than type in\par \verbatim on comp; symbolic; faslout "tri"; in "tri.red"; faslend; bye; \endverbatim\noindent We stress the fact that this procedure is definitely LISP dependent. Ask your local REDUCE or LISP wizards how to adapt to it. % ---------------------------------------------------------------------- \sec Examples\par % ---------------------------------------------------------------------- Some examples --- which we think might be representative --- shall demonstrate the capabilities of our TRI. For each example we state (a) the REDUCE command (i.e. the input), (b) the tolerance if it differs from the default, and (c) the output as produced in a \TeX\ run.\par \newcount\exacount\exacount=0 \def\strut{\vrule height11pt depth4pt width0pt} \def\exa#1 \mod#2 \tol#3 \cod#4 \^^M{\global\advance\exacount by1\par {\offinterlineskip \vbox{ \hrule \line{\strut\vrule \hbox to 8mm{\hfil\caps\the\exacount\hfil}\vrule \quad\rm#1\hfill\vrule \hbox to 32mm{\hfill{\smallcaps Mode: }{\tt #2}\hfill}\vrule \hbox to 32mm{\hfill{\smallcaps Tolerance: }{\tt #3}\hfill}\vrule} \hrule \line{\strut\vrule\hfill\tt#4\hfill\vrule} \hrule} }\nobreak} \bigskip\input tridefs % ------------------------------ Examples ------------------------------ \exa Standard \mod TeXindent \tol 250 \cod (x+y){*}{*}16{/}(v-w){*}{*}16; \ $$\displaylines{\qdd \(x^{16} +16\cdot x^{15}\cdot y +120\cdot x^{14}\cdot y^{2} +560\cdot x^{13}\cdot y^{3}\nl \OFF{327680} +1820\cdot x^{12}\cdot y^{4} +4368\cdot x^{11}\cdot y^{5} +8008\cdot x^{10}\cdot y^{6}\nl \OFF{327680} +11440\cdot x^{9}\cdot y^{7} +12870\cdot x^{8}\cdot y^{8} +11440\cdot x^{7}\cdot y^{9}\nl \OFF{327680} +8008\cdot x^{6}\cdot y^{10} +4368\cdot x^{5}\cdot y^{11} +1820\cdot x^{4}\cdot y^{12}\nl \OFF{327680} +560\cdot x^{3}\cdot y^{13} +120\cdot x^{2}\cdot y^{14} +16\cdot x\cdot y^{15} +y^{16} \) /\nl \(v^{16} -16\cdot v^{15}\cdot w +120\cdot v^{14}\cdot w^{2} -560\cdot v^{13}\cdot w^{3}\nl \OFF{327680} +1820\cdot v^{12}\cdot w^{4} -4368\cdot v^{11}\cdot w^{5} +8008\cdot v^{10}\cdot w^{6} -11440\cdot v^{9}\cdot w^{7}\nl \OFF{327680} +12870\cdot v^{8}\cdot w^{8} -11440\cdot v^{7}\cdot w^{9} +8008\cdot v^{6}\cdot w^{10} -4368\cdot v^{5}\cdot w^{11}\nl \OFF{327680} +1820\cdot v^{4}\cdot w^{12} -560\cdot v^{3}\cdot w^{13} +120\cdot v^{2}\cdot w^{14} -16\cdot v\cdot w^{15} +w^{16} \) \Nl}$$ \exa Integration \mod TeX \tol -; \cod int(1/(x{*}{*}3+2),x) \ $$ - \(\frac{2^{\frac{1}{ 3}}\cdot \(2\cdot \sqrt{3}\cdot \arctan \(\frac{2^{\frac{1}{ 3}} -2\cdot x}{ 2^{\frac{1}{ 3}}\cdot \sqrt{3}} \) + \ln \(2^{\frac{2}{ 3}} -2^{\frac{1}{ 3}}\cdot x +x^{2} \) -2\cdot \ln \(2^{\frac{1}{ 3}} +x \) \) }{ 12} \) $$ \exa Integration \mod TeXindent \tol 1000 \cod int(1/(x{*}{*}4+3*x{*}{*}2-1,x); \ $$\displaylines{\qdd \(\sqrt{2}\cdot \(3\cdot \sqrt{ \sqrt{13} -3}\cdot \sqrt{13}\cdot \ln \(- \(\sqrt{ \sqrt{13} -3}\cdot \sqrt{2} \) +2\cdot x \) \nl \OFF{2260991} -3\cdot \sqrt{ \sqrt{13} -3}\cdot \sqrt{13}\cdot \ln \(\sqrt{ \sqrt{13} -3}\cdot \sqrt{2} +2\cdot x \) \nl \OFF{2260991} +13\cdot \sqrt{ \sqrt{13} -3}\cdot \ln \(- \(\sqrt{ \sqrt{13} -3}\cdot \sqrt{2} \) +2\cdot x \) \nl \OFF{2260991} -13\cdot \sqrt{ \sqrt{13} -3}\cdot \ln \(\sqrt{ \sqrt{13} -3}\cdot \sqrt{2} +2\cdot x \) \nl \OFF{2260991} +6\cdot \sqrt{ \sqrt{13} +3}\cdot \sqrt{13}\cdot \arctan \(\frac{2\cdot x}{ \sqrt{ \sqrt{13} +3}\cdot \sqrt{2}} \) \nl \OFF{2260991} -26\cdot \sqrt{ \sqrt{13} +3}\cdot \arctan \(\frac{2\cdot x}{ \sqrt{ \sqrt{13} +3}\cdot \sqrt{2}} \) \) \) /104 \Nl}$$ \exa Solving Equations \mod TeXindent \tol 1000 \cod solve(x{*}{*}3+x{*}{*}2*mu+nu=0,x); \ $$\displaylines{\qdd \{x= \[- \(\(\(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{2}{ 3}}\cdot \sqrt{3}\cdot i\nl \OFF{3675021} + \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{2}{ 3}}\nl \OFF{3675021} +2\cdot \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot \nl \OFF{3675021} 2^{\frac{1}{ 3}}\cdot 3^{\frac{1}{ 6}}\cdot \mu -2^{\frac{2}{ 3}}\cdot \sqrt{3}\cdot 3^{\frac{1}{ 3}}\cdot i\cdot \mu ^{2} +2^{\frac{2}{ 3}}\cdot 3^{\frac{1}{ 3}}\cdot \mu ^{2} \) /\nl \OFF{3347341} \(6\cdot \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot 2^{\frac{1}{ 3}}\cdot 3^{\frac{1}{ 6}} \) \) \] \,\nl \OFF{327680} x= \[\(\(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{2}{ 3}}\cdot \sqrt{3}\cdot i\nl \OFF{2837617} - \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{2}{ 3}}\nl \OFF{2837617} -2\cdot \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot \nl \OFF{2837617} 2^{\frac{1}{ 3}}\cdot 3^{\frac{1}{ 6}}\cdot \mu -2^{\frac{2}{ 3}}\cdot \sqrt{3}\cdot 3^{\frac{1}{ 3}}\cdot i\cdot \mu ^{2} -2^{\frac{2}{ 3}}\cdot 3^{\frac{1}{ 3}}\cdot \mu ^{2} \) /\nl \OFF{2509937} \(6\cdot \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot 2^{\frac{1}{ 3}}\cdot 3^{ \frac{1}{ 6}} \) \] \,\nl \OFF{327680} x= \[\(\(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{2}{ 3}}\nl \OFF{2837617} - \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \nl \OFF{3675021} \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot 2^{\frac{1}{ 3}}\cdot 3^{ \frac{1}{ 6}}\cdot \mu +2^{\frac{2}{ 3}}\cdot 3^{\frac{1}{ 3}}\cdot \mu ^{2} \) /\nl \OFF{2509937} \(3\cdot \(9\cdot \sqrt{4\cdot \mu ^{3}\cdot \nu +27\cdot \nu ^{2}} -2\cdot \sqrt{3}\cdot \mu ^{3} -27\cdot \sqrt{3}\cdot \nu \) ^{\frac{1}{ 3}}\cdot 2^{\frac{1}{ 3}}\cdot 3^{ \frac{1}{ 6}} \) \] \} \Nl}$$ \exa Matrix Printing \mod TeX \tol -- \cod mat((1,a-b,1/(c-d)),(a*{*}2-b*{*}2,1,sqrt(c)),((a+b)/(c-d),sqrt(d),1)); \ $$ \pmatrix{1&a -b& \frac{1}{ c -d}\cr a^{2} -b^{2}&1& \sqrt{c}\cr \frac{a +b}{ c -d}& \sqrt{d}&1\cr } $$ % ---------------------------------------------------------------------- \sec Caveats\par % ---------------------------------------------------------------------- Techniques for printing mathematical expressions are available everywhere. This TRI adds only a highly specialized version for most REDUCE output. The emphasis is on the word \i{most}. One major caveat is that we cannot print SYMBOLIC-mode output from REDUCE. This could be done best in a WEB-like programming-plus-% documentation style. Nevertheless, as Knuth's WEB is already available for PASCAL and C, hopefully someone will write a LISP-WEB or a REDUCE-WEB as well.\par Whenever you discover a bug in our program please let us know. Send us a short report accompanied by an output listing.\note{You can reach us with e-mail at the following addresses: Werner Antweiler: antweil\@epas.utoronto.ca, Andreas Strotmann: strotmann@rrz.uni-koeln.de and Volker Winkelmann: winkelmann@rrz.uni-koeln.de.} We'll try to fix the error. The whole TRI package consists of following files:\par \itemize{3cm} \litem{\tt tri.tex}This text as a \TeX-input file.\par \litem{\tt tri.red}The REDUCE-LISP source code for the TRI.\par \litem{\tt tridefs.tex}The \TeX-input file to be used together with output from the TRI.\par \litem{\tt redwidth.tex}The \TeX-input file for interactive determination of \TeX-item widths.\par \litem{\tt tritest.red}Run this REDUCE file to check if TRI works correctly.\par \litem{\tt tritest.tex}When you have run {\tt tritest.red} just make a \TeX\ run with this file to see all the nice things TRI is able to produce.\par \enditemize % ---------------------------------------------------------------------- \sec References\par % ---------------------------------------------------------------------- \aut Antweiler, W.; Strotmann, A.; Pfenning, Th.; Winkelmann, V. \ttl Zwischenbericht "uber den Status der Arbeiten am REDUCE-\TeX-Anschlu\3 \pub Internal Paper, Rechenzentrum der Universit"at zu K"oln \ref \\ \dat November 1986 \inx 1986 \ \aut Fateman, Richard J. \ttl \TeX\ Output from MACSYMA-like Systems \pub ACM SIGSAM Bulletin, Vol. 21, No. 4, Issue \#82 \ref pp. 1--5 \dat November 1987 \inx 1987 \ \aut Knuth, Donald E.; Plass, Michael F. \ttl Breaking Paragraphs into Lines \pub Software---Practice and Experience, Vol. 11 \ref pp. 1119--1184 \dat 1981 \inx 1981 \ \aut Knuth, Donald E. \ttl The \TeX book \pub Addison-Wesley, Readings/Ma. \ref \\ \dat sixth printing, 1986 \inx 1986 \ \aut Hearn, Anthony C. \ttl REDUCE User's Manual, Version 3.3 \pub The RAND Corporation, Santa Monica, Ca. \ref \\ \dat July 1987 \inx 1987 \ \bye