%\filename{kernelmacros.tex}
%\edited{last by stolfi on Wed Sep 16 19:59:59 1987}

% Font- and format-independent macros for TeX 82

% CHARACTER CODES

  % Catcodes:

    \catcode`\{=1 % left brace is begin-group character
    \catcode`\}=2 % right brace is end-group character

  \message{catcodes ...}

    % We had to define the \catcodes right away, before the message line,
    % since \message uses the { and } characters.

    % When INITEX (the TeX initializer) starts up,
    % it has defined the following \catcode values:
    % \catcode`\^^@=9 % ascii null is ignored
    % \catcode`\^^M=5 % ascii return is end-line
    % \catcode`\\=0 % backslash is TeX escape character
    % \catcode`\%=14 % percent sign is comment character
    % \catcode`\ =10 % ascii space is blank space
    % \catcode`\^^?=15 % ascii delete is invalid
    % \catcode`\A=11 ... \catcode`\Z=11 % uppercase letters
    % \catcode`\a=11 ... \catcode`\z=11 % lowercase letters
    % all others are type 12 (other)

    \chardef\active=13 % \active is a mnemonic for category 13 (active)

    \catcode`\$=3 % dollar sign ('044) is math shift
    \catcode`\&=4 % ampersand ('046) is alignment tab
    \catcode`\#=6 % hash mark ('043) is macro parameter character
    \catcode`\^=7 % circumflex ('136) is for superscripts
    \catcode`\_=8 % underline ('137) is for subscripts
    \catcode'011=10 % ascii tab is a blank space
    \catcode'176=\active % ascii tilde (~) is active

    % \catcode`\^^L=\active
    %   \outer\def^^L{\par} % ascii form-feed ('014) is "\outer\par"
    \catcode`\^^L=14 % treat ascii form-feed ('014) as begin comment

    % We make @ signs act like letters, temporarily, to avoid conflict
    % between user names and internal control sequences of plain format.

    \catcode`@=11

    % We also cause <returns> to be ignored, temporarily, to avoid them being
    %  included in replacement texts of definitions.

    \endlinechar=-1

    % \bgroup and \egroup can be used inside macros to generate 
    % unbalanced braces. Eg,
    %   
    %    \def\foo{\hbox\bgroup}
    %    \def\bar{\egroup}
    %     ...
    %    \foo Hic est ad-hoc hack \bar   % same as \hbox{Hic...hack}
    
    \let\bgroup={ \let\egroup=}

% PARAMETER MNEMONICS

  \message{mnemonics ...}

  % New mnemonics for some of TeX's glue parameters and operations

    % Now we definitively mix up the nomenclature...
    %  We try to use
    %    \XXglue or \XXXsep for <glue> (\XXXsep for mostly vertical glue),
    %    \XXskip for \hskip <glue> or \vskip <glue>,
    %    \XXheight, \XXwidth, \XXdepth, \XXsize, \XXdist, \XXindent
    %        for <dimen>
    %    \XXspace for \kern <dimen>,

    \let\glue=\skip \let\skip=\undef
    \let\gluedef=\skipdef \let\skipdef=\undef
    \let\muglue=\muskip \let\muskip=\undef
    \let\mugluedef=\muskipdef \let\muskipdef=\undef
    \let\thinmuglue=\thinmuskip
    \let\medmuglue=\medmuskip
    \let\thickmuglue=\thickmuskip
    \let\baselinesep=\baselineskip
    \let\linesep=\lineskip
    \let\lineseplimit=\lineskiplimit
    \let\parsep=\parskip
    \let\abovedisplaysep=\abovedisplayskip
    \let\abovedisplayshortsep=\abovedisplayshortskip
    \let\belowdisplaysep=\belowdisplayskip
    \let\belowdisplayshortsep=\belowdisplayshortskip
    \let\topsep=\topskip
    \let\splittopsep=\splittopskip
    \let\leftglue=\leftskip
    \let\rightglue=\rightskip
    \let\lastglue=\lastskip
    \let\parfillglue=\parfillskip
    \let\tabglue=\tabskip
    \let\spaceglue=\spaceskip
    \let\xspaceglue=\xspaceskip
    
    \let\basefont=\textfont % note that \textfont is actually the math font...

% PRIVATE CONSTANTS

  \message{private constants ...}

    % To make the plain macros more efficient in time and space,
    % several constant values are declared here as control sequences.
    % If they were changed, anything could happen; so they are private symbols.

    \chardef\@ne=1
    \chardef\tw@=2
    \chardef\thr@@=3
    \chardef\sixt@@n=16
    \chardef\@cclv=255
    \mathchardef\@cclvi=256
    \mathchardef\@m=1000
    \mathchardef\@M=10000
    \mathchardef\@MM=20000

% REGISTER ALLOCATION TOOLS

  \message{allocation ...}

    % Here are macros for the automatic allocation of \count, \box, \dimen,
    % \glue (\skip), \muglue (\muskip), and \toks registers,
    % as well as \read and \write
    % stream numbers, \fam codes, and \insert numbers.

  % Notes on register usage

    % When a register is used only temporarily, it need not be allocated;
    % grouping can be used, making the value previously in the register return
    % after the close of the group.  The main use of these macros is for
    % registers that are defined by one macro and used by others, possibly at
    % different nesting levels.  All such registers should be defined through
    % these macros; otherwise conflicts may occur, especially when two or more
    % more macro packages are being used at once.

    % The following counters are reserved:
    %  0 to 9  page numbering
    %      10  count allocation
    %      11  dimen allocation
    %      12  glue allocation
    %      13  muglue allocation
    %      14  box allocation
    %      15  toks allocation
    %      16  read file allocation
    %      17  write file allocation
    %      18  math family allocation
    %      19  insert allocation
    %      20  the most recently allocated number
    %      21  constant -1
    % New counters are allocated starting with 22, 23, etc.
    % Other registers are
    % allocated starting with 10.  This leaves 0 through 9 for the user to play
    % with safely, except that counts 0 to 9 are considered to be the page and
    % subpage numbers (since they are displayed during output). In this scheme,
    % \count 10 always contains the number of the highest-numbered counter that
    % has been allocated, \count 14 the highest-numbered box, etc.
    % Inserts are given numbers 254, 253, etc., since they require a \count,
    % \dimen, \glue, and \box all with the same number; \count 19 contains the
    % lowest-numbered insert that has been allocated. Of course, \box255 is
    % reserved for \output; \count255, \dimen255, and \glue255
    % can be used freely.

    % It is recommends that macro designers always use
    % \global assignments with respect to registers numbered 1, 3, 5, 7, 9, and
    % always non-\global assignments with respect to registers
    % 0, 2, 4, 6, 8, 255.
    % This will prevent ``save stack buildup'' that might otherwise occur.

  % Internal registers used by the allocator

    \count10=21 % allocates \count registers 22, 23, ...
    \count11=9 % allocates \dimen registers 10, 11, ...
    \count12=9 % allocates \glue registers 10, 11, ...
    \count13=9 % allocates \muglue registers 10, 11, ...
    \count14=9 % allocates \box registers 10, 11, ...
    \count15=9 % allocates \toks registers 10, 11, ...
    \count16=-1 % allocates input streams 0, 1, ...
    \count17=-1 % allocates output streams 0, 1, ...
    \count18=3 % allocates math font families 4, 5, ...
    \count19=255 % allocates insertions 254, 253, ...
    \countdef\insc@unt=19 % the insertion counter
    \countdef\allocationnumber=20 % the most recent allocation
    \countdef\m@ne=21 \m@ne=-1 % a handy constant
    \def\wlog{\immediate\write\m@ne} % write on log file (only)

  % Internal names for some scratch registers that don't need to be allocated

    \countdef\count@=255
    \dimendef\dimen@=0
    \dimendef\dimen@i=1 % global only
    \dimendef\dimen@ii=2
    \gluedef\glue@=0
    \toksdef\toks@=0

  % Register allocation macros

    % Now, we define \newcount, \newbox, etc. so that you can say \newcount\foo
    % and \foo will be defined (with \countdef) to be the next counter.
    % To find out which counter \foo is, you can look at \allocationnumber.
    % Since there's no \boxdef command, \chardef is used to define a \newbox,
    % \newinsert, \newfam, and so on.

    \def\newcount{\alloc@0\count\countdef\insc@unt}
    \def\newdimen{\alloc@1\dimen\dimendef\insc@unt}
    \def\newglue{\alloc@2\glue\gluedef\insc@unt}
    \def\newmuglue{\alloc@3\muglue\mugluedef\@cclvi}
    \def\newbox{\alloc@4\box\chardef\insc@unt}

    \def\newhelp#1#2{\newtoks#1#1\expandafter{\csname#2\endcsname}}
    \def\newtoks{\alloc@5\toks\toksdef\@cclvi}
    \def\newread{\alloc@6\read\chardef\sixt@@n}
    \def\newwrite{\alloc@7\write\chardef\sixt@@n}
    \def\newfam{\alloc@8\fam\chardef\sixt@@n}

    \outer\def\alloc@#1#2#3#4#5{\global\advance\count1#1by\@ne
      \ch@ck#1#4#2% make sure there's still room
      \allocationnumber=\count1#1%
      \global#3#5=\allocationnumber
      \wlog{\string#5=\string#2\the\allocationnumber}}

    \def\ch@ck#1#2#3{\ifnum\count1#1<#2%
      \else\errmessage{No room for a new #3}\fi}

  % Allocation of insertion categories

    \outer\def\newinsert#1{\global\advance\insc@unt by\m@ne
      \ch@ck0\insc@unt\count
      \ch@ck1\insc@unt\dimen
      \ch@ck2\insc@unt\glue
      \ch@ck4\insc@unt\box
      \allocationnumber=\insc@unt
      \global\chardef#1=\allocationnumber
      \wlog{\string#1=\string\insert\the\allocationnumber}}

  % If statement allocation:

    % For example, \newif\iffoo creates \footrue, \foofalse to go with \iffoo.

    \outer\def\newif#1{\count@\escapechar \escapechar\m@ne
      \expandafter\expandafter\expandafter
       \edef\@if#1{true}{\let\noexpand#1=\noexpand\iftrue}%
      \expandafter\expandafter\expandafter
       \edef\@if#1{false}{\let\noexpand#1=\noexpand\iffalse}%
      \@if#1{false}\escapechar\count@} % the condition starts out false
    \def\@if#1#2{\csname\expandafter\if@\string#1#2\endcsname}
    {\uccode`1=`i \uccode`2=`f \uppercase{\gdef\if@12{}}} % `if' is required

  % Macro to extend definitions:

    % For example, \appendef\foo{\baz bar gee} will redefine \foo
    %  as being its old replacement text followed by "\baz bar gee ".
    % Works only for parameterless macros, though...

    \long\def\appendef#1#2{\toks0=\expandafter{#1}\toks2={#2}
      \edef#1{\the\toks0 \the\toks2 }
    }

% GENERAL-PURPOSE DIMENSIONS, GLUES, PENALTIES

  \message{registers ...}

  % Some private registers:

    \newdimen\p@ \p@=1pt % this saves macro space and time
    \newdimen\z@ \z@=0pt % can be used both for 0pt and 0
    \newglue\z@glue \z@glue=0pt plus0pt minus0pt
    \newbox\voidb@x % permanently void box register

  % Other useful definitions:

    \def\empty{}
    \def\null{\hbox{}}

    \newdimen\maxdimen
    \maxdimen=16383.99999pt % the largest legal <dimen>

  % Magnification factors:

    % \mag=1000 % INITEX does this
    \def\magstephalf{1095 }
    \def\magstep#1{\ifcase#1 1000\or 1200\or 1440\or 1728\or 2074\or
    2488\or 2986\fi\relax}

  % Useful penalties (to follow \hbreak, \vbreak, or similar)

    \def\forbidden{\penalty \@M}
    \def\allowed{\penalty \z@}
    \def\suggested{\penalty -200 }
    \def\preferred{\penalty -500 }
    \def\required{\penalty-\@M}

% DEBUGGING

  \message{debugging ...}

  % Set TeX's trace parameters

    % \pausing=0
    % \tracingonline=0
    % \tracingmacros=0
    % \tracingstats=0
    % \tracingparagraphs=0
    % \tracingpages=0
    % \tracingoutput=0
    \tracinglostchars=1
    % \tracingcommands=0
    % \tracingrestores=0
    % \globaldefs=0
    % \maxdeadcycles=25 % INITEX does this
    \showboxbreadth=5
    \showboxdepth=3

    \hfuzz=0.1pt
    \vfuzz=0.1pt
    \overfullrule=5pt

    \def\tracingall{\tracingonline\@ne\tracingcommands\tw@
      \tracingstats\tw@\tracingpages\@ne\tracingoutput\@ne
      \tracinglostchars\@ne\tracingmacros\@ne\tracingparagraphs\@ne
      \tracingrestores\@ne\showboxbreadth\maxdimen
      \showboxdepth\maxdimen\errorstopmode}

    \def\showhyphens#1{\setbox0\vbox{
      \parfillglue\z@glue\hsize\maxdimen\tenrm
      \pretolerance\m@ne\tolerance\m@ne\hbadness0\showboxdepth0\ #1}}

  % Show box boundaries.

    %  Usage: \tracebox{\hbox{...}}
    %         \tracebox{\box7}
    %         \tracebox{\copy3} etc.
    %
    %    \tracebox<box> is basically the same as <box>,
    %   but will put a thin border around it (half in, half out
    %    of the box) without changing its dimensions

    \def\tracebox#1{{\setbox0=#1\relax\dimen0=\dp0
      \hbox{\lower\dimen0\vbox{\hrule height0.2pt\kern-0.2pt
      \hbox{\vrule width0.2pt\kern-0.2pt \box0 \kern-0.2pt\vrule width0.2pt}
      \kern-0.2pt\hrule height0.2pt}}}}

  % Bug mark.

    %  Usage: As seen in figure 3.\bug, ...
    %  The \bug macro is also useful for flagging TEX errors in
    %   the press file; just answer i\bug<CR> to error messages.

    \newbox\bugb@x % to be set by the font-loading file
    \def\bug{{\copy\bugb@x}}
    \def\scream{\errmessage{bug here!}\bug{}}

    % The call \obsolete\foo{\baz} is like \gdef\foo\baz, but will 
    % complain on the first usage of \foo.

    \long\def\obsolete#1#2{\long\gdef#1{\scream\bug\long\gdef#1{#2}#1}}

% ORDINARY TEXT

  \message{text ...}

  % Non-dimensional parameters affecting line breaking and page building:

    \pretolerance=100
    \tolerance=200 % INITEX sets this to 10000
    \hbadness=1000
    \vbadness=1000
    \linepenalty=10
    \hyphenpenalty=50
    \exhyphenpenalty=50
    \binoppenalty=700
    \relpenalty=500
    % \outputpenalty=0, set before TeX enters \output
    \doublehyphendemerits=10000
    \finalhyphendemerits=5000
    \adjdemerits=10000
    % \looseness=0, cleared by TeX after each paragraph
    % \hangafter=1 % INITEX does this, also TeX after each paragraph
    \defaulthyphenchar=`\-
    \defaultskewchar=-1
    \newlinechar=-1

  % Character spacing factors:

    %  INITEX sets \sfcode x=1000 for all x, except that \sfcode`X=999
    %  for uppercase letters. The following changes are needed:

    \sfcode`\)=0 \sfcode`\'=0 \sfcode`\]=0

    \def\frenchspacing{\sfcode`\.\@m \sfcode`\?\@m \sfcode`\!\@m
      \sfcode`\:\@m \sfcode`\;\@m \sfcode`\,\@m}
    \def\nonfrenchspacing{\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000%
      \sfcode`\:2000\sfcode`\;1500\sfcode`\,1250 }

    \def\slash{/\penalty\exhyphenpenalty} % a `/' that acts like a `-'

  % standard horizontal glues and skips (values to be defined externally)

    \def\thinspace{\kern .16667em }
    \def\negthinspace{\kern-.16667em }
    \def\enspace{\kern.5em }

    \def\space{ }

    \def~{\penalty\@M \ } % `tying space'

    \def\enskip{\hskip.5em\relax}
    \def\quad{\hskip1em\relax}
    \let\emskip=\quad
    \def\qquad{\hskip2em\relax}

  % Start horizontal mode:

    \def\hmode{\unhbox\voidb@x} % begins a paragraph, if necessary

  % Line breaks:

    \def\hbreak{} % Allows \hbreak\forbidden, \hbreak\suggested, etc

    % Poor man's \par (forces line break w/o parindent or parsep)

    \def\brk{\unskip\hskip\parfillglue\hbreak\required}
    \let\linebreak=\brk

    \let\endgraf=\par \let\endline=\cr

  % Special meanings of <return>:

    % In \obeylines, we say `\let^^M=\par' instead of `\def^^M{\par}'
    % since this allows, for example, `\let\par=\cr \obeylines \halign{...'

    \def\^^M{\ } % control <return> = control <space>
    \def\^^I{\ } % same for <tab>

    {\catcode`\^^M=\active % these lines must end with %
     \gdef\obeylines{\catcode`\^^M\active \let^^M=\par} %
     \gdef\ignorelines{\catcode`\^^M=5}} %

    {\catcode`\^^M=\active \global\let^^M=\par}
        % in case ^^M appears in a \write

  % Obey spaces:

    \def\obeyspaces{\catcode`\ \active}
    {\obeyspaces\global\let =\ }
    \def\ignorespaces{\catcode`\ =10}

  % Uppercase/lowercase mapping:

    %  INITEX sets \uccode`x=`X and \uccode `X=`X for all letters x,
    %  and \lccode`x=`x, \lccode`X=`x; all other values are zero.
    %  No changes to those tables are needed in plain TeX format.

    % Underlining (text)

    \def\underbar#1{$\setbox\z@\hbox{#1}\dp\z@=\z@
      \mathsurround=\z@ \underline{\box\z@}$}

  % Alignment macros for overstriking and accenting

    % \rlap{foo} will write foo and backspace by its width
    % \llap{foo} will backspace by the width of foo and write it

    \def\rlap#1{\hbox to\z@{#1\hss}}
    \def\llap#1{\hbox to\z@{\hss#1}}

    % \overlap{foo\crcr baz} will put foo and baz on boxes of the same length
    %  and superimpose the two boxes so that the origins coincide.
    % Normally they will be aligned by their left edge,
    %  but centering and other justifications can be obtained with \hfil,
    %   \hidewidth, etc.

    \def\overlap#1{\hmode\vtop{\linesep\z@glue\lineseplimit-\maxdimen
       \putalign{#1}}}

    % \putatop{foo \crcr baz} will put foo on top of baz
    % \putbeneath{baz \crcr foo} put foo under baz
    % The spacing between foo and baz can be specified by setting \linesep
    %  and \lineseplimit before calling the macros

    \def\putabove#1{\hmode\vbox{\putalign{#1}}}
    \def\putbelow#1{\hmode\vtop{\putalign{#1}}}

    \def\putalign#1{\baselinesep\z@glue\tabglue\z@glue
       \halign{##\crcr#1\crcr}}

  % Special characters and accents:

    % Transforms a math hex code into a text-mode character

    \def\mathhexbox#1#2#3{\hmode\hbox{$\mathsurround=\z@ \mathchar"#1#2#3$}}

    \def\dots{\relax\ifmmode\ldots\else$\mathsurround=\z@\ldots\,$\fi}

  % Black slug
  
    \def\blackslug{\vrule width 1.0ex height1.3ex depth0.3ex}

  % Puts #1 in a \vbox, and puts a border around it:
  
    \def\framebox#1{\vbox
     {\hrule
      \hbox{\vrule\hskip3pt\vbox{\vskip3pt #1 \vskip3pt}\hskip3pt\vrule}
      \hrule}}

% INDENTATIONS AND ITEMS

  \message{paragraphs ...}

  % unit of indentation for text:
  
    \newglue\textindentglue

  % Indenting a group of paragraphs

    % Usage
    % \begindent
    %   Bla bla bla...
    %   Bla bla...
    %   \begindent\moreindent 20pt
    %     Ble blu bloo...\par
    %     Bli blee blaw...\par
    %   \endintdent
    % \endindent

    \def\begindent{\par\smallvbreak\penalty800
      \begingroup
      \advance\leftglue by \textindentglue
      \parindent\z@}
    \def\moreindent{\afterassignment\m@reindent\glue@=}
    \def\m@reindent{\advance\leftglue by \glue@}
    \def\endindent{\par\endgroup\smallvbreak}

  % Items

    % Usage
    % \begindent
    %   \item{1.} Bla bla bla...\par More Bla bla bla... \par
    %   \item{2.} Bla bla..\par
    %     \begindent
    %       \item{2.1.} Ble blu bloo...\par
    %       \item{2.2.} Bli blee blaw...\par
    %     \endindent
    % \endindent

    \def\item#1{
      \ifhmode\endgraf\fi \penalty-50
      \hmode\llap{#1\enspace}\ignorespaces
    }

  % Narrower margins.

    % Say {\narrower Bla bla bla...} to indent by \textindentglue
    %   on both sides every paragraph between the braces.

    \def\narrower{\advance\leftglue\textindentglue
      \advance\rightglue\textindentglue}

  % Digressions: small print text, indented.

    % Say \begdigress Bla bla bla...\enddigress for digression in smaller text
    %   indented on both sides.

    \def\begdigress{\smallvskip
      \begingroup\narrower\smallsize\rm}

    \def\enddigress{\par\endgroup\smallvskip}

% HYPHENATION

  \message{hyphenation ...}

    \uchyph=1
    \endlinechar=`\^^M \input hyphen.tex \endlinechar=-1

% BOX TWIDDLING AND ALIGNMENT

  \message{box twiddling ...}

  % Macros for special alignment entries: \multispan, \hidewidth

    \newglue\hideglue \hideglue=-1000pt plus 1fill %

    \def\hidewidth{\hskip\hideglue}

    \newcount\mscount

    \def\multispan#1{\omit \mscount#1
      \loop\ifnum\mscount>\@ne \sp@n\repeat}

    \def\sp@n{\span\omit\advance\mscount\m@ne}

  % Tabs

    \newif\ifus@ \newif\if@cr
    \newbox\tabs \newbox\tabsyet \newbox\tabsdone

    \def\cleartabs{\global\setbox\tabsyet\null \setbox\tabs\null}
    \outer\def\settabs{\setbox\tabs\null \futurelet\next\sett@b}
    \def\sett@b{\ifx\next\+\let\next\relax
       \def\next{\afterassignment\s@tt@b\let\next}%
      \else\let\next\s@tcols\fi\next}
    \def\s@tt@b{\let\next\relax\us@false\m@ketabbox}
    \def\tabalign{\us@true\m@ketabbox} % non-\outer version of \+
    \outer\def\+{\tabalign}
    \def\s@tcols#1\columns{\count@#1 \dimen@\hsize
      \loop\ifnum\count@>\z@ \@nother \repeat}
    \def\@nother{\dimen@ii\dimen@ \divide\dimen@ii\count@
      \setbox\tabs\hbox{\hbox to\dimen@ii{}\unhbox\tabs}%
      \advance\dimen@-\dimen@ii \advance\count@\m@ne}

    \def\m@ketabbox{\begingroup
      \global\setbox\tabsyet\copy\tabs
      \global\setbox\tabsdone\null
      \def\cr{\@crtrue\crcr\egroup\egroup
       \ifus@\unvbox\z@\lastbox\fi\endgroup
       \setbox\tabs\hbox{\unhbox\tabsyet\unhbox\tabsdone}}%
      \setbox\z@\vbox\bgroup\@crfalse
       \ialign\bgroup&\t@bbox##\t@bb@x\crcr}
    
    \def\t@bbox{\setbox\z@\hbox\bgroup}
    \def\t@bb@x{\if@cr\egroup % now \box\z@ holds the column
      \else\hss\egroup \global\setbox\tabsyet\hbox{\unhbox\tabsyet
         \global\setbox\@ne\lastbox}% now \box\@ne holds its size
       \ifvoid\@ne\global\setbox\@ne\hbox to\wd\z@{}%
       \else\setbox\z@\hbox to\wd\@ne{\unhbox\z@}\fi
       \global\setbox\tabsdone\hbox{\box\@ne\unhbox\tabsdone}\fi
      \box\z@}

% VERTICAL MODE GOODIES

  \message{vertical mode ...}

  %  Strut

    % The following box should be set by \smallsize or \normalsize
    %  (or \largesize, if available) to an \hbox containing a \vrule of
    %  zero width, whose height and depth are slightly larger than
    %  those of the of the current \rm font.

    \newbox\strutbox

    \def\strut{\relax\ifmmode\copy\strutbox\else\unhcopy\strutbox\fi}

  % Standard vertical glues and skips (change with \baselinesep)

    \def\smallvglue{0.67\baselinesep} % was 0.5 was 0.3
    \def\medvglue{1.0\baselinesep}   % was 0.75
    \def\bigvglue{1.5\baselinesep}   % was 1.2

    \def\smallvskip{\vskip\smallvglue}
    \def\medvskip{\vskip\medvglue}
    \def\bigvskip{\vskip\bigvglue}

    % There seems to be a bug in TeX that causes the outcome of
    %  \ifdim\lastglue... come out reversed.
    % Setting \glue0=\lastglue and testing \ifdim\glue0 seems to work.
    
    \def\unvskip{
      {\glue\z@=\lastglue\ifdim\glue\z@=\z@\else\vskip-\lastglue\fi}
    }

  % Page breaks

    \def\vbreak{\par} % page breaks are automatic in vertical mode

    \def\eject{\vbreak\required}
    \def\goodbreak{\vbreak\preferred} % encourage break
    \def\supereject{\vbreak\penalty-\@MM}

    \def\filbreak{\par\vfil\penalty-200\vfilneg}

    \def\d@break#1{\ifhmode\par\fi
      { 
        \glue0=\lastglue
        \ifdim\glue0>0pt
          \ifdim\glue0<#1 
            \vskip-\glue0\penalty-50\vskip#1
          \fi
        \else
          \penalty-50\vskip#1
        \fi
      }
    }
    
    \def\smallvbreak{\d@break\smallvglue}
    \def\medvbreak{\d@break\medvglue}
    \def\bigvbreak{\d@break\bigvglue}

  % Non-dimensional parameters affecting page building/breaking

    \clubpenalty=150
    % \postdisplaypenalty=0
    % \interlinepenalty=0
    % \floatingpenalty=0, set during \insert
    \widowpenalty=150
    \displaywidowpenalty=50
    \brokenpenalty=100
    \predisplaypenalty=10000

  % Interline glue options

    \def\nointerlineskip{\prevdepth-1000\p@} % no interline skip here

    \def\offinterlineskip{\baselinesep=-1000\p@
      \linesep=\z@ \lineseplimit\maxdimen} % turn off all interline skip

  % Full-width lines

    \def\line{\hbox to\hsize}
    \def\leftline#1{\line{#1\hss}}
    \def\rightline#1{\line{\hss#1}}
    \def\centerline#1{\line{\hss#1\hss}}

  % Ragged and centered paragraphs

    % The following should be specified in vertical mode
    %  (including \vboxes) after \hsize is set.
    %  Spacing will not be as fancy as in Knuth's macros, but I will worry
    %  about it if and when that becomes a problem.

    \def\raggedright{\rightglue=0pt plus 0.7\hsize\leftglue=0pt
      \parfillglue=0pt }
    \def\raggedleft{\leftglue=0pt plus 0.7\hsize\rightglue=0pt
      \parfillglue=0pt\parindent=0pt }
    \def\centered{\leftglue=0pt plus 0.6\hsize
      \rightglue=0pt plus 0.6\hsize
      \parfillglue=0pt\parindent=0pt }

  % vertically centered non-math boxes
  % \vbal is like \vbox, but works in any mode, and centers the
  % result with respect to the baseline (rather than the math axis).
  
    \def\vbal{\hbox\bgroup\afterassignment\vbal@@\setbox0=\vbox}
    \def\vbal@@{\aftergroup\vbal@@@}  % isn't TeX wonderful?
    \def\vbal@@@{\dimen0=\ht0 \advance\dimen0 by -\dp0
        \lower 0.5\dimen0\box0 
        \egroup    % Closes the \hbox.
      }
      
  % separating rules
  
    \def\seprule{\par\vskip\smallvglue\hrule}

% ITERATION

  \message{iteration ...}

  % Knuth iteration construct

    \def\loop#1\repeat{\def\body{#1}\iterate}
    \def\iterate{\body \let\next=\iterate \else\let\next=\relax\fi \next}
    \let\repeat=\fi % this makes \loop...\if...\repeat skippable

  % Counted repetition (note: definitions within it are local!)

    % Usage: \rep5{Foo} is roughly equivalent to {Foo}{Foo}{Foo}{Foo}{Foo}

    \def\rep{\afterassignment\r@p\count@=}

    \def\r@p#1{\loop\ifnum\count@>0 {#1}\advance\count@ by-1\repeat}

% FONT-INDEPENDENT MATH MACROS

  \message{math ...}

  % Math glues, skips, and special boxes:

    \thinmuglue=3mu
    \medmuglue=4mu plus 2mu minus 4mu
    \thickmuglue=5mu plus 5mu

    \def\,{\mskip\thinmuglue}
    \def\>{\mskip\medmuglue}
    \def\;{\mskip\thickmuglue}
    \def\!{\mskip-\thinmuglue}

  % Generic alignment macros:

    % \ialign is \halign with initial \tabglue = 0pt

    \def\ialign{\tabglue\z@glue\halign} % initialized \halign

    \def\buildrel#1\over#2{\mathrel{\mathop{#2}\limits^{#1}}}

    \def\putover#1#2{\vbox{\offinterlineskip
      \ialign{\ctr{##}\crcr #1\crcr\noalign{\vskip1pt} #2\crcr}}}

    \def\putunder#1#2{\vtop{\offinterlineskip
      \ialign{\ctr{##}\crcr #1\crcr\noalign{\vskip1pt} #2\crcr}}}

  % Alternatives:
  %
  %   $ \cases{+1 & if $x>0$,\cr 0 & if $x=0$, or\cr -1 & if $x<0$.\cr} $

    \def\cases#1{\left\{\,\vcenter{\resetlinesep\mathsurround=\z@
       \ialign{$ ##\hfil$&\quad##\hfil\crcr#1\crcr}}\right.}

  % Brace-delimited alternatives: 
  %
  %   $ x = \bracedalts{+1 \cr 0 \cr -1} 
  %       \iff
  %     y = \bracedalts{>0 \cr 0 \cr <0} $

    \def\bracedalts#1{
      \left\{\,
      \vcenter{\resetlinesep\mathsurround=\z@
        \ialign{&\ctr{$ ## $}\cr
          #1\crcr
        }
      }
      \,\right\}
    }

  % Matrices:

    % Remember to redefine \matrixbaselinesep, \matrixcolumnsep
    
    \def\matrixbaselinesep{1.0\baselinesep}
    \def\matrixcolumnsep{1em}
    
    \def\matrixalign#1{
      \resetlinesep
      \baselinesep=\matrixbaselinesep
      \mathsurround=\z@
      \hrule height0pt\kern0.1\baselinesep
      \ialign{
        \hfil$\displaystyle ## $\hfil
          && \kern\matrixcolumnsep\hfil$\displaystyle ## $\hfil\crcr
        \mathstrut\crcr\noalign{\kern-\baselinesep}
        #1\crcr
        \mathstrut\crcr\noalign{\kern-\baselinesep}
      }
      \kern0.1\baselinesep
    }
    
    \def\matrix#1{\vcenter{\matrixalign{#1}}}

    \def\pmatrix#1{\left(\,\matrix{#1}\,\right)}

  % Determinants

    \def\detmat#1{\vcenter{\vskip1pt
         \hbox{$\left|\;\matrix{#1}\;\right|$}
       \vskip1pt}}

  % Macros for opening up lines:

    \newdimen\jot % Unit of space for use with \openup

    % Increases all interline spacings by a given amount:

    \def\openup{\afterassignment\@penup\dimen@=}

    \def\@penup{\advance\linesep by\dimen@
      \advance\baselinesep by \dimen@
      \advance\lineseplimit by \dimen@ }

    % Additional inter-line spacing for \halign and co(use after \cr)

      %   Usage: \halign{ ... \cr\vsk7 ...} for 7 \jots of extra space

    \def\vsk#1{\noalign{\vskip #1\jot plus #1\jot}}

  % Equation alignment (\eqalign, \eqaligno, \leqaligno):

    % Justification macros for \halign templates:

    \newglue\centerglue \centerglue=0pt plus 1000pt minus 1000pt

    \def\lft#1{#1\hfil} % left-justified entry
    \def\ctr#1{\null\hfil #1\hfil} % centered
    \def\rt#1{\null\hfil #1} % right-justified entry

    \def\eqalign#1{
      \vcenter{
        \openup1\jot\mathsurround=\z@
        \ialign{
          \strut\hfil$\displaystyle{##{}}$&&$\displaystyle{{}##}$\hfil\crcr
          #1\crcr
        }
      }
    }

    % Prepare spacing parameters for \eqalignno, \leqalignno, \displaylines

    \newcount\interdisplaylinepenalty
    \interdisplaylinepenalty=100

    \def\openalign{\openup1\jot \mathsurround=\z@
      \interlinepenalty\interdisplaylinepenalty
    }

    \def\eqalignno#1{
      \openalign\relax\tabglue=\centerglue
      \halign to\displaywidth{
        \hfil$\displaystyle{##{}}$\tabglue\z@glue
          &$\displaystyle{{}##}$\hfil\tabglue=\centerglue
          &\llap{$ ## $}\tabglue=\z@glue\crcr
        \noalign{\vskip-\jot}
        #1\crcr
      }
    }

    \def\leqalignno#1{
      \openalign\tabglue=\centerglue
      \halign to\displaywidth{
        \hfil$\displaystyle{##{}}$\tabglue=\z@glue
          &$\displaystyle{{}##}$\hfil\tabglue=\centerglue
          &\kern-\displaywidth\rlap{$ ## $}\tabglue=\displaywidth\crcr
        \noalign{\vskip-\jot}
        #1\crcr
      }
    }

  % Multiple display lines:

    \def\displaylines#1{
      \openalign
      \halign{
        \hbox to\displaywidth{$\hfil\displaystyle##\hfil$}\crcr
        \noalign{\vskip-\jot}
        #1\crcr
      }
    }

  % Operators in roman font:

    \def\log{\mathop{\rm log}\nolimits}
    \def\lg{\mathop{\rm lg}\nolimits}
    \def\ln{\mathop{\rm ln}\nolimits}
    \def\lim{\mathop{\rm lim}}
    \def\limsup{\mathop{\rm lim\,sup}}
    \def\liminf{\mathop{\rm lim\,inf}}
    \def\sin{\mathop{\rm sin}\nolimits}
    \def\arcsin{\mathop{\rm arcsin}\nolimits}
    \def\sinh{\mathop{\rm sinh}\nolimits}
    \def\cos{\mathop{\rm cos}\nolimits}
    \def\arccos{\mathop{\rm arccos}\nolimits}
    \def\cosh{\mathop{\rm cosh}\nolimits}
    \def\tan{\mathop{\rm tan}\nolimits}
    \def\arctan{\mathop{\rm arctan}\nolimits}
    \def\tanh{\mathop{\rm tanh}\nolimits}
    \def\cot{\mathop{\rm cot}\nolimits}
    \def\coth{\mathop{\rm coth}\nolimits}
    \def\sec{\mathop{\rm sec}\nolimits}
    \def\csc{\mathop{\rm csc}\nolimits}
    \def\max{\mathop{\rm max}}
    \def\min{\mathop{\rm min}}
    \def\sup{\mathop{\rm sup}}
    \def\inf{\mathop{\rm inf}}
    \def\arg{\mathop{\rm arg}\nolimits}
    \def\ker{\mathop{\rm ker}\nolimits}
    \def\dim{\mathop{\rm dim}\nolimits}
    \def\hom{\mathop{\rm hom}\nolimits}
    \def\det{\mathop{\rm det}}
    \def\exp{\mathop{\rm exp}\nolimits}
    \def\Pr{\mathop{\rm Pr}}
    \def\gcd{\mathop{\rm gcd}}

    \def\bmod{\mskip-\medmuglue\mskip5mu
      \mathbin{\rm mod}\penalty900\mskip5mu\mskip-\medmuglue}
    \def\pmod#1{\allow\mkern18mu({\rm mod}\,\,#1)}

  % Logical connectives in text roman font

    \def\rmiff{\,\mathrel{\rm iff}\,} % "iff" in text font
    \def\rmif{\,\mathrel{\rm if}\,} % "if" in text font
    \def\rmand{\,\mathrel{\rm and}\,} % "and" in text font
    \def\rmor{\,\mathrel{\rm or}\,} % "or" in text font

  % Polymorphic math constructs (\mathpalette):

    % To use, let \foo be a two parameter macro, <baz>  be any argument.
    % Then \mathpalette\foo<baz> is same as \foo\displaystyle{<baz>} in
    %  displaystyle, \foo\textstyle{<baz>} in \textstyle, etc.

    \def\mathpalette#1#2{\mathchoice
      {#1\displaystyle{#2}}
      {#1\textstyle{#2}}
      {#1\scriptstyle{#2}}
      {#1\scriptscriptstyle{#2}}
    }

    % Similarly, use \scriptpalette\foo{baz} to get the effect of
    % \foo<style><baz>, where <style> is the sub/superscript style
    % appropriate to the current base style:
  
    \def\scriptpalette#1#2{\mathchoice
     {#1\scriptstyle{#2}}
     {#1\scriptstyle{#2}}
     {#1\scriptscriptstyle{#2}}
     {#1\scriptscriptstyle{#2}}
    }

    % \mbox{...} makes a box out of a formula:

    \def\mbox#1{\mathpalette\m@thbox{#1}}
    \def\m@thbox#1#2{\hbox{$\mathsurround=\z@ #1 #2 $}}
    
  % Macros to get/change sizes of formulas

    % (\phantom,\vphantom,\hphantom) make empty boxes
    %   with (dimensions, height&depth, width) of argument

    \newif\ifv@ \newif\ifh@

    \def\phantom{\v@true\h@true\ph@nt}
    \def\vphantom{\v@true\h@false\ph@nt}
    \def\hphantom{\v@false\h@true\ph@nt}

    \def\ph@nt{\ifmmode\def\next{\mathpalette\mathph@nt}%
      \else\let\next\makeph@nt\fi\next}
    \def\makeph@nt#1{\setbox\z@\hbox{#1}\finph@nt}
    \def\mathph@nt#1#2{\setbox\z@\hbox{$\mathsurround=\z@#1{#2}$}\finph@nt}
    \def\finph@nt{\setbox\tw@\null
      \ifv@ \ht\tw@\ht\z@ \dp\tw@\dp\z@\fi
      \ifh@ \wd\tw@\wd\z@\fi \box\tw@}

    % Smash reduces height and depth of argument to zero.

    \def\smash{\relax % \relax, in case this comes first in \halign
      \ifmmode\def\next{\mathpalette\mathsm@sh}
      \else\let\next\makesm@sh
      \fi\next}
    \def\makesm@sh#1{\setbox\z@\hbox{#1}\finsm@sh}
    \def\mathsm@sh#1#2{\setbox\z@\hbox{$\mathsurround=\z@#1{#2}$}\finsm@sh}
    \def\finsm@sh{\ht\z@\z@ \dp\z@\z@ \box\z@}

    % Mathstrut is a strut for one-line math formulas:

    \def\mathstrut{\vphantom(}

  \message{done.}

% BEGINNING OF END

  % Restores meaning of @ and end-of-line character:

    \catcode`@=12 \endlinechar=`\^^M

% END

