diff options
Diffstat (limited to 'Master/texmf-dist/source/latex-dev/tools/calc.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex-dev/tools/calc.dtx | 1357 |
1 files changed, 1357 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex-dev/tools/calc.dtx b/Master/texmf-dist/source/latex-dev/tools/calc.dtx new file mode 100644 index 00000000000..0bc90f736ba --- /dev/null +++ b/Master/texmf-dist/source/latex-dev/tools/calc.dtx @@ -0,0 +1,1357 @@ +% \iffalse meta-comment +% +% Copyright (C) 1993-2019 +% +% The LaTeX3 Project and any individual authors listed elsewhere +% in this file. +% +% This file is part of the Standard LaTeX `Tools Bundle'. +% ------------------------------------------------------- +% +% It may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3c +% of this license or (at your option) any later version. +% The latest version of this license is in +% https://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% The list of all files belonging to the LaTeX `Tools Bundle' is +% given in the file `manifest.txt'. +% +% \fi +% \iffalse +%% File `calc.dtx'. +%% Copyright (C) 1992--1995 +%% Kresten Krab Thorup and Frank Jensen. +%% Copyright (C) 1997--2007 +%% 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} + [2017/05/25 v4.3 Infix arithmetic (KKT,FJ)] +% +% \iffalse +%<*driver> +\documentclass{ltxdoc} +\EnableCrossrefs +\RecordChanges +\usepackage{calc} +\begin{document} +\DocInput{calc.dtx} +\end{document} +%</driver> +% \fi +% +% \GetFileInfo{calc.dtx} +% +% \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} +% +% \MaintainedByLaTeXTeam{tools} +% \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 |tabular| |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}. +% In August 2005 the package was further extended to provide the command +%\begin{quote} +% |\totalheightof{|\<text>|}| +%\end{quote} +% This command does exactly what you'd expect from its name. +% Additionally the package also provides the command +%\begin{quote} +% |\settototalheight{|\<cmd>|}{|\<text>|}| +%\end{quote} +% +% +% 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\txtwd} +%\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\ is scanning for a \<number> etc.\ it is +% common to terminate the scanning with a space token or by inserting +% \cs{relax}. As of version~4.3 \textsf{calc} allows \cs{relax} tokens +% to appear in places where they would usually be used for terminating +% \TeX's scanning. In short this is just before any of \texttt{+-*/)} +% or at the end of the expression being evaluated. +% +% 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} +% +% +% +% Another new feature introduced in August 2005 was $\max$ and $\min$ +% operations with associated macros +%\begin{quote} +% |\maxof{|\<\textit{type} expression>|}{|\<\textit{type} expression>|}| +% \\ +% |\minof{|\<\textit{type} expression>|}{|\<\textit{type} expression>|}| +%\end{quote} +% When \textit{type} is either \meta{glue} or \meta{dimen} these macros +% are allowed only as part of addition or subtraction but when +% \textit{type} is \meta{integer} they can also be used when +% multiplying and dividing. In the latter case they follow the +% same syntax rules as |\ratio| and |\real| which means they must come +% after the |*| or the |/|. Thus +%\begin{verbatim} +% \setcounter{x}{3*\maxof{4+5}{3*4}+\minof{2*\real{1.6}}{5-1}} +%\end{verbatim} +% will assign $3\times\max(9,12)+\min(3,4)=39$ to |x|. Similarly +%\begin{verbatim} +% \setlength{\parindent}{% +% \minof{3pt}{\parskip}*\real{1.5}*\maxof{2*\real{1.6}}{2-1}} +%\end{verbatim} +% will assign $\min(13.5\textrm{pt},4.5\cs{parskip})$ to \cs{parindent} +% +% +% +% \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>^^A +% \is \<\textit{type} term>^^A +% \alt \<\textit{type} expression> \<plus or minus> \<\textit{type} term> +% +% \<\textit{type} term>^^A +% \is \<\textit{type} term> \<\textit{type} scan stop> +% \alt \<\textit{type} factor>^^A +% \alt \<\textit{type} term> \<multiply or divide> \<integer>^^A +% \alt \<\textit{type} term> \<multiply or divide> \<real number>^^A +% \alt \<\textit{type} term> \<multiply or divide>^^A +% \<$\max$ or $\min$ integer>^^A +% +% \<\textit{type} scan stop>^^A +% \is \<empty>^^A +% \alt \<optional space>^^A +% \alt |\relax| +% +% \<\textit{type} factor>^^A +% \is \<\textit{type}>^^A +% \alt \<text dimen factor>^^A +% \alt \<$\max$ or $\min$ \textit{type}>^^A +% \alt |(|$_{12}$ \<\textit{type} expression> |)|$_{12}$ +% +% \<integer> \is \<number> +% +% \<$\max$ or $\min$ \textit{type}> \is \<$\max$ or $\min$ command>^^A +% |{| \<\textit{type} expression> |}|^^A +% |{| \<\textit{type} expression> |}| +% +% \<$\max$ or $\min$ command> \is |\maxof|^^A +% \alt |\minof| +% +% \<text dimen factor>^^A +% \is \<text dimen command>|{| \<text> |}| +% +% \<text dimen command>^^A +% \is |\widthof|^^A +% \alt |\heightof|^^A +% \alt |\depthof|^^A +% \alt |\totalheightof|^^A +% +% \<multiply or divide>^^A +% \is |*|$_{12}$^^A +% \alt |/|$_{12}$ +% +% \<real number>^^A +% \is |\ratio{| \<dimen expression> |}{| \<dimen expression> |}|^^A +% \alt |\real{| \<optional signs> \<decimal constant> |}| +% +% \<plus or minus>^^A +% \is |+|$_{12}$^^A +% \alt |-|$_{12}$ +% +% \<decimal constant>^^A +% \is |.|$_{12}$^^A +% \alt |,|$_{12}$^^A +% \alt \<digit> \<decimal constant>^^A +% \alt \<decimal constant> \<digit> +% +% \<digit>^^A +% \is |0|$_{12}$^^A +% \alt |1|$_{12}$^^A +% \alt |2|$_{12}$^^A +% \alt |3|$_{12}$^^A +% \alt |4|$_{12}$^^A +% \alt |5|$_{12}$^^A +% \alt |6|$_{12}$^^A +% \alt |7|$_{12}$^^A +% \alt |8|$_{12}$^^A +% \alt |9|$_{12}$ +% +% \<optional signs>^^A +% \is \<optional spaces>^^A +% \alt \<optional signs> \<plus or minus> \<optional spaces> +% +% \end{calc-syntax} +% +% +% Relying heavily on \TeX\ to do the underlying assignments, it is +% only natural for \texttt{calc} to simulate \TeX's parsing machinery +% for these quantities. Therefore it a)~imposes the same restrictions +% on the catcode of syntax characters as \TeX\ and b)~tries to expand +% its argument fully. a)~means that implicit characters for the tokens +% |*|$_{12}$, |/|$_{12}$, |(|$_{12}$, and |)|$_{12}$ will not +% work\footnote{e\TeX\ also assumes these catcodes when parsing a +% \cs{numexpr}, \cs{dimexpr}, \cs{glueexpr}, or \cs{muglueexpr} and +% does not allow implicit characters.} but because of~b), the +% expansion should allow you to use macros that expand to explicit +% syntax characters. +% +% +% \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} +% \PrintChanges +% } +% +% \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} +% \changes{v4.2}{2005/08/06}{Removed a few redundant \cs{expandafter}s} +% 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|. +% \begin{macrocode} +\def\calc@assign@generic#1#2#3#4{\let\calc@A#1\let\calc@B#2% + \calc@open(#4!% + \global\calc@A\calc@B\endgroup#3\calc@B} +% \end{macrocode} +% \end{macro} +% +% \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} +% +% \begin{macro}{\setcounter} +% \begin{macro}{\addtocounter} +% \changes{v4.2}{2005/08/06} +% {Fix to make \cs{addtocounter} work with \texttt{amstext}} +% \begin{macro}{\steptocounter} +% \changes{v4.2}{2005/08/06} +% {Avoid redundant processing. PR/3795} +% \begin{macro}{\setlength} +% \begin{macro}{\addtolength} +% 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}}} +% \end{macrocode} +% \begin{macrocode} + \def\addtocounter#1#2{\@ifundefined{c@#1}{\@nocounterr{#1}}% + {\calc@assign@count{\global\advance\csname c@#1\endcsname}{#2}}}% +% \end{macrocode} +% We also fix \cs{stepcounter} to not go through the whole \texttt{calc} +% process. +% \begin{macrocode} + \def\stepcounter#1{\@ifundefined {c@#1}% + {\@nocounterr {#1}}% + {\global\advance\csname c@#1\endcsname \@ne + \begingroup + \let\@elt\@stpelt \csname cl@#1\endcsname + \endgroup}}% +% \end{macrocode} +% If the \texttt{amstext} package is loaded we must add the +% |\iffirstchoice@| switch as well. We patch the commands this +% way since it's good practice when we know how many arguments they take. +% \begin{macrocode} +\@ifpackageloaded{amstext}{% + \expandafter\def\expandafter\stepcounter + \expandafter#\expandafter1\expandafter{% + \expandafter\iffirstchoice@\stepcounter{#1}\fi + } + \expandafter\def\expandafter\addtocounter + \expandafter#\expandafter1\expandafter#\expandafter2\expandafter{% + \expandafter\iffirstchoice@\addtocounter{#1}{#2}\fi + } +}{} +% \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}.) +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \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} +% \begin{macro}{\@calc@pre@scan} +% \changes{v4.2}{2005/08/06} +% {Added macro and force expansion} +% +% 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 |\romannumeral-`\a| part is a little trick which forces expansion +% in case |#1| is a normal macro, something that occurs from time to +% time. A conditional test inside will possibly leave a trailing +% \cs{fi} but this remnant is removed later when \cs{calc@post@scan} +% performs the same trick. +% +% The many |\expandafter|s are needed to efficiently end the nested +% conditionals so that |\calc@textsize| and |\calc@maxmin@addsub| can +% process their argument. +% \changes{v4.1a}{1998/06/07} +% {Added code for text sizes: CAR} +% \changes{v4.1b}{1998/07/07} +% {Correction to ifx true case} +% \changes{v4.2}{2005/08/06} +% {Added \cs{maxof} and \cs{minof} operations} +% \begin{macrocode} +\def\calc@pre@scan#1{% + \expandafter\@calc@pre@scan\romannumeral-`\a#1} +\def\@calc@pre@scan#1{% + \ifx(#1% + \expandafter\calc@open + \else + \ifx\widthof#1% + \expandafter\expandafter\expandafter\calc@textsize + \else + \ifx\maxof#1% + \expandafter\expandafter\expandafter\expandafter + \expandafter\expandafter\expandafter\calc@maxmin@addsub + \else + \calc@numeric% no \expandafter needed for this one. + \fi + \fi + \fi + #1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@open} +% \begin{macro}{\calc@initB} +% |\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} +% \end{macro} +% \end{macro} +% \begin{macro}{\calc@numeric} +% |\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} +% \end{macro} +% +% \begin{macro}{\widthof} +% \begin{macro}{\heightof} +% \begin{macro}{\depthof} +% \changes{v4.1a}{1998/06/07} +% {Added macros: CAR} +% \begin{macro}{\totalheightof} +% \changes{v4.2}{2005/08/06} +% {Added macro} +% \changes{v4.2}{2005/08/06} +% {Added informative message for reserved macros} +% +% 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 sped up: +% CAR.} Thus the test in |\@calc@pre@scan| finds any of them. +% +% As we have to check for these commands explicitly we must ensure +% that our definition wins. Using \cs{newcommand} gives an error when +% loading \texttt{calc} and may be mildly surprising. This should be +% a little more informative. +% \begin{macrocode} +\@for\reserved@a:=widthof,heightof,depthof,totalheightof,maxof,minof\do +{\@ifundefined{\reserved@a}{}{% + \PackageError{calc}{% + The\space calc\space package\space reserves\space the\space + command\space name\space `\@backslashchar\reserved@a'\MessageBreak + but\space it\space has\space already\space been\space defined\space + with\space the\space meaning\MessageBreak + `\expandafter\meaning\csname\reserved@a\endcsname'.\MessageBreak + This\space original\space definition\space will\space be\space lost}% + {If\space you\space need\space a\space command\space with\space + this\space definition,\space you\space must\space use\space a\space + different\space name.}}% +} +\let\widthof\ignorespaces +\let\heightof\ignorespaces +\let\depthof\ignorespaces +\let\totalheightof\ignorespaces +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@textsize} +% \changes{v4.1a}{1998/06/07} +% {Added macro: CAR} +% \changes{v4.1a}{1998/06/07} +% {Added macro: CAR} +% \changes{v4.2}{2005/08/06} +% {Extended macro with \cs{totalheightof}} +% The presence of the above four 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 Arseneau and David Carlisle.} +% +% Within the text argument we must restore the normal meanings of +% the four 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 + \def\totalheightof{\ht\dp}% +% \end{macrocode} +% We must expand the argument one level if it's \cs{totalheightof} +% and it doesn't hurt the other three. +% \begin{macrocode} + \expandafter\@settodim\expandafter{#1}% + {\global\calc@A}% + {% + \let\widthof\ignorespaces + \let\heightof\ignorespaces + \let\depthof\ignorespaces + \let\totalheightof\ignorespaces + #2}% + \endgroup + \calc@post@scan} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\calc@post@scan} +% \begin{macro}{\@calc@post@scan} +% \changes{v4.2}{2005/08/06}{Added macro and force expansion} +% \changes{v4.3}{2007/08/22}{Discard terminating \cs{relax} tokens and +% avoid extra error message from \cs{calc@next}} +% 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, an optional \cs{relax}, 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. +% \begin{macrocode} +\def\calc@post@scan#1{% + \expandafter\@calc@post@scan\romannumeral-`\a#1} +\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 + \ifx#1\relax\let\calc@next\calc@post@scan \else + \def\calc@next{\calc@error#1}% + \fi + \fi + \fi + \fi + \fi + \fi + \fi + \calc@next} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@add} +% \begin{macro}{\calc@subtract} +% \begin{macro}{\calc@generic@add} +% \begin{macro}{\calc@addAtoB} +% \begin{macro}{\calc@subtractAfromB} +% 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} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\real} +% \begin{macro}{\ratio} +% \begin{macro}{\calc@ratio@x} +% \begin{macro}{\calc@real@x} +% The multiplicative operators, `\texttt{*}' and `\texttt{/}', may be +% followed by a |\real|, |\ratio|, |\minof|, or |\maxof| token. The +% last two of these control sequences are defined by \texttt{calc} as +% they are needed by the scanner for addition or subtraction while the +% first two 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 |\real| or |\ratio|, 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} +% \end{macro} +% \end{macro} +% \begin{macro}{\calc@multiplyx} +% \changes{v4.2}{2005/08/06} +% {Added $\protect\max$ and $\protect\min$ operations} +% \begin{macro}{\calc@dividex} +% \changes{v4.2}{2005/08/06} +% {Added $\protect\max$ and $\protect\min$ operations} +% Test which operator followed |*| or |/|. If none followed it's just +% a standard multiplication or division. +% \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 + \ifx\maxof#1\let\calc@next\calc@maxmin@multiply \else + \let\calc@next\calc@multiply + \fi + \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 + \ifx\maxof#1\let\calc@next\calc@maxmin@divide \else + \let\calc@next\calc@divide + \fi + \fi + \fi + \calc@next#1} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@multiply} +% \begin{macro}{\calc@divide} +% \begin{macro}{\calc@generic@multiply} +% \begin{macro}{\calc@multiplyBbyA} +% \begin{macro}{\calc@divideBbyA} +% 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. +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@close} +% |\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} +% \end{macro} +% +% \subsection{Calculating a ratio} +% +% \begin{macro}{\calc@ratio@multiply} +% \begin{macro}{\calc@ratio@divide} +% 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} +% \end{macro} +% \end{macro} +% \begin{macro}{\calc@Ccount} +% \begin{macro}{\calc@numerator} +% \begin{macro}{\calc@denominator} +% We shall need two registers for temporary usage in the +% calculations. We can save one register since we can reuse +% |\calc@Bcount|. +% \begin{macrocode} +\newcount\calc@Ccount +\let\calc@numerator=\calc@Bcount +\let\calc@denominator=\calc@Ccount +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% \begin{macro}{\calc@ratio@evaluate} +% 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} +% \end{macro} +% 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{macro}{\calc@next@digit} +% \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} +% \end{macro} +% \begin{macro}{\calc@multiply@by@real} +% 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.) +% \end{macro} +% +% \subsection{Multiplication by real numbers} +% +% \begin{macro}{\calc@real@multiply} +% \begin{macro}{\calc@real@divide} +% 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} +% \end{macro} +% \end{macro} +% +% \subsection{$\max$ and $\min$ operations} +% +% \begin{macro}{\maxof} +% \begin{macro}{\minof} +% \changes{v4.2}{2005/08/06} +% {Added macros} +% With version 4.2, the $\max$ and $\min$ operators were +% added to \texttt{calc}. The user functions for them are \cs{maxof} and +% \cs{minof} respectively. +% These macros are internally similar to \cs{widthof} etc.\ in that they +% are unexpandable and easily recognizable by the scanner. +% \begin{macrocode} +\let\maxof\@@italiccorr +\let\minof\@@italiccorr +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\calc@Cskip} +% \begin{macro}{\ifcalc@count@} +% The $\max$ and $\min$ operations take two arguments so we need an extra +% \<skip> register. We also add a switch for determining when to perform +% a \<skip> or a \<count> assignment. +% \begin{macrocode} +\newskip\calc@Cskip +\newif\ifcalc@count@ +% \end{macrocode} +% \end{macro} +% \end{macro} +% \begin{macro}{\calc@maxmin@addsub} +% \begin{macro}{\calc@maxmin@generic} +% \changes{v4.2}{2005/08/06}{Macros added} +% When doing addition or subtraction with a $\max$ or $\min$ operator, we +% first check if |\calc@A| is a \<count> register or not and then set the +% switch. Then call the real function which sets |\calc@A| to the desired +% value and continue as usual with |\calc@post@scan|. +% \begin{macrocode} +\def\calc@maxmin@addsub#1#2#3{\begingroup + \ifx\calc@A\calc@Acount% + \calc@count@true + \else + \calc@count@false + \fi + \calc@maxmin@generic#1{#2}{#3}% + \endgroup + \calc@post@scan +} +% \end{macrocode} +% Check the switch and do either \<count> or \<skip> assignments. Note that +% |\maxof| and |\minof| are not set to |>| and |<| until after the +% assignments, which ensures we can nest them without problems. Then set +% |\calc@A| to the correct one. +% \begin{macrocode} +\def\calc@maxmin@generic#1#2#3{% + \begingroup + \ifcalc@count@ + \calc@assign@count\calc@Ccount{#2}% + \calc@assign@count\calc@Bcount{#3}% + \def\minof{<}\def\maxof{>}% + \global\calc@A\ifnum\calc@Ccount#1\calc@Bcount + \calc@Ccount\else\calc@Bcount\fi + \else + \calc@assign@skip\calc@Cskip{#2}% + \calc@assign@skip\calc@Bskip{#3}% + \def\minof{<}\def\maxof{>}% + \global\calc@A\ifdim\calc@Cskip#1\calc@Bskip + \calc@Cskip\else\calc@Bskip\fi + \fi + \endgroup +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\calc@maxmin@divmul} +% \begin{macro}{\calc@maxmin@multiply} +% \begin{macro}{\calc@maxmin@divide} +% \changes{v4.2}{2005/08/06}{Macros added} +% When doing division or multiplication we must be using \<count> registers +% so we set the switch. Other than that it is almost business as usual when +% multiplying or dividing. |#1| is the instruction to either multiply or +% divide |\calc@B| by |\calc@A|, |#2| is either |\maxof| or |\minof| which +% is waiting in the input stream and |#3| and |#4| are the calc expressions. +% We end it all as usual by calling |\calc@post@scan|. +% \begin{macrocode} +\def\calc@maxmin@divmul#1#2#3#4{% + \endgroup\begingroup + \calc@count@true + \aftergroup#1% + \calc@maxmin@generic#2{#3}{#4}% + \endgroup\begingroup + \calc@post@scan +} +% \end{macrocode} +% The two functions called when seeing a |*| or a |/|. +% \begin{macrocode} +\def\calc@maxmin@multiply{\calc@maxmin@divmul\calc@multiplyBbyA} +\def\calc@maxmin@divide {\calc@maxmin@divmul\calc@divideBbyA} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% \section{Reporting errors} +% \begin{macro}{\calc@error} +% \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: + - * / )}} +% \end{macrocode} +% \end{macro} +% +% \section{Other additions} +% \begin{macro}{\@settodim} +% \changes{v4.2}{2005/08/06} +% {Changed kernel macro} +% \begin{macro}{\settototalheight} +% \changes{v4.2}{2005/08/06} +% {Added macro} +% The kernel macro \cs{@settodim} is changed so that it runs through a list +% containing \cs{ht}, \cs{wd}, and \cs{dp} and than advance the length +% one step at a time. We just have to use a scratch register in case the +% user decides to put in a \cs{global} prefix on the length register. +% A search on the internet confirmed that some people do that kind of thing. +% \begin{macrocode} +\def\@settodim#1#2#3{% + \setbox\@tempboxa\hbox{{#3}}% + \dimen@ii=\z@ + \@tf@r\reserved@a #1\do{% + \advance\dimen@ii\reserved@a\@tempboxa}% + #2=\dimen@ii + \setbox\@tempboxa\box\voidb@x} +% \end{macrocode} +% Now the user level macro is straightforward. +% \begin{macrocode} +\def\settototalheight{\@settodim{\ht\dp}} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% That's the end of the package. +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \Finale +\endinput + |