Plan 9 from Bell Labs’s /usr/web/sources/contrib/steve/root/sys/lib/texmf/source/latex/tools/calc.dtx

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


% \iffalse
%% File `calc.dtx'.
%% Copyright (C) 1992--1995
%%          Kresten Krab Thorup and Frank Jensen.
%% Copyright (C) 1997--1998
%%          Kresten Krab Thorup, Frank Jensen and the LaTeX3 Project.
%%
%% The original authors (fj@hugin.dk and  krab@daimi.aau.dk) have
%% contributed this package to the LaTeX distribution.
%% Problems with this package should now be sent using latexbug.tex to
%% the normal LaTeX bug report address.
%
%<*dtx>
          \ProvidesFile{calc.dtx}
%</dtx>
%<package>\NeedsTeXFormat{LaTeX2e}
%<package>\ProvidesPackage{calc}
%<driver> \ProvidesFile{calc.drv}
% \fi
%         \ProvidesFile{calc.dtx}
          [1998/06/07 v4.1a Infix arithmetic (KKT,FJ)]
%
% \iffalse
%<*driver>
\documentclass{ltxdoc}
\usepackage{calc}
\begin{document}
\DocInput{calc.dtx}
\end{document}
%</driver>
% \fi
%
% \GetFileInfo{calc.dtx}
% \CheckSum{427}
%
% \title{The \texttt{calc} package\\Infix notation
%        arithmetic in \LaTeX\thanks{We thank Frank Mittelbach for his
%        valuable comments and suggestions which have greatly improved
%        this package.}}
% \author{Kresten Krab Thorup, Frank Jensen (and Chris Rowley)}
% \date{\filedate}
%
% \maketitle
%
% \changes{v4.0d}{1997/11/08}
%    {Contributed to tools distribution}
% \changes{v4.1a}{1998/06/07}
%    {Added text sizes: CAR}
% \changes{v4.1a}{1998/06/07}
%    {Attempt to make user-syntax robust: CAR}
%
% \newenvironment{calc-syntax}
%    {\par
%     \parskip\medskipamount
%     \def\is{\ \hangindent3\parindent$\longrightarrow$~}%
%     \def\alt{\ $\vert$~}%
%     \rightskip 0pt plus 1fil
%     \def\<##1>{\mbox{\NormalSpaces$\langle$##1\/$\rangle$}}%
%     \IgnoreSpaces\obeyspaces%
% }{\par\vskip\parskip}
% {\obeyspaces\gdef\NormalSpaces{\let =\space}\gdef\IgnoreSpaces{\def {}}}
%
% \def\<#1>{$\langle$#1\/$\rangle$}%
% \def\s#1{\ensuremath{[\![#1]\!]}}
% \def\savecode#1{\hbox{${}_{\hookrightarrow[#1]}$}}
% \def\gassign{\Leftarrow}
% \def\lassign{\leftarrow}
%
% \begin{abstract}
% The \texttt{calc} package reimplements the \LaTeX\ commands
% |\setcounter|, |\addtocounter|, |\setlength|, and |\addtolength|.
% Instead of a simple value, these commands now accept an infix
% notation expression.
% \end{abstract}
% 
% \section{Introduction}
%
% Arithmetic in \TeX\ is done using low-level operations such as
% |\advance| and |\multiply|.  This may be acceptable when developing
% a macro package, but it is not an acceptable interface for the
% end-user.
%
% This package introduces proper infix notation arithmetic which is
% much more familiar to most people.  The infix notation is more
% readable and easier to modify than the alternative: a sequence of
% assignment and arithmetic instructions.  One of the arithmetic
% instructions (|\divide|) does not even have an equivalent in
% standard \LaTeX.
%
% The infix expressions can be used in arguments to macros (the
% \texttt{calc} package doesn't employ category code changes to
% achieve its goals)\footnote{However, it therefore assumes that the
%    category codes of the special characters, such as \texttt{(*/)}
%    in its syntax do not change.}.
%
% \section{Informal description}
%
% Standard \LaTeX\ provides the following set of commands to
% manipulate counters and lengths \cite[pages 194 and~216]{latexman}.
% \begin{itemize}
% \item[]\hskip-\leftmargin
%    |\setcounter{|\textit{ctr}|}{|\textit{num}|}| sets the
%    value of the counter \textit{ctr} equal to (the value of)
%    \textit{num}.  (Fragile)
% \item[]\hskip-\leftmargin
%    |\addtocounter{|\textit{ctr}|}{|\textit{num}|}|
%    increments the value of the counter \textit{ctr} by (the
%    value of) \textit{num}.  (Fragile)
%
% \item[]\hskip-\leftmargin
%    |\setlength{|\textit{cmd}|}{|\textit{len}|}| sets the value of
%    the length command \textit{cmd} equal to (the value of) \textit{len}.
%    (Robust)
% \item[]\hskip-\leftmargin
%    |\addtolength{|\textit{cmd}|}{|\textit{len}|}| sets the value of
%    the length command \textit{cmd} equal to its current value plus
%    (the value of) \textit{len}.  (Robust)
% \end{itemize}
% (The |\setcounter| and |\addtocounter| commands have global effect,
% while the |\setlength| and |\addtolength| commands obey the normal
% scoping rules.)  In standard \LaTeX, the arguments to these commands
% must be simple values.  The \texttt{calc} package extends these
% commands to accept infix notation expressions, denoting values of
% appropriate types.  Using the \texttt{calc} package, \textit{num} is
% replaced by \<integer expression>, and \textit{len} is replaced by
% \<glue expression>.  The formal syntax of \<integer expression> and
% \<glue expression> is given below.
%
% In addition to these commands to explicitly set a length, many \LaTeX\
% commands take a length argument. After loading this package, most of
% these commands will accept a  \<glue expression>. This includes
% the optional width argument of |\makebox|, the width argument of
% |\parbox|, |minipage|, and a |tabluar| |p|-column, and many similar
% constructions. (This package does not redefine any of these commands,
% but they are defined by default to read their arguments by |\setlength|
% and so automatically benefit from the enhanced |\setlength| command
% provided by this package.)
%
% In the following, we shall use standard \TeX\ terminology.  The
% correspondence between \TeX\ and \LaTeX\ terminology is as follows:
% \LaTeX\ counters correspond to \TeX's count registers; they hold
% quantities of type \<number>.  \LaTeX\ length commands correspond to
% \TeX's dimen (for rigid lengths) and skip (for rubber lengths)
% registers; they hold quantities of types \<dimen> and \<glue>,
% respectively.
%
% \TeX\ gives us primitive operations to perform arithmetic on registers as
% follows:
% \begin{itemize}
%   \item addition and subtraction on all types of quantities without
%       restrictions;
%   \item multiplication and division by an \emph{integer} can be
%       performed on a register of any type;
%   \item multiplication by a \emph{real} number (i.e., a number with a
%       fractional part) can be performed on a register of any type,
%       but the stretch and shrink components of a glue quantity are
%       discarded.
% \end{itemize}
% The \texttt{calc} package uses these \TeX\ primitives but provides a
% more user-friendly notation for expressing the arithmetic.
%
% An expression is formed of numerical quantities (such as explicit
% constants and \LaTeX\ counters and length commands) and binary
% operators (the tokens `\texttt{+}', `\texttt{-}', `\texttt{*}', and
% `\texttt{/}' with their usual meaning) using the familiar infix
% notation; parentheses may be used to override the usual precedences
% (that multiplication/division have higher precedence than
% addition/subtraction). 
%
% Expressions must be properly typed.  This means, e.g., that a dimen 
% expression must be a sum of dimen terms: i.e., you cannot say
% `\texttt{2cm+4}' but `\texttt{2cm+4pt}' is valid.
%
% In a dimen term, the dimension part must come first; the same holds
% for glue terms.  Also, multiplication and division by non-integer
% quantities require a special syntax; see below.
%
% Evaluation of subexpressions at the same level of precedence
% proceeds from left to right.  Consider a dimen term such as
% ``\texttt{4cm*3*4}''.  First, the value of the factor \texttt{4cm} is
% assigned to a dimen register, then this register is multiplied
% by~$3$ (using |\multiply|), and, finally, the register is multiplied
% by~$4$ (again using |\multiply|).  This also explains why the
% dimension part (i.e., the part with the unit designation) must come
% first; \TeX\ simply doesn't allow untyped constants to be assigned
% to a dimen register.
%
% The \texttt{calc} package also allows multiplication and division by
% real numbers.  However, a special syntax is required: you must use
% |\real{|\<decimal constant>|}|\footnote{Actually, instead of
% \<decimal constant>, the more general \<optional signs>\<factor> can
% be used.  However, that doesn't add any extra expressive power to
% the language of infix expressions.} or
% |\ratio{|\<dimen expression>|}{|\<dimen expression>|}| to denote a
% real value to be used for multiplication/division.  The first form has
% the obvious meaning, and the second form denotes the number obtained
% by dividing the value of the first expression by the value of the
% second expression. 
%
%    A later addition to the package (in June 1998) allows an additional
%    method of specifying a factor of type dimen by setting some text
%    (in LR-mode) and measuring its dimensions: these are denoted as
%    follows.
%\begin{quote}
%    |\widthof{|\<text>|}|\quad
%    |\heightof{|\<text>|}|\quad
%    |\depthof{|\<text>|}|
%\end{quote}
%    These calculate the natural sizes of the \<text> in exactly the
%    same way as is done for the commands |\settowidth| etc.~on
%    Page~216 of the manual~\cite{latexman}.
%
%    Note that there is a small difference in the usage of these two
%    methods of accessing text dimensions.  After
%    |\settowidth{\txtwd}{Some text}| you can use:
%\begin{verbatim}
%    \setlength{\parskip}{0.68\textwd}
%\end{verbatim}
%    whereas using the more direct access to the width of the text
%    requires the longer form for multiplication, thus:
%\begin{verbatim}
%    \setlength{\parskip}{\widthof{Some text} * \real{0.68}}
%\end{verbatim}
%    
% \TeX\ discards the stretch and shrink components of glue when glue
% is multiplied by a real number.  So, for example,
%\begin{verbatim}
%    \setlength{\parskip}{3pt plus 3pt * \real{1.5}}
%\end{verbatim}
% will set the paragraph separation to 4.5pt with no stretch or
% shrink.  (Incidentally, note how spaces can be used to enhance
% readability.)
%
% When \TeX\ performs arithmetic on integers, any fractional part of
% the results are discarded.  For example,
%\begin{verbatim}
%    \setcounter{x}{7/2}
%    \setcounter{y}{3*\real{1.6}}
%    \setcounter{z}{3*\real{1.7}}
%\end{verbatim}
% will assign the value~$3$ to the counter~\texttt{x}, the value~$4$
% to~\texttt{y}, and the value~$5$ to~\texttt{z}.  This truncation
% also applies to \emph{intermediate} results in the sequential
% computation of a composite expression; thus, the following command
%\begin{verbatim}
%    \setcounter{x}{3 * \real{1.6} * \real{1.7}}
%\end{verbatim}
% will assign~$6$ to~\texttt{x}.
%
% As an example of the use of |\ratio|, consider the problem of
% scaling a figure to occupy the full width (i.e., |\textwidth|) of
% the body of a page.  Assume that the original dimensions of the
% figure are given by the dimen (length) variables, |\Xsize| and
% |\Ysize|.  The height of the scaled figure can then be expressed by
%\begin{verbatim}
%    \setlength{\newYsize}{\Ysize*\ratio{\textwidth}{\Xsize}}
%\end{verbatim}
%
% \section{Formal syntax}
%
% The syntax is described by the following set of rules.
% Note that the definitions of \<number>, \<dimen>, \<glue>,
% \<decimal constant>, and \<plus or minus> are
% as in Chapter~24 of The \TeX book~\cite{texbook}; and \<text>
% is LR-mode material, as in the manual~\cite{latexman}.
% We use \textit{type} as a meta-variable, standing for
% `integer', `dimen', and `glue'.\footnote{This version of the
% \texttt{calc} package doesn't support evaluation of muglue expressions.}
% \begin{calc-syntax}
%    \<\textit{type} expression>
%       \is  \<\textit{type} term>
%       \alt \<\textit{type} expression> \<plus or minus> \<\textit{type} term>
%
%    \<\textit{type} term>
%       \is  \<\textit{type} factor>
%       \alt \<\textit{type} term> \<multiply or divide> \<integer factor>
%       \alt \<\textit{type} term> \<multiply or divide> \<real number>
%
%    \<\textit{type} factor>
%       \is  \<\textit{type}>
%       \alt \<text dimen factor>
%       \alt |(|$_{12}$ \<\textit{type} expression> |)|$_{12}$
%
%    \<integer> \is \<number>
%
%    \<text dimen factor>
%       \is  \<text dimen command>|{| \<text> |}|
%
%    \<text dimen command>
%       \is   |\widthof|
%       \alt  |\heightof|
%       \alt  |\depthof|
%
%    \<multiply or divide>
%       \is  |*|$_{12}$
%       \alt |/|$_{12}$
%
%    \<real number>
%       \is  |\ratio{| \<dimen expression> |}{| \<dimen expression> |}|
%       \alt |\real{|  \<decimal constant> |}|
% \end{calc-syntax}
%
%    Note that during most of the parsing of calc expressions, no
%    expansion happens; thus the above syntax must be
%    explicit\footnote{Two exceptions to this are: the first token
%    is expanded one-level (thus the whole expression can be put into a
%    macro); wherever a \<decimal constant> or \<\texttt{type}> is
%    expected.}.
% \StopEventually{
% \begin{thebibliography}{1}
%    \bibitem{texbook}
%       \textsc{D. E. Knuth}.
%       \newblock \textit{The \TeX{}book} (Computers \& Typesetting Volume A).
%       \newblock Addison-Wesley, Reading, Massachusetts, 1986.
%    \bibitem{latexman}
%       \textsc{L. Lamport}.
%       \newblock \textit{\LaTeX, A Document Preparation System.}
%       \newblock Addison-Wesley, Reading, Massachusetts, Second
%       edition 1994/1985.
% \end{thebibliography}
% }
%
% \section{The evaluation scheme}
% \label{evaluation:scheme}
%
% In this section, we shall for simplicity consider only expressions
% containing `$+$' (addition) and `$*$' (multiplication) operators.
% It is trivial to add subtraction and division.
%
% An expression $E$ is a sum of terms: $T_1+\cdots+T_n$; a term is a
% product of factors: $F_1*\cdots*F_m$; a factor is either a simple
% numeric quantity~$f$ (like \<number> as described in the \TeX book),
% or a parenthesized expression~$(E')$. 
%
% Since the \TeX\ engine can only execute arithmetic operations in a
% machine-code like manner, we have to find a way to translate the
% infix notation into this `instruction set'.
%
% Our goal is to design a translation scheme that translates~$X$ (an
% expression, a term, or a factor) into a sequence of \TeX\ instructions
% that does the following [Invariance Property]: correctly
% evaluates~$X$, leaves the result in a global register~$A$ (using a
% global assignment), and does not perform global assignments to the
% scratch register~$B$; moreover, the code sequence must be balanced
% with respect to \TeX\ groups.  We shall denote the code sequence
% corresponding to~$X$ by \s{X}.
%
% In the replacement code specified below, we use the following
% conventions:
% \begin{itemize}
%    \item $A$ and $B$ denote registers; all assignments to~$A$ will
%       be global, and all assignments to~$B$ will be local.
%    \item ``$\gassign$'' means global assignment to the register on
%       the lhs.
%    \item ``$\lassign $'' means local assignment to the register on
%       the lhs.
%    \item ``\savecode C'' means ``save the code~$C$ until the current
%       group (scope) ends, then execute it.''  This corresponds to
%       the \TeX-primitive |\aftergroup|.
%    \item ``$\{$'' denotes the start of a new group, and ``$\}$''
%       denotes the end of a group.
% \end{itemize}
%
% Let us consider an expression $T_1+T_2+\cdots+T_n$.  Assuming that
% \s{T_k} ($1\le k\le n$) attains the stated goal, the following code
% clearly attains the stated goal for their sum:
% \begin{eqnarray*}
% \s{T_1+T_2+\cdots+T_n}&\Longrightarrow&
%       \{\,\s{T_1}\,\} \; B\lassign A \quad
%       \{\,\s{T_2}\,\} \; B\lassign B+A \\
%       &&\qquad \ldots \quad \{\,\s{T_n}\,\} \; B\lassign B+A
%                       \quad A\gassign B
% \end{eqnarray*}
% Note the extra level of grouping enclosing each of \s{T_1}, \s{T_2},
% \ldots,~\s{T_n}.  This will ensure that register~$B$, used to
% compute the sum of the terms, is not clobbered by the intermediate
% computations of the individual terms.  Actually, the group
% enclosing~\s{T_1} is unnecessary, but it turns out to be simpler if
% all terms are treated the same way.
%
% The code sequence ``$\{\,\s{T_2}\,\}\;B\lassign B+A$'' can be translated
% into the following equivalent code sequence:
% ``$\{\savecode{B\lassign B+A}\,\s{T_2}\,\}$''.  This observation turns
% out to be the key to the implementation: The ``$\savecode{B\lassign
% B+A}$'' is generated \emph{before} $T_2$ is translated, at the same
% time as the `$+$' operator between $T_1$ and~$T_2$ is seen.
%
% Now, the specification of the translation scheme is straightforward:
% \begin{eqnarray*}
%    \s{f}&\Longrightarrow&A\gassign f\\[\smallskipamount]
%    \s{(E')}&\Longrightarrow&\s{E'}\\[\smallskipamount]
%    \s{T_1+T_2+\cdots+T_n}&\Longrightarrow&
%       \{\savecode{B\lassign A}\,\s{T_1}\,\} \quad
%       \{\savecode{B\lassign B+A}\,\s{T_2}\,\} \\
%       &&\qquad \ldots \quad \{\savecode{B\lassign B+A}\,\s{T_n}\,\}
%                       \quad A\gassign B
%                       \\[\smallskipamount]
%    \s{F_1*F_2*\cdots*F_m}&\Longrightarrow&
%       \{\savecode{B\lassign A}\,\s{F_1}\,\} \quad
%       \{\savecode{B\lassign B*A}\,\s{F_2}\,\}\\
%       &&\qquad \ldots \quad \{\savecode{B\lassign B*A}\,\s{F_m}\,\}
%                       \quad A\gassign B 
% \end{eqnarray*}
% By structural induction, it is easily seen that the stated property
% is attained.
%
% By inspection of this translation scheme, we see that we have to
% generate the following code:
% \begin{itemize}
%    \item we must generate ``$\{\savecode{B\lassign
%       A}\{\savecode{B\lassign A}$'' at the left border of an
%       expression (i.e., for each left parenthesis and the implicit
%       left parenthesis at the beginning of the whole expression);
%    \item we must generate ``$\}A\gassign B\}A\gassign B$'' at the
%       right border of an expression (i.e., each right parenthesis
%       and the implicit right parenthesis at the end of the full
%       expression);
%    \item `\texttt{*}' is replaced by ``$\}\{\savecode{B\lassign
%       B*A}$'';
%    \item `\texttt{+}' is replaced by
%       ``$\}A\gassign B\}\{\savecode{B\lassign
%       B+A}\{\savecode{B\lassign A}$'';
%    \item when we see (expect) a numeric quantity, we insert the
%    assignment code ``$A\gassign$'' in front of the quantity and let
%    \TeX\ parse it.
% \end{itemize}
%
% \section{Implementation}
%
% For brevity define
% \begin{calc-syntax}
%    \<numeric> \is \<number> \alt \<dimen> \alt \<glue> \alt \<muglue>
% \end{calc-syntax}
% So far we have ignored the question of how to determine the type of
% register to be used in the code.  However, it is easy to see that
% (1)~`$*$' always initiates an \<integer factor>, (2)~all
% \<numeric>s in an expression, except those which are part of an
% \<integer factor>, are of the same type as the whole expression, and
% all \<numeric>s in an \<integer factor> are \<number>s. 
%
% We have to ensure that $A$ and~$B$ always have an appropriate type
% for the \<numeric>s they manipulate.  We can achieve this by having
% an instance of $A$ and~$B$ for each type.  Initially, $A$~and~$B$
% refer to registers of the proper type for the whole expression.
% When an \<integer factor> is expected, we must change $A$ and~$B$ to
% refer to integer type registers.  We can accomplish this by
% including instructions to change the type of $A$ and~$B$ to integer
% type as part of the replacement code for~`$*$; if we append such
% instructions to the replacement code described above, we also ensure
% that the type-change is local (provided that the type-changing
% instructions only have local effect).  However, note that the
% instance of~$A$ referred to in $\savecode{B\lassign B*A}$ is the
% integer instance of~$A$.
%
% We shall use |\begingroup| and |\endgroup| for the open-group and
% close-group characters.  This avoids problems with spacing in math
% (as pointed out to us by Frank Mittelbach).
%
% \subsection{Getting started}
%
% Now we have enough insight to do the actual implementation in \TeX.
% First, we announce the macro package\footnote{Code moved to top of file}.
%    \begin{macrocode} 
%<*package>
%\NeedsTeXFormat{LaTeX2e}
%\ProvidesPackage{calc}[\filedate\space\fileversion]
%    \end{macrocode}
%
% \subsection{Assignment macros}
%
% \begin{macro}{\calc@assign@generic}
% The |\calc@assign@generic| macro takes four arguments: (1~and~2) the
% registers to be used 
% for global and local manipulations, respectively; (3)~the lvalue
% part; (4)~the expression to be evaluated.
%
% The third argument (the lvalue) will be used as a prefix to a
% register that contains the value of the specified expression (the
% fourth argument).
%
% In general, an lvalue is anything that may be followed by a variable
% of the appropriate type.  As an example, |\linepenalty| and
% |\global\advance\linepenalty| may both be followed by an \<integer
% variable>.
%
% The macros described below refer to the registers by the names
% |\calc@A| and |\calc@B|; this is accomplished by
% |\let|-assignments.
%
% As discovered in Section~\ref{evaluation:scheme}, we have to
% generate code as 
% if the expression is parenthesized.  As described below,
% |\calc@open| is the macro that replaces a left parenthesis by its
% corresponding \TeX\ code sequence.  When the scanning process sees
% the exclamation point, it generates an |\endgroup| and stops.  As we
% recall from Section~\ref{evaluation:scheme}, the correct expansion
% of a right 
% parenthesis is ``$\}A\gassign B\}A\gassign B$''.  The remaining
% tokens of this expansion are inserted explicitly, except that the
% last assignment has been replaced by the lvalue part (i.e.,
% argument~|#3| of |\calc@assign@generic|) followed by |\calc@B|.
% \end{macro}
%    \begin{macrocode}
\def\calc@assign@generic#1#2#3#4{\let\calc@A#1\let\calc@B#2%
    \expandafter\calc@open\expandafter(#4!%
    \global\calc@A\calc@B\endgroup#3\calc@B}
%    \end{macrocode}
% (The |\expandafter| tokens allow the user to use expressions stored
% one-level deep in a macro as arguments in assignment commands.)
%
% \begin{macro}{\calc@assign@count}
% \begin{macro}{\calc@assign@dimen}
% \begin{macro}{\calc@assign@skip}
% We need three instances of the |\calc@assign@generic| macro,
% corresponding to the types \<integer>, \<dimen>, and \<glue>.
%    \begin{macrocode}
\def\calc@assign@count{\calc@assign@generic\calc@Acount\calc@Bcount}
\def\calc@assign@dimen{\calc@assign@generic\calc@Adimen\calc@Bdimen}
\def\calc@assign@skip{\calc@assign@generic\calc@Askip\calc@Bskip}
%    \end{macrocode}
% \end{macro}\end{macro}\end{macro}
% These macros each refer to two registers, one
% to be used globally and one to be used locally.
% We must allocate these registers.
%    \begin{macrocode}
\newcount\calc@Acount   \newcount\calc@Bcount
\newdimen\calc@Adimen   \newdimen\calc@Bdimen
\newskip\calc@Askip     \newskip\calc@Bskip
%    \end{macrocode}
%
% \subsection{The \LaTeX\ interface}
%
% As promised, we redefine the following standard \LaTeX\ commands:
% |\setcounter|, 
% |\addtocounter|, |\setlength|, and |\addtolength|.
%    \begin{macrocode}
\def\setcounter#1#2{\@ifundefined{c@#1}{\@nocounterr{#1}}%
   {\calc@assign@count{\global\csname c@#1\endcsname}{#2}}}
\def\addtocounter#1#2{\@ifundefined{c@#1}{\@nocounterr{#1}}%
   {\calc@assign@count{\global\advance\csname c@#1\endcsname}{#2}}}
%    \end{macrocode}
%    \begin{macrocode}
\DeclareRobustCommand\setlength{\calc@assign@skip}
\DeclareRobustCommand\addtolength[1]{\calc@assign@skip{\advance#1}}
%    \end{macrocode}
% (|\setlength| and |\addtolength| are robust according to
% \cite{latexman}.)
%
% \subsection{The scanner}
%
% We evaluate expressions by explicit scanning of characters.  We do
% not rely on active characters for this.
%
% The scanner consists of two parts, |\calc@pre@scan| and
% |\calc@post@scan|; |\calc@pre@scan| consumes left parentheses, and
% |\calc@post@scan| consumes binary operator, |\real|, |\ratio|, and
% right parenthesis tokens.
% \begin{macro}{\calc@pre@scan}
%
%    Note that this is called at least once on every use of calc
%    processing, even when none of the extended syntax is present; it
%    therefore needs to be made very efficient.
%
%    It reads the initial part of expressions, until some \<text dimen
%    factor> or \<numeric> is seen; in fact, anything not explicitly
%    recognized here is taken to be a \<numeric> of some sort as this
%    allows unary
%   `\texttt{+}' and unary `\texttt{-}' to be treated easily and
%    correctly\footnote{In the few contexts where signs are allowed:
%    this could, I think, be extended (CAR).} but means that anything
%    illegal will simply generate a \TeX-level error, often a
%    reasonably comprehensible one!
%
%    The many |\expandafter|s are needed to efficiently end the nested
%    conditionals so that |\calc@textsize| can process its argument.
% \changes{v4.1a}{1998/06/07}
%    {Added code for text sizes: CAR}
%    \begin{macrocode}
\def\calc@pre@scan#1{%
   \ifx(#1%
       \let\calc@next\calc@open
   \else
        \ifx\widthof#1%
            \expandafter\expandafter\expandafter\calc@textsize
        \else
            \calc@numeric% no \expandafter needed for this one.
        \fi
   \fi
   #1}
%    \end{macrocode}
% \end{macro}
% |\calc@open| is used when there is a left parenthesis right ahead.
% This parenthesis is replaced by \TeX\ code corresponding to the code
% sequence ``$\{\savecode{B\lassign A}\{\savecode{B\lassign A}$''
% derived in Section~\ref{evaluation:scheme}.  Finally,
% |\calc@pre@scan| is 
% called again.
%    \begin{macrocode}
\def\calc@open({\begingroup\aftergroup\calc@initB
   \begingroup\aftergroup\calc@initB
   \calc@pre@scan}
\def\calc@initB{\calc@B\calc@A}
%    \end{macrocode}
% |\calc@numeric| assigns the following value to |\calc@A| and then
% transfers control to |\calc@post@scan|.
%    \begin{macrocode}
\def\calc@numeric{\afterassignment\calc@post@scan \global\calc@A}
%    \end{macrocode}
%
% \begin{macro}{\widthof}
% \begin{macro}{\heightof}
% \begin{macro}{\depthof}
% \changes{v4.1a}{1998/06/07}
%    {Added macros: CAR}
%
%    These do not need any particular definition when they are scanned
%    so, for efficiency and robustness, we make them all equivalent to
%    the same harmless (I hope) unexpandable command\footnote{If this
%    level of safety is not needed then the code can be speeded up:
%    CAR.}.  Thus the test in |\calc@pre@scan| finds any of them.
%    They are first defined using |\newcommand| so that they appear to
%    be normal user commands to a \LaTeX{} user\footnote{Is this
%    necessary, CAR?}.
%    \begin{macrocode}
\newcommand\widthof{}
\let\widthof\ignorespaces
\newcommand\heightof{}
\let\heightof\ignorespaces
\newcommand\depthof{}
\let\depthof\ignorespaces
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\calc@textsize}
% \changes{v4.1a}{1998/06/07}
%    {Added macro: CAR}
%    The presence of the above three commands invokes this code, where
%    we must distinguish them from each other.
%    This implementation is somewhat optimized by using low-level
%    code from the commands |\settowidth|, etc\footnote{It is based on
%    suggestions by Donald Arsenau and David Carlisle.}.
%
%    Within the text argument we must restore the normal meanings of
%    the three user-level commands since arbitrary material can appear
%    in here, including further uses of calc.
%    \begin{macrocode}
\def\calc@textsize #1#2{%
  \begingroup
    \let\widthof\wd
    \let\heightof\ht
    \let\depthof\dp
    \@settodim #1%
      {\global\calc@A}%
      {%
       \let\widthof\ignorespaces
       \let\heightof\ignorespaces
       \let\depthof\ignorespaces
       #2}%
  \endgroup
  \calc@post@scan}
%    \end{macrocode}
% \end{macro}
%    
% \begin{macro}{\calc@post@scan}
% The macro |\calc@post@scan| is called right after a value has been
% read.  At this point, a binary operator, a sequence of right
% parentheses, and the end-of-expression mark (`|!|') is
%    allowed\footnote{Is \texttt{!} a good choice, CAR?}.
% Depending on our findings, we call a suitable macro to generate the
% corresponding \TeX\ code (except when we detect the
% end-of-expression marker: then scanning ends, and
% control is returned to |\calc@assign@generic|).
% 
% This macro may be optimized by selecting a different order of
% |\ifx|-tests.  The test for `\texttt{!}' (end-of-expression) is
% placed first as it will always be performed: this is the only test
% to be performed if the expression consists of a single \<numeric>.
% This ensures that documents that do not use the extra expressive
% power provided by the \texttt{calc} package only suffer a minimum
% slowdown in processing time.
% \end{macro}
%    \begin{macrocode}
\def\calc@post@scan#1{%
   \ifx#1!\let\calc@next\endgroup \else
    \ifx#1+\let\calc@next\calc@add \else
     \ifx#1-\let\calc@next\calc@subtract \else
      \ifx#1*\let\calc@next\calc@multiplyx \else
       \ifx#1/\let\calc@next\calc@dividex \else
        \ifx#1)\let\calc@next\calc@close \else \calc@error#1%
        \fi
       \fi
      \fi
     \fi
    \fi
   \fi
   \calc@next}
%    \end{macrocode}
%
% The replacement code for the binary operators `\texttt{+}' and
% `\texttt{-}' follow a common pattern; the only difference is the
% token that is stored away by |\aftergroup|.  After this replacement
% code, control is transferred to |\calc@pre@scan|.
%    \begin{macrocode}
\def\calc@add{\calc@generic@add\calc@addAtoB}
\def\calc@subtract{\calc@generic@add\calc@subtractAfromB}
\def\calc@generic@add#1{\endgroup\global\calc@A\calc@B\endgroup
   \begingroup\aftergroup#1\begingroup\aftergroup\calc@initB
   \calc@pre@scan}
\def\calc@addAtoB{\advance\calc@B\calc@A}
\def\calc@subtractAfromB{\advance\calc@B-\calc@A}
%    \end{macrocode}
%
%    \begin{macro}{\real}
%    \begin{macro}{\ratio}
%    The multiplicative operators, `\texttt{*}' and `\texttt{/}', may be
%    followed by a |\real| or a |\ratio| token.  Those control sequences
%    are not defined (at least not by the \texttt{calc} package); this,
%    unfortunately, leaves them highly non-robust.  We therefore
%    equate them to |\relax| but only if they have not already been
%    defined\footnote{Suggested code from David Carlisle.}
%    (by some other package: dangerous but possible!); this
%    will also make them appear to be undefined to a \LaTeX{} user
%    (also possibly dangerous).
% \changes{v4.1a}{1998/06/07}
%    {Added macro set-ups to make them robust but undefined: CAR}
%    \begin{macrocode}
\ifx\real\@undefined\let\real\relax\fi
\ifx\ratio\@undefined\let\ratio\relax\fi
%    \end{macrocode}
%    In order to test for them, we define these two\footnote{May not
%    need the extra names, CAR?}.
%    \begin{macrocode}
\def\calc@ratio@x{\ratio}
\def\calc@real@x{\real}
%    \end{macrocode}
%    \end{macro}
%    \end{macro}
%    
%    \begin{macrocode}
\def\calc@multiplyx#1{\def\calc@tmp{#1}%
   \ifx\calc@tmp\calc@ratio@x \let\calc@next\calc@ratio@multiply \else
      \ifx\calc@tmp\calc@real@x \let\calc@next\calc@real@multiply \else
         \let\calc@next\calc@multiply
      \fi
   \fi
   \calc@next#1}
\def\calc@dividex#1{\def\calc@tmp{#1}%
   \ifx\calc@tmp\calc@ratio@x \let\calc@next\calc@ratio@divide \else
      \ifx\calc@tmp\calc@real@x \let\calc@next\calc@real@divide \else
         \let\calc@next\calc@divide
      \fi
   \fi
   \calc@next#1}
%    \end{macrocode}
% The binary operators `\texttt{*}' and `\texttt{/}' also insert code
% as determined above.  Moreover, the meaning of |\calc@A| and
% |\calc@B| is changed as factors following a multiplication and
% division operator always have integer type; the original meaning of
% these macros will be restored when the factor has been read and
% evaluated.
%    \begin{macrocode}
\def\calc@multiply{\calc@generic@multiply\calc@multiplyBbyA}
\def\calc@divide{\calc@generic@multiply\calc@divideBbyA}
\def\calc@generic@multiply#1{\endgroup\begingroup
   \let\calc@A\calc@Acount \let\calc@B\calc@Bcount
   \aftergroup#1\calc@pre@scan}
\def\calc@multiplyBbyA{\multiply\calc@B\calc@Acount}
\def\calc@divideBbyA{\divide\calc@B\calc@Acount}
%    \end{macrocode}
% Since the value to use in the multiplication/division operation is
% stored in the |\calc@Acount| register, the |\calc@multiplyBbyA| and
% |\calc@divideBbyA| macros use this register.
%
% |\calc@close| generates code for a right parenthesis (which was
% derived to be ``$\}A\gassign B\}A\gassign B$'' in
% Section~\ref{evaluation:scheme}).  After this code, the control is
% returned to 
% |\calc@post@scan| in order to look for another right parenthesis or
% a binary operator.
%    \begin{macrocode}
\def\calc@close
   {\endgroup\global\calc@A\calc@B
    \endgroup\global\calc@A\calc@B
    \calc@post@scan}
%    \end{macrocode}
%
% \subsection{Calculating a ratio}
%
% When |\calc@post@scan| encounters a |\ratio| control sequence, it hands
% control to one of the macros |\calc@ratio@multiply| or |\calc@ratio@divide|,
% depending on the preceding character. Those macros both forward the
% control to the macro |\calc@ratio@evaluate|, which performs two steps: (1) it
% calculates the ratio, which is saved in the global macro token
% |\calc@the@ratio|; (2) it makes sure that the value of |\calc@B| will be
% multiplied by the ratio as soon as the current group ends.
%
% The following macros call |\calc@ratio@evaluate| which multiplies
% |\calc@B| by the ratio, but |\calc@ratio@divide| flips the arguments
% so that the `opposite' fraction is actually evaluated.
%    \begin{macrocode}
\def\calc@ratio@multiply\ratio{\calc@ratio@evaluate}
\def\calc@ratio@divide\ratio#1#2{\calc@ratio@evaluate{#2}{#1}}
%    \end{macrocode}
% We shall need two registers for temporary usage in the
% calculations.  We can save one register since we can reuse
% |\calc@Bcount|.
%    \begin{macrocode}
\let\calc@numerator=\calc@Bcount
\newcount\calc@denominator
%    \end{macrocode}
% Here is the macro that handles the actual evaluation of ratios.  The
% procedure is 
% this: First, the two expressions are evaluated and coerced to
% integers. The whole procedure is enclosed in a group to be able to
% use the registers |\calc@numerator| and |\calc@denominator| for temporary
% manipulations.
%    \begin{macrocode}
\def\calc@ratio@evaluate#1#2{%
   \endgroup\begingroup
      \calc@assign@dimen\calc@numerator{#1}%
      \calc@assign@dimen\calc@denominator{#2}%
%    \end{macrocode}
% Here we calculate the ratio.  First, we check for negative numerator
% and/or denominator; note that \TeX\ interprets two minus signs the
% same as a plus sign.  Then, we calculate the integer part.
% The minus sign(s), the integer part, and a decimal point, form the
% initial expansion of the |\calc@the@ratio| macro. 
%    \begin{macrocode}
      \gdef\calc@the@ratio{}%
      \ifnum\calc@numerator<0 \calc@numerator-\calc@numerator
         \gdef\calc@the@ratio{-}%
      \fi
      \ifnum\calc@denominator<0 \calc@denominator-\calc@denominator
         \xdef\calc@the@ratio{\calc@the@ratio-}%
      \fi
      \calc@Acount\calc@numerator
      \divide\calc@Acount\calc@denominator
      \xdef\calc@the@ratio{\calc@the@ratio\number\calc@Acount.}%
%    \end{macrocode}
% Now we generate the digits after the decimal point, one at a time.
% When \TeX\ scans these digits (in the actual multiplication
% operation), it forms a fixed-point number with 16~bits for
% the fractional part.  We hope that six digits is sufficient, even
% though the last digit may not be rounded correctly.
%    \begin{macrocode}
      \calc@next@digit \calc@next@digit \calc@next@digit
      \calc@next@digit \calc@next@digit \calc@next@digit
   \endgroup
%    \end{macrocode}
% Now we have the ratio represented (as the expansion of the global
% macro |\calc@the@ratio|) in the syntax \<decimal constant>
% \cite[page~270]{texbook}.  This is fed to |\calc@multiply@by@real|
% that will 
% perform the actual multiplication.  It is important that the
% multiplication takes place at the correct grouping level so that the
% correct instance of the $B$ register will be used.  Also note that
% we do not need the |\aftergroup| mechanism in this case.
%    \begin{macrocode}
   \calc@multiply@by@real\calc@the@ratio
   \begingroup
   \calc@post@scan}
%    \end{macrocode}
% The |\begingroup| inserted before the |\calc@post@scan| will be
% matched by the |\endgroup| generated as part of the replacement of a
% subsequent binary operator or right parenthesis.
%    \begin{macrocode}
\def\calc@next@digit{%
      \multiply\calc@Acount\calc@denominator
      \advance\calc@numerator -\calc@Acount
      \multiply\calc@numerator 10
      \calc@Acount\calc@numerator
      \divide\calc@Acount\calc@denominator
      \xdef\calc@the@ratio{\calc@the@ratio\number\calc@Acount}}
%    \end{macrocode}
% In the following code, it is important that we first assign the
% result to a dimen register.  Otherwise, \TeX\ won't allow us to
% multiply with a real number.
%    \begin{macrocode}
\def\calc@multiply@by@real#1{\calc@Bdimen #1\calc@B \calc@B\calc@Bdimen}
%    \end{macrocode}
% (Note that this code wouldn't work if |\calc@B| were a muglue
% register.  This is the real reason why the \texttt{calc} package
% doesn't support muglue expressions.  To support muglue expressions
% in full, the |\calc@multiply@by@real| macro must use a muglue register
% instead of |\calc@Bdimen| when |\calc@B| is a muglue register;
% otherwise, a dimen register should be used.  Since integer
% expressions can appear as part of a muglue expression, it would be
% necessary to determine the correct register to use each time a
% multiplication is made.)
%
% \subsection{Multiplication by real numbers}
%
% This is similar to the |\calc@ratio@evaluate| macro above, except that
% it is considerably simplified since we don't need to calculate the
% factor explicitly.
%    \begin{macrocode}
\def\calc@real@multiply\real#1{\endgroup
   \calc@multiply@by@real{#1}\begingroup
   \calc@post@scan}
\def\calc@real@divide\real#1{\calc@ratio@evaluate{1pt}{#1pt}}
%    \end{macrocode}
%
% \section{Reporting errors}
%
% \changes{v4.0d}{1997/11/08}
%    {Use \cs{PackageError} for error messages (DPC)}
% \changes{v4.0e}{1997/11/11}
%    {typo fixed}
% If |\calc@post@scan| reads a character that is not one of `\texttt{+}',
% `\texttt{-}', `\texttt{*}', `\texttt{/}', or `\texttt{)}', an error
% has occurred, and this is reported to the user.  Violations in the
% syntax of \<numeric>s will be detected and reported by \TeX.
% \changes{v4.1a}{1998/06/07}
%    {Improved, I hope, error message: CAR}
%    \begin{macrocode}
\def\calc@error#1{%
   \PackageError{calc}%
     {`#1' invalid at this point}%
     {I expected to see one of: + - * / )}}
%</package>
%    \end{macrocode}
%
% \Finale
\endinput


Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.