% \iffalse meta-comment % % Copyright (C) 1997-2003 by Michael J. Downes % Copyright (C) 2007-2008 by Morten Hoegholm % Copyright (C) 2007-2014 by Lars Madsen % Copyright (C) 2007-2020 by Will Robertson % Copyright (C) 2010-2017 by Joseph Wright % Copyright (C) 2020-2020 by Ulrike Fischer % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3 of this license or (at your option) any later % version. The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of % LaTeX version 2005/12/01 or later. % % This work has the LPPL maintenance status "maintained". % % The Current Maintainer of this work is Will Robertson. % % This work consists of the main source file breqn.dtx % and the derived files % breqn.sty, breqn.pdf, breqn.ins. % % Distribution: % CTAN:macros/latex/contrib/mh/breqn.dtx % CTAN:macros/latex/contrib/mh/breqn.pdf % % Unpacking: % tex breqnbundle.ins % % Documentation: % The class ltxdoc loads the configuration file ltxdoc.cfg % if available. Here you can specify further options, e.g. % use A4 as paper format: % \PassOptionsToClass{a4paper}{article} % % Programm calls to get the documentation (example): % pdflatex breqn.dtx % makeindex -s gind.ist breqn.idx % pdflatex breqn.dtx % makeindex -s gind.ist breqn.idx % pdflatex breqn.dtx % % Installation: % TDS:tex/latex/breqn/breqn.sty % TDS:doc/latex/breqn/breqn.pdf % TDS:source/latex/breqn/breqn.dtx % %<*driver> \NeedsTeXFormat{LaTeX2e} \documentclass{ltxdoc} \CodelineIndex \EnableCrossrefs \setcounter{IndexColumns}{2} \usepackage{color,verbatim,xspace,varioref,listings,amsmath,trace} \usepackage{geometry} \def\partname{Part} \definecolor{hilite}{rgb}{0.2,0.4,0.7} \def\theCodelineNo{\textcolor{hilite}{\sffamily\tiny\arabic{CodelineNo}}} \lstloadlanguages{[AlLaTeX]TeX} \lstnewenvironment{literalcode} {\lstset{gobble=2,columns=fullflexible,basicstyle=\color{hilite}\ttfamily}} {} \makeatletter {\catcode`\%=12 \long\gdef\@gobble@percent@space#1{\ifx #1%\expandafter\@gobble\else\expandafter#1\fi}} \AtBeginDocument{\def\verbatim@processline{\expandafter\check@percent \the\verbatim@line\par}} \newwrite\tmp@out \newcounter{xio} \newenvironment{xio}{% example input and output \par\addvspace\bigskipamount \hbox{\itshape \refstepcounter{xio}\kern-\p@ Example \thexio}\@nobreaktrue \immediate\openout\tmp@out\jobname.tmp \relax \begingroup \let\do\@makeother\dospecials\catcode`\^^M\active \def\verbatim@processline{ \immediate\write\tmp@out{\expandafter\@gobble@percent@space \the\verbatim@line}}% \verbatim@start }{% \immediate\closeout\tmp@out \@verbatim\frenchspacing\@vobeyspaces \@@input \jobname.tmp \relax \endgroup \par\medskip \noindent\ignorespaces \@@input \jobname.tmp \relax \par\medskip } \providecommand*\pkg[1]{\textsf{#1}} \providecommand*\cls[1]{\textsf{#1}} \providecommand*\opt[1]{\texttt{#1}} \providecommand*\env[1]{\texttt{#1}} \providecommand*\fn[1]{\texttt{#1}} \providecommand*\cn[1]{\cs{#1}} \providecommand*\csarg[1]{\texttt{\char`\{#1\char`\}}} \providecommand*\tex{\TeX\xspace} \providecommand*\latex{\LaTeX\xspace} \providecommand*\dbldollars{\texttt{\detokenize{$$}}}%$$ \providecommand*\arg{} \edef\arg{\expandafter\@gobble\string\#} \newenvironment{aside}{\begin{quote}\bfseries}{\end{quote}} \newenvironment{dn}{\begin{quote}\bfseries}{\end{quote}} \newcommand\dash{\textemdash} \newcommand\dbslash[1]{\texttt{\string\\}} \newcommand\thepkg{the \pkg{breqn} package\xspace} \providecommand*\texbook{\textsl{The \protect\TeX{}book}\xspace} \providecommand*\dotsc{\ldots} \providecommand*\eqref[1]{(\ref{#1})} \providecommand*\qq[1]{\textquotedblleft#1\textquotedblright} \providecommand*\quoted[1]{\textquoteleft#1\textquoteright} \providecommand*\dquoted[1]{\textquotedblleft#1\textquotedblright} \providecommand*\ie{i.e.,\xspace} \providecommand*\eg{e.g.,\xspace} \providecommand*\etc{etc.\xspace} \providecommand*\cf{cf.\xspace} \providecommand*\ndash{\unskip\textendash\ignorespaces} \providecommand*\mdash{\unskip\textemdash\ignorespaces} \makeatother \usepackage{breqn} \begin{document} \DocInput{breqn.dtx} \end{document} % % \fi % % % \title{The \pkg{breqn} package} % \def\fileversion{0.98l} % \def\filedate{2021/10/28} % \date{\pkg{breqn} bundle: \filedate\space\fileversion} % \author{Authors: Michael J. Downes, Morten H\o gholm\\ Maintained by Morten H\o gholm, Will Robertson\\ Feedback: \texttt{https://github.com/wspr/breqn/issues}} % % \maketitle % \begin{abstract} % The \pkg{breqn} package facilitates automatic line-breaking of % displayed math expressions. % \end{abstract} % % % \tableofcontents % % % \part{User's guide} % % \section{A bit of history} % % Originally \pkg{breqn}, \pkg{flexisym}, and \pkg{mathstyle} were % created by Michael J.~Downes from the American Mathematical Society % during the 1990's up to late 2002. Sadly---and much to the shock of % the \TeX\ world---Michael passed away in early 2003 at the age of % only~44. % % The American Mathematical Society kindly allowed Morten H\o gholm to % assume maintainership of this part of his work and we wish to % express our gratitude to them and to Barbara Beeton in particular for % providing the files needed. % % MH brought Michael's work to a wider audience, thereby allowing users to create % more \emph{masterpieces of the publishing art} as we think he would % have wanted. % % Following the July 2008 breqn release, \pkg{breqn} was left in the hands % of a maintenance team, while MH moved on with other projects. % % \section{Package loading} % % The \pkg{breqn} package automatically loads \pkg{amsmath} to avoid loading order conflicts. % It also automatically loads \pkg{flexisym} and \pkg{mathstyle}, but in some cases these % packages need to be loaded separately. The canonical order for package loading is: % \begin{verbatim} % \usepackage{amsmath} % \usepackage{flexisym} % \usepackage{breqn} % \end{verbatim} % % The recommended way of loading the \pkg{breqn} package is to load it % \emph{before} other packages dealing with math symbols, \ie, before % \pkg{amssymb}, or packages such as \pkg{mathpazo} or \pkg{mathptmx}. % However, this can sometimes lead to macro definition clashes, and in such cases % you may need to juggle the loading order to make it work. % % \subsection{Options for \pkg{flexisym}} % % The \pkg{flexisym} package (described in section \vref{flexisym}) is % required by \pkg{breqn} and ensures the math symbols are set up % correctly. By default \pkg{breqn} loads it with support for Computer % Modern but if you use a different math package requiring slightly % different definitions, \pkg{flexisym} must be explicitly loaded before \pkg{breqn} as shown above. % Below is an example of how you enable \pkg{breqn} to work with the widely % used \pkg{mathpazo} package. % \begin{verbatim} %\usepackage{mathpazo} %\usepackage[mathpazo]{flexisym} %\usepackage{breqn} % \end{verbatim} % Currently, the packages \pkg{mathpazo} and \pkg{mathptmx} are % supported. Despair not: Chances are that the package will work using % the default settings. If you find that a particular math font % package doesn't work then please see implementation in % \fn{flexisym.dtx} for how to create a support file---it is easier % than one might think. Contributions welcome. % % % \section{Introduction} % % The \pkg{breqn} package for \LaTeX\ provides solutions to a number of % common difficulties in writing displayed equations and getting % high-quality output. For example, it is a well-known inconvenience that % if an equation must be broken into more than one line, \cs{left} \dots\ % \cs{right} constructs cannot span lines. The \pkg{breqn} package makes % them work as one would expect whether or not there is an intervening % line break. % % The single most ambitious goal of the \pkg{breqn} package, however, is % to support automatic linebreaking of displayed equations. Such % linebreaking cannot be done without substantial changes under the hood % in the way math formulas are processed. For this reason, especially in % the alpha release, users should proceed with care and keep an eye out % for unexpected glitches or side effects. % % \section{Principal features} % The principal features of the \pkg{breqn} package are: % \begin{description} % % \item[semantically oriented structure] The way in which compound % displayed formulas are subdivided matches the logical structure more % closely than, say, the standard \env{eqnarray} environment. Separate % equations in a group of equations are written as separate environments % instead of being bounded merely by \dbslash/ commands. Among other % things, this clears up a common problem of wrong math symbol spacing at % the beginning of continuation lines. It also makes it possible to % specify different vertical space values for the space between lines of a % long, broken equation and the space between separate equations in a % group of equations. % % \item[automatic line breaking] Overlong equations will be broken % automatically to the prevailing column width, and continuation lines % will be indented following standard conventions. % % \item[line breaks within delimiters] Line breaks within \cs{left} \dots\ % \cs{right} delimiters work in a natural way. Line breaks can be % forbidden below a given depth of delimiter nesting through a package % option. % % \item[mixed math and text] Display equations that contain mixed % math and text, or even text only, are handled naturally by means of a % \env{dseries} environment that starts out in text mode instead of math % mode. % % \item[ending punctuation] The punctuation at the end of a displayed % equation can be handled in a natural way that makes it easier to promote % or demote formulas from\slash to inline math, and to apply special % effects such as adding space before the punctuation. % % \item[flexible numbering] Equation numbering is handled in a natural % way, with all the flexibility of the \pkg{amsmath} package and with no % need for a special \cs{nonumber} command. % % \item[special effects] It is easy to apply special effects to individual % displays, e.g., changing the type size or adding a frame. % % \item[using available space] Horizontal shrink is made use of % whenever feasible. With most other equation macros it is frozen when it % occurs between \cs{left} \dots\ \cs{right} delimiters, or in any sort of % multiline structure, so that some expressions require two lines that would % otherwise fit on one. % % \item[high-quality spacing] The \cs{abovedisplayshortskip} is used when % applicable (other equation macros fail to apply it in equations of more % than one line). % % \item[abbreviations] Unlike the \pkg{amsmath} equation environments, the % \pkg{breqn} environments can be called through user-defined abbreviations % such as \cs{beq} \dots\ \cs{eeq}. % % \end{description} % % \section{Shortcomings of the package} % The principal known deficiencies of the \pkg{breqn} package are: % % \subsection{Incompatibilities} As it pushes the envelope % of what is possible within the context of \LaTeXe, \thepkg will tend % to break other packages when used in combination with them, or to fail % itself, when there are any areas of internal overlap; successful use may % in some cases depend on package loading order. % % % % \subsection{Indention of delimited fragments} When line breaks within % delimiters are involved, the automatic indention of continuation lines % is likely to be unsatisfactory and need manual adjustment. I don't see % any easy way to provide a general solution for this, though I have some % ideas on how to attain partial improvements. % % \subsection{Math symbol subversion} % In order for automatic line breaking to work, the operation of all the % math symbols of class 2, 3, 4, and 5 must be altered (relations, binary % operators, opening delimiters, closing delimiters). This is done by an % auxiliary package \pkg{flexisym}. As long as you stick to the advertised % \LaTeX\ interface for defining math symbols (\cs{DeclareMathSymbol}), % things should work OK most of the time. Any more complex math symbol % setup is quite likely to quarrel with the \pkg{flexisym} package. % See Section~\vref{flexisym} for further information. % % \subsection{Subscripts and superscripts} % % Because of the changes to math symbols of class 2--5, writing certain % combinations such as \verb'^+' or \verb'_\pm' or \verb'^\geq' without % braces would lead to error messages; (The problem described here % already exists in standard \LaTeX\ to a lesser extent, as you may know % if you ever tried \verb'^\neq' or \verb'^\cong'; and indeed there are % no examples in the \LaTeX\ book to indicate any sanction for omitting % braces around a subscript or superscript.) % % The \pkg{flexisym} package therefore calls, as of version 0.92, another % package called \pkg{mathstyle} which turns \verb'^' and \verb'_' into % active characters. This is something that I believe is desirable in any % case, in the long run, because having a proper mathstyle variable % eliminates some enormous burdens that affect almost any % nontrivial math macros, as well as many other things where the % connection is not immediately obvious, e.g., the \LaTeX\ facilities for % loading fonts on demand. % % Not that this doesn't introduce new and interesting problems of its % own---for example, you don't want to put usepackage statements % after flexisym for any package that refers to, e.g., \verb'^^J' or % \verb'^^M' % internally (too bad that the \LaTeX\ package loading code does not % include automatic defenses to ensure normal catcodes in the interior of % a package; but it only handles the \verb'@' character). % % But I took a random AMS journal article, with normal end-user kind of % \LaTeX\ writing, did some straightforward substitutions to change all % the equations into dmath environments, and ran it with active math % sub/sup: everything worked OK. This suggests to me that it can work in % the real world, without an impossible amount of compatibility work. % % \section{Incomplete} % In addition, in the \textbf{alpha release [1997/10/30]} the following % gaps remain to be filled in: % \begin{description} % \item[documentation] % The documentation could use amplification, especially more % illustrations, and I have undoubtedly overlooked more than a few errors. % % \item[group alignment] The algorithm for doing alignment % of mathrel symbols across equations in a \env{dgroup} environment % needs work. Currently the standard and \opt{noalign} alternatives % produce the same output. % % \item[single group number] When a \env{dgroup} has a group number and % the individual equations are unnumbered, the handling and placement of % the group number aren't right. % % \item[group frame] Framing a group doesn't work, you might be able to % get frames on the individual equations at best. % % \item[group brace] The \opt{brace} option for \env{dgroup} is intended % to produce a large brace encompassing the whole group. This hasn't been % implemented yet. % % \item[darray environment] The \env{darray} environment is unfinished. % % \item[dseries environment] The syntax and usage for the \env{dseries} % environment are in doubt and may change. % % \item[failure arrangements] When none of the line-breaking passes for a % \env{dmath} environment succeeds\dash i.e., at least one line is % overfull\dash the final arrangement is usually rather poor. A better % fall-back arrangement in the failure case is needed. % % \end{description} % % \section{Package options} % % Many of the package options for \thepkg are the same as options of the % \env{dmath} or \env{dgroup} environments, and some of them require an % argument, which is something that cannot be done through the normal % package option mechanism. Therefore most of the \pkg{breqn} package % options are designed to be set with the \cs{breqnsetup} command after the % package is loaded. For example, to load the package and set the % maximum delimiter nesting depth for line breaks to~1: % \begin{verbatim} % \usepackage{breqn} % \breqnsetup{breakdepth={1}} % \end{verbatim} % % See the discussion of environment options, Section~\vref{envopts}, for % more information. % % Debugging information is no longer available as a package % option. Instead, the tracing information has been added in a fashion % so that it can be enabled as a docstrip option: % \begin{verbatim} % \generate{\file{breqn.sty}{\from{breqn.dtx}{package,trace}}} % \end{verbatim} % % % \section{Environments and commands} % \subsection{Environments} % All of the following environments take an optional argument for % applying local effects such as changing the typesize or adding a % frame to an individual equation. % % \begin{description} % \item[\env{dmath}] Like \env{equation} but supports line breaking and variant % numbers. % % \item[\env{dmath*}] Unnumbered; like \env{displaymath} but supports line % breaking % % \item[\env{dseries}] Like \env{equation} but starts out in text mode; % intended for series of mathematical expressions of the form `A, B, and % C'. As a special feature, if you use % \begin{verbatim} % \begin{math} ... \end{math} % \end{verbatim} % for each expression in the series, a suitable amount of inter-expression % space will be automatically added. This is a small step in the direction of % facilitating conversion of display math to inline math, and vice versa: If % you write a display as % \begin{verbatim} % \begin{dseries} % \begin{math}A\end{math}, % \begin{math}B\end{math}, % and % \begin{math}C\end{math}. % \end{dseries} % \end{verbatim} % then conversion to inline form is simply a matter of removing the % \verb'\begin{dseries}' and \verb'\end{dseries}' lines; the contents of the % display need no alterations. % % It would be nice to provide the same feature for \verb'$' notation but % there is no easy way to do that because the \verb'$' function has no % entry point to allow changing what happens before math mode is entered. % Making it work would therefore require turning \verb'$' into an active % character, something that I hesitate to do in a \LaTeXe\ context. % % \item[\env{dseries*}] Unnumbered variant of \env{dseries} % % \item[\env{dgroup}] Like the \env{align} environment of \pkg{amsmath}, % but with each constituent equation wrapped in a \env{dmath}, % \env{dmath*}, \env{dseries}, or \env{dseries*} environment instead of being % separated by \dbslash/. The equations are numbered with a group number. % When the constituent environments are the numbered forms (\env{dmath} or % \env{dseries}) they automatically switch to `subequations'-style % numbering, i.e., something like (3a), (3b), (3c), \dots, depending on % the current form of non-grouped equation numbers. See also % \env{dgroup*}. % % \item[\env{dgroup*}] Unnumbered variant of \env{dgroup}. If the % constituent environments are the numbered forms, they get normal % individual equation numbers, i.e., something like (3), (4), (5), \dots~. % % \item[\env{darray}] Similar to \env{eqnarray} but with an argument like % \env{array} for giving column specs. Automatic line breaking is not % done here. % % \item[\env{darray*}] Unnumbered variant of \env{darray}, rather like % \env{array} except in using \cs{displaystyle} for all column % entries. % % \item[\env{dsuspend}] Suspend the current display in order to print % some text, without loss of the alignment. There is also a command % form of the same thing, \cs{intertext}. % \end{description} % % \subsection{Commands} % % The commands provided by \thepkg are: % \begin{description} % \item[\cs{condition}] This command is used for % a part of a display which functions as a condition on the main % assertion. For example: % \begin{verbatim} % \begin{dmath} % f(x)=\frac{1}{x} \condition{for $x\neq 0$} % \end{dmath}. % \end{verbatim} % \begin{dmath} % f(x)=\frac{1}{x} \condition{for $x\neq 0$} % \end{dmath}. % The \cs{condition} command automatically switches to text mode (so that % interword spaces function the way they should), puts in a comma, and % adds an appropriate amount of space. To facilitate promotion\slash % demotion of formulas, \cs{condition} \qq{does the right thing} if used % outside of display math. % % To substitute a different punctuation mark instead of the default comma, % supply it as an optional argument for the \cs{condition} command: % \begin{verbatim} % \condition[;]{...} % \end{verbatim} % (Thus, to get no punctuation: \verb'\condition[]{...}'.) % % For conditions that contain no text, you can use the starred form of the % command, which means to stay in math mode: % \begin{verbatim} % \begin{dmath} % f(x)=\frac{1}{x} \condition*{x\neq 0} % \end{dmath}. % % If your material contains a lot of conditions like these, you might like % to define shorter abbreviations, e.g., % \begin{verbatim} % \newcommand{\mc}{\condition*}% math condition % \newcommand{\tc}{\condition}% text condition % \end{verbatim} % But \thepkg refrains from predefining such abbreviations in order that % they may be left to the individual author's taste. % % \item[\cs{hiderel}] In a compound equation it is sometimes desired to % use a later relation symbol as the alignment point, rather than the % first one. To do this, mark all the relation symbols up to the desired % one with \cs{hiderel}: % \begin{verbatim} % T(n) \hiderel{\leq} T(2^n) \leq c(3^n - 2^n) ... % \end{verbatim} % \end{description} % % \section{Various environment options}\label{envopts} % % The following options are recognized for the \env{dmath}, \env{dgroup}, % \env{darray}, and \env{dseries} environments; some of the options do not % make sense for all of the environments, but if an option is used where % not applicable it is silently ignored rather than treated as an error. % \changes{v0.98b}{2010/08/27}{replaced relindent with indentstep} % % \begin{verbatim} % \begin{dmath}[style={\small}] % \begin{dmath}[number={BV}] % \begin{dmath}[labelprefix={eq:}] % \begin{dmath}[label={xyz}] % \begin{dmath}[indentstep={2em}] % \begin{dmath}[compact] % \begin{dmath}[spread={1pt}] % \begin{dmath}[frame] % \begin{dmath}[frame={1pt},framesep={2pt}] % \begin{dmath}[breakdepth={0}] % \end{verbatim} % % Use the \opt{style} option to change the type size of an individual % equation. This option can also serve as a catch-all option for % altering the equation style in other ways; the contents are simply % executed directly within the context of the equation. % % Use the \opt{number} option if you want the number for a particular % equation to fall outside of the usual sequence. If this option is used % the equation counter is not incremented. If for some reason you need to % increment the counter and change the number at the same time, use the % \opt{style} option in addition to the \opt{number} option: % \begin{verbatim} % style={\refstepcounter{equation}} % \end{verbatim} % % Use of the normal \cs{label} command instead of the \opt{label} option % works, I think, most of the time (untested). \opt{labelprefix} prepends % its argument to the label (only useful as a global option, really), % and must be called before \opt{label}. % % \changes{v0.98b}{2010/08/27}{replaced relindent with indentstep} % Use the \opt{indentstep} option to specify something other than the % default amount for the indention of relation symbols. The default is % 8pt. % % Use the \opt{compact} option in compound equations to inhibit line % breaks at relation symbols. By default a line break will be taken before % each relation symbol except the first one. With the \opt{compact} option % \LaTeX\ will try to fit as much material as possible on each line, but % breaks at relation symbols will still be preferred over breaks at binary % operator symbols. % % Use the \opt{spread} option to increase (or decrease) the amount of % interline space in an equation. See the example given above. % % Use the \opt{frame} option to produce a frame around the body of the % equation. The thickness of the frame can optionally be specified by % giving it as an argument of the option. The default thickness is % \cs{fboxrule}. % % Use the \opt{framesep} option to change the amount of space separating % the frame from what it encloses. The default space is \cs{fboxsep}. % % Use the \opt{breakdepth} option to change the level of delimiter nesting % to which line breaks are allowed. To prohibit line breaks within % delimiters, set this to 0: % \begin{verbatim} % \begin{dmath}[breakdepth={0}] % \end{verbatim} % The default value for breakdepth is 2. Even when breaks are allowed % inside delimiters, they are marked as less desirable than breaks outside % delimiters. Most of the time a break will not be taken within delimiters % until the alternatives have been exhausted. % % Options for the \env{dgroup} environment: all of the above, and also % \begin{verbatim} % \begin{dgroup}[noalign] % \begin{dgroup}[brace] % \end{verbatim} % % By default the equations in a \env{dgroup} are mutually aligned on their % relation symbols ($=$, $<$, $\geq$, and the like). With the % \opt{noalign} option each equation is placed individually without % reference to the others. % % The \opt{brace} option means to place a large brace encompassing the % whole group on the same side as the equation number. % % Options for the \env{darray} environment: all of the above (where % sensible), and also % \begin{verbatim} % \begin{darray}[cols={lcr@{\hspace{2em}}lcr}] % \end{verbatim} % The value of the \opt{cols} option for the darray environment should be % a series of column specs as for the \env{array} environment, with the % following differences: % \begin{itemize} % \item For l, c, and r what you get is not text, but math, and % displaystyle math at that. To get text you must use a 'p' column % specifier, or put an \cs{mbox} in each of the individual cells. % % \item Vertical rules don't connect across lines. % \end{itemize} % % \section{The \pkg{flexisym} package}\label{flexisym} % % The \pkg{flexisym} package does some radical changes in the setup for % math symbols to allow their definitions to change dynamically throughout % a document. The \pkg{breqn} package uses this to make symbols of classes % 2, 3, 4, 5 run special functions inside an environment such as % \env{dmath} that provide the necessary support for automatic line % breaking. % % The method used to effect these changes is to change the definitions of % \cs{DeclareMathSymbol} and \cs{DeclareMathDelimiter}, and then % re-execute the standard set of \LaTeX\ math symbol definitions. % Consequently, additional mathrel and mathbin symbols defined by other % packages will get proper line-breaking behavior if the other package is % loaded after the \pkg{flexisym} package and the symbols are defined % through the standard interface. % % % % \section{Caution! Warning!} % Things to keep in mind when writing documents with \thepkg: % \begin{itemize} % % \item The notation $:=$ must be written with the command \cs{coloneq}. % Otherwise the $:$ and the $=$ will be treated as two separate relation % symbols with an \qq{empty RHS} between them, and they will be printed % on separate lines. % % \item Watch out for constructions like \verb'^+' where a single binary % operator or binary relation symbol is subscripted or superscripted. When % the \pkg{breqn} or \pkg{flexisym} package is used, braces are mandatory % in such constructions: \verb'^{+}'. This applies for both display and % in-line math. % % \item If you want \LaTeX\ to make intelligent decisions about line % breaks when vert bars are involved, use proper pairing versions of the % vert-bar symbols according to context: \verb'\lvert n\rvert' instead of % \verb'|n|'. With the nondirectional \verb'|' there is no way for \LaTeX\ % to reliably deduce which potential breakpoints are inside delimiters % (more highly discouraged) and which are not. % % \item If you use the \pkg{german} package or some other package that % turns double quote \verb'"' into a special character, you may encounter % some problems with named math symbols of type mathbin, mathrel, % mathopen, or mathclose in moving arguments. For example, \cs{leq} in a % section title will be written to the \fn{.aux} file as something like % \verb'\mathchar "3214'. This situation probably ought to be improved, % but for now use \cs{protect}. % % \item Watch out for the \texttt{[} character at the beginning of a % \env{dmath} or similar environment, if it is supposed to be interpreted % as mathematical content rather than the start of the environment's % optional argument. % % This is OK: % \begin{verbatim} % \begin{dmath} % [\lambda,1]... % \end{dmath} % \end{verbatim} % This will not work as expected: % \begin{verbatim} % \begin{dmath}[\lambda,1]...\end{dmath} % \end{verbatim} % % \item Watch out for unpaired delimiter symbols (in display math only): % \begin{verbatim} % ( ) [ ] \langle \rangle \{ \} \lvert \rvert ... % \end{verbatim} % If an open delimiter is used without a close delimiter, or vice versa, % it is normally harmless but may adversely affect line breaking. This is only % for symbols that have a natural left or right directionality. Unpaired % \cs{vert} and so on are fine. % % When a null delimiter is used as the other member of the pair % (\verb'\left.' or \verb'\right.') this warning doesn't apply. % % \item If you inadvertently apply \cs{left} or \cs{right} to something % that is not a delimiter, the error messages are likely to be a bit % more confusing than usual. The normal \LaTeX\ response to an error such % as % \begin{verbatim} % \left + % \end{verbatim} % is an immediate message % \begin{verbatim} % ! Missing delimiter (. inserted). % \end{verbatim} % When \thepkg is in use, \LaTeX\ will fail to realize anything is wrong % until it hits the end of the math formula, or a closing delimiter % without a matching opening delimiter, and then the first message is an % apparently pointless % \begin{verbatim} % ! Missing \endgroup inserted. % \end{verbatim} % % \end{itemize} % % \section{Examples} % % \renewcommand\theequation{\thesection.\arabic{equation}} % % Knuth, SNA p74 % \begin{xio} % Replace $j$ by $h-j$ and by $k-j$ in these sums to get [cf.~(26)] % \begin{dmath}[label={sna74}] % \frac{1}{6} \left(\sigma(k,h,0) +\frac{3(h-1)}{h}\right) % +\frac{1}{6} \left(\sigma(h,k,0) +\frac{3(k-1)}{k}\right) % =\frac{1}{6} \left(\frac{h}{k} +\frac{k}{h} +\frac{1}{hk}\right) % +\frac{1}{2} -\frac{1}{2h} -\frac{1}{2k}, % \end{dmath} % which is equivalent to the desired result. % \end{xio} % % % Knuth, SNA 4.6.2, p387 % \begin{xio} % \newcommand\mx[1]{\begin{math}#1\end{math}}% math expression % % % Now every column which has no circled entry is completely zero; % so when $k=6$ and $k=7$ the algorithm outputs two more vectors, % namely % \begin{dseries}[frame] % \mx{v^{[2]} =(0,5,5,0,9,5,1,0)}, % \mx{v^{[3]} =(0,9,11,9,10,12,0,1)}. % \end{dseries} % From the form of the matrix $A$ after $k=5$, it is evident that % these vectors satisfy the equation $vA =(0,\dotsc,0)$. % \end{xio} % % \begin{xio} % \begin{dmath*} % T(n) \hiderel{\leq} T(2^{\lceil\lg n\rceil}) % \leq c(3^{\lceil\lg n\rceil} % -2^{\lceil\lg n\rceil}) % <3c\cdot3^{\lg n} % =3c\,n^{\lg3} % \end{dmath*}. % \end{xio} % % \begin{xio} % The reduced minimal Gr\"obner basis for $I^q_3$ consists of % \begin{dgroup*} % \begin{dmath*} % H_1^3 = x_1 + x_2 + x_3 % \end{dmath*}, % \begin{dmath*} % H_2^2 = x_1^2 + x_1 x_2 + x_2^2 - q_1 - q_2 % \end{dmath*}, % \begin{dsuspend} % and % \end{dsuspend} % \begin{dmath*} % H_3^1 = x_1^3 - 2x_1 q_1 - x_2 q_1 % \end{dmath*}. % \end{dgroup*} % \end{xio} % % % %\section{Technical notes on tag placement} % %The method used by the breqn package to place the equation number is %rather more complicated than you might think, and the whole reason is %to allow the number to stay properly centered on the total height even %when the height fluctuates due to stretching or shrinking of the page. % % %Consider the following equation: %\begin{dmath}[number={3.15}] % N_{0} \simeq \left( \frac{\nu}{\lVert u\rVert_{H^{i}}} \right) % \lvert I\rvert^{-1/2} %\end{dmath} %It will have only one line, if the column width is not too narrow. % %Scrutinizing the vertical list will shed light on some of the basic properties %shared by all breqn equations. After that we will look at what would happen if %two or more lines were needed. The numbers added on the left in the following %\cs{showlists} output mark the points of interest. %\begin{verbatim} %[1] \penalty 10000 % \glue(\abovedisplayskip) 0.0 % \penalty 10000 % \glue(\belowdisplayskip) 0.0 %[2] \glue 4.0 plus 4.0 % \glue(\lineskip) 1.0 %[3] \vbox(16.53902+0.0)x0.0, glue set 16.53902fil % .\glue 0.0 plus 1.0fil minus 1.0fil % \penalty 10000 %[4] \glue -8.51945 %[5] \hbox(7.5+2.5)x25.55563 % .\OT1/cmr/m/n/10 ( % .\OT1/cmr/m/n/10 3 % .\OT1/cmr/m/n/10 . % .\OT1/cmr/m/n/10 1 % .\OT1/cmr/m/n/10 5 % .\kern 0.0 % .\OT1/cmr/m/n/10 ) % \penalty 10000 %[6] \glue(\parskip) -18.01956 %[7] \hbox(16.53902+9.50012)x360.0, glue set 1.78647 %\end{verbatim} %\begin{enumerate} %\item These four lines are a hidden display structure from \TeX's % primitive \texttt{\$\$} mechanism. It is used only to get the value % of \cs{predisplaysize} so that we can later calculate by hand % whether to use the short display skips or the regular ones. (The % reason that we have to do it by hand traces back to the fact that % \TeX\ 3.x does not allow unhboxing in math mode.) The penalties come % from \cs{predisplaypenalty} and \cs{postdisplaypenalty}, which were % locally set to 10000 to ensure there would be no unintended page % breaks at these glue nodes. % %\item These two glue nodes are the ones that would normally have been % produced at the top of a display; the first one is the above-display % skip node (though we had to put it in by hand with \cs{vskip}) and % the second one is the usual baselineskip/lineskip node. % %\item This is a dummy copy of the equation's first line, which is % thrown in here to get the proper value of baselineskip (or lineskip % in this case). Why do we need this? Because this ensures that we get % the top spacing right before we fiddle with the glue nodes % surrounding the equation number. And if the equation has a frame, % this box is a good place to add it from. % %\item This is a special glue node that brings us to the right vertical % position for adding the equation number. Its value is calculated % from the variables that you would expect, given the presence of the % dummy first line above the num- ber: starting position of the % equation, height of first line, total height of equation body. If % the equation body had more than one line, with stretchable glue % between the lines, half of the stretch would be added in this glue % node. % %\item The hbox containing the equation number. % %\item Backspace to bring the equation body to the right starting point. We use % \cs{parskip} to put this glue in place because we're going to get a % parskip node here in any case when we add the equation body with (in % essence). If we didn't do this we'd get two glue nodes instead of % one, to no purpose. % %\cs{\noindent} \cs{unhbox}\cs{EQ@box}. % % %\item And lastly we see here the first line of the equation body, % which appears to have height 16.5pt and depth 9.5pt. %\end{enumerate} % %For comparison, the vertical list produced from the above equation in %standard \LaTeX\ would look like this, if the same values of %columnwidth and abovedisplayskip are used: %\begin{verbatim} %[1] \penalty 10000 %[2] \glue(\abovedisplayskip) 4.0 plus 4.0 % \glue(\lineskip) 1.0 % \hbox(16.53902+9.50012)x232.94844 %[3] .\hbox(7.5+2.5)x25.55563 % ..\hbox(7.5+2.5)x25.55563 % ...\OT1/cmr/m/n/10 ( % ...\OT1/cmr/m/n/10 3 % ...\OT1/cmr/m/n/10 . % ...\OT1/cmr/m/n/10 1 % ...\OT1/cmr/m/n/10 5 % ...\kern 0.0 % ...\OT1/cmr/m/n/10 ) % .\kern101.49591 %[4] .\hbox(16.53902+9.50012)x105.8969 % ... %[5] \penalty 0 %[6] \glue(\belowdisplayskip) 4.0 plus 4.0 % \glue(\lineskip) 1.0 % \hbox(6.94444+1.94444)x345.0, glue set 62.1106fil %\end{verbatim} % %\begin{enumerate} % \item \cs{predisplaypenalty} % \item \cs{abovedisplayskip} % \item equation number box % \item equation body % \item \cs{postdisplaypenaltly} % \item \cs{belowdisplayskip} %\end{enumerate} % % % \section{Technical notes on Equation Layouts} % \textbf{MJD [1998/12/28]} % % \providecommand{\qq}[1]{\textquotedblleft#1\textquotedblright} % \providecommand{\mdash}{\textemdash} % \providecommand{\ndash}{\textendash} % % \newcommand{\ititle}[1]{\textit{#1}} % % \newcommand{\LR}[2][.4]{% % \framebox[#1\displaywidth]{$\displaystyle{}#2$}% % } % % \newcommand{\LHS}[1]{\LR[\relifactor]{#1}} % % \newdimen\relindent \newdimen\rhswd % % \newcommand{\dwline}{% % \hbox to\curdw{\vrule height1ex % \leaders\hrule height.55ex depth-.45ex\hfil % \tiny \space display width % \leaders\hrule height.55ex depth-.45ex\hfil % \vrule height1ex}% % } % % \newenvironment{layout}[1][.15]{% % \noindent % $$\edef\curdw{\the\displaywidth}% % \def\relifactor{#1}% % \gdef\layoutcr{\cr}\def\\{\layoutcr}% % \binoppenalty 10000 \relpenalty 10000 % \setbox8\vbox\bgroup % \advance\baselineskip .35\baselineskip % \advance\lineskip .35\baselineskip \lineskiplimit\lineskip % \relindent=#1\displaywidth % \rhswd=\displaywidth \advance\rhswd-\relindent % \global\row 0 \gdef\rhsskew{}% % \halign\bgroup \global\advance\row 1 $\hfil\displaystyle{}##$&% % \ifnum\row>1 \rhsskew \fi $\displaystyle{}##\hfil$\cr % }{% % \crcr\egroup\egroup % \vcenter{\halign{\hfil##\hfil\cr % \hbox{\hss\dwline\hss}\cr\noalign{\vskip.6\baselineskip}\box8 \cr}}% % $$\relax % \ignorespacesafterend % } % % \newcommand{\stagger}{\omit\span\gdef\layoutcr{\cr\omit\span}} % % \newcount\row % % \newcommand{\rhsskew}{} % \newcommand{\skewleft}[1]{\gdef\rhsskew{\kern-#1\relax}} % % % \subsection{Misc examples} % % Let us consider which of these have 50\% or more of wasted whitespace % \emph{within the bounding box of the visible material}. % \begin{layout}[.4] % \LHS{L}&=\LR[.35]{R_{1}}\\ % &=\LR[.25]{R_{1}} % \end{layout} % % \subsection{Ladder and step layouts} % % \subsubsection{Straight ladder layout} % This is distinguished by a relatively short LHS and one or more RHS's of % any length. % \begin{layout} % \LHS{L} &= \LR[.5]{R_{1}}\\ % &=\LR[.3]{R_{2}}\\ % &=\LR[.25]{R_{3}}\\ % &\qquad\ldots % \end{layout} % The simplest kind of equation that fits on one line and has only one RHS % may be viewed as a trivial subcase of the straight ladder layout: % \begin{layout} % \LHS{L} &= \LR[.5]{R} % \end{layout} % If some of the RHS's are too wide to fit on a single line they may be % broken at binary operator symbols such as plus or minus. This is still % classified as a straight ladder layout if none of the fragments intrude % into the LHS column, because the underlying parshape is the same. % \begin{layout} % \LHS{L} &= \LR[.4]{R_{1a}}\\ % &\quad +\LR[.6]{R_{1b}}\\ % &=\LR[.3]{R_{2}}\\ % &=\LR[.25]{R_{3a}}\\ % &\quad +\LR[.45]{R_{3b}}\\ % &\quad +\LR[.54]{R_{3c}}\\ % &\qquad\ldots % \end{layout} % % \subsubsection{Skew ladder layout} % \begin{layout}[.5] % \skewleft{.35\displaywidth} % \LHS{L}&= \LR[.3]{R_{1}}\\ % &=\LR[.6]{R_{2}}\\ % &=\LR[.25]{R_{3}}\\ % &\qquad\ldots % \end{layout} % In a skew ladder layout, the combined LHS width plus width of $R_{1}$ % does not exceed the available width, but one of the other RHS's is so % wide that aligning its relation symbol with the others cannot be done % without making it run over the right margin: $\mbox{width}(L) + % \mbox{width}_{\mathrm{max}}(R_{i})>\mbox{width}_{\mathrm{avail}}$. In % that case we next try aligning all but the first relation symbol, % allowing all the $R_{i}$ after $R_1$ to shift leftward. % % \subsubsection{Drop ladder layout} % \begin{layout}[.6] % \makebox[.15\displaywidth][l]{\LHS{L}}\\ % &= \LR[.6]{R_{1}}\\ % &=\LR[.3]{R_{2}}\\ % &=\LR[.25]{R_{3}}\\ % &\qquad\ldots % \end{layout} % The drop ladder layout is similar to the skew ladder layout but with the % width of $R_1$ too large for it to fit on the same line as the LHS. Then % we move $R_1$ down to a separate line and try again to align all the % relation symbols. Note that this layout consumes more vertical space % than the skew ladder layout. % % \subsubsection{Step layout} % \begin{layout}[.6] % \stagger % \LHS{R_{a}}\\ % \qquad + \LR[.7]{R_{b}}\\ % \qquad\qquad + \LR[.6]{R_{c}}\\ % \qquad\qquad\qquad + \LR[.45]{R_{d}}\\ % \qquad\qquad\qquad\qquad\ldots % \end{layout} % The chief characteristic of the step layout is that there is no relation % symbol, so that the available line breaks are (usually) all at binary % operator symbols. Let $w_1$ and $w_l$ be the widths of the first and % last fragments. We postulate that the ideal presentation is as follows: % Choose a small stairstep indent $I$ (let's say 1 or 2 em). We want the % last fragment to be offset at least $I$ from the start of the first % fragment, and to end at least $I$ past the end of the first fragment. If % there are only two lines these requirements determine a target width % $w_T=\max(w_1+I,w_l+I)$. If there are more than two lines ($l>2$) then % use $w_T = \max(w_1 + (l-1)I, w_l+I, w_{\mathrm{avail}}$ and reset $I$ % to $w_T/(l-1)$ if $w_T = w_{\mathrm{avail}}$. % % Furthermore, we would like the material to be distributed as evenly as % possible over all the lines rather than leave the last line exceedingly % short. If the total width is $1.1(\mbox{width}_{\mathrm{avail}})$, we % don't want to have .9 of that on line 1 and .2 of it on line 2: % \begin{layout}[.9] % \stagger % \LHS{R_{a}\hfil+\hfil R_{b}\hfil+\hfil R_{c}}\\ % \qquad + \LR[.1]{R_{d}} % \end{layout} % Better to split it as evenly as possible, if the available breakpoints % permit. % \begin{layout}[.5] % \stagger % \LHS{R_{a}\hfil+\hfil R_{b}}\\ % \qquad + \LR[.5]{R_{c}\hfil+\hfil R_d} % \end{layout} % A degenerate step layout may arise if an unbreakable fragment of % the equation is so wide that indenting it to its appointed starting % point would cause it to run over the right margin. In that case, we want % to shift the fragment leftward just enough to bring it within the right % margin: % \begin{layout}[.6] % \stagger % \LHS{L_{a}}\\ % \quad + \LR[.8]{L_{b}}\\ % \qquad + \LR[.7]{L_{c}}\\ % \; + \LR[.87]{L_{d}}\\ % \qquad\ldots % \end{layout} % And then we may want to regularize the indents as in the drop ladder % layout. Let's call this a dropped step layout: % \begin{layout}[.6] % \stagger % \LHS{L_{a}}\\ % \quad + \LR[.8]{L_{b}}\\ % \quad + \LR[.7]{L_{c}}\\ % \quad + \LR[.87]{L_{d}}\\ % \qquad\ldots % \end{layout} % % \subsection{Strategy} % % Here is the basic procedure for deciding which equation layout to use, % before complications like equation numbers and delimiter clearance come % into the picture. Let $A$ be the available width, $w_{\mathrm{total}}$ % the total width of the equation contents, $w(L)$ the width of the % left-hand side, $w_{\max}(R)$ the max width of the right-hand sides, $I$ % the standard indent for step layout, and $O$ the standard offset for % binary operators if a break occurs in the middle of an RHS. Also let % $t_L$ and $t_R$ represent certain thresholds for the width of the LHS or % the RHS at which a layout decision may change, as explained below. % % \begin{small} % \begin{enumerate} % \renewcommand{\labelenumi}{(\theenumi)} % \item \ititle{Does everything fit on one line?}\label{i:LR} % $w_{\mathrm{total}}\leq A$? % % Yes: print the equation on a single line (done). % % No: Check whether the equation has both LHS and RHS (\ref{i:lhs-check}). % % \item \ititle{Is there a left-hand side?}\label{i:lhs-check} % Are there any relation symbols in the equation? % % Yes: Try a ladder layout (\ref{i:ladder}). % % No: Try a step layout (\ref{i:step}). % % \item\ititle{Does the LHS leave room to fit the widest RHS?}\label{i:ladder} % $w(L)+w_{\max}(R)1$) is wider than % $A-I$; try an almost-columnar layout (\ref{i:almost-columnar}). % % \item\ititle{Drop ladder layout}\label{i:drop} % Set up a parshape [0pt $w(L)$ $I$ $A-I$] and run a trial break. % This is the same parshape as for a skew ladder layout except that the % width of the first line is limited to the LHS width, so that the RHS is % forced to drop down to the next line. % % \ititle{Line breaks OK?} % % Yes: Drop ladder layout succeeded (done). % % No: One of the unbreakable fragments of the $R_i$ ($i>1$) is wider than % $A-I$; try an almost-columnar layout (\ref{i:almost-columnar}). % % \item\ititle{Almost-columnar layout}\label{i:almost-columnar} % This presupposes a trial break that yielded a series of expressions or % fragments, one per line. Let $w(F)$ denote the width of the first % fragment and $w(R_i)$ the widths of the remaining fragments. % Set up a parshape [0pt $w(F)$ $A-w_{\max}(R_i)$ $w_{\max}(R_i)$]: in other % words, set the first line flush left and the longest line flush right % and all other lines indented to the same position as the longest line. % But as a matter of fact there is one other refinement for extreme cases: % if $w_{\max}(R_i)>A$ then the parshape can be simplified without loss to % [0pt $w(F)$ 0pt $A$]\mdash for that is the net effect of substituting % $\min(A,w_{\max})$ in stead of $w_{\max}$. % (Done.) % % \item\ititle{Step layout}\label{i:step} Set target width $w_T$ to $A - % 2I$. Set parshape to [0pt $w_T$ $I$ $w_T -I$ $2I$ $w_T -2I$ \ldots\ % $(l-1)I$ $w_T - (l-1)I$], where $l=\lceil w_{\mathrm{total}}/A\rceil$ % is the expected number of lines that will be required. Trial break % with that parshape in order to find out the width of the last line. % % \ititle{Indents OK?} % % Yes: Step layout succeeded (done). % % No: One of the fragments is too wide to fit in % the allotted line width, after subtracting the indent specified by the % parshape. Try a dropped step layout (\ref{i:drop-step}) % % \item\ititle{Dropped step layout}\label{i:drop-step} Set up a parshape % [0pt $A$ $I$ $A-I$] and run a trial break. Note that this is actually % the same parshape as for a skew ladder layout. % % \ititle{Line breaks OK?} % % Yes: Dropped step layout succeeded (done). % % No: One of the unbreakable fragments of the $R_i$ ($i>1$) is wider than % $A-I$; as a last resort try an almost-columnar layout (\ref{i:almost-columnar}). % % \end{enumerate} % \par\end{small} % % \section{To do} % % \begin{itemize} % \item Handling of QED % \item Space between \verb'\end{dmath}' and following punctuation will % prevent the punctuation from being drawn into the equation. % \item Overriding the equation layout % \item Overriding the placement of the equation number % \item \qq{alignid} option for more widely separated equations where % shared alignment is desired (requires two passes) % \item Or maybe provide an \qq{alignwidths} option where you give % lhs/rhs width in terms of ems? And get feedback later on discrepancies % with the actual measured contents? % \item \cs{intertext} not needed within dgroup! But currently there are % limitations on floating objects within dgroup. % \item \verb'align={1}' or 2, 3, 4 expressing various levels of demand % for group-wide alignment. Level 4 means force alignment even if some % lines then have to run over the right margin! Level 1, the default, % means first break LHS-RHS equations as if it occurred by itself, then % move them left or right within the current line width to align them if % possible. Levels 2 and 3 mean try harder to align but give up if % overfull lines result. % \item Need an \cs{hshift} command to help with alignment of % lines broken at a discretionary times sign. Also useful for adjusting % inside-delimiter breaks. % \end{itemize} % % \StopEventually{} % \clearpage % \newgeometry{left=4cm} % \part{Implementation} % % % The package version here is Michael's v0.90 updated by Bruce % Miller. Michael's changes between v0.90 and his last v0.94 will be % incorporated where applicable. % % % The original sources of \pkg{breqn} and related files exist in a % non-dtx format devised by Michael Downes himself. % Lars Madsen has kindly written a Perl script for transforming the % original source files into near-perfect dtx state, requiring only % very little hand tuning. Without his help it would have been nigh % impossible to incorporate the original sources with Michael's % comments. A big, big thank you to him. % % % % \section{Introduction} % The \pkg{breqn} package provides environments % \env{dmath}, \env{dseries}, and \env{dgroup} for % displayed equations with \emph{automatic line breaking}, % including automatic indention of relation symbols and binary operator % symbols at the beginning of broken lines. These environments % automatically pull in following punctuation so that it can be written in % a natural way. The \pkg{breqn} package also provides a % \env{darray} environment similar to the \env{array} % environment but using \cs{displaystyle} for all the array cells and % providing better interline spacing (because the vertical ruling % feature of \env{array} is dropped). % These are all autonumbered environments like \env{equation} % and have starred forms that don't add a number. For a more % comprehensive and detailed description of the features and intended % usage of the \pkg{breqn} package see \fn{breqndoc.tex}. % % % % % \section{Strategy} % Features of particular note are the ability to have % linebreaks even within a \cs{left} \ndash \cs{right} pair of % delimiters, and the automatic alignment on relations and binary % operators of a split equation. To make \env{dmath} handle % all this, we begin by setting the body of the equation in a special % paragraph form with strategic line breaks whose purpose is not to % produce line breaks in the final printed output but rather to mark % significant points in the equation and give us entry points for % unpacking \cn{left} \ndash \cn{right} boxes. % After the initial typesetting, we take the resulting stack of line % fragments and, working backward, splice them into a new, single-line % paragraph; this will eventually be poured into a custom parshape, after % we do some measuring to calculate what that parshape should be. % This streamlined horizontal list may contain embedded material % from user commands intended to alter line breaks, horizontal alignment, % and interline spacing; such material requires special handling. % % To make the `shortskip' possibility work even for % multiline equations, we must plug in a dummy \tex display to give us % the value of \cs{predisplaysize}, and calculate for ourselves when % to apply the short skips. % % In order to measure the equation body and do various % enervating calculations on whether the equation number will fit and so % on, we have to set it in a box. Among other things, this means % that we can't unhbox it inside \dbldollars \dots \dbldollars , or % even \verb"$" \dots \verb"$": \tex doesn't allow you to % \cs{unhbox} in math mode. But we do want to unhbox it rather % than just call \cs{box}, otherwise we can't take advantage of % available shrink from \cs{medmuskip} to make equations shrink to % fit in the available width. So even for simple one-line equations % we are forced to fake a whole display without going through \tex 's % primitive display mechanism (except for using it to get % \cs{predisplaysize} as mentioned above). % % % In the case of a framed equation body, the current implementation is % to set the frame in a separate box, of width zero and height zero, % pinned to the upper left corner of the equation body, and then print the % equation body on top of it. % For attaching an equation number it would be much simpler to wrap % the equation body in the frame and from then on treat the body as a % single box instead of multiple line boxes. % But I had a notion that it might be possible some day to support % vertical stretching of the frame. % % % % % \section{Prelim} % % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e} % \end{macrocode} % % Declare package name and date. % \begin{macrocode} \RequirePackage{expl3} \ProvidesExplPackage{breqn}{2021/10/28}{0.98l}{Breaking equations} % \end{macrocode} % Regrettably, \pkg{breqn} is internally a mess, so we have to take % some odd steps. % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % % \section{Package options} % % First we need to get the catcodes sorted out. % \begin{macrocode} \edef\breqnpopcats{% \catcode\number`\"=\number\catcode`\" \relax} \AtEndOfPackage{\breqnpopcats}% \catcode`\^=7 \catcode`\_=8 \catcode`\"=12 \relax \DeclareOption{mathstyleoff}{% \PassOptionsToPackage{mathstyleoff}{flexisym}% } % \end{macrocode} % Process options. % \begin{macrocode} \ProcessOptions\relax % \end{macrocode} % % % % % \section{Required packages} % % Although breqn can be loaded without amsmath, there's not much point, and explicitly % loading amsmath here prevents loading-order issues later. % \begin{macrocode} \RequirePackage{amsmath} % \end{macrocode} % % Similarly, if graphicx is loaded atbegindocument there is a catcode clash, so load it here too. % (see test file 00-clash-1.lvt) % \begin{macrocode} \RequirePackage{graphicx} % \end{macrocode} % % The \pkg{flexisym} package makes it possible to attach % extra actions to math symbols, in particular mathbin, mathrel, mathopen, % and mathclose symbols. % Normally it would suffice to call \cs{RequirePackage} without % any extra testing, but the nature of the package is such that it is % likely to be called earlier with different (no) options. % Then is it really helpful to be always warning the user about % \quoted{Incompatible Package Options!}? % I don't think so. % \begin{macrocode} \@ifpackageloaded{flexisym}{}{% \RequirePackage{flexisym}[2009/08/07] \edef\breqnpopcats{\breqnpopcats \catcode\number`\^=\number\catcode`\^ \catcode\number`\_=\number\catcode`\_ }% \catcode`\^=7 \catcode`\_=8 \catcode`\"=12 \relax } % \end{macrocode} % The \pkg{keyval} package for handling equation options and % \pkg{calc} to ease writing computations. % \begin{macrocode} \RequirePackage{keyval,calc}\relax % \end{macrocode} % % % \begin{macro}{\breqnsetup} % \begin{macrocode} \newcommand{\breqnsetup}[1]{\setkeys{breqn}{#1}} % \end{macrocode} % \end{macro} % % % % % \section{Some useful tools} % % % % \begin{macro}{\MaybeRawNoindent} % Breqn does a lot of low-level paragraph stuff which iesn't % supposed to execute paragraph hooks, so with a newer \LaTeX{} it % needs to run the versions that prevent the hooks from executing. % \begin{macrocode} \providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} % \end{macrocode} % % \begin{macrocode} \IfFormatAtLeastTF{2021/06/01} {% \def\MaybeRawNoindent{\ifvmode\expandafter\RawNoindent\fi}% }% {% \let\MaybeRawNoindent\noindent \let\RawParEnd\@@par } % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@nx} % \begin{macro}{\@xp} % The comparative brevity of \cs{@nx} and \cs{@xp} is % valuable not so much for typing convenience as for reducing visual % clutter in code sections that require a lot of expansion control. % \begin{macrocode} \let\@nx\noexpand \let\@xp\expandafter % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@emptytoks} % Constant empty token register, analogous to \cs{@empty}. % \begin{macrocode} \@ifundefined{@emptytoks}{\newtoks\@emptytoks}{} % \end{macrocode} % \end{macro} % % % \begin{macro}{\f@ur} % Constants 0\ndash 3 are provided in plain \tex , but not 4. % \begin{macrocode} \chardef\f@ur=4 % \end{macrocode} % \end{macro} % % % \begin{macro}{\inf@bad} % \cs{inf@bad} is for testing box badness. % \begin{macrocode} \newcount\inf@bad \inf@bad=1000000 % \end{macrocode} % \end{macro} % % % \begin{macro}{\maxint} % % We want to use \cs{maxint} rather than coerced % \cs{maxdimen} for \cs{linepenalty} in one place. % \begin{macrocode} \newcount\maxint \maxint=2147483647 % \end{macrocode} % \end{macro} % % % \begin{macro}{\int@a} % \begin{macro}{\int@b} % \begin{macro}{\int@b} % % Provide some shorter aliases for various scratch registers. % \begin{macrocode} \let\int@a=\@tempcnta \let\int@b=\@tempcntb \let\int@c=\count@ % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\dim@a} % \begin{macro}{\dim@b} % \begin{macro}{\dim@c} % \begin{macro}{\dim@d} % \begin{macro}{\dim@e} % \begin{macro}{\dim@A} % % Same for dimen registers. % \begin{macrocode} \let\dim@a\@tempdima \let\dim@b\@tempdimb \let\dim@c\@tempdimc \let\dim@d\dimen@ \let\dim@e\dimen@ii \let\dim@A\dimen@i % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\skip@a} % \begin{macro}{\skip@b} % \begin{macro}{\skip@c} % % Same for skip registers. % \begin{macrocode} \let\skip@a\@tempskipa \let\skip@b\@tempskipb \let\skip@c\skip@ % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\toks@a} % \begin{macro}{\toks@b} % \begin{macro}{\toks@c} % \begin{macro}{\toks@d} % \begin{macro}{\toks@e} % \begin{macro}{\toks@f} % % Same for token registers. % \begin{macrocode} \let\toks@a\@temptokena \let\toks@b\toks@ \toksdef\toks@c=2 \toksdef\toks@d=4 \toksdef\toks@e=6 \toksdef\toks@f=8 % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\abs@num} % We need an absolute value function for comparing % penalties. % \begin{macrocode} \def\abs@num#1{\ifnum#1<\z@-\fi#1} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@ifnext} % \begin{macro}{\@ifnexta} % The \cs{@ifnext} function is a variation of % \cs{@ifnextchar} that doesn't skip over intervening whitespace. % We use it for the optional arg of \dbslash inside % \env{dmath} \etc because we don't want % unwary users to be tripped up by an unexpected attempt on \latex 's part % to interpret a bit of math as an optional arg: % \begin{literalcode} % \begin{equation} % ...\\ % [z,w]... % \end{equation} % \end{literalcode} % . % \begin{macrocode} \def\@ifnext#1#2#3{% \let\@tempd= #1\def\@tempa{#2}\def\@tempb{#3}% \futurelet\@tempc\@ifnexta } % \end{macrocode} % Switch to \cs{@tempa} iff the next token matches. % \begin{macrocode} \def\@ifnexta{\ifx\@tempc\@tempd \let\@tempb\@tempa \fi \@tempb} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\breqn@ifstar} % Similarly let's remove space-skipping from \cs{@ifstar} % because in some rare case of \dbslash inside an equation, followed by % a space and a \verb"*" where the \verb"*" is intended as the math % binary operator, it would be a disservice to gobble the star as an % option of the \dbslash command. In all other contexts the chance % of having a space \emph{before} the star is extremely small: either % the command is a control word which will get no space token after it in % any case because of \tex 's tokenization rules; or it is a control % symbol such as \dbslash \verb"*" which is exceedingly unlikely to be % written as \dbslash \verb"*" by any one who really wants the % \verb"*" to act as a modifier for the \dbslash command. % \begin{macrocode} \def\breqn@ifstar#1#2{% \let\@tempd*\def\@tempa*{#1}\def\@tempb{#2}% \futurelet\@tempc\@ifnexta } % \end{macrocode} % \end{macro} % % % \begin{macro}{\breqn@optarg} % Utility function for reading an optional arg % \emph{without} skipping over any intervening spaces. % \begin{macrocode} \def\breqn@optarg#1#2{\@ifnext[{#1}{#1[#2]}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@True} % \begin{macro}{\@False} % \begin{macro}{\@Not} % \begin{macro}{\@And} % After \verb"\let\foo\@True" the test % \begin{literalcode} % \if\foo % \end{literalcode} % evaluates to true. Would rather avoid \cs{newif} because it % uses three csnames per Boolean variable; this uses only one. % \begin{macrocode} \def\@True{00} \def\@False{01} \def\@Not#1{0\ifcase#11 \or\@xp 1\else \@xp 0\fi} \def\@And#1#2{0\ifcase#1#2 \@xp 0\else \@xp 1\fi} \def\@Or#1#2{0\ifnum#1#2<101 \@xp 0\else \@xp 1\fi} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % % \begin{macrocode} \def\theb@@le#1{\if#1 True\else False\fi} % \end{macrocode} % \begin{macro}{\freeze@glue} % % Remove the stretch and shrink from a glue register. % \begin{macrocode} \def\freeze@glue#1{#11#1\relax} % \end{macrocode} % \end{macro} % \begin{macro}{\z@rule} % \begin{macro}{\keep@glue} % Note well % the intentional absence of \cs{relax} at the end of the replacement % text of \cs{z@rule}; use it with care. % \begin{macrocode} \def\z@rule{\vrule\@width\z@}% no \relax ! use with care % \end{macrocode} % Different ways to keep a bit of glue from disappearing at the % beginning of a line after line breaking: % \begin{itemize} % \item Zero-thickness rule % \item Null character % \item \cs{vadjust}\verb"{}" (\texbook , Exercise ??) % \end{itemize} % The null character idea would be nice except it % creates a mathord which then screws up math spacing for \eg a following % unary minus sign. (the vrule \emph{is} transparent to % the math spacing). The vadjust is the cheapest in terms of box % memory\mdash it vanishes after the pass through \tex 's % paragrapher. % It is what I would have used, except that the equation contents get % run through two paragraphing passes, once for breaking up LR boxes and % once for the real typesetting. % If \cs{keep@glue} were done with an empty vadjust, it would % disappear after the first pass and\mdash in particular\mdash the % pre-bin-op adjustment for relation symbols would disappear at a line break. % \begin{macrocode} \def\keep@glue{\z@rule\relax} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\replicate} % % This is a fully expandable way of making N copies of a token % list. % Based on a post of David Kastrup to comp.text.tex circa January % 1999. % The extra application of \cs{number} is needed for maximal % robustness in case the repeat count N is given in some weird \tex form % such as \verb|"E9| or \verb|\count9|. % \begin{macrocode} % usage: \message{H\replicate{5}{i h}ow de doo dee!} \begingroup \catcode`\&=11 \gdef\replicate#1{% \csname &\expandafter\replicate@a\romannumeral\number\number#1 000q\endcsname } \endgroup % \end{macrocode} % \end{macro} % % % \begin{macro}{\replicate@a} % \begin{macrocode} \long\def\replicate@a#1#2\endcsname#3{#1\endcsname{#3}#2} % \end{macrocode} % \end{macro} % % % \begin{macro}{\8m}% fix % \begin{macrocode} \begingroup \catcode`\&=11 \long\gdef\&m#1#2{#1\csname \endcsname{#1}} \endgroup % \end{macrocode} % \end{macro} % % % \begin{macro}{\8q}% fix % \begin{macrocode} \@xp\let\csname\string &q\endcsname\@gobble % \end{macrocode} % \end{macro} % % \begin{macro}{\mathchars@reset} % % Need to patch up this function from flexisym a little, to better % handle certain constructed symbols like \cs{neq}. % \begin{macrocode} \ExplSyntaxOn \g@addto@macro\mathchars@reset{% %\let\@symRel\@secondoftwo \let\@symBin\@secondoftwo %\let\@symDeL\@secondoftwo \let\@symDeR\@secondoftwo %\let\@symDeB\@secondoftwo \cs_set_eq:NN \math_csym_Rel:Nn \use_ii:nn \cs_set_eq:NN \math_csym_Bin:Nn \use_ii:nn \cs_set_eq:NN \math_csym_DeL:Nn \use_ii:nn \cs_set_eq:NN \math_csym_DeR:Nn \use_ii:nn \cs_set_eq:NN \math_csym_DeB:Nn \use_ii:nn } \ExplSyntaxOff % \end{macrocode} % \end{macro} % % % \begin{macro}{\@saveprimitive} % If some preceding package redefined one of the % primitives that we must change, we had better do some checking to make % sure that we are able to save the primitive meaning for internal use. % This is handled by the \cs{@saveprimitive} function. We % follow the example of \cs{@@input} where the primitive meaning is % stored in an internal control sequence with a \verb"@@" prefix. % Primitive control sequences can be distinguished by the fact that % \cs{string} and \cs{meaning} return the same information. % Well, not quite all: \cs{nullfont} and \cs{topmark} % and the other \cs{...mark} primitives being the exceptions. % \begin{macrocode} \providecommand{\@saveprimitive}[2]{% \begingroup \edef\@tempa{\string#1}\edef\@tempb{\meaning#1}% \ifx\@tempa\@tempb \global\let#2#1% \else % \end{macrocode}% % If [arg1] is no longer primitive, then we are in trouble unless % [arg2] was already given the desired primitive meaning somewhere % else. % \begin{macrocode} \edef\@tempb{\meaning#2}% \ifx\@tempa\@tempb \else \@saveprimitive@a#1#2% \fi \fi \endgroup } % \end{macrocode} % Aux function, check for the special cases. % Most of the time this branch will be skipped so we can % stuff a lot of work into it without worrying about speed costs. % \begin{macrocode} \providecommand\@saveprimitive@a[2]{% \begingroup \def\@tempb##1#1##2{\edef\@tempb{##2}\@car{}}% \@tempb\nullfont{select font nullfont}% \topmark{\string\topmark:}% \firstmark{\string\firstmark:}% \botmark{\string\botmark:}% \splitfirstmark{\string\splitfirstmark:}% \splitbotmark{\string\splitbotmark:}% #1{\string#1}% \@nil % for the \@car \edef\@tempa{\expandafter\strip@prefix\meaning\@tempb}% \edef\@tempb{\meaning#1}% \ifx\@tempa\@tempb \global\let#2#1% \else \PackageError{breqn}% {Unable to properly define \string#2; primitive \noexpand#1no longer primitive}\@eha \fi \fi \endgroup } % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@math} % \begin{macro}{\@@endmath} % \begin{macro}{\@@display} % \begin{macro}{\@@enddisplay} % Move the math-start and math-end functions into control % sequences. If I were redesigning \tex I guess I'd put these % functions into primitive control words instead of linking them to a % catcode. That way \tex would not have to do the special % lookahead at a \verb"$" to see if there's another one coming up. % Of course that's related to the question of how to provide user % shorthand for common constructions: \tex , or an editing interface of % some sort. % \begin{macrocode} \begingroup \catcode`\$=\thr@@ % just to make sure \global\let\@@math=$ \gdef\@@display{$$}% $$$ \endgroup \let\@@endmath=\@@math \let\@@enddisplay=\@@display % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\@@insert} % \begin{macro}{\@@mark} % \begin{macro}{\@@vadjust} % Save the primitives \cs{vadjust}, \cs{insert}, % \cs{mark} because we will want to change them locally during % equation measuring to keep them from getting in the way of our vertical % decomposition procedures. We follow the example of % \cs{@@input}, \cs{@@end}, \cs{@@par} where the primitive % meaning is stored in an internal control sequence with a \verb"@@" % prefix. % \begin{macrocode} \@saveprimitive\vadjust\@@vadjust \@saveprimitive\insert\@@insert \@saveprimitive\mark\@@mark % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % % % \section{Debugging} % Debugging help. % \begin{macrocode} %<*trace> \errorcontextlines=2000\relax \typeout{BREQN DEBUGGING MODE ACTIVE} % \end{macrocode} % % \begin{macro}{\breqn@debugmsg} % Print a debugging message. % \begin{macrocode} \long\def\breqn@debugmsg#1{\GenericWarning{||}{||=\space#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\debugwr} % Sometimes the newline behavior of \cs{message} is % unsatisfactory; this provides an alternative. % \begin{macrocode} \def\debugwr#1{\immediate\write\sixt@@n{||= #1}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\debug@box} % Record the contents of a box in the log file, without stopping. % \begin{macrocode} \def\debug@box#1{% \batchmode{\showboxbreadth\maxdimen\showboxdepth99\showbox#1}% \errorstopmode } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eqinfo} % Show lots of info about the material before launching into the % trials. % \begin{macrocode} \def\eqinfo{% \debug@box\EQ@copy \wlog{!! EQ@copy: \the\wd\EQ@copy\space x \the\ht\EQ@copy+\the\dp\EQ@copy }% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\debug@para} % Check params that affect line breaking. % \begin{macrocode} \def\debug@para{% \debugwr{\hsize\the\hsize, \parfillskip\the\parfillskip}% \breqn@debugmsg{\leftskip\the\leftskip, \rightskip\the\rightskip}% \breqn@debugmsg{\linepenalty\the\linepenalty, \adjdemerits\the\adjdemerits}% \breqn@debugmsg{\pretolerance\the\pretolerance, \tolerance\the\tolerance, \parindent\the\parindent}% } % \end{macrocode} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % % % % \section{The \cs{listwidth} variable} % The dimen variable \cs{listwidth} is \cs{linewidth} % plus \cs{leftmargin} plus \cs{rightmargin}, which is typically % less than \cs{hsize} if the list depth is greater than one. % In case a future package will provide this variable, define it only % if not yet defined. % \begin{macrocode} \@ifundefined{listwidth}{\newdimen\listwidth}{} \listwidth=\z@ % \end{macrocode} % % % % % \section{Parameters} % % Here follows a list of parameters needed. % % \begin{macro}{\eqfontsize} % \begin{macro}{\eqcolor} % \begin{macro}{\eqmargin} % \begin{macro}{\eqindent} % \begin{macro}{\eqbinoffset} % \begin{macro}{\eqnumside} % \begin{macro}{\eqnumplace} % \begin{macro}{\eqnumsep} % \begin{macro}{\eqnumfont} % \begin{macro}{\eqnumform} % \begin{macro}{\eqnumsize} % \begin{macro}{\eqnumcolor} % \begin{macro}{\eqlinespacing} % \begin{macro}{\eqlineskip} % \begin{macro}{\eqlineskiplimit} % \begin{macro}{\eqstyle} % \begin{macro}{\eqinterlinepenalty} % \begin{macro}{\intereqpenalty} % \begin{macro}{\intereqskip} % % Note: avoid M, m, P, p because they look like they might be the % start of a keyword \quoted{minus} or \quoted{plus}. Then % \tex looks further to see if the next letter is i or l. And if % the next thing is an undefined macro, the attempt to expand the macro % results in an error message. % \begin{macrocode} \def\eqfontsize{} % Inherit from context [NOT USED?] \def\eqcolor{black} % Default to black [NOT USED?] \newdimen\eqnumsep \eqnumsep=10pt % Min space between equ number and body \newdimen\eqmargin \eqmargin=8pt % For `multline' gap emulation % \end{macrocode} % The \cs{eqindent} and \cs{eqnumside} variables need to % have their values initialized from context, actually. But % that takes a bit of work, which is postponed till later. % \begin{macrocode} \def\eqindent{C}% % C or I, centered or indented \def\eqnumside{R}% % R or L, right or left \def\eqnumplace{M}% % M or T or B, middle top or bottom % \end{macrocode} % Typesetting the equation number is done thus: % \begin{literalcode} % {\eqnumcolor \eqnumsize \eqnumfont{\eqnumform{\eq@number}}} % \end{literalcode} % . % \begin{macrocode} %d\eqnumfont{\upshape}% % Upright even when surrounding text is slanted \def\eqnumfont{}% % Null for easier debugging [mjd,1997/09/26] \def\eqnumform#1{(#1\@@italiccorr)} % Add parens \def\eqnumsize{} % Allow numbers to have different typesize ... % \end{macrocode} % Tricky questions on \cs{eqnumsize}. Should the default % be \cs{normalsize}? Then the user can scale down the % equation body with \cs{small} and not affect the equation % number. Or should the default be empty? Then in large % sections of smaller text, like the dangerous bend stuff in % \emph{\TeX book}, the equation number size will keep in synch % with the context. % Maybe need an \cs{eqbodysize} param as well to allow separating % the two cases. % \begin{macrocode} \def\eqnumcolor{} % ... or color than eq body e.g. \color{blue} \newlength\eqlinespacing \eqlinespacing=14pt plus2pt % Base-to-base space between lines \newlength\eqlineskip \eqlineskip=3pt plus2pt % Min space if eqlinespacing too small \newdimen\eqlineskiplimit \eqlineskiplimit=2pt % Threshold for switching to eqlineskip % \end{macrocode} % The value of \cs{eqbinoffset} should include a negative shrink % component that cancels the shrink component of medmuskip, otherwise % there can be a noticeable variation in the indent of adjacent lines if % one is shrunken a lot and the other isn't. % \begin{macrocode} \newmuskip \eqbinoffset \eqbinoffset=15mu minus-3mu % Offset from mathrel alignment pt for mathbins \newmuskip\eqdelimoffset \eqdelimoffset=2mu % Additional offset for break inside delims \newdimen\eqindentstep \eqindentstep=8pt % Indent used when LHS wd is n/a or too large \newtoks\eqstyle % Customization hook \newcount\eqbreakdepth \eqbreakdepth=2 % Allow breaks within delimiters to this depth \newcount \eqinterlinepenalty \eqinterlinepenalty=10000 % No page breaks between equation lines \newcount \intereqpenalty \intereqpenalty=1000 % Pagebreak penalty between equations [BRM: Was \@M] \newlength \intereqskip \intereqskip=3pt plus2pt % Additional vert space between equations \newcount\prerelpenalty \prerelpenalty=-\@M % Linebreak penalty before mathrel symbols \newcount\prebinoppenalty \prebinoppenalty=888 % Linebreak penalty before mathbins % \end{macrocode} % When breaking equations we never right-justify, so a stretch % component of the muskip is never helpful and sometimes it is definitely % undesirable. Note that thick\slash medmuskips frozen inside a % fraction or radical may turn out noticeably larger than neighboring % unfrozen ones. Nonetheless I think this way is the best % compromise short of a new \tex that can make those built-up objects % shrink horizontally in proportion; the alternative is to pretty much % eliminate the shrink possibility completely in displays. % \begin{macrocode} \newmuskip \Dmedmuskip \Dmedmuskip=4mu minus 3mu % medmuskip in displays \newmuskip \Dthickmuskip \Dthickmuskip=5mu minus 2mu % thickmuskip in displays % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % And now some internal variables. 1997/10/22: some of % these are dead branches that need to be pruned. % % MH: Started cleaning up a bit. No more funny loops. % \begin{macrocode} \def\eq@number{} % Internal variable \newlength\eqleftskip \eqleftskip=\@centering % Space on the left [NOT USED?] \newlength\eqrightskip \eqrightskip=\@centering % Space on the right [NOT USED?] \newlength\eq@vspan \eq@vspan=\z@skip % Glue used to vcenter the eq number \newmuskip\eq@binoffset \eq@binoffset=\eqbinoffset % Roughly, \eqbinoffset + \eqdelimoffset \newsavebox\EQ@box % Storage for equation body \newsavebox\EQ@copy % For eq body sans vadjust/insert/mark material \newsavebox\EQ@numbox % For equation number \newdimen\eq@wdNum % width of number + separation [NEW] \newsavebox\GRP@numbox % For group number [NEW] \newdimen\grp@wdNum % width of number + separation [NEW] %%B\EQ@vimbox % Vadjust, insert, or mark material %%B\EQ@vimcopy % Spare copy of same %%B\eq@impinging % Temporary box for measuring number placement \newcount \eq@lines % Internal counter, actual number of lines \newcount \eq@curline % Loop counter \newcount \eq@badness % Used in testing for overfull lines \newcount \EQ@vims % For bookkeeping \def\@eq@numbertrue{\let\eq@hasNumber\@True}% \def\@eq@numberfalse{\let\eq@hasNumber\@False}% \let\eq@hasNumber\@False % \end{macrocode} % Here for the dimens, it would be advisable to do some more careful % management to conserve dimen registers. First of all, most of the % dimen registers are needed in the measuring phase, which is a tightly % contained step that happens after the contents of the equation have been % typeset into a box and before any external functions have a chance to % regain control\mdash \eg , the output routine. % Therefore it is possible to make use of the the dimen registers 0--9, % reserved by convention for scratch use, without fear of conflict with % other macros. But I don't want to use them directly with the % available names: % \begin{literalcode} % \dimen@ \dimen@i \dimen@ii \dimen3 \dimen4 ... \dimen9 % \end{literalcode} % . It would be much more useful to have names for these registers % indicative of way they are used. % % Another source whence dimen registers could be borrowed is the % \pkg{amsmath} package, which allocates six registers for % equation-measuring purposes. We can reuse them under different % names since the \pkg{amsmath} functions and our functions will % never be used simultaneously. % \begin{literalcode} % \eqnshift@ \alignsep@ \tagshift@ \tagwidth@ \totwidth@ \lineht@ % \end{literalcode} % \begin{macrocode} \newdimen\eq@dp % Depth of last line \newdimen\eq@wdL % Width of the left-hand-side \newdimen\eq@wdT % Total width for framing \newdimen\eq@wdMin % Width of narrowest line in equation \newdimen\grp@wdL % Max width of LHS's in a group \newdimen\grp@wdR % Max RHS of all equations in a group \newdimen\grp@wdT \newdimen\eq@wdRmax \newdimen\eq@firstht % Height of first line % \end{macrocode} % BRM: measure the condition too. % \begin{macrocode} \newdimen\eq@wdCond \newdimen\eq@indentstep % Indent amount when LHS is not present \newdimen\eq@linewidth % Width actually used for display \newdimen\grp@linewidth % Max eq@linewidth over a group % \end{macrocode} % Maybe \cs{eq@hshift} could share the same register as % \cs{mathindent} [mjd,1997/10/22]. % \begin{macrocode} \newdimen\eq@hshift \let\eq@isIntertext\@False % \end{macrocode} % Init \cs{eq@indentstep} to a nonzero value so that we can % detect and refrain from clobbering a user setting of zero. % And \cs{eq@sidespace} to \cs{maxdimen} because % that is the right init before computing a min. % \begin{macrocode} \eq@indentstep=\maxdimen \newdimen\eq@given@sidespace % \end{macrocode} % % \begin{macro}{\eq@overrun} % MH: Appears to be unused. % % Not a dimen register; don't need to advance it. % \begin{macrocode} \def\eq@overrun{0pt} % \end{macrocode} % \end{macro} % % % To initialize \cs{eqnumside} and \cs{eqindent} properly, % we may need to grub around a bit in \cs{@filelist}. However, % if the \pkg{amsmath} package was used, we can use its option % data. More trouble: if a documentclass sends an option of % \opt{leqno} to \pkg{amsmath} by default, and it gets % overridden by the user with a \opt{reqno} documentclass option, % then \pkg{amsmath} believes itself to have received % \emph{both} options. % \begin{macrocode} \@ifpackagewith{amsmath}{leqno}{% \@ifpackagewith{amsmath}{reqno}{}{\def\eqnumside{L}}% }{% % \end{macrocode} % If the \pkg{amsmath} package was not used, the next % method for testing the \opt{leqno} option is to see if % \fn{leqno.clo} is present in \cs{@filelist}. % \begin{macrocode} \def\@tempa#1,leqno.clo,#2#3\@nil{% \ifx @#2\relax\else \def\eqnumside{L}\fi }% \@xp\@tempa\@filelist,leqno.clo,@\@nil % \end{macrocode} % Even that test may fail in the case of \cls{amsart} if it does % not load \pkg{amsmath}. Then we have to look whether % \cs{iftagsleft@} is defined, and if so whether it is true. % This is tricky if you want to be careful about conditional nesting % and don't want to put anything in the hash table unnecessarily. % \begin{macrocode} \if L\eqnumside \else \@ifundefined{iftagsleft@}{}{% \edef\eqnumside{% \if TT\csname fi\endcsname\csname iftagsleft@\endcsname L\else R\fi }% } \fi } % \end{macrocode} % A similar sequence of tests handles the \quoted{fleqn or not fleqn} % question for the \cls{article} and \cls{amsart} % documentclasses. % \begin{macrocode} \@ifpackagewith{amsmath}{fleqn}{% \def\eqindent{I}% }{% \def\@tempa#1,fleqn.clo,#2#3\@nil{% \ifx @#2\relax\else \def\eqindent{I}\fi }% \@xp\@tempa\@filelist,fleqn.clo,@\@nil \if I\eqindent \else \@ifundefined{if@fleqn}{}{% \edef\eqindent{% \if TT\csname fi\endcsname\csname if@fleqn\endcsname I\else C\fi }% }% \fi } % \end{macrocode} % BRM: This conditional implies we must use ALL indented or ALL centered? % \begin{macrocode} %\if I\eqindent \@ifundefined{mathindent}{% \newdimen\mathindent }{% \@ifundefined{@mathmargin}{}{% \mathindent\@mathmargin }% } %\fi % \end{macrocode} % % % % % \section{Measuring equation components} % Measure the left-hand side of an equation. This % function is called by mathrel symbols. For the first mathrel we % want to discourage a line break more than for following mathrels; so % \cs{mark@lhs} gobbles the following \cs{rel@break} and % substitutes a higher penalty. % \begin{aside} % Maybe the LHS should be kept in a separate box. % \end{aside} % % % % \begin{macro}{\EQ@hasLHS} % % Boolean: does this equation have a \dquoted{left-hand side}? % \begin{macrocode} \let\EQ@hasLHS=\@False % \end{macrocode} % \end{macro} % % % \begin{macro}{\EQ@QED} % % If nonempty: the qed material that should be incorporated into this % equation after the final punctuation. % \begin{macrocode} \let\EQ@QED=\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\mark@lhs} % % \begin{macrocode} \def\mark@lhs#1{% \ifnum\lr@level<\@ne \let\mark@lhs\relax \global\let\EQ@hasLHS=\@True \global\let\EQ@prebin@space\EQ@prebin@space@a \mark@lhs@a % \end{macrocode} % But the penalty for the first mathrel should still be lower than a % binoppenalty. If not, when the LHS contains a binop, the split % will occur inside the LHS rather than at the mathrel. % On the other hand if we end up with a multline sort of equation % layout where the RHS is very short, the break before the relation symbol % should be made \emph{less} desirable than the breakpoints inside % the LHS. % Since a lower penalty takes precedence over a higher one, we start % by putting in the highest relpenalty; during subsequent measuring if we % find that that RHS is not excessively short then we put in an extra % \dquoted{normal} relpenalty when rejoining the LHS and RHS. % \begin{macrocode} \penalty9999 % instead of normal \rel@break % else no penalty = forbid break \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\mark@lhs@a} % % Temporarily add an extra thickmuskip to the LHS; it will be removed % later. This is necessary to compensate for the disappearance of % the thickmuskip glue preceding a mathrel if a line break is taken at % that point. Otherwise we would have to make our definition of % mathrel symbols more complicated, like the one for mathbins. The % penalty of $2$ put in with vadjust is a flag for % \cs{eq@repack} to suggest that the box containing this line should % be measured to find the value of \cs{eq@wdL}. The % second vadjust ensures that the normal prerelpenalty and thickmuskip % will not get lost at the line break during this preliminary pass. % % BRM: I originally thought the \verb"\mskip\thickmuskip" was messing % up summation limits in LHS. But I may have fixed that problem by % fixing other things\ldots % \begin{macrocode} \def\mark@lhs@a{% \mskip\thickmuskip \@@vadjust{\penalty\tw@}\penalty-\@Mi\@@vadjust{}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\hiderel} % If you want the LHS to extend past the first mathrel symbol to a % following one, mark the first one with \cs{hiderel}: % \begin{literalcode} % a \hiderel{=} b = c... % \end{literalcode} % . % \begin{aside} % I'm not sure now why I didn't use \cs{begingroup} % \cs{endgroup} here \begin{dn} % mjd,1999/01/21 % \end{dn} % . % \end{aside} % % \begin{macrocode} \newcommand\hiderel[1]{\mathrel{\advance\lr@level\@ne#1}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\m@@Bin} % \begin{macro}{\m@@Rel} % \begin{macro}{\bin@break} % \begin{macro}{\rel@break} % \begin{macro}{\bin@mark} % \begin{macro}{\rel@mark} % \begin{macro}{\d@@Bin} % \begin{macro}{\d@@Rel} % % \cf \pkg{flexisym} handling of mathbins and mathrels. These % are alternate definitions of \cs{m@Bin} and \cs{m@Rel}, % activated by \cs{display@setup}. % \begin{macrocode} %%%%\let\m@@Bin\m@Bin %%%%%\let\m@@Rel\m@Rel \let\EQ@prebin@space\relax \def\EQ@prebin@space@a{\mskip-\eq@binoffset \keep@glue \mskip\eq@binoffset} \def\bin@break{\ifnum\lastpenalty=\z@\penalty\prebinoppenalty\fi \EQ@prebin@space} \def\rel@break{% \ifnum\abs@num\lastpenalty <\abs@num\prerelpenalty \penalty\prerelpenalty \fi } \ExplSyntaxOn %%%\def\d@@Bin{\bin@break \m@@Bin} %%%%\def\d@@Rel{\mark@lhs \rel@break \m@@Rel} \cs_set:Npn \math_dsym_Bin:Nn {\bin@break\math_bsym_Bin:Nn} \cs_set:Npn \math_dsym_Rel:Nn {\mark@lhs \rel@break \math_bsym_Rel:Nn } \ExplSyntaxOff % \end{macrocode} % The difficulty of dealing properly with the subscripts and % superscripts sometimes appended to mathbins and mathrels is one of the % reasons that we do not attempt to handle the mathrels as a separate % \quoted{column} a la \env{eqnarray}. % % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\m@@symRel} % \begin{macro}{\d@@symRel} % \begin{macro}{\m@@symBin} % \begin{macro}{\d@@symBin} % \begin{macro}{\m@@symDel} % \begin{macro}{\d@@symDel} % \begin{macro}{\m@@symDeR} % \begin{macro}{\d@@symDeR} % \begin{macro}{\m@@symDeB} % \begin{macro}{\d@@symDeB} % \begin{macro}{\m@@symDeA} % \begin{macro}{\d@@symDeA} % % More of the same. % \begin{macrocode} \ExplSyntaxOn %%\let\m@@symRel\@symRel %%%\def\d@@symRel{\mark@lhs \rel@break \m@@symRel} \cs_set_protected:Npn \math_dcsym_Bin:Nn {\bin@break \math_bcsym_Bin:Nn} \cs_set_protected:Npn \math_dcsym_Rel:Nn { \mark@lhs \rel@break \math_bcsym_Rel:Nn} %%\let\m@@symBin\@symBin \def\d@@symBin{\bin@break \m@@symBin} %%\let\m@@symDel\@symDel %%\let\m@@symDeR\@symDeR %%\let\m@@symDeB\@symDeB %%\let\m@@symDeA\@symDeA % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\display@setup} % \begin{macro}{\everydisplay} % Setup. Note that \latex reserves the primitive % \cs{everydisplay} under the name \cs{frozen@everydisplay}. % BRM: Disable this! It also affects non-breqn math!!!! % \begin{macrocode} %\global\everydisplay\expandafter{\the\everydisplay \display@setup} % \end{macrocode} % Change some math symbol function calls. % \begin{macrocode} \def\display@setup{% \medmuskip\Dmedmuskip \thickmuskip\Dthickmuskip \math_setup_display_symbols: %%\let\m@Bin\d@@Bin \let\m@Rel\d@@Rel %%\let\@symRel\d@@symRel \let\@symBin\d@@symBin %%\let\m@DeL\d@@DeL \let\m@DeR\d@@DeR \let\m@DeB\d@@DeB %%\let\m@DeA\d@@DeA %%\let\@symDeL\d@@symDeL \let\@symDeR\d@@symDeR %%\let\@symDeB\d@@symDeB \let\@symDeA\d@@symDeA \let\left\eq@left \let\right\eq@right \global\lr@level\z@ \global\eq@wdCond\z@ %BRM: new % \end{macrocode} % If we have an embedded array environment (for example), we % don't want to have each math cell within the array resetting % \cs{lr@level} globally to 0\mdash not good! % And in general I think it is safe to say that whenever we have a % subordinate level of boxing we want to revert to a normal math setup. % \begin{macrocode} \everyhbox{\everyhbox\@emptytoks \let\display@setup\relax \textmath@setup \let\textmath@setup\relax }% \everyvbox{\everyvbox\@emptytoks \let\display@setup\relax \textmath@setup \let\textmath@setup\relax }% } % \end{macrocode} % The \cs{textmath@setup} function is needed for embedded inline % math inside text inside a display. % % BRM: DS Experiment: Variant of \cs{display@setup} for use within % dseries environmnents % \begin{macrocode} \def\dseries@display@setup{% \medmuskip\Dmedmuskip \thickmuskip\Dthickmuskip \math_setup_display_symbols: %%%% \let\m@Bin\d@@Bin %%%\let\m@Rel\d@@Rel %%% \let\@symRel\d@@symRel %%% \let\@symBin\d@@symBin %%% \let\m@DeL\d@@DeL \let\m@DeR\d@@DeR \let\m@DeB\d@@DeB %%% \let\m@DeA\d@@DeA %%% \let\@symDeL\d@@symDeL \let\@symDeR\d@@symDeR %%% \let\@symDeB\d@@symDeB \let\@symDeA\d@@symDeA \let\left\eq@left \let\right\eq@right \global\lr@level\z@ \everyhbox{\everyhbox\@emptytoks \let\display@setup\relax \textmath@setup \let\textmath@setup\relax }% \everyvbox{\everyvbox\@emptytoks \let\display@setup\relax \textmath@setup \let\textmath@setup\relax }% \displaystyle } % \end{macrocode} % % \begin{macrocode} \def\textmath@setup{% \math_setup_inline_symbols: %%%% \let\m@Bin\m@@Bin \let\m@Rel\m@@Rel %%%% \let\@symRel\m@@symRel \let\@symBin\m@@symBin %%%% \let\m@DeL\m@@DeL \let\m@DeR\m@@DeR \let\m@DeB\m@@DeB %%%% \let\m@DeA\m@@DeA %%%% \let\@symDeL\m@@symDeL \let\@symDeR\m@@symDeR %%%% \let\@symDeB\m@@symDeB \let\@symDeA\m@@symDeA \let\left\@@left \let\right\@@right } \ExplSyntaxOff % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\if@display} % \begin{macro}{\everydisplay} % The test \cs{ifinner} is unreliable for distinguishing % whether we are in a displayed formula or an inline formula: any display % more complex than a simple one-line equation typically involves the use % of \verb"$" \cs{displaystyle} \dots \verb"$" instead of % \dbldollars \dots \dbldollars . So we provide a more reliable % test. But it might have been provided already by the % \pkg{amsmath} package. % \begin{macrocode} \@ifundefined{@displaytrue}{% \@xp\newif\csname if@display\endcsname \everydisplay\@xp{\the\everydisplay \@displaytrue}% }{} % \end{macrocode} % % \begin{aside} % Is there any reason to maintain separate % \cs{everydisplay} and \cn{eqstyle}? % % \end{aside} % % % \end{macro} % \end{macro} % % % % % \section{The \env{dmath} and \env{dmath*} environments} % % Options for the \env{dmath} and \env{dmath*} % environments. % \begin{literalcode} % \begin{dmath}[label={eq:xyz}] % \begin{dmath}[labelprefix={eq:},label={xyz}] % \end{literalcode} % WSPR: added the option for a label prefix, designed to be used in the preamble like so: % \begin{literalcode} % \breqnsetup{labelprefix={eq:}} % \end{literalcode} % \begin{macrocode} \define@key{breqn}{label}{% \edef\next@label{\noexpand\label{\next@label@pre#1}}% \let\next@label@pre\@empty} \define@key{breqn}{labelprefix}{\def\next@label@pre{#1}} \global\let\next@label\@empty \global\let\next@label@pre\@empty % \end{macrocode} % Allow a variant number. % \begin{literalcode} % \begin{dmath}[number={\nref{foo}\textprime}] % \end{literalcode} % \begin{macrocode} \define@key{breqn}{number}{\def\eq@number{#1}% \let\@currentlabel\eq@number } % \end{macrocode} % \begin{literalcode} % \begin{dmath}[shiftnumber] % \begin{dmath}[holdnumber] % \end{literalcode} % Holding or shifting the number. % \begin{macrocode} \define@key{breqn}{shiftnumber}{\let\eq@shiftnumber\@True} \define@key{breqn}{holdnumber}{\let\eq@holdnumber\@True} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[density={.5}] % \end{literalcode} % \begin{macrocode} \define@key{breqn}{density}{\def\eq@density@factor{#1}} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[indentstep={1em}] % \end{literalcode} % To change the amount of indent for post-initial lines. Note: % for lines that begin with a mathbin symbol there is a fixed amount of % indent already built in (\cs{eqbinoffset}) and it cannot be % reduced through this option. The indentstep amount is the indent % used for lines that begin with a mathrel symbol. % \begin{macrocode} \define@key{breqn}{indentstep}{\eqindentstep#1\relax} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[compact] % \begin{dmath}[compact=-2000] % \end{literalcode} % To make mathrels stay inline to the extent possible, use the compact % option. % Can give a numeric value in the range $-10000 \dots 10000$ % to adjust the behavior. % $-10000$: always break at a rel symbol; $10000$: never % break at a rel symbol. % \begin{macrocode} \define@key{breqn}{compact}[-99]{\prerelpenalty=#1\relax} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[layout={S}]% % \end{literalcode} % Specify a particular layout. % We take care to ensure that \cs{eq@layout} ends up containing % one and only one letter. % \begin{macrocode} \define@key{breqn}{layout}[?]{% \edef\eq@layout{\@car#1?\@nil}% } % \end{macrocode} % \begin{literalcode} % \begin{dmath}[spread={1pt}] % \end{literalcode} % To change the interline spacing in a particular equation. % \begin{macrocode} \define@key{breqn}{spread}{% \addtolength\eqlinespacing{#1}% \addtolength\eqlineskip{#1}% \eqlineskiplimit\eqlineskip } % \end{macrocode} % To change the amount of space on the side for \dquoted{multline} layout. % \begin{macrocode} \define@key{breqn}{sidespace}{% \setlength\eq@given@sidespace{#1}% } % \end{macrocode} % \begin{literalcode} % \begin{dmath}[style={\small}] % \end{literalcode} % The \opt{style} option is mainly intended for changing the % type size of an equation but as a matter of fact you could put arbitrary % \latex code here \mdash thus the option name is \quoted{style} rather % than just \quoted{typesize}. In order for this option to work when % setting options globally, we need to put the code in % \cs{eqstyle} rather than execute it directly. % \begin{macrocode} \define@key{breqn}{style}{\eqstyle\@xp{\the\eqstyle #1}} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[shortskiplimit={1em}] % \end{literalcode} % If the line immediately preceeding a display has length $l$, the % first line of the display is indented $i$, and a shortskip limit $s$ % is set, then the spacing above the display is equal to % \cs{abovedisplayshortskip} if $l+s < i $ and \cs{abovedisplayskip} % otherwise. The default shortskip limit is 2\,em which is what \TeX\ % hardcodes but this parameter overrides that. % \begin{macrocode} \define@key{breqn}{shortskiplimit}{\def\eq@shortskiplimit{#1}} \def\eq@shortskiplimit{2em} % \end{macrocode} % % \begin{literalcode} % \begin{dmath}[frame] % \end{literalcode} % The \opt{frame} option merely puts a framebox around the body % of the equation. To change the thickness of the frame, give the % thickness as the argument of the option. For greater control, you % can change the appearance of the frame by redefining % \cs{eqframe}. It must be a command taking two arguments, the % width and height of the equation body. The top left corner of the % box produced by \cs{eqframe} will be pinned to the top-left corner % of the equation body. % \begin{macrocode} \define@key{breqn}{frame}[\fboxrule]{\def\eq@frame{T}% \dim@a#1\relax\edef\eq@framewd{\the\dim@a}% % \end{macrocode} % Until such time as we provide a frame implementation that allows the % frame to stretch and shrink, we'd better remove any stretch/shrink from % the interline glue in this case. % \begin{macrocode} \freeze@glue\eqlinespacing \freeze@glue\eqlineskip } \define@key{breqn}{fullframe}[]{\def\eq@frame{U}% \freeze@glue\eqlinespacing \freeze@glue\eqlineskip } \def\eq@frame{F} % no frame \def\eq@framewd{\fboxrule} % \end{macrocode} % Wishful thinking? % \begin{literalcode} % \begin{dmath}[frame={width={2pt},color={blue},sep={2pt}}] % \end{literalcode} % To change the space between the frame and the equation there is a % framesep option. % \begin{macrocode} \define@key{breqn}{framesep}[\fboxsep]{% \if\eq@frame F\def\eq@frame{T}\fi \dim@a#1\relax \edef\eq@framesep{\the\dim@a}% \freeze@glue\eqlinespacing \freeze@glue\eqlineskip } \def\eq@framesep{\fboxsep} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[background={red}] % \end{literalcode} % Foreground and background colors for the equation. By default % the background area that is colored is the size of the equation, plus % fboxsep. If you need anything fancier for the background, you'd % better do it by defining \cs{eqframe} in terms of % \cs{colorbox} or \cs{fcolorbox}. % \begin{macrocode} \define@key{breqn}{background}{\def\eq@background{#1}% \freeze@glue\eqlinespacing \freeze@glue\eqlineskip } % \end{macrocode} % \begin{literalcode} % \begin{dmath}[color={purple}] % \end{literalcode} % \begin{macrocode} \define@key{breqn}{color}{\def\eq@foreground{#1}} % \end{macrocode} % \begin{literalcode} % \begin{dmath}[center] % \begin{dmath}[nocenter] % \end{literalcode} % The \opt{center} option means add leftskip stretch to make the % individual lines be centered; this is the default for % \env{dseries}. % \begin{macrocode} \define@key{breqn}{center}[]{\let\eq@centerlines\@True} \define@key{breqn}{nocenter}[]{\let\eq@centerlines\@False} \let\eq@centerlines\@False % \end{macrocode} % \begin{literalcode} % \begin{dgroup}[noalign] % \end{literalcode} % Equation groups normally have alignment of the primary relation % symbols across the whole group. The \opt{noalign} option % switches that behavior. % \begin{macrocode} \define@key{breqn}{noalign}[]{\let\grp@aligned\@False} \let\grp@aligned\@True % default % \end{macrocode} % \begin{literalcode} % \begin{dgroup}[breakdepth={2}] % \end{literalcode} % Break depth of 2 means that breaks are allowed at mathbin symbols % inside two pairs of delimiters, but not three. % \begin{macrocode} \define@key{breqn}{breakdepth}{\eqbreakdepth#1\relax} % \end{macrocode} % \begin{literalcode} % \begin{darray}[cols={lcrlcr}] % \end{literalcode} % The \opt{cols} option only makes sense for the % \env{darray} environment but we liberally allow all the options to % be used with all the environments and just ignore any unsensible ones % that happen to come along. % \begin{macrocode} \define@key{breqn}{cols}{\global\let\@preamble\@empty \darray@mkpream#1\@percentchar } % \end{macrocode} % % FORMAT STATUS% % \begin{verbatim} % \def\eq@frame{T}% % CLM works tolerably % \def\eqindent{C}\def\eqnumside{L}\def\eqnumplace{M} % CLT works tolerably % \def\eqindent{C}\def\eqnumside{L}\def\eqnumplace{T} % ILM % \def\eqindent{I}\def\eqnumside{L}\def\eqnumplace{M}\mathindent40\p@ % ILT % \def\eqindent{I}\def\eqnumside{L}\def\eqnumplace{T}\mathindent40\p@ % Indended w/left number % work ok if mathindent is larger than number width, % but then equations must fit into smaller space. % Is shiftnumber allowed to put eqn at left, instead of indent? % CRM % \def\eqindent{C}\def\eqnumside{R}\def\eqnumplace{M} % CRB % \def\eqindent{C}\def\eqnumside{R}\def\eqnumplace{B} % IRM % \def\eqindent{I}\def\eqnumside{R}\def\eqnumplace{M}\mathindent10\p@ % IRB % \def\eqindent{I}\def\eqnumside{R}\def\eqnumplace{B}\mathindent10\p@ % \end{verbatim} % % The main environments. % %BRM: The following incorporates several changes: % 1) modifications supplied by MJD to fix the eaten \cs{paragraph} problem. % 2) Added \cs{display@setup} here, rather than globally. % % \begin{macro}{\@dmath@start@hook} % \begin{macro}{\@dgroup@start@hook} % \begin{macrocode} \let\@dmath@start@hook\@empty \let\@dgroup@start@hook\@empty % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dmath} % \begin{macro}{\enddmath} % For the \env{dmath} environment we don't want the standard % optional arg processing because of the way it skips over whitespace, % including newline, while looking for the \verb"[" char; which is not good % for math material. So we call \cs{@optarg} instead. % \begin{macrocode} \newenvironment{dmath}{% \@dmath@start@hook \let\eq@hasNumber\@True \breqn@optarg\@dmath{}}{} \def\@dmath[#1]{% % \breqn@debugmsg{=== DMATH ==================================================}% \everydisplay\expandafter{\the\everydisplay \display@setup}% \if@noskipsec \leavevmode \fi \if@inlabel \leavevmode \global\@inlabelfalse \fi \if\eq@group\else\eq@prelim\fi \setkeys{breqn}{#1}% \the\eqstyle % \end{macrocode} % The equation number might have been overridden in \verb|#1|. % \begin{macrocode} \eq@setnumber % \end{macrocode} % Start up the displayed equation by reading the contents into a % box register. Enclose this phase in an extra group so that % modified \cs{hsize} and other params will be auto-restored % afterwards. % \begin{macrocode} \begingroup \eq@setup@a \eq@startup } % \end{macrocode} % Before it finishes off the box holding the equation body, % \cs{enddmath} needs to look ahead for punctuation (and % \cs{qed}?). % \begin{macrocode} \def\enddmath#1{% \check@punct@or@qed } \def\end@dmath{% \gdef\EQ@setwdL{}% Occasionally undefined ??? \eq@capture \endgroup \EQ@setwdL % \end{macrocode} % Measure (a copy of) the equation body to find the minimum width % required to get acceptable line breaks, how many lines will be required % at that width, and whether the equation number needs to be shifted to % avoid overlapping. This information will then be used by % \cs{eq@finish} to do the typesetting of the real equation body. % \begin{macrocode} \eq@measure % \end{macrocode} % Piece together the equation from its constituents, recognizing % current constraints. If we are in an equation group, this might % just save the material on a stack for later processing. % \begin{macrocode} \if\eq@group \grp@push \else \eq@finish\fi } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\dmath*} % \begin{macro}{\enddmath*} % Ah yes, now the lovely \env{dmath*} environment. % \begin{macrocode} \newenvironment{dmath*}{% \@dmath@start@hook \let\eq@hasNumber\@False \breqn@optarg\@dmath{}% }{} \@namedef{end@dmath*}{\end@dmath} \@namedef{enddmath*}#1{\check@punct@or@qed} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\eq@prelim} % If \cs{everypar} has a non-null value, it's probably % some code from \cs{@afterheading} that sets \cs{clubpenalty} % and\slash or removes the parindent box. Both of those actions % are irrelevant and interfering for our purposes and need to be deflected % for the time being. % If an equation appears at the very beginning of a list item % (possibly from a trivlist such as \env{proof}), we need to % trigger the item label. % \begin{macrocode} \def\eq@prelim{% \if@inlabel \indent \par \fi \if@nobreak \global\@nobreakfalse \predisplaypenalty\@M \fi \everypar\@emptytoks % \end{macrocode} % If for some reason \env{dmath} is called between paragraphs, % \cn{noindent} is better than \cn{leavevmode}, which would produce % an indent box and an empty line to hold it. If we are in a list % environment, \cn{par} is defined as \verb"{\@@par}" to preserve % \cs{parshape}. % \begin{macrocode} \noindent \eq@nulldisplay \par %% \eq@saveparinfo %% needs work \let\intertext\breqn@intertext } % \end{macrocode} % \end{macro} % \begin{macro}{\breqn@parshape@warning} % Warning message extracted to a separate function to streamline the % calling function. % \begin{macrocode} \def\breqn@parshape@warning{% \PackageWarning{breqn}{% Complex paragraph shape cannot be followed by this equation}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@prevshape} % Storage; see \cs{eq@saveparinfo}. % \begin{macrocode} \let\eq@prevshape\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@saveparinfo} % Save the number of lines and parshape info for the text preceding % the equation. % \begin{macrocode} \def\eq@saveparinfo{% \count@\prevgraf \advance\count@-\thr@@ % for the null display \edef\eq@prevshape{\prevgraf\the\count@\space}% \ifcase\parshape % case 0: no action required \or \edef\eq@prevshape{\eq@prevshape \parshape\@ne\displayindent\displaywidth\relax }% % \end{macrocode} % Maybe best to set \cs{eq@prevshape} the same in the else case % also. Better than nothing. % \begin{macrocode} \else \breqn@parshape@warning \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@setnumber} % If the current equation number is not explicitly given, then % use an auto-generated number, unless the no-number switch has been % thrown (\env{dmath*}). % \cs{theequation} is the number form to be used for all equations, % \cs{eq@number} is the actual value for the current equation % (might be an exception to the usual sequence). % \begin{macrocode} \def\eq@setnumber{% \eq@wdNum\z@ \if\eq@hasNumber \ifx\eq@number\@empty \stepcounter{equation}\let\eq@number\theequation \fi % \fi % \end{macrocode} % This sets up numbox, etc, even if unnumbered????? % \begin{macrocode} \ifx\eq@number\@empty \else % \end{macrocode} % Put the number in a box so we can use its measurements in our % number-placement calculations. The extra braces around % \cs{eqnumform} make it possible for \cs{eqnumfont} to have % either an \cs{itshape} (recommended) or a \cs{textit} % value. % \begin{macrocode} % \breqn@debugmsg{Number \eq@number}% \set@label{equation}\eq@number \global\sbox\EQ@numbox{% \next@label \global\let\next@label\@empty \eqnumcolor\eqnumsize\eqnumfont{\eqnumform{\eq@number}}% }% \global\eq@wdNum\wd\EQ@numbox\global\advance\eq@wdNum\eqnumsep % \let\eq@hasNumber\@True % locally true \fi \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@finish} % The information available at this point from preliminary % measuring includes the number of lines required, the width of the % equation number, the total height of the equation body, and (most % important) the parshape spec that was used in determining height and % number of lines. % % Invoke the equation formatter for the requested centering/indentation % having worked out the best parshape. % BRM: This portion is extensively refactored to get common operations % together (so corrections get consistently applied). % % MH: I've destroyed Bruce's nice refactoring a bit to get the % abovedisplayskips correct for both groups of equations and single % \env{dmath} environments. I will have to redo that later. % \begin{macrocode} \newcount\eq@final@linecount \let\eq@GRP@first@dmath\@True \def\eq@finish{% \begingroup % \breqn@debugmsg{Formatting equation}% % \debug@showmeasurements \if F\eq@frame\else \freeze@glue\eqlinespacing \freeze@glue\eqlineskip \fi % \eq@topspace{\vskip\parskip}% Set top spacing \csname eq@\eqindent @setsides\endcsname % Compute \leftskip,\rightskip \adjust@parshape\eq@parshape% Final adjustment of parshape for left|right skips % \end{macrocode} % If we are in an a group of equations we don't want to calculate the % top space for the first one as that will be delayed until later when % the space for the group is calculated. However, we do need to store % the leftskip used here as that will be used later on for calculating % the top space. % \begin{macrocode} \if\eq@group \if\eq@GRP@first@dmath \global\let\eq@GRP@first@dmath\@False \xdef\dmath@first@leftskip{\leftskip=\the\leftskip\relax}% % \breqn@debugmsg{Stored\space\dmath@first@leftskip} \else \eq@topspace{\vskip\parskip}% Set top spacing \fi \else \eq@topspace{\vskip\parskip}% Set top spacing \fi % \debug@showformat % \end{macrocode} % We now know the final line count of the display. If it is a % single-line display, we want to know as that greatly simplifies the % equation tag placement (until such a time where this algorithm has % been straightened out). % \begin{macrocode} \afterassignment\remove@to@nnil \eq@final@linecount=\expandafter\@gobble\eq@parshape\@nnil % \end{macrocode} % Now, invoke the appropriate typesetter according to number placement % \begin{macrocode} \if\eq@hasNumber \if\eq@shiftnumber \csname eq@typeset@\eqnumside Shifted\endcsname \else % \end{macrocode} % If there is only one line and the tag doesn't have to be shifted, we % call a special procedure to put the tag correctly. % \begin{macrocode} \ifnum\eq@final@linecount=\@ne \csname eq@typeset@\eqnumside @single\endcsname \else \csname eq@typeset@\eqnumside\eqnumplace\endcsname \fi \fi \else \eq@typeset@Unnumbered \fi \endgroup \eq@botspace } % \end{macrocode} % \end{macro} % % % These are temporary until the tag position algorithm gets % rewritten. At least the tag is positioned correctly for single-line % displays. The horizontal frame position is not correct but the % problem lies elsewhere. % \begin{macrocode} \def\eq@typeset@L@single{% \nobreak \eq@params\eq@parshape \nointerlineskip % \noindent \MaybeRawNoindent \add@grp@label \rlap{\kern-\leftskip\box\EQ@numbox}% \if F\eq@frame \else \rlap{\raise\eq@firstht\hbox to\z@{\eq@addframe\hss}}% \fi \eq@dump@box\unhbox\EQ@box %\@@par \RawParEnd } \def\eq@typeset@R@single{% \nobreak \eq@params\eq@parshape \nointerlineskip % \noindent \MaybeRawNoindent \add@grp@label \if F\eq@frame \else \rlap{\raise\eq@firstht\hbox to\z@{\eq@addframe\hss}}% \fi \rlap{\kern-\leftskip\kern\linewidth\kern-\wd\EQ@numbox\copy\EQ@numbox}% \eq@dump@box\unhbox\EQ@box %\@@par \RawParEnd } % \end{macrocode} % % % % \section{Special processing for end-of-equation} % % At the end of a displayed equation environment we need to peek ahead % for two things: following punction such as period or command that % should be pulled in for inclusion at the end of the equation; and % possibly also an \verb"\end{proof}" with an implied \dquoted{qed} % symbol that is traditionally included at the end of the display rather % than typeset on a separate line. % We could require that the users type \cs{qed} explicitly at the % end of the display when they want to have the display take notice of it. % But the reason for doing that would only be to save work for the % programmer; the most natural document markup would allow an inline % equation and a displayed equation at the end of a proof to differ only % in the environment name: % \begin{literalcode} % ... \begin{math} ... \end{math}. % \end{proof} % \end{literalcode} % versus % \begin{literalcode} % ... % \begin{dmath} % ... % \end{dmath}. % \end{proof} % \end{literalcode} % . % The technical difficulties involved in supporting this markup within % \latex2e are, admittedly, nontrivial. % Nonetheless, let's see how far we can go. % % % The variations that we will support are only the most % straightforward ones: % \begin{literalcode} % \end{dmath}. % \end{proof} % \end{literalcode} % or % \begin{literalcode} % \end{dmath}. % Perhaps a comment % \end{proof} % \end{literalcode} % . % If there is anything more complicated than a space after the % period we will not attempt to scan any further for a possible % \verb"\end{proof}". % This includes material such as: % \begin{literalcode} % \begin{figure}...\end{figure}% % \footnote{...} % \renewcommand{\foo}{...} % \par % \end{literalcode} % or even a blank line\mdash because in \latex a blank line is % equivalent to \cs{par} and the meaning of \cs{par} is % \dquoted{end-paragraph}; in my opinion if explicit end-of-paragraph % markup is given before the end of an element, it has to be respected, % and the preceding paragraph has to be fully finished off before % proceeding further, even inside an element like \dquoted{proof} whose % end-element formatting requires integration with the end of the % paragraph text. % And \tex nically speaking, a \cs{par} token that comes from a % blank line and one that comes from the sequence of characters % \verb"\" \verb"p" \verb"a" \verb"r" are equally explicit. % I hope to add support for \cs{footnote} in the future, as it % seems to be a legitimate markup possibility in that context from a % purely logical point of view, but there are additional technical % complications if one wants to handle it in full generality % \begin{dn} % mjd,1999/02/08 % \end{dn} % . % % % \begin{macro}{\peek@branch} % This is a generalized \dquoted{look at next token and choose some action % based on it} function. % \begin{macrocode} \def\peek@branch#1#2{% \let\peek@b#1\let\peek@space#2\futurelet\@let@token\peek@a } \def\peek@skipping@spaces#1{\peek@branch#1\peek@skip@space} \def\peek@a{% \ifx\@let@token\@sptoken \expandafter\peek@space \else \expandafter\peek@b\fi } \lowercase{\def\peek@skip@space} {\futurelet\@let@token\peek@a}% % \end{macrocode} % \end{macro} % % % \begin{macro}{\check@punct} % \changes{v0.96a}{2007/12/17}{Insert \cs{finish@end} if no special % case is found.} % For this one we need to recognize and grab for inclusion any of the % following tokens: \verb",;.!?", both catcode 12 (standard \latex % value) and catcode 13 (as might hold when the Babel package is % being used). % We do not support a space preceding the punctuation since that would % be considered simply invalid markup if a display-math environment were % demoted to in-line math; and we want to keep their markup as parallel as % possible. % If punctuation does not follow, then the \cs{check@qed} branch % is not applicable. % \begin{macrocode} \def\check@punct{\futurelet\@let@token\check@punct@a} \def\check@punct@a{% \edef\@tempa{% \ifx\@let@token\@sptoken\@nx\finish@end \else\ifx\@let@token ,\@nx\check@qed \else\ifx\@let@token .\@nx\check@qed \else\check@punct@b % check the less common possibilities \fi\fi\fi }% \@tempa } \begingroup \toks@a{% \ifx\@let@token ;\@nx\check@qed \else\ifx\@let@token ?\@nx\check@qed \else\ifx\@let@token !\@nx\check@qed } \toks@c{\fi\fi\fi}% matching with \toks@a \catcode`\.=\active \catcode`\,=\active \catcode`\;=\active \catcode`\?=\active \catcode`\!=\active \toks@b{% \else\ifx\@let@token ,\@nx\check@qed \else\ifx\@let@token .\@nx\check@qed \else\ifx\@let@token ;\@nx\check@qed \else\ifx\@let@token ?\@nx\check@qed \else\ifx\@let@token !\@nx\check@qed \else\@nx\finish@end \fi\fi\fi\fi\fi } \xdef\check@punct@b{% \the\toks@a\the\toks@b\the\toks@c } \endgroup % \end{macrocode} % % \begin{macrocode} \let\found@punct\@empty \def\check@qed#1{% \gdef\found@punct{#1}% \peek@skipping@spaces\check@qed@a } \def\check@qed@a{% \ifx\end\@let@token \@xp\check@qed@b \else \@xp\finish@end \fi } % \end{macrocode} % For each environment ENV that takes an implied qed at the end, the % control sequence ENVqed must be defined; and it must include suitable % code to yield the desired results in a displayed equation. % \begin{macrocode} \def\check@qed@b#1#2{% \@ifundefined{#2qed}{}{% \toks@\@xp{\found@punct\csname#2qed\endcsname}% \xdef\found@punct{\the\toks@}% }% \finish@end \end{#2}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\latex@end} % \begin{macro}{\finish@end} % The lookahead for punctuation following a display requires % mucking about with the normal operation of \cn{end}. Although % this is not exactly something to be done lightly, on the other hand this % whole package is so over-the-top anyway, what's a little more % going to hurt? And rationalizing this aspect of % equation markup is a worthy cause. Here is the usual % definition of \cs{end}. % \begin{literalcode} % \def\end#1{ % \csname end#1\endcsname \@checkend{#1}% % \expandafter\endgroup\if@endpe\@doendpe\fi % \if@ignore \global\@ignorefalse \ignorespaces \fi % } % \end{literalcode} % We can improve the chances of this code surviving through future % minor changes in the fundamental definition of \cs{end} by taking a % little care in saving the original meaning. % \begin{macrocode} \def\@tempa#1\endcsname#2\@nil{\def\latex@end##1{#2}} \ifcsname end \endcsname % 2019: \end was made robust \expandafter\expandafter\expandafter\@tempa\csname end \endcsname{#1}\@nil \@namedef{end }#1{\csname end#1\endcsname \latex@end{#1}}% \else % pre-2019: the old approach \expandafter\@tempa\end{#1}\@nil \def\end#1{\csname end#1\endcsname \latex@end{#1}}% \fi % \end{macrocode} % Why don't we call \cs{CheckCommand} here? Because that % doesn't help end users much; it works better to use it during package % testing by the maintainer. % % Note to self: I always forget how this redefinition works. Here's a summary. % The approach is: % \begin{verbatim} % \def\enddmath#1{\check@punct@or@qed} % \end{verbatim} % When hitting the end of the dmath environment we then have: % \begin{verbatim} % \csname end#1\endcsname \latex@end{#1} % \enddmath \latex@end{dmath} % \check@punct@or@qed {dmath} % <- \enddmath absorbs one arg % \xdef\found@punct{\@empty}\def\finish@end{\csname end@dmath\endcsname\latex@end{dmath}}\check@punct % \end{verbatim} % At which point \verb|\check@punct| is `past' the end of the environment and can look ahead. % % % If a particular environment needs to call a different end action, the % end command of the environment should be defined to gobble two args and % then call a function like \cs{check@punct@or@qed}. % \begin{macrocode} \def\check@punct@or@qed#1{% \xdef\found@punct{\@empty}% BRM: punctuation was being remembered past this eqn. % WSPR: err, why isn't that just \global\let\found@punct\@empty ? \def\finish@end{\csname end@#1\endcsname\latex@end{#1}}% \check@punct } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\eqpunct} % User-settable function for handling % the punctuation at the end of an equation. You could, for example, % define it to just discard the punctuation. % \begin{macrocode} \newcommand\eqpunct[1]{\thinspace#1} % \end{macrocode} % \end{macro} % % \begin{macro}{\set@label} % \cs{set@label} just sets \cs{@currentlabel} but it % takes the counter as an argument, in the hope that \latex will some % day provide an improved labeling system that includes type info on the % labels. % \begin{macrocode} \providecommand\set@label[2]{\protected@edef\@currentlabel{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@topspace} % \begin{macro}{\eq@botspace} % The action of \cs{eq@topspace} is complicated by the % need to test whether the \quoted{short} versions of the display skips % should be used. This can be done only after the final parshape % and indent have been determined, so the calls of this function are % buried relatively deeply in the code by comparison to the calls of % \cs{eq@botspace}. This also allows us to optimize % slightly by setting the above-skip with \cs{parskip} instead of % \cs{vskip}. \verb|#1| is either \cs{noindent} or % \verb"\vskip\parskip". % % BRM: Hmm; we need to do *@setspace BEFORE this for small skips to work! % \begin{macrocode} \def\eq@topspace#1{% \begingroup \global\let\EQ@shortskips\@False % \end{macrocode} % If we are in \env{dgroup} or \env{dgroup*} and not before the top % one, we just insert \cs{intereqskip}. Otherwise we must check for % shortskip. % \begin{macrocode} \if\@And{\eq@group}{\@Not\eq@GRP@first@dmath}% %\breqn@debugmsg{Between lines}% \parskip\intereqskip \penalty\intereqpenalty %\breqn@debugmsg{parskip=\the\parskip}% \else \eq@check@shortskip \if\EQ@shortskips \parskip\abovedisplayshortskip \aftergroup\belowdisplayskip\aftergroup\belowdisplayshortskip % \end{macrocode} % BRM: Not exactly \TeX's approach, but seems right\ldots % \begin{macrocode} \ifdim\predisplaysize>\z@\nointerlineskip\fi \else \parskip\abovedisplayskip \fi \fi \if F\eq@frame \else \addtolength\parskip{\eq@framesep+\eq@framewd}% \fi %<*trace> \breqn@debugmsg{Topspace: \theb@@le\EQ@shortskips, \parskip=\the\parskip, \predisplaysize=\the\predisplaysize}% % #1% \endgroup } % \end{macrocode} % \begin{macro}{\eq@check@shortskip} % \changes{v0.96a}{2007/12/17}{Insert \cs{finish@end} if no special % case is found.} % \changes{v0.97a}{2007/12/22}{Use design parameter and fix % shortskips properly.} % \begin{macrocode} \def\eq@check@shortskip {% \global\let\EQ@shortskips\@False \setlength\dim@a{\abovedisplayskip+\ht\EQ@numbox}% % \end{macrocode} % Here we work around the hardwired standard TeX value and use the % designer parameter instead. % \begin{macrocode} \ifdim\leftskip<\predisplaysize \else % \end{macrocode} % If the display was preceeded by a blank line, \cs{predisplaysize} is % $-\cs{maxdimen}$ and so we should insert a fairly large skip to % separate paragraphs, i.e., no short skip. Perhaps this should be a % third parameter \cs{abovedisplayparskip}. % \begin{macrocode} \ifdim -\maxdimen=\predisplaysize \else \if R\eqnumside \global\let\EQ@shortskips\@True \else \if\eq@shiftnumber \else \if T\eqnumplace \ifdim\dim@a<\eq@firstht \global\let\EQ@shortskips\@True \fi \else \setlength\dim@b{\eq@vspan/2}% \ifdim\dim@a<\dim@b \global\let\EQ@shortskips\@True \fi \fi \fi \fi \fi \fi } % \end{macrocode} % \end{macro} % % At the end of an equation, need to put in a pagebreak penalty % and some vertical space. Also set some flags to remove parindent % and extra word space if the current paragraph text continues without an % intervening \cs{par}. % \begin{macrocode} \def\eq@botspace{% \penalty\postdisplaypenalty % \end{macrocode} % Earlier calculations will have set \cs{belowdisplayskip} locally % to \cs{belowdisplayshortskip} if applicable. So we can just use % it here. % \begin{macrocode} \if F\eq@frame \else \addtolength\belowdisplayskip{\eq@framesep+\eq@framewd}% \fi \vskip\belowdisplayskip \@endpetrue % kill parindent if current paragraph continues \global\@ignoretrue % ignore following spaces \eq@resume@parshape } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\eq@resume@parshape} % This should calculate the total height of the equation, % including space above and below, and set prevgraf to the number it would % be if that height were taken up by normally-spaced normal-height % lines. We also need to restore parshape if it had a non-null % value before the equation. Not implemented yet. % \begin{macrocode} \def\eq@resume@parshape{} % \end{macrocode} % \end{macro} % % \section{Preprocessing the equation body} % \begin{macro}{\eq@startup} % Here is the function that initially collects the equation % material in a box. % % \begin{macrocode} \def\eq@startup{% \global\let\EQ@hasLHS\@False \setbox\z@\vbox\bgroup % \noindent \MaybeRawNoindent % no matching \RawParEnd (implicit at box end) \@@math \displaystyle \penalty-\@Mi } % \end{macrocode} % % This setup defines the environment for the first typesetting % pass, note the \cs{hsize} value for example. % \begin{macrocode} \def\eq@setup@a{% \everymath\everydisplay %\let\@newline\eq@newline % future possibility? \let\\\eq@newline \let\insert\eq@insert \let\mark\eq@mark \let\vadjust\eq@vadjust \hsize\maxdimen \pretolerance\@M % \end{macrocode} % Here it is better not to use \cs{@flushglue} (0pt % plus1fil) for \cs{rightskip}, or else a negative penalty % (such as $-99$ for \cs{prerelpenalty}) will tempt % \tex to use more line breaks than necessary in the first typesetting % pass. Ideal values for \cs{rightskip} and % \cs{linepenalty} are unclear to me, but they are rather sensitively % interdependent. Choice of 10000 pt for rightskip is derived by % saying, let's use a value smaller than 1 fil and smaller than % \cs{hsize}, but more than half of \cs{hsize} so that if a line % is nearly empty, the glue stretch factor will always be less than 2.0 % and so the badness will be less than 100 and so \tex will not issue % badness warnings. % \begin{macrocode} \linepenalty\@m \rightskip\z@\@plus\@M\p@ \leftskip\z@skip \parfillskip\z@skip \clubpenalty\@ne \widowpenalty\z@ \interlinepenalty\z@ % \end{macrocode} % After a relation symbol is discovered, binop symbols should start % including a special offset space. % But until then \cs{EQ@prebin@space} is a no-op. % \begin{macrocode} \global\let\EQ@prebin@space\relax % \end{macrocode} % Set binoppenalty and relpenalty high to prohibit line breaks % after mathbins and mathrels. As a matter of fact, the penalties are % then omitted by \tex , since bare glue without a penalty is % \emph{not} a valid breakpoint if it occurs within % mathon\ndash mathoff items. % \begin{macrocode} \binoppenalty\@M \relpenalty\@M } % \end{macrocode} % \end{macro} % % % \begin{figure} % \centering % The contents of an equation after the initial typesetting pass, % as shown by \cs{showlists}. This is the material on which the % \cs{eq@repack} function operates. The equation was % \begin{literalcode} % a=b +\left(\frac{c\sp 2}{2} -d\right) +(e -f) +g % \end{literalcode} % . The contents are shown in four parts in this figure and the next % three. The first part contains two line boxes, one for the mathon % node and one for the LHS. % \begin{literalcode} % \hbox(0.0+0.0)x16383.99998, glue set 1.6384 % .\mathon % .\penalty -10000 % .\glue(\rightskip) 0.0 plus 10000.0 % \penalty 1 % \glue(\baselineskip) 7.69446 % \hbox(4.30554+0.0)x16383.99998, glue set 1.63759 % .\OML/cmm/m/it/10 a % .\glue 2.77771 minus 1.11108 % .\penalty -10001 % .\glue(\rightskip) 0.0 plus 10000.0 % \penalty 2 % \glue(\lineskip) 1.0 % ... % \end{literalcode} % \caption{Preliminary equation contents, part 1} % \end{figure} % \begin{figure}\centering % This is the first part of the RHS, up to the % \cs{right}, where a line break has been forced so that we can break % open the left-right box. % \begin{literalcode} % ... % \penalty 2 % \glue(\lineskip) 1.0 % \hbox(14.9051+9.50012)x16383.99998, glue set 1.63107 % .\penalty -99 % .\glue(\thickmuskip) 2.77771 minus 1.11108 % .\OT1/cmr/m/n/10 = % .\glue(\thickmuskip) 2.77771 minus 1.11108 % .\OML/cmm/m/it/10 b % .\penalty 888 % .\glue -10.5553 % .\rule(*+*)x0.0 % .\penalty 10000 % .\glue 10.5553 % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OT1/cmr/m/n/10 + % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\hbox(14.9051+9.50012)x43.36298 % ..\hbox(0.39998+23.60025)x7.36115, shifted -14.10013 % ...\OMX/cmex/m/n/5 \hat \hat R % ..\hbox(14.9051+6.85951)x11.21368 % ...\hbox(14.9051+6.85951)x11.21368 % ... [fraction contents, elided] % ..\penalty 5332 % ..\glue -10.5553 % ..\rule(*+*)x0.0 % ..\penalty 10000 % ..\glue 10.5553 % ..\glue(\medmuskip) 2.22217 minus 1.66663 % ..\OMS/cmsy/m/n/10 \hat \hat @ % ..\glue(\medmuskip) 2.22217 minus 1.66663 % ..\OML/cmm/m/it/10 d % ..\hbox(0.39998+23.60025)x7.36115, shifted -14.10013 % ...\OMX/cmex/m/n/5 \hat \hat S % .\penalty -10000 % .\glue(\rightskip) 0.0 plus 10000.0 % \penalty 3 % \glue(\lineskip) 1.0 % ... % \end{literalcode} % \caption{Preliminary equation contents, part 2} % \end{figure} % % \begin{figure} % \centering % This is the remainder of the RHS after the post-\cs{right} % split. % \begin{literalcode} % ... % \penalty 3 % \glue(\lineskip) 1.0 % \hbox(7.5+2.5)x16383.99998, glue set 1.63239 % .\penalty 888 % .\glue -10.5553 % .\rule(*+*)x0.0 % .\penalty 10000 % .\glue 10.5553 % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OT1/cmr/m/n/10 + % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OT1/cmr/m/n/10 ( % .\OML/cmm/m/it/10 e % .\penalty 5332 % .\glue -10.5553 % .\rule(*+*)x0.0 % .\penalty 10000 % .\glue 10.5553 % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OMS/cmsy/m/n/10 \hat \hat @ % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OML/cmm/m/it/10 f % .\kern1.0764 % .\OT1/cmr/m/n/10 ) % .\penalty 888 % .\glue -10.5553 % .\rule(*+*)x0.0 % .\penalty 10000 % .\glue 10.5553 % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OT1/cmr/m/n/10 + % .\glue(\medmuskip) 2.22217 minus 1.66663 % .\OML/cmm/m/it/10 g % .\kern0.35878 % .\penalty -10000 % .\glue(\rightskip) 0.0 plus 10000.0 % \glue(\baselineskip) 9.5 % ... % \end{literalcode} % \caption{Preliminary equation contents, part 3} % \end{figure} % % \begin{figure} % \centering % This is the mathoff fragment. % \begin{literalcode} % ... % \glue(\baselineskip) 9.5 % \hbox(0.0+0.0)x16383.99998, glue set 1.6384 % .\mathoff % .\penalty 10000 % .\glue(\parfillskip) 0.0 % .\glue(\rightskip) 0.0 plus 10000.0 % \end{literalcode} % \caption{Preliminary equation contents, part 4} % \end{figure} % % \begin{macro}{\eq@capture} % \begin{macro}{\eq@punct} % If an equation ends with a \cs{right} delim, the last thing % on the math list will be a force-break penalty. Then don't % redundantly add another forcing penalty. (question: when does a % penalty after a linebreak not disappear? Answer: when you have % two forced break penalties in a row). Ending punctuation, if % any, goes into the last box with the mathoff kern. If the math list % ends with a slanted letter, then there will be an italic correction % added after it by \tex . Should we remove it? I guess % so. % % % \subsection{Capturing the equation} % % BRM: There's a problem here (or with \cs{ss@scan}). If the LHS has % \cs{left} \cs{right} pairs, \cs{ss@scan} gets involved. It seems to produce % a separate box marked w/\cs{penalty} 3. But it appears that \cs{eq@repack} % is only expecting a single box for the LHS; when it measures that % box it's missing the (typically larger) bracketted section, % so the LHS is measured => 0pt (or very small). % I'm not entirely clear what Michael had in mind for this case; % whether it's an oversight, or whether I've introduced some other bug. % At any rate, my solution is to measure the RHS (accumulated in \cs{EQ@box}), % at the time of the relation, and subtract that from the total size. % \begin{macrocode} \newdimen\eq@wdR\eq@wdR\z@%BRM \def\eq@capture{% \ifnum\lastpenalty>-\@M \penalty-\@Mi \fi % \end{macrocode} % We want to keep the mathoff kern from vanishing at the line break, % so that we can reuse it later. % \begin{macrocode} \keep@glue\@@endmath \eq@addpunct \@@par \eq@wdL\z@ % \end{macrocode} % First snip the last box, which contains the mathoff node, and put it % into \cs{EQ@box}. Then when we call \cs{eq@repack} it % will recurse properly. % \begin{macrocode} \setbox\tw@\lastbox \global\setbox\EQ@box\hbox{\unhbox\tw@\unskip\unskip\unpenalty}% \unskip\unpenalty \global\setbox\EQ@copy\copy\EQ@box %% \global\setbox\EQ@vimcopy\copy\EQ@vimbox \clubpenalty\z@ %\batchmode\showboxbreadth\maxdimen\showboxdepth99\showlists\errorstopmode \eq@wdR\z@%BRM: eq@wdL patch \eq@repack % recursive % \end{macrocode} % Finally, add the mathon item to \cs{EQ@box} and \cs{EQ@copy}. % \begin{macrocode} \setbox\tw@\lastbox \global\setbox\EQ@box\hbox{\unhcopy\tw@\unskip\unpenalty \unhbox\EQ@box}% \global\setbox\EQ@copy\hbox{\unhbox\tw@\unskip\unpenalty \unhbox\EQ@copy}% %\batchmode\showbox\EQ@copy \showthe\eq@wdL\errorstopmode \ifdim\eq@wdR>\z@% BRM: eq@wdL patch \setlength\dim@a{\wd\EQ@box-\eq@wdR % Apparently missing a \thickmuskip = 5mu = 5/18em=0.27777777777.. ? + 0.2777777777777em}% FUDGE??!?!?! \ifdim\dim@a>\eq@wdL %<*trace> \breqn@debugmsg{Correcting LHS from \the\eq@wdL\space to \the\dim@a = \the\wd\EQ@box - \the\eq@wdR}% % \eq@wdL\dim@a \xdef\EQ@setwdL{\eq@wdL\the\eq@wdL\relax}% \fi \fi %<*trace> \breqn@debugmsg{Capture: total length=\the\wd\EQ@box \MessageBreak ==== has LHS=\theb@@le\EQ@hasLHS, \eq@wdL=\the\eq@wdL, \eq@wdR=\the\eq@wdR, \MessageBreak ==== \eq@wdCond=\the\eq@wdCond}% % \egroup % end vbox started earlier %<*trace> %\debugwr{EQ@box}\debug@box\EQ@box %\debugwr{EQ@copy}\debug@box\EQ@copy % } % \end{macrocode} % Now we have two copies of the equation, one in \cs{EQ@box}, % and one in \cs{EQ@copy} with inconvenient stuff like inserts and % marks omitted. % % \cs{eq@addpunct} is for tacking on text punctuation at the end % of a display, if any was captured by the \quoted{gp} lookahead. % \begin{macrocode} \def\eq@addpunct{% \ifx\found@punct\@empty \else \eqpunct{\found@punct}% \fi % BRM: Added; the punctuation kept getting carried to following environs \xdef\found@punct{\@empty}% \EQ@afterspace } % \end{macrocode} % Needed for the \env{dseries} environment, among other things. % \begin{macrocode} \global\let\EQ@afterspace\@empty % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\eq@repack} % The \cs{eq@repack} function looks at the information at hand % and proceeds accordingly. % % TeX Note: this scans BACKWARDS from the end of the math. % \begin{macrocode} \def\eq@repack{% % A previous penalty of 3 on the vertical list means that we need % to break open a left-right box. % \begin{macrocode} \ifcase\lastpenalty % case 0: normal case \setbox\tw@\lastbox \eq@repacka\EQ@copy \eq@repacka\EQ@box \unskip \or % case 1: finished recursing % \end{macrocode} % Grab the mathon object since we need it to inhibit line breaking at % bare glue nodes later. % \begin{macrocode} \unpenalty \setbox\tw@\lastbox \eq@repacka\EQ@copy \eq@repacka\EQ@box \@xp\@gobble \or % case 2: save box width = LHS width % \end{macrocode} % Don't need to set \cs{EQ@hasLHS} here because it was set earlier % if applicable. % \begin{macrocode} \unpenalty \setbox\tw@\lastbox \setbox\z@\copy\tw@ \setbox\z@\hbox{\unhbox\z@\unskip\unpenalty}% \addtolength\eq@wdL{\wd\z@} \setlength\eq@wdR{\wd\EQ@box}% BRM: eq@wdL patch \xdef\EQ@setwdL{\eq@wdL\the\eq@wdL\relax}% % \end{macrocode} % At this point, box 2 typically ends with % \begin{literalcode} % .\mi10 a % .\glue 2.77771 plus 2.77771 % .\penalty -10001 % .\glue(\rightskip) 0.0 plus 10000.0 % \end{literalcode} % and we want to ensure that the thickmuskip glue gets removed. % And we now arrange for \cs{EQ@copy} and \cs{EQ@box} to % keep the LHS in a separate subbox; this is so that we can introduce a % different penalty before the first relation symbol if necessary, % depending on the layout decisions that are made later. % \begin{macrocode} \global\setbox\EQ@copy\hbox{% \hbox{\unhcopy\tw@\unskip\unpenalty\unskip}% \box\EQ@copy }% \global\setbox\EQ@box\hbox{% \hbox{\unhbox\tw@\unskip\unpenalty\unskip}% \box\EQ@box }% \unskip \or % case 3: unpack left-right box \unpenalty \eq@lrunpack \else \breqn@repack@err \fi \eq@repack % RECURSE } % \end{macrocode} % Error message extracted to streamline calling function. % \begin{macrocode} \def\breqn@repack@err{% \PackageError{breqn}{eq@repack penalty neq 0,1,2,3}\relax } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@repacka} % We need to transfer each line into two separate boxes, one % containing everything and one that omits stuff like \cs{insert}s % that would interfere with measuring. % \begin{macrocode} \def\eq@repacka#1{% \global\setbox#1\hbox{\unhcopy\tw@ \unskip \count@-\lastpenalty \ifnum\count@<\@M \else \advance\count@-\@M \fi \unpenalty % \end{macrocode} % If creating the measure copy, ignore all cases above case 3 by % folding them into case 1. % \begin{macrocode} \ifx\EQ@copy#1\ifnum\count@>\thr@@ \count@\@ne\fi\fi \ifcase\count@ % case 0, normal line break \penalty-\@M % put back the linebreak penalty \or % case 1, do nothing (end of equation) \relax \or % case 2, no-op (obsolete case) \or % case 3, transfer vspace and/or penalty \ifx#1\EQ@box \eq@revspace \else \eq@revspaceb \fi \or % case 4, put back an insert \eq@reinsert \or % case 5, put back a mark \eq@remark \or % case 6, put back a vadjust \eq@readjust \else % some other break penalty \penalty-\count@ \fi \unhbox#1}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@nulldisplay} % Throw in a null display in order to get predisplaysize \etc . % My original approach here was to start the null display, then measure % the equation, and set a phantom of the equation's first line before % ending the null display. That would allow finding out if \tex used % the short displayskips instead of the normal ones. But because of % some complications with grouping and the desirability of omitting % unnecessary invisible material on the vertical list, it seems better to % just collect information about the display (getting \cs{prevdepth} % requires \cs{halign}) and manually perform our own version of % \TeX's shortskip calculations. This approach also gives greater % control, \eg , the threshold amount of horizontal space between % predisplaysize and the equation's left edge that determines when the % short skips kick in becomes a designer-settable parameter rather than % hardwired into \TeX . % \begin{macrocode} \def\eq@nulldisplay{% \begingroup \frozen@everydisplay\@emptytoks \@@display \predisplaypenalty\@M \postdisplaypenalty\@M \abovedisplayskip\z@skip \abovedisplayshortskip\z@skip \belowdisplayskip\z@skip \belowdisplayshortskip\z@skip \xdef\EQ@displayinfo{% \prevgraf\the\prevgraf \predisplaysize\the\predisplaysize \displaywidth\the\displaywidth \displayindent\the\displayindent \listwidth\the\linewidth % \end{macrocode} % Not sure how best to test whether leftmargin should be % added. Let's do this for now [mjd,1997/10/08]. % \begin{macrocode} \ifdim\displayindent>\z@ \advance\listwidth\the\leftmargin \advance\listwidth\the\rightmargin \fi \relax}% % \end{macrocode} % An \cs{halign} containing only one \cs{cr} (for the % preamble) puts no box on the vertical list, which means that no % \cs{baselineskip} will be added (so we didn't need to set it to % zero) and the previous value of prevdepth carries through. Those % properties do not hold for an empty simple equation without % \cs{halign}. % \begin{macrocode} \halign{##\cr}% \@@enddisplay \par \endgroup \EQ@displayinfo } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@newline} % \begin{macro}{\eq@newlinea} % \begin{macro}{\eq@newlineb} % Here we use \cs{@ifnext} so that in a sequence like % \begin{literalcode} % ...\\ % [a,b] % \end{literalcode} % \latex does not attempt to interpret the \verb"[a,b]" as a % vertical space amount. We would have used \cs{eq@break} in the % definition of \cs{eq@newlineb} except that it puts in a % \cs{keep@glue} object which is not such a good idea if a mathbin % symbol follows \mdash the indent of the mathbin will be wrong because % the leading negative glue will not disappear as it should at the line % break. % \begin{macrocode} \def\eq@newline{% \breqn@ifstar{\eq@newlinea\@M}{\eq@newlinea\eqinterlinepenalty}} \def\eq@newlinea#1{% \@ifnext[{\eq@newlineb{#1}}{\eq@newlineb{#1}[\maxdimen]}} \def\eq@newlineb#1[#2]{\penalty-\@M} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\eq@revspace} % \begin{macro}{\eq@revspaceb} % When \cs{eq@revspace} (re-vspace) is called, we are the % end of an equation line; we need to remove the existing penalty of % $-10002$ in order to put a vadjust object in front of it, then put % back the penalty so that the line break will still take place in the % final result. % \begin{macrocode} \def\eq@revspace{% \global\setbox\EQ@vimbox\vbox{\unvbox\EQ@vimbox \unpenalty \global\setbox\@ne\lastbox}% \@@vadjust{\unvbox\@ne}% \penalty-\@M } % \end{macrocode} % The b version is used for the \cs{EQ@copy} box. % \begin{macrocode} \def\eq@revspaceb{% \global\setbox\EQ@vimcopy\vbox{\unvbox\EQ@vimcopy \unpenalty \global\setbox\@ne\lastbox}% \@@vadjust{\unvbox\@ne}% \penalty-\@M } % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\eq@break} % The function \cs{eq@break} does a preliminary linebreak with % a flag penalty. % \begin{macrocode} \def\eq@break#1{\penalty-1000#1 \keep@glue} % \end{macrocode} % \end{macro} % % % % % \section{Choosing optimal line breaks} % The question of what line width to use when breaking an % equation into several lines is best examined in the light of an extreme % example. Suppose we have a two-column layout and a displayed % equation falls inside a second-level list with nonzero leftmargin and % rightmargin. Then we want to try in succession a number of % different possibilities. In each case if the next possibility is % no wider than the previous one, skip ahead to the one after. % \begin{enumerate} % \item First try linewidth(2), the linewidth for the current % level-2 list. % % % \item If we cannot find adequate linebreaks at that width, next try % listwidth(2), the sum of leftmargin, linewidth, and rightmargin for % the current list. % % % \item If we cannot find linebreaks at that width, next try linewidth % (1) (skipping this step if it is no larger then % listwidth(2)). % % % \item If we cannot find linebreaks at that width, next try % listwidth(1). % % % \item If we cannot find linebreaks at that width, next try column % width. % % % \item If we cannot find linebreaks at that width, next try text % width. % % % \item If we cannot find linebreaks at that width, next try equation % width, if it exceeds text width (\ie , if the style allows equations % to extend into the margins). % % % \end{enumerate} % % % \begin{figure} % \centering % needs work % \caption{first-approximation parshape for equations}\label{f:parshape-1} % \end{figure} % % At any given line width, we run through a series of parshape % trials and, essentially, use the first one that gives decent line % breaks. % But the process is a bit more complicated in fact. % In order to do a really good job of setting up the parshapes, we % need to know how many lines the equation will require. % And of course the number of lines needed depends on the parshape! % So as our very first trial we run a simple first-approximation % parshape (Figure~\vref{f:parshape-1}) whose % main purpose is to get an estimate on the number of lines that will be % needed; it chooses a uniform indent for all lines after the first one % and does not take any account of the equation number. % A substantial majority of equations only require one line anyway, % and for them this first trial will succeed. % In the one-line case if there is an equation number and it doesn't % fit on the same line as the equation body, we don't go on to other % trials because breaking up the equation body will not gain us % anything\mdash we know that we'll have to use two lines in any case % \mdash so we might as well keep the equation body together on one line % and shift the number to a separate line. % % If we learn from the first trial that the equation body % requires more than one line, the next parshape trial involves adjusting % the previous parshape to leave room for the equation number, if % present. If no number is present, again no further trials are % needed. % % Some remarks about parshape handling. The \tex % primitive doesn't store the line specs anywhere, \verb"\the\parshape" % only returns the number of line specs. This makes it well nigh % impossible for different packages that use \cs{parshape} to work % together. Not that it would be terribly easy for the package % authors to make inter-package collaboration work, if it were % possible. If we optimistically conjecture that % someone some day may take on such a task, then the thing to do, % obviously, is provide a parshape interface that includes a record of all % the line specs. For that we designate a macro \cs{@parshape} % which includes not only the line specs, but also the line count and even % the leading \cs{parshape} token. % This allows it to be directly executed without an auxiliary if-empty % test. It should include a trailing \cs{relax} when it has a % nonempty value. % \begin{macrocode} \let\@parshape\@empty % \end{macrocode} % % % The function \cs{eq@measure} runs line-breaking trials % on the copy of the equation body that is stored in the box register % \cs{EQ@copy}, trying various possible layouts in order of % preference until we get successful line breaks, where \quoted{successful} % means there were no overfull lines. The result of the trials is, % first, a parshape spec that can be used for typesetting the real % equation body in \cs{EQ@box}, and second, some information that % depends on the line breaks such as the depth of the last line, the % height of the first line, and positioning information for the equation % number. The two main variables in the equation layout are the line % width and the placement of the equation number, if one is present. % % % \begin{macro}{\eq@measure} % Run linebreak trials on the equation contents and measure the % results. % \begin{macrocode} \def\eq@measure{% % \end{macrocode} % If an override value is given for indentstep in the env options, use % it. % \begin{macrocode} \ifdim\eq@indentstep=\maxdimen \eq@indentstep\eqindentstep \fi % \end{macrocode} % If \cs{eq@linewidth} is nonzero at this point, it means that % the user specified a particular target width for this equation. % In that case we override the normal list of trial widths. % \begin{macrocode} \ifdim\eq@linewidth=\z@ \else \edef\eq@linewidths{{\the\eq@linewidth}}\fi \begingroup \eq@params \leftskip\z@skip % \end{macrocode} % Even if \cs{hfuzz} is greater than zero a box whose contents % exceed the target width by less then hfuzz still has a reported badness % value of 1000000 (infinitely bad). Because we use inf-bad % to test whether a particular trial succeeds or fails, we want to make % such boxes return a smaller badness. To this end we include an % \cs{hfuzz} allowance in \cs{rightskip}. In fact, % \cs{eq@params} ensures that \cs{hfuzz} for equations is at % least 1pt. % \begin{macrocode} \rightskip\z@\@plus\columnwidth\@minus\hfuzz % \eqinfo \global\EQ@continue{\eq@trial}% \eq@trial % uses \eq@linewidths \eq@failout % will be a no-op if the trial succeeded \endgroup % \end{macrocode} % \quoted{local} parameter settings are passed outside the endgroup through % \cs{EQ@trial}. % \begin{macrocode} \EQ@trial } % \end{macrocode} % \end{macro} % \begin{macrocode} %<*trace> \def\debug@showmeasurements{% \breqn@debugmsg{=> \number\eq@lines\space lines}% \begingroup \def\breqn@elt##1X##2{\MessageBreak==== \space\space##1/##2}% \let\breqn@endelt\@empty \breqn@debugmsg{=> trial info:\eq@measurements}% \breqn@debugmsg{=> bounding box: \the\eq@wdT x\the\eq@vspan, badness=\the\eq@badness}% \let\breqn@elt\relax \let\breqn@endelt\relax \endgroup } \def\debug@showmeasurements{% \begingroup \def\breqn@elt##1X##2{\MessageBreak==== ##1/##2}% \let\breqn@endelt\@empty \breqn@debugmsg{===> Measurements: \number\eq@lines\space lines \eq@measurements \MessageBreak ==== bounding box: \the\eq@wdT x\the\eq@vspan, badness=\the\eq@badness \MessageBreak ==== \leftskip=\the\leftskip, \rightskip=\the\rightskip}% \endgroup } % % \end{macrocode} % % Layout Trials Driver % Basically, trying different sequences of parshapes. % % % \begin{macro}{\EQ@trial} % Init. % \begin{macrocode} \let\EQ@trial\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\EQ@continue} % This is a token register used to carry trial info past a % group boundary with only one global assignment. % \begin{macrocode} \newtoks\EQ@continue % \end{macrocode} % \end{macro} % % % \begin{macro}{\EQ@widths} % This is used for storing the actual line-width info of the equation % contents after breaking. % \begin{macrocode} \let\EQ@widths\@empty % \end{macrocode} % \end{macro} % \begin{macro}{\EQ@fallback} % \begin{macrocode} \let\EQ@fallback\@empty % \end{macrocode} % \end{macro} % \begin{macro}{\eq@linewidths} % This is the list of target widths for line breaking. % %======================================== % BRM: Odd; I don't think I've seen this use anything but \cs{displaywidth}... % \begin{macrocode} \def\eq@linewidths{\displaywidth\linewidth\columnwidth} % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@trial} % The \cs{eq@trial} function tries each candidate % line width in \cs{eq@linewidths} until an equation layout is found % that yields satisfactory line breaks. % \begin{macrocode} \def\eq@trial{% \ifx\@empty\eq@linewidths \global\EQ@continue{}% \else \iffalse{\fi \@xp\eq@trial@a \eq@linewidths}% \fi \the\EQ@continue } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@trial@a} % The \cs{eq@trial@a} function reads the leading line % width from \cs{eq@linewidths}; if the new line width is greater % than the previous one, start running trials with it; otherwise do % nothing with it. % Finally, run a peculiar \cs{edef} that leaves % \cs{eq@linewidths} redefined to be the tail of the list. % If we succeed in finding satisfactory line breaks % for the equation, we will reset \cs{EQ@continue} in such a % way that it will terminate the current trials. % An obvious branch here would be to check whether the width of % \cs{EQ@copy} is less than \cs{eq@linewidth} and go immediately % to the one-line case if so. % However, if the equation contains more than one RHS, by % default each additional RHS starts on a new line\mdash \ie , we want % the ladder layout anyway. % So we choose the initial trial on an assumption of multiple lines % and leave the one-line case to fall out naturally at a later point. % \begin{macrocode} \def\eq@trial@a#1{% \dim@c#1\relax \if T\eq@frame \eq@frame@adjust\dim@c \fi \ifdim\dim@c>\eq@linewidth \eq@linewidth\dim@c % \breqn@debugmsg{Choose Shape for width(#1)=\the\eq@linewidth}% \let\eq@trial@b\eq@trial@d \csname eq@try@layout@\eq@layout\endcsname % \else % \breqn@debugmsg{Next width (#1) is shorter; skip it}% \fi \edef\eq@linewidths{\iffalse}\fi } \def\eq@frame@adjust#1{% %\addtolength#1{-2\eq@framewd-2\eq@framesep}% \dim@a\eq@framewd \advance\dim@a\eq@framesep \advance#1-2\dim@a } % \end{macrocode} % \end{macro} %======================================== % Note curious control structure. % Try to understand interaction of \cs{EQ@fallback}, \cs{EQ@continue}, % \cs{eq@failout} % \begin{macrocode} \def\eq@trial@succeed{% \aftergroup\@gobbletwo % cancel the \EQ@fallback code; see \eq@trial@c (?) \global\EQ@continue{\eq@trial@done}% } % \end{macrocode} % \begin{macro}{\eq@trial@done} % Success. % \begin{macrocode} \def\eq@trial@done{% % \breqn@debugmsg{End trial: Success!}% \let\eq@failout\relax } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@trial@init} % This is called from \cs{eq@trial@b} to initialize or % re-initialize certain variables as needed when running one or more % trials at a given line width. % By default assume success, skip the fallback code. % \begin{macrocode} \def\eq@trial@init{\global\let\EQ@fallback\eq@nextlayout} % \end{macrocode} % \end{macro} % \begin{macro}{\eq@nextlayout} % % In the fallback case cancel the current group to avoid unnecessary % group nesting (with associated save-stack cost, \etc ). % \begin{macrocode} \def\eq@nextlayout#1{% \endgroup % \breqn@debugmsg{Nope ... that ain't gonna work.}% \begingroup #1% } % \end{macrocode} % \end{macro} % \begin{macro}{\eq@failout} % % . % \begin{macrocode} \def\eq@failout{% %\breqn@debugmsg{End trial: failout}% \global\let\EQ@trial\EQ@last@trial } % \end{macrocode} % \end{macro} % \begin{macro}{\eq@trial@save} % % Save the parameters of the current trial. % \begin{macrocode} \def\eq@trial@save#1{% %<*trace> % \begingroup \def\breqn@elt##1X##2{\MessageBreak==== \space\space##1/##2}\let\breqn@endelt\@empty\breqn@debugmsg{=> trial info:\eq@measurements}% % \breqn@debugmsg{=> bounding box: \the\eq@wdT x\the\eq@vspan, badness=\the\eq@badness\MessageBreak}% % \let\breqn@elt\relax \let\breqn@endelt\relax % \endgroup % \xdef#1{% \eq@linewidth\the\eq@linewidth % save info about the fit \eq@lines\the\eq@lines \eq@badness\the\eq@badness \def\@nx\eq@badline{\eq@badline}% % save size info \eq@wdT\the\eq@wdT \eq@wdMin\the\eq@wdMin \eq@vspan\the\eq@vspan \eq@dp\the\eq@dp \eq@firstht\the\eq@firstht % save info about the LHS \eq@wdL\the\eq@wdL \def\@nx\EQ@hasLHS{\EQ@hasLHS}% % save info about the numbering \def\@nx\eq@hasNumber{\eq@hasNumber}% % save info about the chosen layout \def\@nx\eq@layout{\eq@layout}% \def\@nx\eq@parshape{\@parshape}% \def\@nx\eq@measurements{\eq@measurements}% \def\@nx\adjust@rel@penalty{\adjust@rel@penalty}% \def\@nx\eq@shiftnumber{\eq@shiftnumber}% \def\@nx\eq@isIntertext{\@False}% }% } % \end{macrocode} % \end{macro} % \begin{macro}{\eq@trial@b} % % By default this just runs \cs{eq@trial@c}; \cf % \cs{eq@trial@d}. % \begin{macrocode} \def\eq@trial@b{\eq@trial@c} % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@trial@c} % % Run the equation contents through the current parshape. % \begin{macrocode} \def\eq@trial@c#1#2{% % \breqn@debugmsg{Trying layout "#1" with\MessageBreak==== parshape\space\@xp\@gobble\@parshape}% \begingroup \eq@trial@init \def\eq@layout{#1}% \setbox\z@\vbox{% \hfuzz\maxdimen \eq@trial@p % run the given parshape \if\@Not{\eq@badline}% \eq@trial@save\EQ@trial % \end{macrocode} % If there is a number, try the same parshape again with adjustments % to make room for the number. % % This is an awkward place for this: % It only allows trying to fit the number w/the SAME layout shape! % \begin{macrocode} \if\eq@hasNumber\eq@retry@with@number\fi \if L\eq@layout \eq@check@density \else \if\@Not{\eq@badline}% \eq@trial@succeed \fi \fi \else \eq@trial@save\EQ@last@trial \fi }% \EQ@fallback{#2}% \endgroup } % \end{macrocode} % \end{macro} % \begin{macro}{\eq@trial@d} % \begin{macrocode} \def\eq@trial@d#1#2{\eq@trial@c{#1}{}} % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@check@density} % \begin{macrocode} \def\eq@check@density{% % \breqn@debugmsg{Checking density for layout L}% \if\@Or{\@Not\EQ@hasLHS}{\eq@shortLHS}% % \breqn@debugmsg{Density check: No LHS, or is short; OK}% \eq@trial@succeed \else\if\eq@dense@enough \eq@trial@succeed \fi\fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@shortLHS} % Test to see if we need to apply the \cs{eq@dense@enough} test. % \begin{macrocode} \def\eq@shortLHS{\ifdim\eq@wdL>.44\eq@wdT 1\else 0\fi 0} % \end{macrocode} % \end{macro} % %\verb|\def\eq@shortLHS{\@False}| %======================================== % \begin{macro}{\eq@trial@p} % Run a trial with the current \cs{@parshape} and measure it. % \begin{macrocode} \def\eq@trial@p{% \@parshape % \eq@dump@box\unhcopy\EQ@copy {\@@par}% leave \parshape readable \eq@lines\prevgraf \eq@fix@lastline \let\eq@badline\@False \if i\eq@layout \ifnum\eq@lines>\@ne \let\eq@badline\@True \fi\fi \eq@curline\eq@lines % loop counter for eq@measure@lines \let\eq@measurements\@empty \eq@ml@record@indents \eq@measure@lines \eq@recalc % \debug@showmeasurements } % \end{macrocode} % \end{macro} % % % \begin{macro}{\adjust@rel@penalty} % Normally this is a no-op. % \begin{macrocode} \let\adjust@rel@penalty\@empty % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@fix@lastline} % Remove parfillskip from the last line box. % \begin{macrocode} \def\eq@fix@lastline{% \setbox\tw@\lastbox \dim@b\wd\tw@ \eq@dp\dp\tw@ % \end{macrocode} % Remove \cs{parfillskip} but retain \cs{rightskip}. % Need to keep the original line width for later shrink testing. % \begin{macrocode} \nointerlineskip\hbox to\dim@b{\unhbox\tw@ \skip@c\lastskip \unskip\unskip\hskip\skip@c }% } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@recalc} % Calculate \cs{eq@wdT} et cetera. % \begin{macrocode} \def\eq@recalc{% \eq@wdT\z@ \eq@wdMin\maxdimen \eq@vspan\z@skip \eq@badness\z@ \let\breqn@elt\eq@recalc@a \eq@measurements \let\breqn@elt\relax } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@recalc@a} % \begin{macrocode} \def\eq@recalc@a#1x#2+#3\breqn@endelt{% \eq@firstht#2\relax \let\breqn@elt\eq@recalc@b \breqn@elt#1x#2+#3\breqn@endelt } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@recalc@b} % \begin{macrocode} \def\eq@recalc@b#1X#2,#3x#4+#5@#6\breqn@endelt{% \setlength\dim@a{#2+#3}% \ifdim\dim@a>\eq@wdT \eq@wdT\dim@a \fi \ifdim\dim@a<\eq@wdMin \eq@wdMin\dim@a \fi \eq@dp#5\relax \addtolength\eq@vspan{#1+#4+\eq@dp}% % \end{macrocode} % Record the max badness of all the lines in \cs{eq@badness}. % \begin{macrocode} \ifnum#6>\eq@badness \eq@badness#6\relax\fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@layout} % A value of \verb"?" for \cs{eq@layout} means that we should % deduce which layout to use by looking at the size of the components. % Any other value means we have a user-specified override on the % layout. % % Layout Definitions. % Based on initial equation measurements, we can choose a sequence of % candidate parshapes that the equation might fit into. % We accept the first shape that `works', else fall to next one. % [The sequence is hardcoded in the \cs{eq@try@layout@} % Would it be useful be more flexible? (eg. try layouts LDA, in order...)] % \begin{macrocode} \def\eq@layout{?} % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@try@layout@?} % This is a branching function used to choose a suitable layout if % the user didn't specify one in particular. % % Default layout: % Try Single line layout first, else try Multiline layouts % \begin{macrocode} \@namedef{eq@try@layout@?}{% \let\eq@trial@b\eq@trial@c \edef\@parshape{\parshape 1 0pt \the\eq@linewidth\relax}% % \eq@trial@b{i}{\eq@try@layout@multi}% \setlength\dim@a{\wd\EQ@copy-2em}% Fudge; can't shrink more than this? % if we're in a numbered group, try hard to fit within the numbers \dim@b\eq@linewidth \if\eq@shiftnumber\else\if\eq@group \if\eq@hasNumber\addtolength\dim@b{-\wd\EQ@numbox-\eqnumsep}% \else\if\grp@hasNumber\addtolength\dim@b{-\wd\GRP@numbox-\eqnumsep}% \fi\fi\fi\fi \ifdim\dim@a<\dim@b% Do we even have a chance of fitting to one line? % \breqn@debugmsg{Choose Shape: (\the\wd\EQ@copy) may fit in \the\dim@b}% % \end{macrocode} % BRM: assuming it might fit, don't push too hard % \begin{macrocode} \setlength\dim@b{\columnwidth-\dim@a+\eq@wdCond}% \rightskip\z@\@plus\dim@b\@minus\hfuzz \eq@trial@b{i}{\eq@try@layout@multi}% \else %<*trace> \breqn@debugmsg{Choose Shape: Too long (\the\wd\EQ@copy) for one line (free width=\the\dim@b)}% % \eq@try@layout@multi \fi } % \end{macrocode} % Layout Multiline layout: % If no LHS, try Stepped(S) layout % Else try Stepped(S), Ladder(L), Drop-ladder(D) or Stepladder(l), depending on LHS length. % \begin{macrocode} \def\eq@try@layout@multi{% \if\EQ@hasLHS \ifdim\eq@wdL>\eq@linewidth % \breqn@debugmsg{Choose Shape: LHS \the\eq@wdL > linewidth}% % \end{macrocode} % Find the total width of the RHS. % If it is relatively short, a step layout is the thing to try. % \begin{macrocode} \setlength\dim@a{\wd\EQ@copy-\eq@wdL}% \ifdim\dim@a<.25\eq@linewidth \eq@try@layout@S \else \eq@try@layout@l \fi % BRM: Originally .7: Extreme for L since rhs has to wrap within the remaining 30+%! \else\ifdim\eq@wdL>.50\eq@linewidth %<*trace> \breqn@debugmsg{Choose Shape: LHS (\the\eq@wdL) > .50 linewidth (linewidth=\the\eq@linewidth)}% % \eq@try@layout@D \else % \breqn@debugmsg{Choose Shape: LHS (\the\eq@wdL) not extraordinarily wide}% \eq@try@layout@L \fi\fi \else % \breqn@debugmsg{Choose Shape: No LHS here}% % \end{macrocode} % Try one-line layout first, then step layout. % \begin{macrocode} \eq@try@layout@S % (already checked case i) \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@try@layout@D} % Change the penalty before the first mathrel symbol to encourage a % break there. % % Layout D=Drop-Ladder Layout, for wide LHS. % \begin{literalcode} % LOOOOOOOONG LHS % = RHS % = ... % \end{literalcode} % If fails, try Almost-Columnar layout % \begin{macrocode} \def\eq@try@layout@D{% \setlength\dim@a{\eq@linewidth -\eq@indentstep}% \edef\@parshape{\parshape 2 0pt \the\eq@wdL\space \the\eq@indentstep\space \the\dim@a\relax }% \def\adjust@rel@penalty{\penalty-99 }% \eq@trial@b{D}{\eq@try@layout@A}% } % \end{macrocode} % \end{macro} % \begin{macro}{\eq@try@layout@L} % Try a straight ladder layout. % Preliminary filtering ensures that \cs{eq@wdL} is less than 70% % of the current line width. % \begin{literalcode} % Layout L=Ladder layout % LHS = RHS % = RHS % ... % \end{literalcode} % If fails, try Drop-ladder layout. % NOTE: This is great for some cases (multi relations?), but % tends to break really badly when it fails.... % \begin{macrocode} \def\eq@try@layout@L{% \setlength\dim@b{\eq@linewidth-\eq@wdL}% \edef\@parshape{\parshape 2 0pt \the\eq@linewidth\space \the\eq@wdL\space \the\dim@b\relax }% \eq@trial@b{L}{\eq@try@layout@D}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@try@layout@S} % In the \dquoted{stepped} layout there is no LHS, or LHS % is greater than the line width and RHS is small. % Then we want to split up the equation into lines of roughly equal % width and stagger them downwards to the right, leaving a small amount of % whitespace on both sides. % But also, if there is an equation number, we want to try first a % layout that leaves room for the number. % Otherwise it would nearly always be the case that the number would % get thrown on a separate line. % % Layout S=Stepped layout, typically no LHS or very long, variations on % \begin{literalcode} % STUFF .... % + MORE STUFF ... % + MORE STUFF ... % \end{literalcode} % If fails, try Almost-Columnar layout % \begin{macrocode} \def\eq@try@layout@S{% \setlength\dim@b{\eq@linewidth-2\eqmargin}% \advance\dim@b-1em% % \end{macrocode} % About how many lines will we need if dim@b is the line width? % \begin{macrocode} \int@a\wd\EQ@copy \divide\int@a\dim@b % \end{macrocode} % Adjust the target width by number of lines times indentstep. % We don't need to decrement \cs{int@a} because \tex % division is integer division with truncation. % \begin{macrocode} \addtolength\dim@b{-\int@a\eq@indentstep}% % \end{macrocode} % Adjust for equation number. % But try not to leave too little room for the equation body. % \begin{macrocode} \if\eq@hasNumber \ifdim\dim@b>15em% % \advance\dim@b-\eqnumsep \advance\dim@b-\wd\EQ@numbox \addtolength\dim@b{-\eq@wdNum}% \fi \fi % \end{macrocode} % Now some hand-waving to set up the parshape. % \begin{macrocode} \int@b\z@ \def\@tempa{\dim}% \edef\@parshape{\parshape 2 0pt \the\dim@b\space \the\eqmargin\space\the\dim@b\relax}% \eq@trial@b{S}{\eq@try@layout@A}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@try@layout@l} % This is the \dquoted{step-ladder} layout: similar to the drop-ladder % layout but the LHS is too wide and needs to be broken up. % % Layout l = Stepladder % Similar to Drop-Ladder, but LHS is long and needs to be broken up. % If fails, try Almost-Columnar layout % \begin{macrocode} \def\eq@try@layout@l{% \setlength\dim@a{\eq@linewidth -\eq@indentstep}% \int@a\eq@wdL \divide\int@a\dim@a \advance\int@a\tw@ \edef\@parshape{\parshape \number\int@a\space 0pt \the\eq@linewidth }% \advance\int@a-\tw@ \setlength\dim@b{2\eq@indentstep}% \setlength\dim@c{\eq@linewidth -\dim@b}% \edef\@parshape{\@parshape \replicate{\int@a}{\space\the\eq@indentstep\space\the\dim@a}% \space\the\dim@b\space\the\dim@c\relax }% \eq@trial@b{l}{\eq@try@layout@A}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@try@layout@A} % In the \dquoted{almost-columnar} layout, which is the layout of last % resort, we let all lines run to the full width and leave the adjusting % of the indents to later. % % Layout A = Almost-Columnar layout. % Pretty much straight full width, more of a last-resort. % If fails, give up. % \begin{macrocode} \def\eq@try@layout@A{% \edef\@parshape{\parshape 1 0pt \the\eq@linewidth\relax}% \if\EQ@hasLHS \def\adjust@rel@penalty{\penalty-99 }\fi \eq@trial@b{A}{}% } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@shiftnumber} % MH: Should be moved to a section where all keys are set to defaults. % \begin{macrocode} \let\eq@shiftnumber\@False % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@retry@with@number@a} % Number placement adjustments % \begin{macrocode} \def\eq@retry@with@number{% \if\eq@shiftnumber % \breqn@debugmsg{Place number: Shifted number requested}% \else % \end{macrocode} % Condition and right numbers? We're just going to have to shift. % \begin{macrocode} \ifdim\eq@wdCond>\z@\if R\eqnumside % \breqn@debugmsg{Place number: Condition w/Right number => Shift number}% \let\eq@shiftnumber\@True \fi\fi % \end{macrocode} % Compute free space. % \begin{macrocode} % \dim@b\eqnumsep\advance\dim@b\wd\EQ@numbox \dim@b\eq@wdNum \if L\eqnumside \ifdim\@totalleftmargin>\dim@b\dim@b\@totalleftmargin\fi \else \addtolength\dim@b{\@totalleftmargin}% \fi \setlength\dim@a{\eq@linewidth-\dim@b}%\advance\dim@a1em\relax% Allowance for shrink? % \end{macrocode} % Set up test against 1-line case only if not in a group % \begin{macrocode} \int@a\@ne\if\eq@group\int@a\maxint\fi % \end{macrocode} % Now check for cases. % \begin{macrocode} \if\eq@shiftnumber % Already know we need to shift \else\ifdim\eq@wdT<\dim@a % Fits! % \end{macrocode} % left \& right skips will be done later, and parshape adjusted if % needed. % \begin{macrocode} % \breqn@debugmsg{Place number: eqn and number fit together}% % \else\ifnum\eq@lines=\int@a % Shift, if single line, unless inside a dgroup. % \end{macrocode} % NOTE: this is too strong for dgroup! % \begin{macrocode} %<*trace> % \breqn@debugmsg{Place number: single line too long with number => Shift number \the\int@a}% % % \let\eq@shiftnumber\@True \else % \end{macrocode} % % Retry: use leftskip for space for number(for now; whether % % right/left) \& adjust parshape % \begin{macrocode} % \leftskip\wd\EQ@numbox\advance\leftskip\eqnumsep \setlength\leftskip{\eq@wdNum}% \setlength\rightskip{\z@\@plus\dim@a}% \adjust@parshape\@parshape %<*trace> \breqn@debugmsg{Place number: Try with \leftskip=\the\leftskip, \rightskip=\the\rightskip, \MessageBreak==== parshape\space\@xp\@gobble\@parshape}% % \nointerlineskip \edef\eq@prev@lines{\the\eq@lines}% \edef\eq@prev@badness{\the\eq@badness}% BRM \eq@trial@p \int@a\eq@prev@badness\relax\advance\int@a 50\relax%? \int@b\eq@prev@lines \if\eq@group\advance\int@b\@ne\fi% Allow 1 extra line in group \ifnum\eq@lines>\int@b % \eq@prev@lines % \breqn@debugmsg{Adjustment causes more breaks => Shift number}% \let\eq@shiftnumber\@True \else\if\eq@badline % \breqn@debugmsg{Adjustment causes bad lines (\the\eq@badness) => Shift}% \let\eq@shiftnumber\@True \else\ifnum\eq@badness>\int@a % BRM: New case %<*trace> \breqn@debugmsg{Adjustment is badder than previous (\the\eq@badness >> \eq@prev@badness) => Shift}% % \let\eq@shiftnumber\@True \else % \breqn@debugmsg{Adjustment succeeded}% \fi\fi%\fi \fi\fi\fi % \end{macrocode} % If we got shifted, restore parshape, etc, % \begin{macrocode} \if\eq@shiftnumber \EQ@trial% Restore parshape & other params, \leftskip\z@\let\eq@shiftnumber\@True % But set shift & leftskip \edef\@parshape{\eq@parshape}% And copy saved parshape back to `working copy' !?!? \fi \eq@trial@save\EQ@trial % Either way, save the trial state. \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\adjust@parshape} % Varies depending on the layout. % % Adjust a parshape variable for a given set of left\textbar right skips. % Note that the fixed part of the left\textbar right skips effectively % comes out of the parshape widths (NOT in addition to it). % We also must trim the widths so that the sum of skips, indents % and widths add up to no more than the \cs{eq@linewidth}. % \begin{macrocode} \def\adjust@parshape#1{% \@xp\adjust@parshape@a#1\relax \edef#1{\temp@a}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\adjust@parshape@a} % \begin{macro}{\adjust@parshape@b} % \begin{macrocode} \def\adjust@parshape@a#1 #2\relax{% \setlength\dim@a{\leftskip+\rightskip}% \edef\temp@a{#1}% \adjust@parshape@b#2 @ @ \relax } \def\adjust@parshape@b#1 #2 {% \ifx @#1\edef\temp@a{\temp@a\relax}% \@xp\@gobble \else \dim@b#1\relax \dim@c#2\relax \addtolength\dim@c{\dim@a+\dim@b}% \ifdim\dim@c>\eq@linewidth\setlength\dim@c{\eq@linewidth}\fi \addtolength\dim@c{-\dim@b}% \edef\temp@a{\temp@a\space\the\dim@b\space\the\dim@c}% \fi \adjust@parshape@b } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\eq@ml@record@indents} % Plunk the parshape's indent values into an array for easy access % when constructing \cs{eq@measurements}. % \begin{macrocode} \def\eq@ml@record@indents{% \int@a\z@ \def\@tempa{% \advance\int@a\@ne \@xp\edef\csname eq@i\number\int@a\endcsname{\the\dim@a}% \ifnum\int@a<\int@b \afterassignment\@tempb \fi \dim@a }% \def\@tempb{\afterassignment\@tempa \dim@a}% \def\@tempc##1##2 {\int@b##2\afterassignment\@tempa\dim@a}% \@xp\@tempc\@parshape } % \end{macrocode} % \end{macro} % % \begin{macro}{\breqn@endelt} % This is a scan marker. % It should get a non-expandable definition. % It could be \cs{relax}, but let's try a chardef instead. % \begin{macrocode} \chardef\breqn@endelt=`\? % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@measurements} % This is similar to a parshape spec but for each line we record more % info: space above, indent, width x height + dp, and badness. % \begin{macrocode} \let\breqn@elt\relax \let\breqn@endelt\relax \def\eq@measurements{% \breqn@elt 4.5pt/5.0pt,66.0ptx6.8pt+2.4pt@27\breqn@endelt ... } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@measure@lines} % Loop through the list of boxes to measure things like total % height (including interline stretch), \etc . We check the % actual width of the current line against the natural width \mdash % after removing rightskip \mdash in case the former is % \emph{less} than the latter because of shrinkage. In that % case we do not want to use the natural width for RHS-max-width because % it might unnecessarily exceed the right margin. % \begin{macrocode} \def\eq@measure@lines{% \let\eq@ml@continue\eq@measure@lines \setbox\tw@\lastbox \dim@b\wd\tw@ % find target width of line \setbox\z@\hbox to\dim@b{\unhbox\tw@}% check for overfull \eq@badness\badness \ifnum\eq@badness<\inf@bad \else \let\eq@badline\@True \fi \eq@ml@a \eq@ml@continue } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@ml@a} % % \begin{macrocode} \def\eq@ml@a{% \setbox\tw@\hbox{\unhbox\z@ \unskip}% find natural width %<*trace> \ifnum\eq@badness<\inf@bad\else\breqn@debugmsg{!?! Overfull: \the\wd\tw@ >\the\dim@b}\fi % % \end{macrocode} % Is actual width less than natural width? % \begin{macrocode} \ifdim\dim@b<\wd\tw@ \setlength\dim@a{\dim@b}% shrunken line \else \setlength\dim@a{\wd\tw@}% OK to use natural width \fi \addtolength\dim@a{-\leftskip}% BRM: Deduct the skip if we're retrying w/number % \end{macrocode} % If there's no aboveskip, assume we've reached the top of the % equation. % \begin{macrocode} \skip@a\lastskip \unskip \unpenalty \ifdim\skip@a=\z@ \let\eq@ml@continue\relax % end the recursion \else % Sum repeated vskips if present \def\@tempa{% \ifdim \lastskip=\z@ \else \addtolength\skip@a{\lastskip}\unskip\unpenalty \@xp\@tempa \fi }% \fi \edef\eq@measurements{\breqn@elt \the\skip@a\space X% extra space to facilitate extracting only the % dimen part later \csname eq@i% \ifnum\eq@curline<\parshape \number\eq@curline \else\number\parshape \fi \endcsname,\the\dim@a x\the\ht\tw@+\the\dp\tw@ @\the\eq@badness\breqn@endelt \eq@measurements }% \advance\eq@curline\m@ne \ifnum\eq@curline=\z@ \let\eq@ml@continue\relax\fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@ml@vspace} % % Handle an embedded vspace. % \begin{macrocode} \def\eq@ml@vspace{% \global\advance\eq@vspan\lastskip \unskip\unpenalty \ifdim\lastskip=\z@ \else \@xp\eq@ml@vspace \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@dense@enough} % % \begin{macrocode} \def\eq@dense@enough{% \ifnum\eq@lines<\thr@@ % \breqn@debugmsg{Density check: less than 3 lines; OK}% \@True \else \ifdim\eq@wdL >.7\eq@wdT % \breqn@debugmsg{Density check: LHS too long; NOT OK}% \@False \else \@xp\@xp\@xp\eq@dense@enough@a \fi \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\true@true@true} % \begin{macro}{\true@false@true} % \begin{macro}{\false@true@false} % \begin{macro}{\false@false@false} % \begin{macrocode} \def\true@true@true {\fi\fi\iftrue \iftrue \iftrue } \def\true@false@true {\fi\fi\iftrue \iffalse\iftrue } \def\false@true@false {\fi\fi\iffalse\iftrue \iffalse} \def\false@false@false{\fi\fi\iffalse\iffalse\iffalse} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\eq@density@factor} % % This number specifies, for the ladder layout, how much of the % equation's bounding box should contain visible material rather than % whitespace. % If the amount of visible material drops below this value, then we % switch to the drop-ladder layout. % The optimality of this factor is highly dependent on the equation % contents; .475 was chosen as the default just because it worked well % with the sample equation, designed to be as average as possible, that I % used for testing. % \begin{macrocode} \def\eq@density@factor{.475} % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@dense@enough@a} % % Calculate whether there is more % visible material than whitespace within the equation's bounding box. % Sum up the actual line widths and compare to the total % \dquoted{area} of the bounding box. % But if we have an extremely large number of lines, fall back to an % approximate calculation that is more conservative about the danger of % exceeding \cs{maxdimen}. % \begin{macrocode} \def\eq@dense@enough@a{% \@True \fi \ifnum\eq@lines>\sixt@@n \eq@dense@enough@b \else \dim@b\z@ \let\breqn@elt\eq@delt \eq@measurements \dim@c\eq@density@factor\eq@wdT \multiply\dim@c\eq@lines % \breqn@debugmsg{Density check: black \the\dim@b/\eq@density@factor total \the\dim@c}% \ifdim\dim@b>\dim@c \true@false@true \else \false@false@false \fi \fi } % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@delt} % Args are space-above, indent, width, height, depth, badness. % \begin{macrocode} \def\eq@delt#1X#2,#3x#4+#5@#6\breqn@endelt{\addtolength\dim@b{#3}}% % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@dense@enough@b} % This is an approximate calculation used to keep from going over % \cs{maxdimen} if the number of lines in our trial break is large % enough to make that a threat. % If l, t, n represent left-side-width, total-width, and number of % lines, the formula is % \begin{literalcode} % l/t < .4n/(.9n-1) % \end{literalcode} % or equivalently, since rational arithmetic is awkward in \tex : % b % \begin{literalcode} % l/t < 4n/(9n-10) % \end{literalcode} % . % \begin{macrocode} \def\eq@dense@enough@b{% \int@b\eq@wdT \divide\int@b\p@ \dim@b\eq@wdL \divide\dim@b\int@b \dim@c\eq@lines\p@ \multiply\dim@c\f@ur \int@b\eq@lines \multiply\int@b 9 \advance\int@b -10% \divide\dim@c\int@b % \breqn@debugmsg{Density check: l/t \the\dim@b\space< \the\dim@c\space 4n/(9n-10)?}% \ifdim\dim@b<\dim@c \true@true@true \else \false@true@false \fi } % \end{macrocode} % \end{macro} % % \begin{macro}{\eq@parshape} % \begin{macrocode} \let\eq@parshape\@empty % \end{macrocode} % \end{macro} % % % \begin{macro}{\eq@params} % The interline spacing and penalties in \cs{eq@params} % are used during both preliminary line breaking and final typesetting. % \begin{macrocode} \def\eq@params{% \baselineskip\eqlinespacing \lineskip\eqlineskip \lineskiplimit\eqlineskiplimit % \end{macrocode} % Forbid absolutely a pagebreak that separates the first line or last % line of a multiline equation from the rest of it. Or in other % words: no equation of three lines or less will be broken at the bottom % of a page; instead it will be moved whole to the top of the next % page. If you really really need a page break that splits the % first or last line from the rest of the equation, you can always fall % back to\cs{pagebreak}, I suppose. % % \begin{macrocode} \clubpenalty\@M \widowpenalty\@M \interlinepenalty\eqinterlinepenalty \linepenalty199 \exhyphenpenalty5000 % was 9999: make breaks at, eg. \* a bit easier. % \end{macrocode} % For equations, hfuzz should be at least 1pt. % But we have to fake it a little because we are running the equation % through \tex 's paragrapher. % In our trials we use minus 1pt in the rightskip rather than hfuzz; % and we must do the same during final breaking of the equation, otherwise % in borderline cases \tex will use two lines instead of one when our % trial indicated that one line would be enough. % \begin{macrocode} \ifdim\hfuzz<\p@ \hfuzz\p@ \fi %\hfuzz=2pt % \ifdim\hfuzz<2pt\relax \hfuzz2pt \fi \parfillskip\z@skip % \hfuzz\z@ % \end{macrocode} % Make sure we skip \tex 's preliminary line-breaking pass to save % processing time. % \begin{macrocode} \tolerance9999 \pretolerance\m@ne } % \end{macrocode} % \end{macro} % % % % % \section{Equation layout options} % Using the notation C centered, I indented (applied to % the equation body), T top, B bottom, M % middle, L left, R right (applied to the equation number), % the commonly used equation types are C, CRM, CRB, CLM, CLT, % I, IRM, IRB, ILM, ILT. In other words, CLM stands for Centered equation % body with Left-hand Middle-placed equation number, and IRB stands for % Indented equation with Right-hand Bottom-placed equation number. % % Here are some general thoughts on how to place an equation % tag. Currently it does not work as desired: the L option positions % the tag app. 10 lines below the math expression, the RM doesn't % position the tag on the baseline for single-line math % expressions. Therefore I am going to first write what I think is % supposed to happen and then implement it. % % Below is a small list where especially the two three specifications % should be quite obvious, I just don't want to forget anything and it % is important to the implementation. % \begin{description} % \item[Definition 1] If a display consists of exactly one line, the % tag should always be placed on the same baseline as the math % expression. % \end{description} % The remaining comments refer to multi-line displays. % \begin{description} % \item[Definition 2] If a tag is to be positioned at the top (T), it % should be placed such that the baseline of the tag aligns with the % baseline of the top line of the display. % % \item[Definition 3] If a tag is to be positioned at the bottom (B), % it should be placed such that the baseline of the tag aligns with % the baseline of the bottom line of the display. % % \item[Definition 4] If a tag is to be positioned vertically centered % (M), it should be placed such that the baseline of the tag is % positioned exactly halfway between the baseline of the top line of % the display and the baseline of the bottom line of the display. % \end{description} % % Definitions 1--3 are almost axiomatic in their % simplicity. Definition~4 is different because I saw at least two % possibilities for which area to span: % \begin{itemize} % \item Calculate distance from top of top line to the bottom of the % bottom line, position the vertical center of the tag exactly % halfway between those two extremes. % % \item Calculate the distance from the baseline of the top line to % the baseline of the bottom line, position the baseline of the tag % exactly halfway between these two extremes. % \end{itemize} % Additional combinations of these methods are possible but make % little sense in my opinion. I have two reasons for choosing the % latter of these possibilities: Firstly, two expressions looking % completely identical with the exception of a superscript in the % first line or a subscript in the last line will have the tag % positioned identically. Secondly, then M means halfway between T and % B positions which makes good sense and then also automatically % fulfills Definition~1. % % From an implementation perspective, these definitions should also % make it possible to fix a deficiency in the current implementation, % namely that the tag does not influence the height of a display, even % if the display is a single line. This means that two single-line % expressions in a \env{dgroup} can be closer together than % \cs{intereqskip} if the math expressions are (vertically) smaller % than the tag. % % \section{Centered Right-Number Equations} % % \begin{macro}{\eq@dump@box} % \arg1 might be \cs{unhbox} or \cs{unhcopy}; \arg2 is % the box name. % \begin{macrocode} \def\eq@dump@box#1#2{% %\debug@box#1% % \noindent \MaybeRawNoindent % did not find the end yet #1#2\setbox\f@ur\lastbox \setbox\tw@\lastbox % \end{macrocode} % If the LHS contains shrinkable glue, in an L layout the alignment % could be thrown off if the first line is shrunk noticeably. % For the time being, disable shrinking on the left-hand side. % The proper solution requires more work \begin{dn} % mjd,1999/03/17 % \end{dn} % . % \begin{macrocode} \if L\eq@layout \box\tw@ \else\unhbox\tw@\fi \adjust@rel@penalty \unhbox\f@ur } % \end{macrocode} % \end{macro} % % Various typesetting bits, invoked from \cs{eq@finish} % BRM: This has been extensively refactored from the original breqn, % initially to get left\textbar right skips and parshape used consistently, % ultimately to get most things handled the same way, in the same order. % % Given that left and right skips have been set, % typeset the frame, number and equation with the % given number side and placement % % \begin{macrocode} \def\eq@typeset@Unnumbered{% \eq@typeset@frame \eq@typeset@equation } \def\eq@typeset@LM{% \setlength\dim@a{(\eq@vspan+\ht\EQ@numbox-\dp\EQ@numbox)/2}% \eq@typeset@leftnumber \eq@typeset@frame \eq@typeset@equation } % \end{macrocode} % Typeset equation and left-top number (and shifted) % \begin{macrocode} \def\eq@typeset@LT{% \dim@a\eq@firstht \eq@typeset@leftnumber \eq@typeset@frame \eq@typeset@equation } % \end{macrocode} % Typeset equation and left shifted number % \begin{macrocode} \def\eq@typeset@LShifted{% % place number \copy\EQ@numbox \penalty\@M \dim@a\eqlineskip \if F\eq@frame\else \setlength\dim@a{\eq@framesep+\eq@framewd}% \fi \kern\dim@a \eq@typeset@frame \eq@typeset@equation } % \end{macrocode} % Typeset equation and right middle number % \begin{macrocode} \def\eq@typeset@RM{% \setlength\dim@a{(\eq@vspan+\ht\EQ@numbox-\dp\EQ@numbox)/2}% \eq@typeset@rightnumber \eq@typeset@frame \eq@typeset@equation } % \end{macrocode} % Typeset equation and right bottom number % \begin{macrocode} \def\eq@typeset@RB{% % NOTE: is \eq@dp useful here \setlength\dim@a{\eq@vspan-\ht\EQ@numbox-\dp\EQ@numbox}% \eq@typeset@rightnumber \eq@typeset@frame \eq@typeset@equation } % \end{macrocode} % Typeset equation and right shifted number % \begin{macrocode} \def\eq@typeset@RShifted{% % place number \eq@typeset@frame \eq@typeset@equation \penalty\@M \dim@a\eqlineskip \if F\eq@frame\else \addtolength\dim@a{\eq@framesep+\eq@framewd}% \fi \parskip\dim@a \hbox to\hsize{\hfil\copy\EQ@numbox}\@@par% } % \end{macrocode} % % Debugging aid to show all relevant formatting info for a given eqn. % \begin{macrocode} %<*trace> \def\debug@showformat{% \breqn@debugmsg{Formatting Layout:\eq@layout\space Center/indent: \eqindent\space Number placement \eqnumside\eqnumplace: \MessageBreak==== \eq@linewidth=\the\eq@linewidth, \@totalleftmargin=\the\@totalleftmargin, \MessageBreak==== Centered Lines=\theb@@le\eq@centerlines, Shift Number=\theb@@le\eq@shiftnumber, \MessageBreak==== \eq@wdT=\the\eq@wdT, \eq@wdMin=\the\eq@wdMin, \MessageBreak==== LHS=\theb@@le\EQ@hasLHS: \eq@wdL=\the\eq@wdL, \MessageBreak==== \eq@firstht=\the\eq@firstht, \eq@vspan=\the\eq@vspan \MessageBreak==== \eq@wdNum=\the\eq@wdNum \MessageBreak==== \eq@wdCond=\the\eq@wdCond, \conditionsep=\the\conditionsep, \MessageBreak==== \leftskip=\the\leftskip, \rightskip=\the\rightskip, \MessageBreak==== \abovedisplayskip=\the\abovedisplayskip, \MessageBreak==== \belowdisplayskip=\the\belowdisplayskip \MessageBreak==== parshape=\eq@parshape}% } % % \end{macrocode} % % Set left \& right skips for centered equations, % making allowances for numbers (if any, right, left) and constraint. % % Amazingly, I've managed to collect all the positioning logic for % centered equations in one place, so it's more manageable. % Unfortunately, by the time it does all it needs to do, % it has evolved I'm (re)using so many temp variables, it's becoming % unmanageble! % % \begin{macrocode} \def\eq@C@setsides{% % \dim@c = space for number, if any, and not shifted. \dim@c\z@ \if\eq@hasNumber\if\eq@shiftnumber\else \dim@c\eq@wdNum \fi\fi % \dim@e = space for condition(on right), if any and formula is only a single line.(to center nicely) % but only count it as being right-aligned if we're not framing, since the frame must enclose it. \dim@e\z@ \if F\eq@frame \ifnum\eq@lines=\@ne\ifdim\eq@wdCond>\z@ \setlength\dim@e{\eq@wdCond+\conditionsep}% \fi\fi\fi % \dim@b = minimum needed on left max(totalleftmargin, left number space) \dim@b\z@ \if L\eqnumside\ifdim\dim@b<\dim@c \dim@b\dim@c \fi\fi \ifdim\dim@b<\@totalleftmargin \dim@b\z@ \else \addtolength\dim@b{-\@totalleftmargin}% \fi % \dim@d = minimum needed on right max(condition, right number space) \dim@d\dim@e \if R\eqnumside\ifdim\dim@d<\dim@c \dim@d\dim@c \fi\fi % \dim@a = left margin; initially half available space % \dim@c = right margin; ditto \setlength\dim@a{(\eq@linewidth-\eq@wdT+\dim@e+\@totalleftmargin)/2}% \dim@c=\dim@a % If too far to the left \ifdim\dim@a<\dim@b \addtolength\dim@c{\dim@a-\dim@b}% \ifdim\dim@c<\z@\dim@c=\z@\fi \dim@a=\dim@b % Or if too far to the right \else\ifdim\dim@c<\dim@d \addtolength\dim@a{\dim@c-\dim@d}% \ifdim\dim@a<\z@\dim@a=\z@\fi \dim@c=\dim@d \fi\fi % Now, \dim@d,\dim@e is the left & right glue to center each line for centerlines \setlength\dim@e{\eq@wdT-\eq@wdMin}\dim@d=\z@ % \end{macrocode} % NOTE: Need some work here centering when there's a condition % \begin{macrocode} % \advance\dim@e-\eq@wdT\multiply\dim@e-1\relax % \if\eq@wdMin<\dim@e\dim@e\eq@wdMin\fi % \multiply\dim@e-1\relax\advance\dim@e\eq@wdT \dim@d\z@ \if\eq@centerlines \divide\dim@e2\relax \dim@d=\dim@e \fi \setlength\leftskip{\dim@a\@plus\dim@d}% \addtolength\dim@e{\dim@c}% \setlength\rightskip{\z@\@plus\dim@e}%\@minus5\p@ % Special case: if framing, reduce the stretchiness of the formula (eg. condition) % Or if we have a right number, FORCE space for it \dim@b\z@ \if F\eq@frame\else \dim@b\dim@c \fi \if\@And{\eq@hasNumber}{\@Not{\eq@shiftnumber}}% \if R\eqnumside \dim@c\eq@wdNum \ifdim\dim@c>\dim@b \dim@b\dim@c \fi \fi \fi % If either of those cases requires hard rightskip, move that part from glue. \ifdim\dim@b>\z@ \addtolength\dim@e{-\dim@c}% \rightskip\dim@b\@plus\dim@e%\@minus5\p@ \fi % And peculiar further special case: in indented environs, width isn't where it would seem \ifdim\eq@wdCond>\z@ \addtolength\rightskip{-\@totalleftmargin}% \fi \parfillskip\z@skip } % \end{macrocode} % % Set the left and right side spacing for indented equations % Some things handled by eq@C@setsides that probably apply here???? % \begin{itemize} % \item centerlines % \item \cs{@totalleftmargin}: SHOULD we move farther right? % \end{itemize} % Leftskip is normally just the requested indentation % \begin{macrocode} \def\eq@I@setsides{% \leftskip\mathindent % \end{macrocode} % But move left, if shifted number presumably because of clashed w/ number? % \begin{macrocode} \if\eq@shiftnumber \setlength\dim@a{\eq@linewidth-\eq@wdT-\mathindent}% \ifdim\dim@a<\z@ \leftskip=\z@ % Or something minimal? \fi \fi % \end{macrocode} % Push gently from right. % \begin{macrocode} \dim@a=\z@ \setlength\dim@b{\eq@linewidth-\leftskip-\eq@wdMin}% % \end{macrocode} % Special case: if framing be much more rigid(?) % \begin{macrocode} \if F\eq@frame \else \setlength\dim@a{\eq@linewidth-\leftskip-\eq@wdT} \addtolength\dim@b{-\dim@a}% \fi % Or force the space for right number, if needed % \begin{macrocode} \if\@And{\eq@hasNumber}{\@Not{\eq@shiftnumber}}% \if R\eqnumside \dim@c=\eq@wdNum \if\dim@c>\dim@a \addtolength\dim@b{-\dim@c}% \dim@a=\dim@c \fi \fi \fi \setlength\rightskip{\dim@a\@plus\dim@b \@minus\hfuzz }%\hfuzz\z@ \parfillskip\z@skip } % \end{macrocode} % \paragraph{Typesetting pieces: frame, equation and number (if any)} % \cs{dim@a} should contain the downward displacement of number's baseline % \begin{macrocode} \def\eq@typeset@leftnumber{% \setlength\skip@c{\dim@a-\ht\EQ@numbox}% \vglue\skip@c% NON discardable \copy\EQ@numbox \penalty\@M \kern-\dim@a } \def\eq@typeset@rightnumber{% \setlength\skip@c{\dim@a-\ht\EQ@numbox}% \vglue\skip@c% NON discardable \hbox to \hsize{\hfil\copy\EQ@numbox}\penalty\@M \kern-\dim@a } \def\eq@typeset@equation{% \nobreak \eq@params\eq@parshape \nointerlineskip % \noindent \MaybeRawNoindent \add@grp@label \eq@dump@box\unhbox\EQ@box % \@@par \RawParEnd } % \end{macrocode} % % \section{Framing an equation} % \begin{macro}{\eqframe} % The \cs{eqframe} function is called in vertical mode % with the reference point at the top left corner of the equation, including % any allowance for \cs{fboxsep}. Its arguments are the width % and height of the equation body, plus fboxsep. % \changes{v0.95}{2007/12/03}{Made \cs{eqframe} obey the key settings % for frame and framesep.} % \begin{macrocode} \newcommand\eqframe[2]{% \begingroup \fboxrule=\eq@framewd\relax\fboxsep=\eq@framesep\relax \framebox{\z@rule\@height#2\kern#1}% \endgroup } % \end{macrocode} % \end{macro} % The frame is not typeset at the correct horizontal position. Will % fix later. % \begin{macrocode} \def\eq@addframe{% \hbox to\z@{% \setlength\dim@a{\eq@framesep+\eq@framewd}% \kern-\dim@a \vbox to\z@{\kern-\dim@a \hbox{\eqframe{\eq@wdT}{\eq@vspan}}% \vss }% \hss }% } \def\eq@typeset@frame{% \if F\eq@frame\else % Tricky: put before \noindent, so it's not affected by glue in \leftskip \nobreak\nointerlineskip \vbox to\eq@firstht{\moveright\leftskip\hbox to\z@{\eq@addframe\hss}\vss}% \kern-\eq@firstht \fi } % \end{macrocode} % % \section{Delimiter handling} % The special handling of delimiters is rather complex, but % everything is driven by two motives: to mark line breaks inside % delimiters as less desirable than line breaks elsewhere, and to make it % possible to break open left-right boxes so that line breaks between % \cs{left} and \cs{right} delimiters are not absolutely % prohibited. To control the extent to which line breaks will be % allowed inside delimiters, set \cs{eqbreakdepth} to the maximum % nesting depth. Depth 0 means never break inside delimiters. % % Note: \cs{eqbreakdepth} is not implemented as a \latex % counter because changes done by \cs{setcounter} \etc are always % global. % % It would be natural to use grouping in the implementation % \mdash at an open delimiter, start a group and increase mathbin % penalties; at a close delimiter, close the group. But this gives us % trouble in situations like the \env{array} environment, where a % close delimiter might fall in a different cell of the \cs{halign} % than the open delimiter. % Ok then, here's what we want the various possibilities to % expand to. Note that \cs{right} and \cs{biggr} are % being unnaturally applied to a naturally open-type delimiter. % \begin{literalcode} % ( -> \delimiter"4... \after@open % \left( -> % \@@left \delimiter"4... \after@open % \right( -> % \@@right \delimiter"4... \after@close % \biggl( -> % \mathopen{\@@left \delimiter... \vrule...\@@right.} % \after@open % \biggr( -> % \mathclose{\@@left \delimiter... \vrule...\@@right.} % \after@close % \bigg\vert -> % \mathord{\@@left \delimiter... \vrule...\@@right.} % \biggm\vert -> % \mathrel{\@@left \delimiter... \vrule...\@@right.} % \end{literalcode} % % First save the primitive meanings of \cs{left} and % \cs{right}. % \begin{macrocode} \@saveprimitive\left\@@left \@saveprimitive\right\@@right % \end{macrocode} % % The variable \cs{lr@level} is used by the first mathrel in % an equation to tell whether it is at top level: yes? break and measure % the LHS, no? keep going. % \begin{macrocode} \newcount\lr@level % \end{macrocode} % % It would be nice to have better error checking here if the % argument is not a delimiter symbol at all. % % Ah, a small problem when renaming commands. In the original version, % |\delimiter| is hijacked in order to remove the |\after@bidir| (or % open or close) instruction following the delimiter declaration. % \begin{macrocode} \ExplSyntaxOn \def\eq@left{% \@ifnext .{\eq@nullleft}{\begingroup \let\math_delimiter:NNnNn \eq@left@a}% } \def\eq@right{% \@ifnext .{\eq@nullright}{\begingroup \let \math_delimiter:NNnNn \eq@right@a}% } % \end{macrocode} % The arguments are: \arg1 delim symbol, \arg2 . % \begin{macrocode} %\def\eq@left@a#1 #2{\endgroup\@@left\delimiter#1\space \after@open} \def\eq@left@a#1#2#3#4#5#6{\endgroup \@@left \math_delimiter:NNnNn #1#2{#3}#4{#5}\after@open} \def\eq@right@a#1#2#3#4#5#6{\endgroup \@@right \math_delimiter:NNnNn #1#2{#3}#4{#5}\after@close \ss@scan{#1#2{#3}#4{#5}}% } \ExplSyntaxOff % \end{macrocode} % The null versions. % \begin{macrocode} \def\eq@nullleft#1{\@@left#1\after@open} \def\eq@nullright#1{\@@right#1\after@close} % \end{macrocode} % % Here is the normal operation of \cs{biggl}, for example. % \begin{literalcode} % \biggl ->\mathopen \bigg % {\mathopen} % % \bigg #1->{\hbox {$\left #1\vbox to14.5\p@ {}\right .\n@space $}} % #1<-( % \end{literalcode} % ^^AFor paren matching: ) % Like \cs{left}, \cs{biggl} coerces its delimiter to be of % mathopen type even if its natural inclination is towards closing. % % The function \cs{delim@reset} makes delimiter characters % work just about the same as they would in normal \latex . % \begin{macrocode} \def\delim@reset{% \let\after@open\relax \let\after@close\relax \let\left\@@left \let\right\@@right } % \end{macrocode} % If the \pkg{amsmath} or \pkg{exscale} package is loaded, it % will have defined \cs{bBigg@}; if not, the macros \cs{big} and % variants will have hard-coded point sizes as inherited through the ages % from \fn{plain.tex}. In this case we can kluge a little by % setting \cs{big@size} to \cs{p@}, so that our definition of % \cs{bBigg@} will work equally well with the different multipliers. % \begin{macrocode} \@ifundefined{bBigg@}{% not defined \let\big@size\p@ \def\big{\bBigg@{8.5}}\def\Big{\bBigg@{11.5}}% \def\bigg{\bBigg@{14.5}}\def\Bigg{\bBigg@{17.5}}% \def\biggg{\bBigg@{20.5}}\def\Biggg{\bBigg@{23.5}}% }{} \def\bBigg@#1#2{% {\delim@reset \left#2% \vrule\@height#1\big@size\@width-\nulldelimiterspace \right. }% } % \end{macrocode} % . % \begin{macrocode} \def\bigl#1{\mathopen\big{#1}\after@open} \def\Bigl#1{\mathopen\Big{#1}\after@open} \def\biggl#1{\mathopen\bigg{#1}\after@open} \def\Biggl#1{\mathopen\Bigg{#1}\after@open} \def\bigggl#1{\mathopen\biggg{#1}\after@open} \def\Bigggl#1{\mathopen\Biggg{#1}\after@open} \def\bigr#1{\mathclose\big{#1}\after@close} \def\Bigr#1{\mathclose\Big{#1}\after@close} \def\biggr#1{\mathclose\bigg{#1}\after@close} \def\Biggr#1{\mathclose\Bigg{#1}\after@close} \def\bigggr#1{\mathclose\biggg{#1}\after@close} \def\Bigggr#1{\mathclose\Biggg{#1}\after@close} %% No change needed, I think. [mjd,1998/12/04] %%\def\bigm{\mathrel\big} %%\def\Bigm{\mathrel\Big} %%\def\biggm{\mathrel\bigg} %%\def\Biggm{\mathrel\Bigg} %%\def\bigggm{\mathrel\biggg} %%\def\Bigggm{\mathrel\Biggg} % \end{macrocode} % % % \begin{macro}{\m@@DeL} \begin{macro}{\d@@DeL} % \begin{macro}{\m@@DeR} \begin{macro}{\d@@DeR} % \begin{macro}{\m@@DeB} \begin{macro}{\d@@DeB} % Original definition of \cs{m@DeL} from % \pkg{flexisym} is as follows. \cs{m@DeR} and % \cs{m@DeB} are the same except for the math class number. % \begin{literalcode} % \def\m@DeL#1#2#3{% % \delimiter"4\@xp\delim@a\csname sd@#1#2#3\endcsname #1#2#3 } % \end{literalcode} % % Save the existing meanings of \cs{m@De[LRB]}. % % Define display variants of DeL, DeR, DeB % \begin{macrocode} \ExplSyntaxOn \cs_set:Npn \math_dsym_DeL:Nn #1#2{\math_bsym_DeL:Nn #1{#2}\after@open} \cs_set:Npn \math_dsym_DeR:Nn #1#2{\math_bsym_DeR:Nn #1{#2}\after@close} \cs_set:Npn \math_dsym_DeB:Nn #1#2{\math_bsym_DeB:Nn #1{#2}\after@bidir} %%%%% %%%%%\let\m@@DeL\m@DeL \let\m@@DeR\m@DeR \let\m@@DeB\m@DeB %%%%%\def\d@@DeL#1#2#3{% %%%%% \delimiter"4\@xp\delim@a\csname sd@#1#2#3\endcsname #1#2#3 \after@open %%%%%} %%%%%\def\d@@DeR#1#2#3{% %%%%% \delimiter"5\@xp\delim@a\csname sd@#1#2#3\endcsname #1#2#3 \after@close %%%%%} %%%%%\def\d@@DeB#1#2#3{% %%%%% \delimiter"0\@xp\delim@a\csname sd@#1#2#3\endcsname #1#2#3 \after@bidir %%%%%} % \end{macrocode} %%BRM: These weren't defined, but apparently should be. % Are these the right values??? % \begin{macrocode} %%%%%%\let\m@@DeA\m@DeA\let\d@@DeA\m@DeA% % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\after@open} % \begin{macro}{\after@close} % \begin{macro}{\after@bidir} % \begin{macro}{\zero@bop} % \begin{macro}{\bop@incr} % \cs{after@open} and \cs{after@close} are carefully % written to avoid the use of grouping and to run as fast as possible. % \cs{zero@bop} is the value used for \cs{prebinoppenalty} at % delimiter level 0, while \cs{bop@incr} is added for each level of % nesting. The standard values provide that breaks will be prohibited % within delimiters below nesting level 2. % \begin{macrocode} \let\after@bidir\@empty \mathchardef\zero@bop=888 \relax \mathchardef\bop@incr=4444 \relax \def\after@open{% \global\advance\lr@level\@ne \prebinoppenalty\bop@incr \multiply\prebinoppenalty\lr@level \advance\prebinoppenalty\zero@bop \ifnum\eqbreakdepth<\lr@level \cs_set_eq:NN \math_sym_Bin:Nn \math_isym_Bin:Nn %%%%%%\let\m@Bin\m@@Bin % \end{macrocode} % Inside delimiters, add some fillglue before binops so that a broken off % portion will get thrown flush right. Also shift it slightly % further to the right to ensure that it clears the opening delimiter. % \begin{macrocode} \else \eq@binoffset=\eqbinoffset \advance\eq@binoffset\lr@level\eqdelimoffset plus1fill\relax \def\dt@fill@cancel{\hskip\z@ minus1fill\relax}% \fi \penalty\@M % BRM: discourage break after an open fence? } \def\after@close{% \global\advance\lr@level\m@ne \prebinoppenalty\bop@incr \multiply\prebinoppenalty\lr@level \advance\prebinoppenalty\zero@bop \ifnum\eqbreakdepth<\lr@level \else \cs_set_eq:NN \math_sym_Bin:Nn \math_dsym_Bin:Nn %%%%%%\let\m@Bin\d@@Bin \fi % \end{macrocode} % When we get back to level 0, no delimiters, remove the stretch % component of \cs{eqbinoffset}. % \begin{macrocode} \ifnum\lr@level<\@ne \eq@binoffset=\eqbinoffset\relax \fi } \ExplSyntaxOff % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\subsup@flag} % \begin{macro}{\ss@scan} % \cs{ss@scan} is called after a \cs{right} delimiter and % looks ahead for sub and superscript tokens. % If sub and/or superscripts are present, we adjust the line-ending % penalty to distinguish the various cases (sub, sup, or both). % This facilitates the later work of excising the sub/sup box and % reattaching it with proper shifting. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Sub/Superscript measurement %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % BRM: There's possibly a problem here. % When \cs{ss@scan} gets invoked after a \cs{left}...\cs{right} pair in the LHS % during \cs{eq@measure}, it produces an extra box (marked with \cs{penalty} 3); % Apparently \cs{eq@repack} expects only one for the LHS. % The end result is \cs{eq@wdL} => 0.0pt !!! (or at least very small) % \begin{macrocode} \let\subsup@flag=\count@ \def\ss@delim@a@new#1#2#3#4#5{\xdef\right@delim@code{\number"#4#5}} % \end{macrocode} % The argument of \cs{ss@scan} is an expanded form of a % right-delimiter macro. % We want to use the last three digits in the expansion % to define \cs{right@delim@code}. % The assignment to a temp register is just a way to scan away the % leading digits that we don't care about. % \begin{macrocode} \def\ss@scan#1{% % \end{macrocode} % This part of the code. % \begin{macrocode} \begingroup \ss@delim@a@new #1% \endgroup \subsup@flag\@M \afterassignment\ss@scan@a \let\@let@token=} \def\ss@scan@a{% \let\breqn@next\ss@scan@b \ifx\@let@token\sb \advance\subsup@flag\@ne\else \ifx\@let@token\@@subscript \advance\subsup@flag\@ne\else \ifx\@let@token\@@subscript@other \advance\subsup@flag\@ne\else \ifx\@let@token\sp \advance\subsup@flag\tw@\else \ifx\@let@token\@@superscript \advance\subsup@flag\tw@\else \ifx\@let@token\@@superscript@other \advance\subsup@flag\tw@\else \ss@finish \let\breqn@next\relax \fi\fi\fi\fi\fi\fi \breqn@next\@let@token } % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOn \def\ss@scan@b#1#2{#1{% % \end{macrocode} % hack! coff! % \begin{macrocode} %%%%%\let\m@Bin\m@@Bin \let\m@Rel\m@@Rel \cs_set_eq:NN \math_sym_Bin:Nn \math_isym_Bin:Nn \cs_set_eq:NN \math_sym_Rel:Nn \math_isym_Rel:Nn #2}\afterassignment\ss@scan@a \let\@let@token=}% \ExplSyntaxOff % \end{macrocode} % We need to keep following glue from disappearing % \mdash \eg , a thickmuskip or medmuskip from a following mathrel or % mathbin symbol. % \begin{macrocode} \def\ss@finish{% \@@vadjust{\penalty\thr@@}% \penalty\right@delim@code \penalty-\subsup@flag \keep@glue } % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\eq@lrunpack} % For \cs{eq@lrunpack} we need to break open a left-right box and % reset it just in case it contains any more special breaks. After % it is unpacked the recursion of \cs{eq@repack} will continue, % acting on the newly created lines. % \begin{macrocode} \def\eq@lrunpack{\setbox\z@\lastbox % \end{macrocode} % We remove the preceding glue item and deactivate % baselineskip for the next line, otherwise we would end up with % three items of glue (counting parskip) at this point instead of % the single one expected by our recursive repacking % procedure. % \begin{macrocode} \unskip \nointerlineskip % \end{macrocode} % Then we open box 0, take the left-right box at the right end of % it, and break that open. If the line-ending penalty is greater than % 10000, it means a sub and/or superscript is present on the right % delimiter and the box containing them must be taken off first. % \begin{macrocode} % \noindent \MaybeRawNoindent \unhbox\z@ \unskip \subsup@flag-\lastpenalty \unpenalty \xdef\right@delim@code{\number\lastpenalty}% \unpenalty \ifnum\subsup@flag>\@M \advance\subsup@flag-\@M \setbox\tw@\lastbox \else \setbox\tw@\box\voidb@x \fi \setbox\z@\lastbox \ifvoid\tw@ \unhbox\z@ \else \lrss@reattach % uses \subsup@flag, box\z@, box\tw@ \fi % \end{macrocode} % The reason for adding a null last line here is that the last % line will contain parfillskip in addition to rightskip, and a final % penalty of $10000$ instead of $-1000N$ % ($1\leq N\leq 9$), which would interfere with the usual % processing. Setting a null last line and discarding it dodges % this complication. The penalty value $-10001$ is a no-op case % in the case statement of \cs{eq@repacka}. % \begin{macrocode} \penalty-\@Mi\z@rule % \@@par \RawParEnd \setbox\z@\lastbox \unskip\unpenalty %%{\showboxbreadth\maxdimen\showboxdepth99\showlists}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\lrss@reattach} % % Well, for a small self-contained computation, carefully % hand-allocated dimens should be safe enough. But let the % maintainer beware! This code cannot be arbitrarily transplanted % or shaken up without regard to grouping and interaction with other % hand-allocated dimens. % \begin{macrocode} \dimendef\sub@depth=8 \dimendef\sup@base=6 \dimendef\prelim@sub@depth=4 \dimendef\prelim@sup@base=2 \def\sym@xheight{\fontdimen5\textfont\tw@} \def\sup@base@one{\fontdimen13\textfont\tw@} \def\sub@base@one{\fontdimen16\textfont\tw@} \def\sub@base@two{\fontdimen17\textfont\tw@} % \end{macrocode} % Note that only \cs{sup@drop} and \cs{sub@drop} come from % the next smaller math style. % \begin{macrocode} \def\sup@drop{\fontdimen18\scriptfont\tw@} \def\sub@drop{\fontdimen19\scriptfont\tw@} % \end{macrocode} % Provide a mnemonic name for the math axis fontdimen, if it's not % already defined. % \begin{macrocode} \providecommand{\mathaxis}{\fontdimen22\textfont\tw@} % \end{macrocode} % % Assumes box 2 contains the sub/sup and box 0 contains the left-right % box. This is just a repeat of the algorithm in \fn{tex.web}, % with some modest simplifications from knowing that this is only going to % be called at top level in a displayed equation, thus always mathstyle = % uncramped displaystyle. % \begin{macrocode} \def\lrss@reattach{% \begingroup % "The TeXbook" Appendix G step 18: \setlength\prelim@sup@base{\ht\z@-\sup@drop}% \setlength\prelim@sub@depth{\dp\z@ +\sub@drop}% \unhbox\z@ \ifcase\subsup@flag % case 0: this can't happen \or \lr@subscript % case 1: subscript only \or \lr@superscript % case 2: superscript only \else \lr@subsup % case 3: sub and superscript both \fi \endgroup } % \end{macrocode} % \begin{macrocode} \def\lr@subscript{% \sub@depth\sub@base@one \ifdim\prelim@sub@depth>\sub@depth \sub@depth\prelim@sub@depth\fi \setlength\dim@a{\ht\tw@ -.8\sym@xheight}% \ifdim\dim@a>\sub@depth \sub@depth=\dim@a \fi \twang@adjust\sub@depth \lower\sub@depth\box\tw@ } % \end{macrocode} % % \begin{macrocode} \def\lr@superscript{% \sup@base\sup@base@one \ifdim\prelim@sup@base>\sup@base \sup@base\prelim@sup@base\fi \setlength\dim@a{\dp\tw@ -.25\sym@xheight}% \ifdim\dim@a>\sup@base \sup@base\dim@a \fi \twang@adjust\sup@base \raise\sup@base\box\tw@ } % \end{macrocode} % % \begin{macrocode} \def\lr@subsup{% \sub@depth\sub@base@two \ifdim\prelim@sub@depth>\sub@depth \sub@depth\prelim@sub@depth \fi \twang@adjust\sub@depth \lower\sub@depth\box\tw@ } % \end{macrocode} % % For delimiters that curve top and bottom, the twang factor allows % horizontal shifting of the sub and superscripts so they don't % fall too far away (or too close for that matter). This is % accomplished by arranging for (\eg ) \verb"\right\rangle" to leave % a penalty $N$ in the math list before the subsup penalty that triggers % \cs{lrss@reattach}, where $N$ is the mathcode of % \cs{rangle} (ignoring \dquoted{small} variant). % \begin{macrocode} \def\twang@adjust#1{% \begingroup \@ifundefined{twang@\right@delim@code}{}{% \setlength\dim@d{#1-\mathaxis}% % put an upper limit on the adjustment \ifdim\dim@d>1em \dim@d 1em \fi \kern\csname twang@\right@delim@code\endcsname\dim@d }% \endgroup } % \end{macrocode} % The method used to apply a \dquoted{twang} adjustment is just an % approximate solution to a complicated problem. % We make the following assumptions that hold true, approximately, % for the most common kinds of delimiters: % \begin{enumerate} % \item % The right delimiter is symmetrical top to bottom. % % % \item There is an upper limit on the size of the adjustment. % % % \item When we have a superscript, the amount of left-skew that we % want to apply is linearly proportional to the distance of the bottom % left corner of the superscript from the math axis, with the ratio % depending on the shape of the delimiter symbol. % % % \end{enumerate} % . % By symmetry, Assumption 3 is true also for subscripts (upper left % corner). % Assumption 2 is more obviously true for parens and braces, where the % largest super-extended versions consist of truly vertical parts with % slight bending on the ends, than it is for a \cs{rangle}. % But suppose for the sake of expediency that it is % approximately true for rangle symbols also. % % % Here are some passable twang factors for the most common types of % delimiters in \fn{cmex10}, as determined by rough measurements from % magnified printouts. % \begin{literalcode} % vert bar, double vert: 0 % square bracket: -.1 % curly brace: -.25 % parenthesis: -.33 % rangle: -.4 % \end{literalcode} % Let's provide a non-private command for changing the twang factor of % a given symbol. % \begin{macrocode} \newcommand{\DeclareTwang}[2]{% \ifcat.\@nx#1\begingroup \lccode`\~=`#1\lowercase{\endgroup \DeclareTwang{~}}{#2}% \else \@xp\decl@twang#1?\@nil{#2}% \fi } % \end{macrocode} % Note that this is dependent on a fixed interpretation of the % mathgroup number \arg4 . % \begin{macrocode} \def\decl@twang#1#2#3#4#5#6#7\@nil#8{% \@namedef{twang@\number"#4#5#6}{#8}% } \DeclareTwang{\rangle}{-.4} \DeclareTwang{)}{-.33} \DeclareTwang{\rbrace}{-.25} % \end{macrocode} % \end{macro} % % % % \section{Series of expressions} % The \env{dseries} environment is for a display % containing a series of expressions of the form \quoted{A, B} or \quoted{A and % B} or \quoted{A, B, and C} and so on. Typically the expressions % are separated by a double quad of space. If the expressions in a % series don't all fit in a single line, they are continued onto extra % lines in a ragged-center format. % \begin{macrocode} \newenvironment{dseries}{\let\eq@hasNumber\@True \breqn@optarg\@dseries{}}{}% \def\enddseries#1{\check@punct@or@qed}% % \end{macrocode} % % And the unnumbered version of same. % \begin{macrocode} \newenvironment{dseries*}{\let\eq@hasNumber\@False \breqn@optarg\@dseries{}}{}% \@namedef{enddseries*}#1{\check@punct@or@qed}% \@namedef{end@dseries*}{\end@dseries}% \def\@dseries[#1]{% % \end{macrocode} % Turn off the special breaking behavior of mathrels \etc for math % formulas embedded in a \env{dseries} environment. % %BRM: DS Expermient: Use alternative display setup. % \begin{macrocode} % \def\display@setup{\displaystyle}% \let\display@setup\dseries@display@setup % Question: should this be the default for dseries??? % \let\eq@centerlines\@True \global\eq@wdCond\z@ % \end{macrocode} % BRM: use special layout for dseries % \begin{macrocode} % \@dmath[#1]% \@dmath[layout={M},#1]% \mathsurround\z@\@@math \penalty\@Mi \let\endmath\ends@math \def\premath{% % \end{macrocode} % BRM: Tricky to cleanup space OR add space ONLY BETWEEN math! % FMi: improvement to measure against current font. % \begin{macrocode} \ifdim\lastskip<\fontdimen2\font \unskip \else\ifnum\lastpenalty<\@M \dquad\fi\fi }% % \end{macrocode} %BRM: Tricky; if a subformula breaks, we'd like to start the next on new line! % \begin{macrocode} \def\postmath{\unpenalty\eq@addpunct \penalty\intermath@penalty \dquad \@ignoretrue}% \ignorespaces } \def\end@dseries{% \unskip\unpenalty \@@endmath \mathsurround\z@ \end@dmath } % \end{macrocode} % BRM: Try this layout for dseries: Essentially layout i, but w/o % limit to 1 line. And no fallback! % \begin{macrocode} \def\eq@try@layout@M{% \edef\@parshape{\parshape 1 0pt \the\eq@linewidth\relax}% \eq@trial@b{M}{}% } % \end{macrocode} % BRM: Tricky to get right value here. % Prefer breaks between formula if we've got to break at all. % \begin{macrocode} %\def\intermath@penalty{-201}% \def\intermath@penalty{-221}% % \end{macrocode} % BRM: A bit tighter than it was ( 1em minus.25em ) % \begin{macrocode} %\newcommand\dquad{\hskip0.4em} \newcommand\dquad{\hskip0.6em minus.3em} \newcommand\premath{}\newcommand\postmath{} % \end{macrocode} % % Change the \env{math} environment to add % \cs{premath} and \cs{postmath}. They are no-ops except % inside a \env{dseries} environment. % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Redefinition of math environment to take advantage of dseries env. % \begin{macrocode} \renewenvironment{math}{% \leavevmode \premath \ifmmode\@badmath\else\@@math\fi }{% \ifmmode\@@endmath\else\@badmath\fi } \def\ends@math#1{\check@punct@or@qed} \def\end@math{% \ifmmode\@@endmath\else\@badmath\fi \postmath } % \end{macrocode} % % % % % \section{Equation groups} % For many equation groups the strategy is easy: just center each % equation individually following the normal rules for a single % equation. In some groups, each equation gets its own number; in % others, a single number applies to the whole group (and may need to be % vertically centered on the height of the group). In still other % groups, the equations share a parent number but get individual equation % numbers consisting of parent number plus a letter. % % If the main relation symbols in a group of equations are to be % aligned, then the final alignment computations cannot be done until the % end of the group \mdash \ie , the horizontal positioning of the first % $n - 1$ equations cannot be done immediately. Yet because of % the automatic line breaking, we cannot calculate an initial value of % RHS-max over the whole group unless we do a trial run on each equation % first to find an RHS-max for that equation. Once we know RHS-group-max % and LHS-group-max we must redo the trial set of each equation because % they may affect the line breaks. If the second trial for an % equation fails (one of its lines exceeds the available width), but % the first one succeeded, fall back to the first trial, \ie let that % equation fall out of alignment with the rest of the group. % % % All right then, here is the general idea of the whole algorithm for % group alignment. % To start with, ignore the possibility of equation numbers so that % our equation group has the form: % \begin{literalcode} % LHS[1] RHS[1,1] RHS[1,2] ... RHS[1,n[1]] % LHS[2] RHS[2,1] RHS[2,2] ... RHS[2,n[2]] % ... % LHS[3] RHS[3,1] RHS[3,2] ... RHS[3,n[3]] % \end{literalcode} % The number of RHS's might not be the same for all of the % equations. % First, accumulate all of the equation contents in a queue, checking % along the way to find the maximum width of all the LHS's and the maximum % width of all the RHS's. % Call these widths maxwd\_L and maxwd\_R. % Clearly if maxwd\_L + maxwd\_R is less than or equal to the available % equation width then aligning all of the equations is going to be simple. % % % Otherwise we are going to have to break at least one of the RHS's % and/or at least one of the LHS's. % The first thing to try is using maxwd\_L for the LHS's and breaking % all the RHS's as needed to fit in the remaining space. % However, this might be a really dumb strategy if one or more of the % LHS's is extraordinarily wide. % So before trying that we check whether maxwd\_L exceeds some % threshold width beyond which it would be unsensible not to break the LHS. % Such as, max(one-third of the available width; six ems), or % something like that. % Or how about this? % Compare the average LHS width and RHS width and divide up the available % width in the same ratio for line breaking purposes. % % % BRM: Fairly broad changes; it mostly didn't work before (for me). % % \begin{description} % \item[\cs{begin}\csarg{dgroup} produces a `numbered' group] % The number is the next equation number. % There are 2 cases: % \begin{itemize} % \item If ANY contained equations are numbered (|\begin{dmath}|), % then they will be subnumbered: eg 1.1a % and the group number is not otherwise displayed. % \item If ALL contained equations are unnumbered (|\begin{dmath*}|) % then the group, as a whole, gets a number displayed, % using the same number placement as for equations. % \end{itemize} % \item[\cs{begin}\csarg{dgroup*} produces an unnumbered group.] % Contained equations are numbered, or not, as normal. % But note that in the mixed case, it's too late to % force the unnumbered eqns to \cs{retry@with@number} % We'll just do a simple check of dimensions, after the fact, % and force a shiftnumber if we're stuck. % % NOTE: Does this work for dseries, as well? (alignment?) % % NOTE: Does \cs{label} attach to the expected thing? % % \item[For number placement] We use shiftnumber placement on ALL equations % if ANY equations need it, or if an unnumbered equation is too % wide to be aligned, given that the group or other eqns are numbered. % [does this latter case interract with the chosen alignment?] % % \item[For Alignment] % As currently coded, it tries to align on relations, by default. % If LHS's are not all present, or too long, it switches to left-justify. % Maybe there are other cases that should switch? % Should there be a case for centered? % % NOTE: Should there be some options to choose alignment? % \end{description} % % \begin{macro}{\eq@group} % \begin{macro}{\GRP@top} % % \begin{macrocode} \let\eq@group\@False \let\grp@shiftnumber\@False \let\grp@hasNumber\@False \let\grp@eqs@numbered\@False \let\grp@aligned\@True % \end{macrocode} % \end{macro} % \end{macro} % % % Definition of the \env{dgroup} environment. % \begin{macrocode} \newenvironment{dgroup}{% \@dgroup@start@hook \let\grp@hasNumber\@True\breqn@optarg\@dgroup{}% }{% \end@dgroup } % \end{macrocode} % And the. % \begin{macrocode} \newtoks\GRP@queue \newenvironment{dgroup*}{% \let\grp@hasNumber\@False\breqn@optarg\@dgroup{}% }{% \end@dgroup } \def\@dgroup[#1]{% % \breqn@debugmsg{=== DGROUP ==================================================}% \let\eq@group\@True \global\let\eq@GRP@first@dmath\@True \global\GRP@queue\@emptytoks \global\setbox\GRP@box\box\voidb@x \global\let\GRP@label\@empty \global\grp@wdL\z@\global\grp@wdR\z@\global\grp@wdT\z@ \global\grp@linewidth\z@\global\grp@wdNum\z@ \global\let\grp@eqs@numbered\@False \global\let\grp@aligned\@True \global\let\grp@shiftnumber\@False \eq@prelim \setkeys{breqn}{#1}% \if\grp@hasNumber \grp@setnumber \fi } \def\end@dgroup{% \EQ@displayinfo \grp@finish \if\grp@hasNumber\grp@resetnumber\fi } % \end{macrocode} % If the \pkg{amsmath} package is not loaded the parentequation % counter will not be defined. % \begin{macrocode} \@ifundefined{c@parentequation}{\newcounter{parentequation}}{} % \end{macrocode} % Init. % \begin{macrocode} \global\let\GRP@label\@empty \def\add@grp@label{% \ifx\@empty\GRP@label \else \GRP@label \global\let\GRP@label\@empty \fi } % \end{macrocode} % Before sending down the `equation' counter to the subordinate level, % set the current number in \cs{EQ@numbox}. The % \cs{eq@setnumber} function does everything we need here. If % the child equations are unnumbered, \cs{EQ@numbox} will retain the % group number at the end of the group. % \begin{macrocode} \def\grp@setnumber{% \global\let\GRP@label\next@label \global\let\next@label\@empty % Trick \eq@setnumber to doing our work for us. \let\eq@hasNumber\@True \eq@setnumber % \end{macrocode} % Define \cn{theparentequation} equivalent to current % \cn{theequation}. \cn{edef} is necessary to expand the % current value of the equation counter. This might in rare cases % cause something to blow up, in which case the user needs to add % \cn{protect}. % \begin{macrocode} \global\sbox\GRP@numbox{\unhbox\EQ@numbox}% \grp@wdNum\eq@wdNum \let\eq@hasNumber\@False \let\eq@number\@empty \eq@wdNum\z@ % \protected@edef\theparentequation{\theequation}% \setcounter{parentequation}{\value{equation}}% % \end{macrocode} % And set the equation counter to 0, so that the normal incrementing % processes will produce the desired results if the child equations are % numbered. % \begin{macrocode} \setcounter{equation}{0}% \def\theequation{\theparentequation\alph{equation}}% % \breqn@debugmsg{Group Number \theequation}% } % \end{macrocode} % At the end of a group, need to reset the equation counter. % \begin{macrocode} \def\grp@resetnumber{% \setcounter{equation}{\value{parentequation}}% } \newbox\GRP@box \newbox\GRP@wholebox % \end{macrocode} % Save data for this equation in the group % \begin{itemize} % \item push the trial data onto end of \cs{GRP@queue}. % \item push an hbox onto the front of \cs{GRP@box} containing: % \cs{EQ@box}, \cs{EQ@copy}, \cs{penalty} 1 and \cs{EQ@numbox}. % \end{itemize} % \begin{macro}{\grp@push} % % For putting the equation on a queue. % \begin{macrocode} \def\grp@push{% \global\GRP@queue\@xp\@xp\@xp{\@xp\the\@xp\GRP@queue \@xp\breqn@elt\@xp{\EQ@trial}% }% \global\setbox\GRP@box\vbox{% \hbox{\box\EQ@box\box\EQ@copy\penalty\@ne\copy\EQ@numbox}% \unvbox\GRP@box }% \EQ@trial \if\eq@isIntertext\else \ifdim\eq@wdL>\grp@wdL \global\grp@wdL\eq@wdL \fi \ifdim\eq@wdT>\grp@wdT \global\grp@wdT\eq@wdT \fi \setlength\dim@a{\eq@wdT-\eq@wdL}% \ifdim\dim@a>\grp@wdR \global\grp@wdR\dim@a \fi \ifdim\eq@linewidth>\grp@linewidth \global\grp@linewidth\eq@linewidth\fi \if\eq@hasNumber \global\let\grp@eqs@numbered\@True \ifdim\eq@wdNum>\grp@wdNum\global\grp@wdNum\eq@wdNum\fi \fi \if\EQ@hasLHS\else\global\let\grp@aligned\@False\fi \if D\eq@layout \global\let\grp@aligned\@False\fi % Layout D (usually) puts rel on 2nd line. \if\eq@shiftnumber\global\let\grp@shiftnumber\@True\fi % One eq shifted forces all. \fi } % \end{macrocode} % \end{macro} % \begin{macro}{\grp@finish} % % Set accumulated equations from a \env{dgroup} environment. % % BRM: Questionable patch!! % When processing the \cs{GRP@queue}, put it into a \cs{vbox}, then \cs{unvbox} it. % This since there's a bizarre problem when the \cs{output} routine % gets invoked at an inopportune moment: All the not-yet-processed % \cs{GRP@queue} ends up in the \cs{@freelist} and bad name clashes happen. % Of course, it could be due to some other problem entirely!!! % \begin{macrocode} \def\grp@finish{% % \debug@box\GRP@box % \breqn@debugmsg{\GRP@queue: \the\GRP@queue}% % \end{macrocode} % == Now that we know the collective measurements, make final decision % about alignment \& shifting. Check if alignment is still possible % \begin{macrocode} \setlength\dim@a{\grp@wdL+\grp@wdR-4em}% Allowance for shrink? \if\grp@aligned \ifdim\dim@a>\grp@linewidth \global\let\grp@aligned\@False \fi \fi % \end{macrocode} % If we're adding an unshifted group number that equations didn't know % about, re-check shifting % \begin{macrocode} \addtolength\dim@a{\grp@wdNum }% Effective length \if\grp@shiftnumber \else \if\@And{\grp@hasNumber}{\@Not\grp@eqs@numbered} \ifdim\dim@a>\grp@linewidth \global\let\grp@shiftnumber\@True \fi \fi \fi % \end{macrocode} % If we can still align, total width is sum of maximum LHS \& RHS % \begin{macrocode} \if\grp@aligned \global\grp@wdT\grp@wdL \global\advance\grp@wdT\grp@wdR \fi %<*trace> \breqn@debugmsg{======= DGROUP Formatting \MessageBreak==== \grp@wdL=\the\grp@wdL, \grp@wdR=\the\grp@wdR \MessageBreak==== Shift Number=\theb@@le\grp@shiftnumber, Eqns. numbered=\theb@@le\grp@eqs@numbered \MessageBreak==== Aligned=\theb@@le\grp@aligned \MessageBreak==== \grp@wdNum=\the\grp@wdNum}% % % \end{macrocode} % BRM: Originally this stuff was dumped directly, without capturing it % in a \cs{vbox} % \begin{macrocode} \setbox\GRP@wholebox\vbox{% \let\breqn@elt\eqgrp@elt \the\GRP@queue }% % \end{macrocode} % If we're placing a group number (not individual eqn numbers) % NOTE: For now, just code up LM number % NOTE: Come back and handle other cases. % NOTE: Vertical spacing is off, perhaps because of inter eqn. glue % % A bit of a hack to get the top spacing correct. Fix this logic % properly some day. Also, we do the calculation in a group for % maximum safety. % \begin{macrocode} \global\let\eq@GRP@first@dmath\@True \begingroup \dmath@first@leftskip \eq@topspace{\vskip\parskip}% \endgroup \if\@And{\grp@hasNumber}{\@Not{\grp@eqs@numbered}}% % \eq@topspace{\vskip\parskip}% \if\grp@shiftnumber \copy\GRP@numbox \penalty\@M \kern\eqlineskip \else \setlength\dim@a{% (\ht\GRP@wholebox+\dp\GRP@wholebox+\ht\GRP@numbox-\dp\GRP@numbox)/2}% \setlength\skip@c{\dim@a-\ht\GRP@numbox}% \vglue\skip@c% NON discardable \copy\GRP@numbox \penalty\@M %<*trace> \breqn@debugmsg{GROUP NUMBER: preskip:\the\skip@c, postkern:\the\dim@a, height:\the\ht\GRP@wholebox, \MessageBreak==== box height:\the\ht\GRP@numbox, box depth:\the\dp\GRP@numbox}% % \kern-\dim@a \kern-\abovedisplayskip % To cancel the topspace above the first eqn. \fi \fi %<*trace> %\debug@box\GRP@wholebox % \unvbox\GRP@wholebox \let\breqn@elt\relax % \end{macrocode} % We'd need to handle shifted, right number here, too!!! % \begin{macrocode} \eq@botspace % not needed unless bottom number? } % \end{macrocode} % \end{macro} % % \begin{macro}{\eqgrp@elt} % % Mission is to typeset the next equation from the group queue. % % The arg is an \cs{EQ@trial} % \begin{macrocode} \def\eqgrp@elt#1{% \global\setbox\GRP@box\vbox{% \unvbox\GRP@box \setbox\z@\lastbox \setbox\tw@\hbox{\unhbox\z@ \ifnum\lastpenalty=\@ne \else \global\setbox\EQ@numbox\lastbox \fi \unpenalty \global\setbox\EQ@copy\lastbox \global\setbox\EQ@box\lastbox }% }% \begingroup \let\eq@botspace\relax #1% \if\eq@isIntertext \vskip\belowdisplayskip \unvbox\EQ@copy \else \grp@override \eq@finish \fi \endgroup } % \end{macrocode} % \end{macro} % Override the \cs{eq@trial} data as needed for this equation in this group % NOTE: w/ numbering variations (see above), we may need to tell % \cs{eq@finish} to allocate space for a number, but not actually have one % \begin{macrocode} \def\grp@override{% % \end{macrocode} % For aligned (possibly becomes an option?) % For now ASSUMING we started out as CLM!!! % \begin{macrocode} \def\eqindent{I}% % \end{macrocode} % compute nominal left for centering the group % \begin{macrocode} \setlength\dim@a{(\grp@linewidth-\grp@wdT)/2}% % \end{macrocode} % Make sure L+R not too wide; should already have unset alignment % \begin{macrocode} \ifdim\dim@a<\z@\dim@a=\z@\fi \dim@b\if L\eqnumside\grp@wdNum\else\z@\fi % \end{macrocode} % make sure room for number on left, if needed. % \begin{macrocode} \if\grp@shiftnumber\else \ifdim\dim@b>\dim@a\dim@a\dim@b\fi \fi \if\grp@aligned \addtolength\dim@a{\grp@wdL-\eq@wdL}% \fi \mathindent\dim@a \ifdim\dim@b>\dim@a \let\eq@shiftnumber\@True \fi % \end{macrocode} % Could set |\def\eqnumplace{T}| (or even (m) if indentation is enough). % % NOTE: Work out how this should interact with the various formats!!! % NOTE: should recognize the case where the LHS's are a bit Wild, % and then do simple left align (not on relation) % \begin{macrocode} } % \end{macrocode} % % % % \section{The \env{darray} environment} % There are two potential applications for darray. One % is like eqnarray where the natural structure of the material crosses the % table cell boundaries, and math operator spacing needs to be preserved % across cell boundaries. And there is also the feature of % attaching an equation number to each row. The other application % is like a regular array but with automatic displaystyle math in each % cell and better interline spacing to accommodate outsize cell % contents. In this case it is difficult to keep the vert ruling % capabilities of the standard \env{array} environment without % redoing the implementation along the lines of Arseneau's % \pkg{tabls} package. Because the vert ruling feature is at % cross purposes with the feature of allowing interline stretch and page % breaks within a multiline array of equations, the \env{darray} % environment is targeted primarily as an alternative to % \env{eqnarray}, and does not support vertical ruling. % % Overall strategy for \env{darray} is to use % \cs{halign} for the body. In the case of a group, use a % single halign for the whole group! % \begin{aside} % What about intertext? % \end{aside} % % That's the most reliable way % to get accurate column widths. Don't spread the halign to the % column width, just use the natural width. Then, if we repack the % contents of the halign into \cs{EQ@box} and \cs{EQ@copy}, as % done for dmath, and twiddle a bit with the widths of the first and last % cell in each row, we can use the same algorithms for centering and % equation number placement as dmath! As well as handling footnotes % and vadjust objects the same way. % % We can't just use \cs{arraycolsep} for \env{darray}, if % we want to be able to change it without screwing up interior arrays. % So let's make a new colsep variable. The initial value is % \quoted{2em, but let it shrink if necessary}. % \begin{macrocode} \newskip\darraycolsep \darraycolsep 20pt plus1fil minus12pt % \end{macrocode} % Let's make a nice big default setup with eighteen columns, split up % into six sets of lcr like \env{eqnarray}. % \begin{macrocode} \newcount\cur@row \newcount\cur@col \def\@tempa#1#2#3{% \cur@col#1 \hfil \setbox\z@\hbox{$\displaystyle####\m@th$}\@nx\col@box \tabskip\z@skip &\cur@col#2 \hfil \setbox\z@\hbox{$\displaystyle\mathord{}####\mathord{}\m@th$}\@nx\col@box \hfil &\cur@col#3 \setbox\z@\hbox{$\displaystyle####\m@th$}\@nx\col@box \hfil\tabskip\darraycolsep } \xdef\darray@preamble{% \@tempa 123&\@tempa 456&\@tempa 789% &\@tempa{10}{11}{12}&\@tempa{13}{14}{15}&\@tempa{16}{17}{18}% \cr } \@ifundefined{Mathstrut@}{\let\Mathstrut@\strut}{} \def\darray@cr{\Mathstrut@\cr} \def\col@box{% %<*trace> %\breqn@debugmsg{Col \number\cur@row,\number\cur@col: \the\wd\z@\space x \the\ht\z@+\the\dp\z@}% % \unhbox\z@ } \newenvironment{darray}{\breqn@optarg\@darray{}}{} \def\@darray[#1]{% % \breqn@debugmsg{=== DARRAY ==================================================}% \if\eq@group\else\eq@prelim\fi % \end{macrocode} % Init the halign preamble to empty, then unless the \quoted{cols} key is % used to provide a non-null preamble just use the % default darray preamble which is a multiple lcr. % \begin{macrocode} \global\let\@preamble\@empty \setkeys{breqn}{#1}% \the\eqstyle \eq@setnumber \ifx\@preamble\@empty \global\let\@preamble\darray@preamble \fi \check@mathfonts % \let\check@mathfonts\relax % tempting, but too risky \@xp\let\csname\string\ \endcsname\darray@cr \setbox\z@\vbox\bgroup \everycr{\noalign{\global\advance\cur@row\@ne}}% \tabskip\z@skip \cur@col\z@ \global\cur@row\z@ \penalty\@ne % flag for \dar@repack \halign\@xp\bgroup\@preamble } % \end{macrocode} % Assimilate following punctuation. % \begin{macrocode} \def\enddarray#1{\check@punct@or@qed} \def\end@darray{% \ifvmode\else \eq@addpunct \Mathstrut@\fi\crcr \egroup \dar@capture \egroup } % \end{macrocode} % % The \cs{dar@capture} function steps back through the % list of row boxes and grinds them up in the best possible way. % \begin{macrocode} \def\dar@capture{% %% \showboxbreadth\maxdimen\showboxdepth99\showlists \eq@wdL\z@ \eq@wdRmax\z@ \dar@repack } % \end{macrocode} % % The \cs{dar@repack} function is a variation of % \cs{eq@repack}. % \begin{macrocode} \def\dar@repack{% \unpenalty \setbox\tw@\lastbox %\batchmode{\showboxbreadth\maxdimen\showboxdepth99\showbox\tw@}\errorstopmode \global\setbox\EQ@box\hbox{% \hbox{\unhcopy\tw@\unskip}\penalty-\@M \unhbox\EQ@box}% \global\setbox\EQ@copy\hbox{% \hbox{\unhbox\tw@\unskip}\penalty-\@M \unhbox\EQ@copy}% \unskip \ifcase\lastpenalty \else\@xp\@gobble\fi \dar@repack } % \end{macrocode} % % % % % \section{Miscellaneous} % The \cs{condition} command. With % the star form, set the argument in math mode instead of text mode. % In a series of conditions, use less space between members of the % series than between the conditions and the main equation body. % % WSPR: tidied/fixed things up as it made sense to me but might have % broken something else! % \begin{macrocode} \newskip\conditionsep \conditionsep=10pt minus5pt% \newcommand{\conditionpunct}{,} % \end{macrocode} % \begin{macro}{\condition} % \begin{macrocode} \newcommand\condition{% \begingroup\@tempswatrue \breqn@ifstar{\@tempswafalse \condition@a}{\condition@a}} % \end{macrocode} % \end{macro} % \begin{macro}{\condition@a} % \begin{macrocode} \newcommand\condition@a[2][\conditionpunct]{% \unpenalty\unskip\unpenalty\unskip % BRM Added \hbox{#1}% \penalty -201\relax\hbox{}% Penalty to allow breaks here. \hskip\conditionsep \setbox\z@\if@tempswa\hbox{#2}\else\hbox{$\textmath@setup #2$}\fi % \end{macrocode} % BRM's layout is achieved with this line commented out but it has the nasty side-effect of shifting the equation number to the next line: % \begin{macrocode} % \global\eq@wdCond\wd\z@ \usebox\z@ \endgroup} % \end{macrocode} % \end{macro} % % The \env{dsuspend} environment. First the old one that didn't work. % \begin{macrocode} \newenvironment{XXXXdsuspend}{% \global\setbox\EQ@box\vbox\bgroup \@parboxrestore % \end{macrocode} % If we are inside a list environment, \cs{displayindent} and % \cs{displaywidth} give us \cs{@totalleftmargin} and % \cs{linewidth}. % \begin{macrocode} \parshape 1 \displayindent \displaywidth\relax \hsize=\columnwidth \noindent\ignorespaces }{% \par\egroup % \end{macrocode} % Let's try giving \cs{EQ@box} the correct height for the first % line and \cs{EQ@copy} the depth of the last line. % \begin{macrocode} \global\setbox\GRP@box\vbox{% \vbox{\copy\EQ@box\vtop{\unvbox\EQ@box}}% \unvbox\GRP@box }% % \end{macrocode} % Need to add a dummy element to \cs{GRP@queue}. % \begin{macrocode} \global\GRP@queue\@xp{\the\GRP@queue \breqn@elt{\gdef\EQ@trial{}}% }% } % \end{macrocode} % And then the one that does work. % \begin{macrocode} \newenvironment{dsuspend}{% \global\setbox\EQ@box\vbox\bgroup \@parboxrestore \parshape 1 \displayindent \displaywidth\relax \hsize=\columnwidth \noindent\ignorespaces }{% \par\egroup \global\setbox\GRP@box\vbox{% \hbox{\copy\EQ@box\vtop{\unvbox\EQ@box}}% \unvbox\GRP@box }% \global\GRP@queue\@xp{\the\GRP@queue % \breqn@elt{\gdef\EQ@trial{\let\eq@isIntertext\@True}}% \breqn@elt{\let\eq@isIntertext\@True}% }% } % \end{macrocode} % Allow \cn{intertext} as a short form of the \env{dsuspend} % environment; it's more convenient to write, but it doesn't support % embedded verbatim because it reads the material as a macro argument. % To support simultaneous use of \pkg{amsmath} and % \pkg{breqn}, the user command \cs{intertext} is left alone % until we enter a \pkg{breqn} environment. % \begin{macrocode} \newcommand\breqn@intertext[1]{\dsuspend#1\enddsuspend} % \end{macrocode} % % % \begin{macro}{\*} % \begin{macro}{\discretionarytimes} % Discretionary times sign. Standard \latex definition % serves only for inline math. Should the thin space be % included? Not sure. % \begin{macrocode} \renewcommand{\*}{% \if@display % \end{macrocode} % Since \cs{eq@binoffset} is mu-glue, we can't use it directly % with \cs{kern} but have to measure it separately in a box. % \begin{macrocode} \setbox\z@\hbox{\mathsurround\z@$\mkern\eq@binoffset$}% \discretionary{}{% \kern\the\wd\z@ \textchar\discretionarytimes }{}% \thinspace \else \discretionary{\thinspace\textchar\discretionarytimes}{}{}% \fi } % \end{macrocode} % This is only the symbol; it can be changed to some other symbol if % desired. % \begin{macrocode} \newcommand{\discretionarytimes}{\times} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\nref} % % This is like \cs{ref} but doesn't apply font changes or other % guff if the reference is undefined. % And it is fully expandable for use as a label value. % \begin{aside} % % Can break with Babel if author uses active characters in label key; % need to address that \begin{dn} % mjd,1999/01/21 % \end{dn} % . % \end{aside} % % \begin{macrocode} \def\nref#1{\@xp\@nref\csname r@#1\endcsname} \def\@nref#1#2{\ifx\relax#1??\else \@xp\@firstoftwo#1\fi} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % \end{macrocode} % \end{macro} % % % \section{Compatibility} % % \paragraph{lineno} (or at the very least, allow documents to compile!) % \begin{macrocode} \AtBeginDocument{% \@ifpackageloaded{lineno}{% \g@addto@macro\@dmath@start@hook{\nolinenumbers}% \g@addto@macro\@dgroup@start@hook{\nolinenumbers}% }{}% } % \end{macrocode} % % % % \section{Wrap-up} % The usual endinput. % \begin{macrocode} % % \end{macrocode} % % % % % \section{To do} % \begin{enumerate} % \item Alignment for equation groups. % % % \item % Use dpc's code for package options in keyval form. % % \item % Encapsulate \dquoted{break math} into a subroutine taking suitable % arguments. % % \item % Need a density check for layout S when linewidth is very small. % % \item % Make \verb":=" trigger a warning about using \cs{coloneq} % instead. % % \item Ill-centered multiline equation (three-line case) in % test008. % % \item Attaching a single group number. % % % \item % Make sure to dump out box registers after done using them. % % \item Do the implementation for \cs{eq@resume@parshape}. % % % \item Check on stackrel and buildrel and relbar and ???. % % % \item Test math symbols at the beginning of array cells. % % \item Test \dbslash cmd in and out of delims. % % \item Framing the equation body: the parshape and number placement % need adjusting when a frame is present. % % % \item Cascading line widths in list env. % % % \item Noalign option for dmath = multline arrangement? % % % \item Nocompact option, suggested 1998/05/19 by Andrew % Swann. % % % \item \cs{delbreak} cmd to add discretionary space at a break % within delimiters. % % % \item Reduce above/below skip when the number is shifted. % % % \item Need a \cs{middelim} command for marking a delimiter symbol % as nondirectional if it has an innate directionality \verb"()[]" \etc . % % % \item % \cs{xrightarrow} from amsmath won't participate in line % breaking unless something extra is done. % Make \cs{BreakingRel} and \cs{BreakingBin} functions? % % \item Placement of number in an indented quotation or % abstract. % % \item If $LHSwd > 2em$, it might be a good idea to try with % eq@indentstep = 2em before shifting the number. Currently this % doesn't happen if the first trial pass (without the number) % succeeds with $indentstep = LHSwd > 2em$. % % % \item Read past \verb"\end{enumerate}" when checking % for \verb"\end{proof}"? % % \item % Look into using a \dquoted{qed-list} of environment names instead of % checking the existence of \cs{proofqed}. % % \item Pick up the vadjust\slash footnote\slash mark handling. % % % \item Forcing\slash prohibiting page breaks after\slash before % an equation. % % % \item Adding a spanner brace on the left and individual numbers on % the right (indy-numbered cases). % % % \item Provide \cs{shiftnumber}, \cs{holdnumber} to % override the decision. % % \item Provide a mechanism for adjusting the vertical position of % the number. Here a version-specific selection macro would be % useful. % \begin{literalcode} % \begin{dmath}[ % style={\foredition{1}{\raisenumber{13pt}}} % ] % \end{literalcode} % % % \item % Add an alignleft option for an equation group to mean, break and % align to a ladder layout as usual within the equations, but for the % group alignment used the leftmost point (for equations that don't % have an LHS, this makes no difference). % % \item % Test with Arseneau's wrapfig for parshape\slash everypar % interaction. % % % \item Fix up the macro/def elements. % % \item Convert the literal examples in section \quoted{Equation types and % forms} to typeset form. % % % \item Compile comparison-examples: \eg , a standard equation % env with big left-right objects that don't shrink, versus how shrinking % can allow it to fit. % % % \item Frame the \dquoted{figures} since they are mostly % text. % % \end{enumerate} % % % % Possible enhancements: % \begin{enumerate} % \item Provide a \opt{pull} option meaning to pull the first % and last lines out to the margin, like the \env{multline} % environment of the \pkg{amsmath} package. Maybe this should % get an optional argument, actually, to specify the amount of space left % at the margin. % % \item With the draft option, one would like to see the equation % labels in the left margin. Need to check with the % \pkg{showkeys} package. % % % \item Options for break preferences: if there's not enough room, do % we first shift the number, or first try to break up the equation % body?. In an aligned group, does sticking to the group alignment % take precedence over minimizing the number of line breaks needed for % individual equations?. And the general preferences probably need % to be overridable for individual instances. % % \item Extend suppress-breaks-inside-delimiters support to inline % math (suggestion of Michael Doob). % % \item Use belowdisplayshortskip above a dsuspend fragment if the % fragment is only one line and short enough compared to the equation line % above it. % % % \item Add \cs{eqfuzz} distinct from \cs{hfuzz}. % Make use of it in the measuring phase. % % % \item Provision for putting in a \quoted{continued} note. % % \item Conserve box mem: modify frac, sub, sup, overline, underline, % sqrt, to turn off \cs{bin@break} and (less urgently) % \cs{rel@break}. % % % \item More explicit support for Russian typesetting conventions (cf % Grinchuk article). % % % \item With package option \opt{refnumbers}, % leave unnumbered all uncited equations, even if they are not done with % the star form (Bertolazzi's easyeqn idea). % % \item In an equation group, use a vertical bracket with the % equation number to mark the lines contained in that equation. % % % \item For a two-line multline thingamabob, try to % make sure that the lines overlap in the middle by 2 em or whatever % (settable design variable). % % \item Provide a separate vertical column for the principal mathrel % symbols and center them within the column if they aren't all the same % width. Maybe an option for \env{dmath}: relwidth=x, so that two % passes are not required to get the max width of all the mathrels. % Or, no, just require it to be an halign or provide a macro to be % applied to all the shorter rels: % \begin{literalcode} % lhs \widerel{19pt}{=} ... % \xrightarrow{foo} ... % \end{literalcode} % % % \item try to use vadjust for keepglue % % \end{enumerate} % % \PrintIndex % % \Finale