summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/pb-diagram
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/pb-diagram
Initial commit
Diffstat (limited to 'macros/latex/contrib/pb-diagram')
-rw-r--r--macros/latex/contrib/pb-diagram/COPYING339
-rw-r--r--macros/latex/contrib/pb-diagram/README68
-rw-r--r--macros/latex/contrib/pb-diagram/lamsarrow.sty770
l---------macros/latex/contrib/pb-diagram/mf1
-rw-r--r--macros/latex/contrib/pb-diagram/pb-diagram.sty963
-rw-r--r--macros/latex/contrib/pb-diagram/pb-examples.tex245
-rw-r--r--macros/latex/contrib/pb-diagram/pb-lams.sty142
-rw-r--r--macros/latex/contrib/pb-diagram/pb-manual.pdfbin0 -> 123892 bytes
-rw-r--r--macros/latex/contrib/pb-diagram/pb-manual.tex574
-rw-r--r--macros/latex/contrib/pb-diagram/pb-xy.sty133
l---------macros/latex/contrib/pb-diagram/tfm1
11 files changed, 3236 insertions, 0 deletions
diff --git a/macros/latex/contrib/pb-diagram/COPYING b/macros/latex/contrib/pb-diagram/COPYING
new file mode 100644
index 0000000000..a43ea2126f
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/COPYING
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ Appendix: How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/macros/latex/contrib/pb-diagram/README b/macros/latex/contrib/pb-diagram/README
new file mode 100644
index 0000000000..1aca8ff21b
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/README
@@ -0,0 +1,68 @@
+This package contains version 5.0 of the "pb-diagram.sty"
+LaTeX macro package by Paul Burchard, along with complete
+documentation and examples. The "diagram" environment provided
+by this package allows the LaTeX user to easily create complex
+commutative diagrams, by placing formula nodes on a conceptual
+grid and attaching arrows to them.
+
+The grid used in these diagrams is not a fixed square grid.
+Instead, the environment automatically generates a correctly scaled
+and shaped rectangular grid which will compactly hold the formulas,
+while leaving room for the arrows between them. Moreover, the
+arrows automatically adapt to the spaces between the formulas
+being connected.
+
+* Improvements from Previous Versions *
+
+version 5.0:
+ - XY-PIC arrow fonts can be used, for even nicer, PostScript-
+ compatible arrows, thanks to Bill Richter <richter@math.nwu.edu>
+ - now distributed under GNU General Public License
+
+version 4.1:
+ - LAMS arrow fonts now compile correctly, thanks to
+ fix from Ingo Hadan <hadan@mathematik.hu-berlin.de>
+ - \arrow command works better outside of diagrams
+
+version 4.0:
+ - makes pb-diagram more compatible with LaTeX2e and AMS-LaTeX
+ - fixes a grid geometry bug that doubled some diagrams
+ - corrects the direction of LAMS-TeX arrow embellishments
+ - adds a double-headed arrow option
+ - leaves many more TeX box nesting levels for arrow labels
+ - produces less verbose output during typesetting
+
+* Upgrading Papers *
+
+In versions 3.6 and earlier, certain uncommon types of diagrams
+came out twice too large; to produce exactly compatible behavior
+in versions 4.0 and later, use the following declaration:
+
+ \let\dggeometry=\dgoldgeometry
+
+In versions 3.4 and earlier, the names of the packages differed;
+here is a dictionary for translating the list of packages to load:
+
+ diagram -> pb-diagram
+ lamsarrow,diagram -> pb-diagram,lamsarrow,pb-lams
+
+* Installation *
+
+ File Name Where to Put It
+ ------------------- -------------------
+ pb-diagram.sty TEXINPUTS
+ pb-xy.sty TEXINPUTS
+ pb-lams.sty TEXINPUTS
+ lamsarrow.sty TEXINPUTS
+ pb-manual.tex documentation area
+ pb-examples.tex documentation area
+ mf/lams*.mf MFINPUTS
+ tfm/lams*.tfm TEXFONTS
+ README
+
+Please let me know if you have any problems with
+this package.
+
+Paul Burchard
+<burchard@pobox.com>
+
diff --git a/macros/latex/contrib/pb-diagram/lamsarrow.sty b/macros/latex/contrib/pb-diagram/lamsarrow.sty
new file mode 100644
index 0000000000..a215c8b1fc
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/lamsarrow.sty
@@ -0,0 +1,770 @@
+% lamsarrow.sty: fancy arrows using lams fonts
+% Author: extracted from Michael Spivak's LamS-TeX by Paul Burchard
+% Version Number: 4.1
+% Version Date: 24 Jan 1997
+%
+%--------------------- LamS-TeX copyright -------------------------
+% COPYRIGHT (C) 1989, 1990, 1991 by the Texplorators Corporation,
+% 1572 West Gray #377, Houston, TX 77019-4948 (ALL RIGHTS RESERVED)
+%------------------------------------------------------------------
+%
+% This macro package allows LaTeX users to make use of the LamS-TeX
+% arrow fonts and create arrows with
+% * any valid LaTeX \line slope (unlike LaTeX's \vector)
+% * all those fancy head/tail symbols and shaft styles.
+%
+% Actually, these macros will accept any slope and approximate it
+% by the closest LaTeX \line slope. In making the approximation
+% to the desired arrow slope, these macros will work to keep the
+% arrow's *vertical* dimension accurate (at the expense
+% of the horizontal one, if necessary). This requires the
+% opposite strategy from LaTeX's \line and \vector commands,
+% where the *horizontal* dimension can always be precisely
+% specified.
+%
+% The macros seem to have the 10pt font size hardcoded in, so
+% the arrow embellishments will be on the marginally small side
+% in 12pt.
+%
+% Commands defined in this style file:
+%
+% \lamsarrow(#1,#2)
+% Draws an arrow which extends #1 \unitlengths in the
+% x-direction and #2 \unitlengths in the y-direction from the
+% current position. #1 and #2 are arbitrary real numbers,
+% not both zero. Intended for use in the picture environment.
+%
+% \lamsvector(#1,#2){#3}
+% Has the same effect as \lamsarrow, except its usage is
+% completely compatible with LaTeX's \vector command. But
+% with \lamsvector, there are no limits on the size of the
+% integers #1, #2, and it is OK if they have common factors.
+% Only valid LaTeX line slopes will actually be drawn, tho.
+%
+% \lamsshaft{#1}
+% A local declaration which changes the style of the shaft
+% of any subsequent lams arrows within the same environment
+% or {...} group. The symbol #1 may be one of:
+%
+% - solid line (default)
+% . dashed line
+% = long equals sign (no head or tail printed)
+% 0 invisible arrow
+% ? reset to default
+%
+% \lamssource{#1}
+% \lamstarget{#1}
+% Local declarations which change the symbol placed at the
+% initial and final points, respectively, of the arrow shaft.
+% Affects subsequent lams arrows within the same environment
+% or {...} group. For either declaration, the symbol #1 may
+% be any one of:
+%
+% Heads:
+% ^ arrow head (default for \lamstarget)
+% V arrow tail (default for \lamssource)
+% ' left half of arrowhead
+% ` right half of arrowhead
+% A double arrowhead
+% Tails:
+% J left fishhook tail
+% L right fishhook tail
+% S squiggle
+% Other:
+% 0 no symbol
+% ? reset to default
+%
+
+% detente message
+\typeout{ * LAMSTEX ARROWS * }
+\typeout{ The arrows you are using are courtesy of LamS-TeX, a }
+\typeout{ full-featured mathematical typsetting package which its }
+\typeout{ creator, at least, believes to be superior to LaTeX. }
+\typeout{ You can obtain LamS-TeX by anonymous FTP from most TeX }
+\typeout{ archives, or through the TUG user group organization. }
+\typeout{ }
+
+% lams arrow fonts
+\font\lamsfont@i=lams1
+\font\lamsfont@ii=lams2
+\font\lamsfont@iii=lams3
+\font\lamsfont@iv=lams4
+\font\lamsfont@v=lams5
+
+% arrow geom params
+% direction
+\newif\ifN@
+\newif\ifE@
+\newif\ifNESW@
+\newif\ifH@
+\newif\ifV@
+% location of source, target
+\newdimen\lams@firstx
+\newdimen\lams@firsty
+\newdimen\lams@lastx
+\newdimen\lams@lasty
+\newdimen\lams@center %ignore
+% shaft char dims
+\newdimen\lams@ht
+\newdimen\lams@wd
+
+% misc
+\newcount\ten@ \ten@10
+
+
+%%%%%%%%%%%%%%%%%%%% \lamssource, \lamstarget, \lamsshaft
+%
+% Used to set arrow style options.
+%
+% EXTERNAL VARS COMPUTED
+%
+% \lams@source \lams@target \lams@shaft
+
+\newcount\lams@source
+\newcount\lams@target
+\newcount\lams@shaft
+
+\def\lamssource#1{%
+ \if#10\lams@source\m@ne\else
+ \if#1?\lams@source\z@\else
+ \if#1V\lams@source\tw@\else
+ \if#1^\lams@source\thr@@\else
+ \if#1'\lams@source6 \else
+ \if#1`\lams@source7 \else
+ \if#1J\lams@source8 \else
+ \if#1L\lams@source9 \else
+ \if#1S\lams@source12 \else
+ \if#1A\lams@source13 \else
+ \@latexerr{Invalid lamsarrow source style: #1}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+\def\lamstarget#1{%
+ \if#10\lams@target\m@ne\else
+ \if#1?\lams@target\z@\else
+ \if#1^\lams@target\tw@\else
+ \if#1V\lams@target\thr@@\else
+ \if#1'\lams@target4 \else
+ \if#1`\lams@target5 \else
+ \if#1J\lams@target\ten@ \else
+ \if#1L\lams@target11 \else
+ \if#1S\lams@target12 \else
+ \if#1A\lams@target13 \else
+ \@latexerr{Invalid lamsarrow target style: #1}%
+ \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi}
+\def\lamsshaft#1{%
+ \if#10\lams@shaft\m@ne\else
+ \if#1?\lams@shaft\z@\else
+ \if#1-\lams@shaft\@ne\else
+ \if#1.\lams@shaft\tw@\else
+ \if#1=\lams@shaft\thr@@\else
+ \@latexerr{Invalid lamsarrow shaft style: #1}%
+ \fi\fi\fi\fi\fi}
+
+
+%%%%%%%%%%%%%%%%%%%% \lams@slope
+%
+% Utility macro to calculate arrow shaft character in lamstex arrow
+% fonts, given the x- and y-dimensions of the raw arrow.
+%
+% EXTERNAL VARS USED
+%
+% \lams@firstx \lams@lastx \lams@firsty \lams@lasty
+% \ifN@ \ifE@
+%
+% EXTERNAL VARS COMPUTED
+%
+% \lams@tani \lams@tanii \lams@ang
+%
+% INTERNAL VARS USED
+%
+% \lams@slopei \lams@slopeii
+% \lams@tanip \lams@taniip \lams@slopeip \lams@slopeiip
+% \count@ \lams@extra
+
+\newcount\lams@tani
+\newcount\lams@tanip
+\newcount\lams@tanii
+\newcount\lams@taniip
+\newdimen\lams@slopei
+\newdimen\lams@slopeip
+\newdimen\lams@slopeii
+\newdimen\lams@slopeiip
+\newcount\lams@ang
+\newcount\lams@extra
+
+\def\lams@slopeselect{%
+ \\161\\152\\143\\134\\255\\126\\357\\238\\349\\45{10}%
+ \\56{11}\\11{12}\\65{13}\\54{14}\\43{15}\\32{16}\\53{17}%
+ \\21{18}\\52{19}\\31{20}\\41{21}\\51{22}\\61{23}}
+
+\def\lams@slope{{\lams@slopei\lams@lasty
+ \advance\lams@slopei-\lams@firsty
+ \ifN@\else\multiply\lams@slopei\m@ne\fi
+ \lams@slopeii\lams@lastx\advance\lams@slopeii-\lams@firstx
+ \ifE@\else\multiply\lams@slopeii\m@ne\fi
+ \ifdim\lams@slopeii<\z@
+ \global\lams@tani6 \global\lams@tanii\@ne\global\lams@ang23
+ \else
+ \dimen@\lams@slopei\multiply\dimen@6
+ \ifdim\dimen@<\lams@slopeii
+ \global\lams@tani\@ne\global\lams@tanii6 \global\lams@ang\@ne
+ \else
+ \dimen@\lams@slopeii\multiply\dimen@6
+ \ifdim\dimen@<\lams@slopei
+ \global\lams@tani6 \global\lams@tanii\@ne\global\lams@ang23
+ \else
+ \global\lams@tanip\z@\global\lams@taniip\@ne
+ \def\\##1##2##3{\global\lams@ang##3\relax
+ \lams@slopeip\lams@slopei\lams@slopeiip\lams@slopeii
+ \multiply\lams@slopeiip##1\relax
+ \multiply\lams@slopeip##2\relax
+ \ifdim\lams@slopeiip<\lams@slopeip
+ \global\lams@tanip##1\relax\global\lams@taniip##2\relax
+ \else
+ \global\lams@tani##1\relax\global\lams@tanii##2\relax
+ \def\\####1####2####3{}%
+ \fi}%
+ \lams@slopeselect
+ \lams@slopei\lams@lasty\advance\lams@slopei-\lams@firsty
+ \ifN@\else\multiply\lams@slopei\m@ne\fi
+ \multiply\lams@slopei\lams@tanii
+ \multiply\lams@slopei\lams@taniip
+ \multiply\lams@slopei\tw@
+ \count@\lams@tani\multiply\count@\lams@taniip
+ \lams@extra\lams@tanip\multiply\lams@extra\lams@tanii
+ \advance\count@\lams@extra
+ \lams@slopeii\lams@lastx\advance\lams@slopeii-\lams@firstx
+ \ifE@\else\multiply\lams@slopeii\m@ne\fi
+ \multiply\lams@slopeii\count@
+ \ifdim\lams@slopei<\lams@slopeii
+ \global\lams@tani\lams@tanip\global\lams@tanii\lams@taniip
+ \global\advance\lams@ang\m@ne
+ \fi
+ \fi
+ \fi
+ \fi}%
+}
+
+
+%%%%%%%%%%%%%%%%%%%% \lamsarrow, \lamsvector
+%
+% User macros for lams arrows. They call \lams@arrow, which sets
+% up parameters for \lams@harrow, \lams@varrow, and \lams@darrow.
+%
+% EXTERNAL VARS USED
+%
+% \lams@source \lams@target
+%
+% EXTERNAL VARS COMPUTED
+%
+% \ifNESW@ \ifN@ \ifE@
+% \lams@center \lams@firstx \lams@firsty \lams@lasty
+% \lams@wd \lams@ht
+%
+% INTERNAL VARS USED
+%
+% \lams@xsize \lams@ysize
+
+\newdimen\lams@xsize
+\newdimen\lams@ysize
+
+\def\lamsvector(#1,#2)#3{%
+ \lams@xsize#3\unitlength\relax
+ \ifnum#1<\z@\multiply\lams@xsize\m@ne\fi
+ \lams@ysize\lams@xsize
+ \ifnum#1=\z@
+ \lams@xsize\z@
+ \ifnum#2<\z@\multiply\lams@ysize\m@ne\fi
+ \else
+ \multiply\lams@ysize#2\relax\divide\lams@ysize#1\relax
+ \fi
+ \lams@arrow{\lams@xsize}{\lams@ysize}%
+}
+
+\def\lamsarrow(#1,#2){%
+ \lams@xsize#1\unitlength\relax\lams@ysize#2\unitlength\relax
+ \lams@arrow{\lams@xsize}{\lams@ysize}%
+}
+
+\def\lams@switchsides{%
+ \ifnum\lams@source=6\relax\lams@source7\else
+ \ifnum\lams@source=7\relax\lams@source6\else
+ \ifnum\lams@source=8\relax\lams@source9\else
+ \ifnum\lams@source=9\relax\lams@source8\fi\fi\fi\fi\relax
+ \ifnum\lams@target=4\relax\lams@target5\else
+ \ifnum\lams@target=5\relax\lams@target4\else
+ \ifnum\lams@target=\ten@\relax\lams@target11\else
+ \ifnum\lams@target=11\relax\lams@target\ten@\fi\fi\fi\fi\relax
+}
+
+\def\lams@arrow#1#2{%
+ \lams@firstx\z@\lams@firsty\z@
+ \lams@lastx#1\relax\lams@lasty#2\relax
+ \lams@center\z@
+ %
+ % compute direction flags
+ \N@false\E@false\H@false\V@false
+ \ifdim\lams@lastx>\z@\E@true\fi
+ \ifdim\lams@lastx=\z@\V@true\fi
+ \ifdim\lams@lasty>\z@\N@true\fi
+ \ifdim\lams@lasty=\z@\H@true\fi
+ \NESW@false
+ \ifN@\ifE@\NESW@true\fi\else\ifE@\else\NESW@true\fi\fi
+ %
+ % fix up one-sided embellishments, depending on direction
+ \ifdim\lams@lastx<\z@ \lams@switchsides \fi
+ \ifdim\lams@lastx=\z@ \ifdim\lams@lasty<\z@ \lams@switchsides \fi\fi
+ %
+ % compute shaft char info with help of \lams@slope macro
+ \ifH@\else\ifV@\else
+ \lams@slope
+ \ifnum\lams@tani>\lams@tanii
+ \lams@ht\ten@\p@\lams@wd\ten@\p@
+ \multiply\lams@wd\lams@tanii\divide\lams@wd\lams@tani
+ \else
+ \lams@wd\ten@\p@\lams@ht\ten@\p@
+ \divide\lams@ht\lams@tanii\multiply\lams@ht\lams@tani
+ \fi
+ \fi\fi
+ %
+ % adjust arrow placement for source and target style
+ \ifH@\else\ifV@\else
+ \ifnum\lams@target=\thr@@
+ \ifN@\advance\lams@lasty-.3\lams@ht
+ \else\advance\lams@lasty.3\lams@ht\fi
+ \fi
+ \ifnum\lams@source=\tw@
+ \ifE@\advance\lams@firstx.3\lams@ht
+ \else\advance\lams@firstx-.3\lams@ht\fi
+ \fi
+ \ifnum\lams@target=12
+ \ifN@\advance\lams@lasty-\lams@ht
+ \else\advance\lams@lasty\lams@ht\fi
+ \fi
+ \fi\fi
+ %
+ % draw arrow, special-casing horizontal and vertical ones
+ \ifH@ \lams@harrow
+ \else\ifV@ \lams@varrow
+ \else \lams@darrow
+ \fi\fi
+}
+
+
+%%%%%%%%%%%%%%%%%%%% \lams@darrow
+%
+% Does actual drawing of diagonal arrows,
+% with the help of \lams@cos.
+%
+% EXTERNAL VARS USED
+%
+% \lams@shaft \lams@source \lams@target
+%
+% \ifNESW@ \ifN@ \ifE@ (computed by \lams@arrow)
+% \lams@center \lams@firstx \lams@firsty \lams@lasty (ibid)
+% \lams@wd \lams@ht (computed by \lams@arrow)
+%
+% \lams@ang \lams@tani \lams@tanii (computed by \lams@slope)
+%
+% \lamsfont@i \lamsfont@ii \lamsfont@iii \lamsfont@iv \lamsfont@v
+%
+% INTERNAL VARS USED
+%
+% \lams@sl (from \lams@ang, used by \lams@cos)
+% \lams@S \lams@T (from \lams@ang, \lams@source, \lams@target)
+% \lams@shift (+/- \lams@firsty) \lams@adj
+% \lams@goal (+/-(\lams@lasty-\lams@firsty))
+% \dimen@ \dimen@ii \count@ (computed by \lams@cos)
+% \arrowfont@ \lams@shaftbox \lams@ZERO
+
+\newdimen\lams@goal
+\newdimen\lams@shift
+\newdimen\lams@adj
+\newcount\lams@T
+\newcount\lams@S
+\newbox\lams@shaftbox
+\newcount\lams@sl
+\newbox\lams@ZERO
+
+\def\lams@next{\ifN@\let\next@\raise\else\let\next@\lower\fi}
+
+\def\lams@cos#1{%
+ \ifnum\lams@tani<\lams@tanii
+ \dimen@#1%
+ \ifnum\lams@sl<8 \count@9
+ \else \ifnum\lams@sl<12 \count@8
+ \else \count@7 \fi\fi
+ \multiply\dimen@\count@\divide\dimen@\ten@
+ \dimen@ii\dimen@\multiply\dimen@ii\lams@tani
+ \divide\dimen@ii\lams@tanii
+ \else
+ \dimen@ii#1%
+ \count@-\lams@sl\advance\count@24
+ \ifnum\count@<8 \count@9 \else \ifnum\count@<12 \count@8
+ \else\count@7 \fi\fi
+ \multiply\dimen@ii\count@\divide\dimen@ii\ten@
+ \dimen@\dimen@ii\multiply\dimen@\lams@tanii
+ \divide\dimen@\lams@tani
+ \fi
+}
+
+\def\lams@darrow{\lams@sl\lams@ang
+ \ifNESW@
+ \ifnum\lams@ang<\ten@
+ \let\arrowfont@\lamsfont@i\global\advance\lams@ang\m@ne
+ \global\multiply\lams@ang13
+ \else
+ \ifnum\lams@ang<19
+ \let\arrowfont@\lamsfont@ii\global\advance\lams@ang-\ten@
+ \global\multiply\lams@ang13
+ \else
+ \let\arrowfont@\lamsfont@iii\global\advance\lams@ang-19
+ \global\multiply\lams@ang13
+ \fi\fi
+ \lams@T\lams@ang
+ \else
+ \ifnum\lams@ang<5
+ \let\arrowfont@\lamsfont@iii\global\advance\lams@ang\m@ne
+ \global\multiply\lams@ang13 \global\advance\lams@ang65
+ \else
+ \ifnum\lams@ang<14
+ \let\arrowfont@\lamsfont@iv\global\advance\lams@ang-5
+ \global\multiply\lams@ang13
+ \else
+ \ifnum\lams@ang<23
+ \let\arrowfont@\lamsfont@v\global\advance\lams@ang-14
+ \global\multiply\lams@ang13
+ \else
+ \let\arrowfont@\lamsfont@i\global\lams@ang117
+ \fi\fi\fi
+ \ifnum\lams@ang=117 \lams@T115 \else\lams@T\lams@ang\fi
+ \fi
+ \lams@S\lams@T
+ \ifE@
+ \ifnum\lams@target=\z@\advance\lams@T\tw@
+ \else\ifnum\lams@target=13 \advance\lams@T\tw@
+ \else\advance\lams@T\lams@target\fi\fi
+ \ifnum\lams@source=\z@
+ \else\ifnum\lams@source=13 \advance\lams@S\thr@@
+ \else\advance\lams@S\lams@source\fi\fi
+ \else
+ \ifcase\lams@target\advance\lams@T\thr@@\or
+ \or\advance\lams@T\thr@@\or
+ \advance\lams@T\tw@\or\advance\lams@T6 \or\advance\lams@T7
+ \or\or\or\or\or\advance\lams@T8 \or\advance\lams@T9 \or
+ \advance\lams@T12 \or\advance\lams@T\thr@@\fi
+ \ifcase\lams@source\or\or\advance\lams@S\thr@@
+ \or\advance\lams@S\tw@\or\or\or\advance\lams@S4
+ \or\advance\lams@S5 \or\advance\lams@S\ten@
+ \or\advance\lams@S11 \or\or\or\advance\lams@S12
+ \or\advance\lams@S\tw@\fi
+ \fi
+ \ifcase\lams@shaft\or\or\global\advance\lams@ang\@ne\else\fi
+ \ifN@\lams@shift\lams@firsty\else\lams@shift-\lams@firsty\fi
+ \ifE@\else\advance\lams@shift\lams@ht\fi
+ \lams@goal\lams@lasty\advance\lams@goal-\lams@firsty
+ \ifN@\else\multiply\lams@goal\m@ne\fi
+ \setbox\lams@shaftbox\hbox{\arrowfont@\char\lams@ang}%
+ \ifnum\lams@shaft=\thr@@
+ \lams@cos{1.5\p@}%
+ \setbox\lams@shaftbox\hbox to\wd\lams@shaftbox{\arrowfont@
+ \rlap{\hskip\dimen@ii
+ \smash{\ifNESW@\let\next@\lower\else\let\next@\raise\fi
+ \next@\dimen@\hbox{\arrowfont@\char\lams@ang}}}%
+ \rlap{\hskip-\dimen@ii
+ \smash{\ifNESW@\let\next@\raise\else\let\next@\lower\fi
+ \next@\dimen@\hbox{\arrowfont@\char\lams@ang}}}\hfil}%
+ \fi
+ \rlap{\smash{\hskip\lams@center\hskip\lams@firstx
+ \ifnum\lams@shaft=\m@ne
+ \else
+ \ifnum\lams@shaft=\thr@@
+ \else
+ \ifnum\lams@source=\m@ne
+ \else
+ \ifnum\lams@source=\z@
+ \else
+ \setbox\lams@ZERO\hbox{%
+ \ifnum\lams@ang=117 \lamsfont@v\else\arrowfont@\fi
+ \char\lams@S}%
+ \ifNESW@
+ \ifnum\lams@source=\tw@
+ \dimen@\lams@shift\advance\dimen@-\lams@ht
+ \ifN@\hskip-\wd\lams@ZERO\fi
+ \lams@next
+ \next@\dimen@\copy\lams@ZERO
+ \ifN@\else\hskip-\wd\lams@ZERO\fi
+ \else
+ \lams@next
+ \ifN@\else\hskip-\wd\lams@ZERO\fi
+ \next@\lams@shift\copy\lams@ZERO
+ \ifN@\hskip-\wd\lams@ZERO\fi
+ \fi
+ \ifnum\lams@source=12
+ \advance\lams@shift\lams@ht\advance\lams@goal-\lams@ht
+ \ifN@\hskip\wd\lams@ZERO\else\hskip-\wd\lams@ZERO\fi
+ \fi
+ \ifnum\lams@source=13
+ \lams@cos{\thr@@\p@}%
+ \ifN@\hskip\dimen@\else\hskip-\wd\lams@ZERO\hskip-\dimen@\fi
+ \lams@adj\lams@shift\advance\lams@adj\dimen@ii
+ \lams@next
+ \next@\lams@adj\copy\lams@ZERO
+ \ifN@\hskip-\dimen@\hskip-\wd\lams@ZERO\else\hskip\dimen@\fi
+ \fi
+ \else
+ \ifN@\hskip-\wd\lams@ZERO\fi
+ \ifnum\lams@source=\tw@
+ \ifN@\hskip\wd\lams@ZERO\else\hskip-\wd\lams@ZERO\fi
+ \dimen@\lams@shift\advance\dimen@-\lams@ht
+ \lams@next
+ \next@\dimen@\copy\lams@ZERO
+ \ifN@\hskip-\wd\lams@ZERO\fi
+ \else
+ \lams@next
+ \next@\lams@shift\copy\lams@ZERO
+ \ifN@\else\hskip-\wd\lams@ZERO\fi
+ \fi
+ \ifnum\lams@source=12
+ \advance\lams@shift\lams@ht\advance\lams@goal-\lams@ht
+ \ifN@\hskip-\wd\lams@ZERO\else\hskip\wd\lams@ZERO\fi
+ \fi
+ \ifnum\lams@source=13
+ \lams@cos{\thr@@\p@}%
+ \ifN@\hskip-\wd\lams@ZERO\hskip-\dimen@\else\hskip\dimen@\fi
+ \lams@adj\lams@shift\advance\lams@adj\dimen@ii
+ \lams@next
+ \next@\lams@adj\copy\lams@ZERO
+ \ifN@\hskip\dimen@\else\hskip-\dimen@\hskip-\wd\lams@ZERO\fi
+ \fi
+ \fi
+ \fi\fi\fi\fi
+ \ifnum\lams@shaft=\m@ne
+ \else
+ \loop
+ \ifdim\lams@goal>\lams@ht
+ \ifE@\else\hskip-\lams@wd\fi
+ \lams@next
+ \next@\lams@shift\copy\lams@shaftbox
+ \ifE@\else\hskip-\lams@wd\fi
+ \advance\lams@shift\lams@ht\advance\lams@goal-\lams@ht
+ \repeat
+ \ifdim\lams@goal>\z@
+ \dimen@\lams@ht\advance\dimen@-\lams@goal
+ \divide\dimen@\lams@tani\multiply\dimen@\lams@tanii
+ \ifE@\hskip-\dimen@\else\hskip-\lams@wd\hskip\dimen@\fi
+ \lams@adj\lams@shift\advance\lams@adj-\lams@ht
+ \advance\lams@adj\lams@goal
+ \lams@next
+ \next@\lams@adj\copy\lams@shaftbox
+ \ifE@\else\hskip-\lams@wd\fi
+ \else
+ \lams@adj\lams@shift\advance\lams@adj-\lams@ht
+ \fi
+ \fi
+ \ifnum\lams@shaft=\m@ne
+ \else
+ \ifnum\lams@shaft=\thr@@
+ \else
+ \ifnum\lams@target=\m@ne
+ \else
+ \setbox\lams@ZERO
+ \hbox{\ifnum\lams@ang=117
+ \lamsfont@v\else\arrowfont@\fi\char\lams@T}%
+ \ifnum\lams@target=\thr@@
+ \advance\lams@adj\lams@ht
+ \ifE@\else\ifN@\hskip-\lams@wd\else\hskip-\wd\lams@ZERO\fi\fi
+ \else
+ \ifnum\lams@target=12
+ \advance\lams@adj\lams@ht
+ \ifE@\else\ifN@\hskip-\lams@wd\else\hskip-\wd\lams@ZERO\fi\fi
+ \else
+ \ifE@\hskip-\wd\lams@ZERO\fi
+ \fi\fi
+ \lams@next
+ \next@\lams@adj\copy\lams@ZERO
+ \ifnum\lams@target=13
+ \hskip-\wd\lams@ZERO
+ \lams@cos{\thr@@\p@}%
+ \ifE@\hskip-\dimen@\else\hskip\dimen@\fi
+ \advance\lams@adj-\dimen@ii
+ \lams@next
+ \next@\lams@adj\box\lams@ZERO
+ \fi
+ \fi\fi\fi}}%
+}
+
+
+%%%%%%%%%%%%%%%%%%%% \lams@harrow
+%
+% Performs actual drawing of horizontal arrows.
+%
+% EXTERNAL VARS USED
+%
+% \lams@shaft \lams@source \lams@target
+%
+% \ifE@ (computed by \lams@arrow)
+% \lams@center \lams@firstx \lams@lastx (ibid)
+% \lamsfont@i \lamsfont@ii (lams fonts)
+%
+% \lams@axis (to correct centering of head/tail symbol chars)
+%
+% INTERNAL VARS USED
+%
+% \dimen@ \dimen@ii
+% \leads@ \lams@ZERO
+
+\newdimen\lams@axis \lams@axis90\p@\divide\lams@axis36
+
+\def\lams@harrow{\dimen@\lams@lastx\advance\dimen@-\lams@firstx
+ \ifE@\let\next@\rlap\else\multiply\dimen@\m@ne\let\next@\llap\fi
+ \next@{\ifE@\hskip\lams@center\hskip\lams@firstx\fi
+ \smash{\raise-\lams@axis\hbox to\dimen@
+ {\lamsfont@ii
+ \ifnum\lams@shaft=\m@ne\else\ifnum\lams@shaft=\thr@@\else
+ \ifE@
+ \ifnum\lams@source=\m@ne
+ \else
+ \ifcase\lams@source\or\or\char118 \or\char117 \or
+ \or\or\char119 \or\char120 \or\char121 \or\char122 \or
+ \or\or\lamsfont@i\char125 \or
+ \char117 \hskip\thr@@\p@\char117 \hskip-\thr@@\p@\fi
+ \fi
+ \else
+ \ifnum\lams@target=\m@ne
+ \else
+ \ifcase\lams@target\char117 \or\or\char117 \or\char118 \or
+ \char119 \or\char120 \or\or\or\or\or\char121 \or
+ \char122 \or\lamsfont@i\char125
+ \or\char117 \hskip\thr@@\p@\char117 \hskip-\thr@@\p@\fi
+ \fi
+ \fi
+ \fi\fi
+ \dimen@\lams@axis\advance\dimen@.2\p@
+ \dimen@ii\lams@axis\advance\dimen@ii-.2\p@
+ \ifnum\lams@shaft=\m@ne
+ \let\leads@\null
+ \else
+ \ifcase\lams@shaft
+ \def\leads@{\hrule\@height\dimen@\@depth-\dimen@ii}\or
+ \def\leads@{\hrule\@height\dimen@\@depth-\dimen@ii}\or
+ \def\leads@{\hbox to\ten@\p@{%
+ \leaders\hrule\@height\dimen@\@depth-\dimen@ii\hfil
+ \hfil
+ \leaders\hrule\@height\dimen@\@depth-\dimen@ii
+ \hskip\z@ plus2fil\relax
+ \hfil
+ \leaders\hrule\@height\dimen@\@depth-\dimen@ii\hfil}}\or
+ \def\leads@{\hbox{\hbox to\ten@\p@{%
+ \dimen@\lams@axis\advance\dimen@1.2\p@
+ \dimen@ii\dimen@\advance\dimen@ii-.4\p@
+ \leaders\hrule\@height\dimen@\@depth-\dimen@ii\hfil}%
+ \kern-\ten@\p@
+ \hbox to\ten@\p@{\dimen@\lams@axis\advance\dimen@-1.2\p@
+ \dimen@ii\dimen@\advance\dimen@ii-.4\p@
+ \leaders\hrule\@height\dimen@\@depth-\dimen@ii\hfil}}}\fi
+ \fi
+ \cleaders\leads@\hfil
+ \ifnum\lams@shaft=\m@ne\else\ifnum\lams@shaft=\thr@@\else
+ \lamsfont@i
+ \ifE@
+ \ifnum\lams@target=\m@ne
+ \else
+ \ifcase\lams@target\char119 \or\or\char119 \or\char120 \or
+ \char121 \or\char122 \or \or\or\or\or\char123 \or
+ \char124 \or\char125 \or
+ \char119 \hskip-\thr@@\p@\char119 \hskip\thr@@\p@\fi
+ \fi
+ \else
+ \ifcase\lams@source\or\or\char120 \or\char119 \or
+ \or\or\char121 \or\char122 \or\char123 \or
+ \char124 \or\or\or\char125 \or
+ \char119 \hskip-\thr@@\p@\char119 \hskip\thr@@\p@\fi
+ \fi
+ \fi\fi}}%
+ \ifE@\else\hskip-\lams@firstx\hskip-\lams@center\fi}%
+}
+
+
+%%%%%%%%%%%%%%%%%%%% \lams@varrow
+%
+% Performs actual drawing of vertical arrows.
+%
+% EXTERNAL VARS USED
+%
+% \lams@shaft \lams@source \lams@target
+%
+% \ifN@ (computed by \lams@arrow)
+% \lams@center \lams@firsty \lams@lasty (ibid)
+%
+% \lamsfont@iii \lamsfont@iv (lams fonts)
+%
+% INTERNAL VARS USED
+%
+% \dimen@ \dimen@ii
+% \leads@ \lams@ZERO
+
+\def\lams@varrow{\dimen@\lams@lasty\advance\dimen@-\lams@firsty
+ \ifN@\else\multiply\dimen@\m@ne\fi
+ \setbox\lams@ZERO\vbox to\dimen@
+ {\ifnum\lams@shaft=\m@ne\else\ifnum\lams@shaft=\thr@@\else
+ \hbox{\lamsfont@iii
+ \ifN@
+ \ifnum\lams@target=\m@ne
+ \else
+ \ifcase\lams@target\char117 \or\or\char117 \or
+ \char118 \or\char119 \or\char120 \or\or\or\or
+ \or\char121 \or\char122 \or\char123 \or
+ \vbox{\hbox{\char117}\nointerlineskip\vskip\thr@@\p@
+ \hbox{\char117}\vskip-\thr@@\p@}\fi
+ \fi
+ \else
+ \ifcase\lams@source\or\or\char118 \or\char117 \or\or
+ \or\char119 \or\char120 \or\char121 \or\char122 \or
+ \or\or\char123 \or
+ \vbox{\hbox{\char117}\nointerlineskip\vskip\thr@@\p@
+ \hbox{\char117}\vskip-\thr@@\p@}\fi
+ \fi}%
+ \nointerlineskip
+ \fi\fi
+ \ifnum\lams@shaft=\m@ne
+ \let\leads@\null
+ \else
+ \ifcase\lams@shaft\let\leads@\vrule\or\let\leads@\vrule\or
+ \def\leads@{\vbox to\ten@\p@{%
+ \hrule\@height1.67\p@\@depth\z@\@width.4\p@
+ \vfil
+ \hrule\@height3.33\p@\@depth\z@\@width.4\p@
+ \vfil
+ \hrule\@height1.67\p@\@depth\z@\@width.4\p@}}\or
+ \def\leads@{\hbox{\vrule\@height\p@\hskip\tw@\p@\vrule}}\fi
+ \fi
+ \cleaders\leads@\vfill\nointerlineskip
+ \ifnum\lams@shaft=\m@ne\else\ifnum\lams@shaft=\thr@@\else
+ \hbox{\lamsfont@iv
+ \ifN@
+ \ifcase\lams@source\or\or\char118 \or\char117 \or
+ \or\or\char119 \or\char120 \or\char121 \or\char122 \or
+ \or\or\lamsfont@iii\char123 \or
+ \vbox{\hbox{\char117}\nointerlineskip\vskip-\thr@@\p@
+ \hbox{\char117}\vskip\thr@@\p@}\fi
+ \else
+ \ifnum\lams@target=\m@ne
+ \else
+ \ifcase\lams@target\char117 \or\or\char117 \or\char118 \or
+ \char119 \or\char120 \or\or\or\or\or\char121 \or
+ \char122 \or\lamsfont@iii\char123 \or
+ \vbox{\hbox{\char117}\nointerlineskip\vskip-\thr@@\p@
+ \hbox{\char117}\vskip\thr@@\p@}\fi
+ \fi
+ \fi}%
+ \fi\fi}%
+ \ifN@
+ \dimen@ii\lams@firsty
+ \else
+ \dimen@ii-\lams@firsty\advance\dimen@ii\ht\lams@ZERO
+ \multiply\dimen@ii\m@ne
+ \fi
+ \rlap{\smash{\hskip\lams@center\raise\dimen@ii\box\lams@ZERO}}%
+}
+
+
diff --git a/macros/latex/contrib/pb-diagram/mf b/macros/latex/contrib/pb-diagram/mf
new file mode 120000
index 0000000000..e7e92ea80e
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/mf
@@ -0,0 +1 @@
+../../../lamstex/mf \ No newline at end of file
diff --git a/macros/latex/contrib/pb-diagram/pb-diagram.sty b/macros/latex/contrib/pb-diagram/pb-diagram.sty
new file mode 100644
index 0000000000..eacab0d577
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-diagram.sty
@@ -0,0 +1,963 @@
+% pb-diagram.sty: LaTeX commutative diagram macros
+% Author: Paul Burchard <burchard@pobox.com>
+% Version Number: 5.0
+% Version Date: 20 Oct 1998
+%
+% Copyright (c) 1990, 1992, 1995, 1998 by Paul Burchard
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%
+% Please see documentation file "pb-manual.tex" for an
+% explanation of how to use the "diagram" environment.
+%
+% For those not inclined to read manuals, here is a short example:
+%
+% \[
+% \begin{diagram}
+% a b* \node{A} \arrow{e,t}{a}
+% A ---> B* ---> C \arrow{s,l}{c} \arrow{ese}
+% | \____ _____/ | \node{B^*} \arrow{e,t}{b^*}
+% c | ___X____ | d \node{C} \arrow{s,r}{d} \arrow{wsw}\\
+% v `/_ _\' v \node{D} \arrow[2]{e,b}{e}
+% D -----------> E \node[2]{E}
+% e \end{diagram}
+% \]
+%
+% I would like to acknowledge inspiration from a macro package
+% of Marc-Paul van der Hulst, and the thorough topological
+% torture-testing of this package by Bill Richter.
+%
+%
+% ---USER-ADJUSTABLE PARAMETERS---
+%
+\newskip\dgARROWLENGTH \dgARROWLENGTH=2.5em\relax
+\newskip\dgTEXTARROWLENGTH \dgTEXTARROWLENGTH=1.1em\relax
+\newskip\dgHORIZPAD \dgHORIZPAD=1em\relax
+\newskip\dgVERTPAD \dgVERTPAD=2ex\relax
+\newskip\dgLABELOFFSET \dgLABELOFFSET=.7ex\relax
+\newcount\dgARROWPARTS \dgARROWPARTS=4\relax
+\newcommand{\dgeverynode}{\displaystyle}
+\newcommand{\dgeverylabel}{\scriptstyle}
+\newif\ifdgVERBOSE \dgVERBOSEtrue
+%
+% for plain LaTeX mode
+\newskip\dgDOTSPACING \dgDOTSPACING=0.35em
+\newskip\dgDOTSIZE \dgDOTSIZE=1.5\fontdimen8\tenln
+%
+% obsolete---for compatibility with version 1.0
+\newcount\dgMAXSQUARE \dgMAXSQUARE=4\relax
+\newcount\dgMINDBLSQ \dgMINDBLSQ=10\relax
+\newskip\dgCOLUMNWIDTH \dgCOLUMNWIDTH=2em\relax
+%
+%
+% -----------------------------------------------------------------
+% -------------------------CUSTOMIZABLE CODE-----------------------
+% -----------------------------------------------------------------
+%
+% ### Do not change this file!!! Create your own style file to ###
+% ### override or add to these definitions. ###
+%
+%
+% ---ARROW STYLE OPTIONS---
+%.
+% The \dgo@XXX commands set arrow geometry and style parameters
+% such as \dg@VECTOR and \dg@LBLPOS. The \dgo@ command should
+% set default values for all option parameters.
+%
+% See sample customizations below for more options.
+%
+\chardef\f@ur=4
+\@namedef{dgo@}{\let\dg@VECTOR=\vector
+ \dg@LBLPOS=\dgARROWPARTS \divide\dg@LBLPOS\tw@}%
+\@namedef{dgo@-}{\let\dg@VECTOR=\line}%
+\@namedef{dgo@!}{\let\dg@VECTOR=\dg@novector}%
+\@namedef{dgo@1}{\dg@LBLPOS=\@ne\relax}%
+\@namedef{dgo@2}{\dg@LBLPOS=\tw@\relax}%
+\@namedef{dgo@3}{\dg@LBLPOS=\thr@@\relax}%
+\@namedef{dgo@4}{\dg@LBLPOS=\f@ur\relax}%
+\@namedef{dgo@5}{\dg@LBLPOS=5\relax}%
+\@namedef{dgo@6}{\dg@LBLPOS=6\relax}%
+\@namedef{dgo@7}{\dg@LBLPOS=7\relax}%
+\@namedef{dgo@8}{\dg@LBLPOS=8\relax}%
+\@namedef{dgo@9}{\dg@LBLPOS=9\relax}%
+%
+%
+% ---ARROW TYPES (directions)---
+%.
+% These macros specify the geometry of a simple arrow in
+% grid coordinates, in the style of LaTeX's \vector command.
+% They set the parameters:
+% \dg@DX, \dg@DY, \dg@SIZE,
+%
+\def\dgt@e{\dg@DX=\@ne \dg@DY=\z@ \dg@SIZE=\@ne}%
+\def\dgt@w{\dg@DX=\m@ne \dg@DY=\z@ \dg@SIZE=\@ne}%
+\def\dgt@n{\dg@DX=\z@ \dg@DY=\@ne \dg@SIZE=\@ne}%
+\def\dgt@s{\dg@DX=\z@ \dg@DY=\m@ne \dg@SIZE=\@ne}%
+\def\dgt@ne{\dg@DX=\@ne \dg@DY=\@ne \dg@SIZE=\@ne}%
+\def\dgt@se{\dg@DX=\@ne \dg@DY=\m@ne \dg@SIZE=\@ne}%
+\def\dgt@nw{\dg@DX=\m@ne \dg@DY=\@ne \dg@SIZE=\@ne}%
+\def\dgt@sw{\dg@DX=\m@ne \dg@DY=\m@ne \dg@SIZE=\@ne}%
+\def\dgt@nne{\dg@DX=\@ne \dg@DY=\tw@ \dg@SIZE=\@ne}%
+\def\dgt@nnw{\dg@DX=\m@ne \dg@DY=\tw@ \dg@SIZE=\@ne}%
+\def\dgt@sse{\dg@DX=\@ne \dg@DY=-\tw@ \dg@SIZE=\@ne}%
+\def\dgt@ssw{\dg@DX=\m@ne \dg@DY=-\tw@ \dg@SIZE=\@ne}%
+\def\dgt@ene{\dg@DX=\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@ese{\dg@DX=\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+\def\dgt@wnw{\dg@DX=-\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@wsw{\dg@DX=-\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+%
+%
+% ---GRID GEOMETRY---
+%
+% Computes the grid geom params \dg@XGRID, \dg@YGRID, and
+% \unitlength, with the result that unit grid rects will
+% be 1000*XGRID by 1000*YGRID \unitlengths in size.
+% Don't set XGRID, YGRID too big or TeX will get arithmetic
+% overflow. Also, the possible aspect ratios XGRID:YGRID
+% are always restricted by the slopes of the arrow font.
+%
+% As inputs, use the pre-supplied values of XGRID and YGRID,
+% which are the calculated required minimum dims for
+% unit grid rects (in sp's).
+%
+\def\dggeometry{%
+ \dg@ZTEMP=\dg@XGRID \multiply\dg@ZTEMP\tw@
+ \ifnum\dg@YGRID=\z@ \dg@ZTEMP=\tw@
+ \else \divide\dg@ZTEMP\dg@YGRID \fi
+ % font limit cutoffs
+ \ifnum\dg@ZTEMP>\f@ur \dg@ZTEMP=\f@ur \fi
+ \ifnum\dg@ZTEMP<\@ne \dg@ZTEMP=\@ne \fi
+ \unitlength=1sp\relax
+ \ifnum\dg@ZTEMP<\tw@
+ % round aspect ratio up toward 2:2, widen rect
+ \advance\dg@ZTEMP\@ne
+ \multiply\unitlength\dg@YGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@YGRID
+ \else
+ % round aspect ratio down toward 2:2, tallen rect
+ \multiply\unitlength\dg@XGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@XGRID
+ \fi
+ \divide\unitlength\@m\relax}
+%
+% Bugwards-compatibility mode for versions 3.6 and earlier.
+% This mode is enabled with \let\dggeometry=\dgoldgeometry
+%
+\def\dgoldgeometry{%
+ \dg@ZTEMP=\dg@XGRID \multiply\dg@ZTEMP\tw@
+ \ifnum\dg@YGRID=\z@ \dg@ZTEMP=\tw@
+ \else \divide\dg@ZTEMP\dg@YGRID \fi
+ % font limit cutoffs
+ \ifnum\dg@ZTEMP>\f@ur \dg@ZTEMP=\f@ur \fi
+ \ifnum\dg@ZTEMP<\@ne \dg@ZTEMP=\@ne \fi
+ % The following calculation is garbled!
+ \unitlength=2sp\relax
+ \ifnum\dg@ZTEMP<\tw@
+ % round aspect ratio up toward 2:2, widen rect
+ \advance\dg@ZTEMP\@ne
+ \multiply\unitlength\dg@YGRID
+ \else
+ % round aspect ratio down toward 2:2, tallen rect
+ \multiply\unitlength\dg@XGRID \divide\unitlength\dg@ZTEMP
+ \fi
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@YGRID \divide\unitlength\@m\relax}
+%
+%
+%
+% ---SAMPLE CUSTOMIZATION: TWO-HEADED ARROWS FOR PLAIN LaTeX---
+%
+% Two-headed arrow command that works like \vector.
+% Uses temp vars XTEMP, YTEMP.
+% Usage: \dg@twoheadedvector(DX,DY){SIZE}
+%
+\@namedef{dgo@<>}{\let\dg@VECTOR=\dg@twoheadedvector}%
+
+\def\dg@twoheadedvector(#1,#2)#3{%
+ \begingroup
+ \dg@XTEMP=#1\relax\multiply\dg@XTEMP\m@ne\relax
+ \dg@YTEMP=#2\relax\multiply\dg@YTEMP\m@ne\relax
+ \begin{picture}(0,0)%
+ \thinlines
+ \put(0,0){\vector(#1,#2){#3}}%
+ \put(0,0){\vector(\dg@XTEMP,\dg@YTEMP){0}}%
+ \end{picture}%
+ \endgroup}%
+%
+%
+%
+% ---SAMPLE CUSTOMIZATION: DOTTED ARROWS FOR PLAIN LaTeX---
+%
+% Dotted arrow command that works like \vector.
+% Uses temp vars XTEMP, YTEMP, ZTEMP, XEND, WEND.
+% Usage: \dg@dotvector(DX,DY){SIZE}
+%
+\@namedef{dgo@..}{\let\dg@VECTOR=\dg@dotvector}%
+
+\def\dg@dotvector(#1,#2)#3{%
+ \begingroup
+ \dg@XTEMP=#1\relax \dg@YTEMP=#2\relax
+ \let\dg@NDOTS=\dg@XEND \let\dg@DOTDIAM=\dg@WEND
+ % Find number of dots: make x-spacing be DOTSPACING for arrows
+ % of |slope| <= 1, and make y-spacing be DOTSPACING otherwise.
+ % Thus, true spacing is never more than 30% off from DOTSPACING.
+ \dg@NDOTS=\unitlength \multiply\dg@NDOTS #3\relax
+ \dg@ZTEMP=\dg@YTEMP \dg@changesign\dg@YTEMP\dg@ZTEMP
+ \ifnum\dg@XTEMP>\z@
+ \ifnum\dg@YTEMP>\dg@XTEMP
+ \multiply\dg@NDOTS\dg@YTEMP \divide\dg@NDOTS\dg@XTEMP \fi
+ \else\ifnum\dg@XTEMP<\z@
+ \ifnum\dg@YTEMP>-\dg@XTEMP
+ \multiply\dg@NDOTS\dg@YTEMP \divide\dg@NDOTS-\dg@XTEMP \fi
+ \fi\fi
+ \dg@YTEMP=\dg@ZTEMP
+ \divide\dg@NDOTS\dgDOTSPACING
+ \ifnum\dg@NDOTS>\z@\else \dg@NDOTS=\@ne \fi
+ % Compute increment vector between dots; round to \unitlength's.
+ % Use NDOTS not DOTSPACING, since DOTSPACING not exactly obeyed.
+ \dg@ZTEMP=\unitlength \multiply\dg@ZTEMP #3\relax
+ \divide\dg@ZTEMP\dg@NDOTS
+ \ifnum\dg@XTEMP=\z@
+ \dg@changesign\dg@ZTEMP\dg@YTEMP \dg@YTEMP=\dg@ZTEMP
+ \else
+ \dg@changesign\dg@ZTEMP\dg@XTEMP
+ \multiply\dg@YTEMP\dg@ZTEMP \divide\dg@YTEMP\dg@XTEMP
+ \dg@XTEMP=\dg@ZTEMP
+ \fi
+ \divide\dg@XTEMP\unitlength \divide\dg@YTEMP\unitlength
+ % Draw dotted line with \multiput
+ % and arrowhead as zero-length \vector
+ \begin{picture}(0,0)%
+ \dg@DOTDIAM=\dgDOTSIZE \divide\dg@DOTDIAM\unitlength
+ \multiput(0,0)(\dg@XTEMP,\dg@YTEMP){\dg@NDOTS}{%
+ \circle*{\dg@DOTDIAM}}%
+ \multiply\dg@XTEMP\dg@NDOTS \multiply\dg@YTEMP\dg@NDOTS
+ \put(\dg@XTEMP,\dg@YTEMP){\vector(#1,#2){0}}%
+ \end{picture}%
+ \endgroup}%
+%
+%
+% ----------------------------------------------------------------
+% ----------------------LaTeX ENHANCEMENTS------------------------
+% ----------------------------------------------------------------
+%
+%
+% Allow user-defined commands and environments to have an
+% optional first arg.
+%
+% For environments, also allow ``*-form'' which ignores spaces
+% after the \end{...} command. (P.S. LaTeX2e has now usurped the
+% ``*-form'' for other purposes in its \newenvironment macro.)
+%
+% Usage:
+% \newoptcommand{\COMMAND}{DEFAULT}[NARGS]{TEXT}
+% \renewoptcommand{\COMMAND}{DEFAULT}[NARGS]{TEXT}
+% \newoptenvironment{NAME}{DEFAULT}[NARGS]{B_TEXT}{E_TEXT}
+% \newoptenvironment*{NAME}{DEFAULT}[NARGS]{B_TEXT}{E_TEXT}
+% \renewoptenvironment{NAME}{DEFAULT}[NARGS]{B_TEXT}{E_TEXT}
+% \renewoptenvironment*{NAME}{DEFAULT}[NARGS]{B_TEXT}{E_TEXT}
+%
+% For example, after defining
+% \newoptcommand{\glug}{defval}[2]{%
+% First is ``#1'', 2nd is ``#2''.}
+% the user can do
+% \glug{hahaha}\\
+% \glug[oof]{bzzzz}
+% to get
+% First is ``defval'', 2nd is ``hahaha''.
+% First is ``oof'', 2nd is ``bzzzz''.
+%
+\def\newoptcommand#1#2{%
+ \@ifnextchar [{\@optargdef#1#2}{\@optargdef#1#2[1]}}
+
+\def\renewoptcommand#1#2{%
+ \edef\@tempa{\expandafter\@cdr\string#1\@nil}%
+ \@ifundefined{\@tempa}{%
+ \@latexerr{\string#1\space undefined}\@ehc}{}%
+ \@ifnextchar [{\@reoptargdef#1#2}{\@reoptargdef#1#2[1]}}
+
+\long\def\@optargdef#1#2[#3]#4{%
+ \@ifdefinable #1{\@reoptargdef#1#2[#3]{#4}}}
+
+\long\def\@reoptargdef#1#2[#3]#4{%
+ \@tempcnta#3\relax \@tempcntb \@ne
+ \let#1\relax \let\@tempa\relax
+ \edef\@tempb{\long\def\csname\string#1\endcsname
+ [\@tempa\the\@tempcntb]}%
+ \advance\@tempcntb \@ne \advance\@tempcnta \m@ne
+ \@whilenum\@tempcnta>0\do{%
+ \edef\@tempb{\@tempb\@tempa\the\@tempcntb}%
+ \advance\@tempcntb \@ne \advance\@tempcnta \m@ne}%
+ \let\@tempa=##\@tempb{#4}\let\@tempa\relax
+ \def#1{\@ifnextchar [{\csname\string#1\endcsname}{%
+ \csname\string#1\endcsname[#2]}}}
+
+\def\newoptenvironment{%
+ \@ifnextchar *{\@@newoptenv{\global\@ignoretrue}}{%
+ \@@newoptenv{}*}}
+
+\def\@@newoptenv#1*#2#3{%
+ \@ifnextchar [{\@newoptenv{#1}{#2}{#3}}{%
+ \@newoptenv{#1}{#2}{#3}[0]}}
+
+\long\def\@newoptenv#1#2#3[#4]#5#6{%
+ \expandafter\newoptcommand\csname#2\endcsname{#3}[#4]{#5}%
+ \expandafter\long\expandafter\def\csname end#2\endcsname{#6#1}}
+
+\def\renewoptenvironment{%
+ \@ifnextchar *{\@@renewoptenv{\global\@ignoretrue}}{%
+ \@@renewoptenv{}*}}
+
+\def\@@renewoptenv#1*#2#3{%
+ \@ifnextchar [{\@renewoptenv{#1}{#2}{#3}}{%
+ \@renewoptenv{#1}{#2}{#3}[0]}}
+
+\long\def\@renewoptenv#1#2#3[#4]#5#6{%
+ \expandafter\renewoptcommand\csname#2\endcsname{#3}[#4]{#5}%
+ \expandafter\long\expandafter\def\csname end#2\endcsname{#6#1}}
+
+%
+%
+% ----------------------------------------------------------------
+% -------------------------CORE CODE------------------------------
+% ----------------------------------------------------------------
+%
+%
+% ---INTERNAL VARIABLES---
+%
+\newcount\dg@HORIZ \newcount\dg@VERT
+\newcount\dg@XLPAD \newcount\dg@YBPAD
+\newcount\dg@XRPAD \newcount\dg@YTPAD
+\newcount\dg@X \newcount\dg@Y
+\newcount\dg@XGRID \newcount\dg@YGRID
+\newcount\dg@SIZE
+\newcount\dg@USERSIZE
+\newcount\dg@DX \newcount\dg@DY
+\newcount\dg@XLBL \newcount\dg@YLBL
+\newcount\dg@XOFFSET \newcount\dg@YOFFSET
+\newcount\dg@LBLOFF
+\newcount\dg@XLBLOFF \newcount\dg@YLBLOFF
+\newcount\dg@LBLPOS
+\newcount\dg@XTEMP \newcount\dg@YTEMP
+\newcount\dg@ZTEMP
+\newcount\dg@XNODE \newcount\dg@YNODE
+\newcount\dg@XEND \newcount\dg@YEND
+\newcount\dg@WEND \newcount\dg@HEND
+\newcount\dg@COUNT
+\newbox\dg@NODEBOX
+\newbox\dg@LABONEBOX \newbox\dg@LABTWOBOX
+%
+%
+% ---THE DIAGRAM ENVIRONMENT---
+%
+% Ignores spaces following the \end{diagram},
+% just like most LaTeX built-in environments do (thus the `*').
+% If optional arg supplied, reverts to version 1.0 behavior.
+%
+\newoptenvironment*{diagram}{}[1]{%
+ \ifdgVERBOSE
+ \global\advance\dg@COUNT\@ne
+ \message{[diagram \the\dg@COUNT}%
+ \fi
+ \let\node=\dg@node \let\\=\dg@cr \let\arrow=\dg@arrow
+ %
+ % COMPATIBILITY MODE FOR VERSION 1.0.
+ %
+ % If opt arg given, use it as "BIGNODE" in old-style grid
+ % geometry calculation.
+ \def\dg@BIGNODE{#1}%
+ \ifx\dg@BIGNODE\@empty\else
+ \setbox\dg@NODEBOX=\hbox{$\dgeverynode{#1}$}%
+ \dg@XTEMP=\wd\dg@NODEBOX
+ \dg@YTEMP=\ht\dg@NODEBOX \advance\dg@YTEMP\dp\dg@NODEBOX
+ \ifnum\dg@YTEMP=\z@ \dg@ZTEMP=\z@
+ \else \dg@ZTEMP=\dg@XTEMP \divide\dg@ZTEMP\dg@YTEMP\fi
+ \ifnum\dg@ZTEMP>\dgMAXSQUARE
+ \ifnum\dg@ZTEMP<\dgMINDBLSQ
+ \dg@XGRID=\thr@@ \dg@YGRID=\tw@
+ \else \dg@XGRID=\tw@ \dg@YGRID=\@ne \fi
+ \else \dg@XGRID=\@ne \dg@YGRID=\@ne \fi
+ \advance\dg@XTEMP\dgHORIZPAD \advance\dg@YTEMP\dgVERTPAD
+ \dg@XLPAD=\dg@XTEMP \divide\dg@XLPAD\tw@
+ \dg@XRPAD=\dg@XTEMP \divide\dg@XRPAD\tw@
+ \dg@YBPAD=\dg@YTEMP \divide\dg@YBPAD\tw@
+ \dg@YTPAD=\dg@YTEMP \divide\dg@YTPAD\tw@
+ \advance\dg@XTEMP\dgARROWLENGTH
+ \divide\dg@XTEMP\dg@XGRID \divide\dg@XTEMP\@m
+ \unitlength=1sp\relax \multiply\unitlength\dg@XTEMP
+ \fi
+ %
+ % PASS (1): SAVE UP NODES AND ARROWS.
+ %
+ \ifdgVERBOSE \message{.}\fi
+ \dg@X=-\@ne \dg@Y=\z@ \dg@HORIZ=\z@\relax
+ \let\dg@SLIST=\@empty
+ \let\dg@NLIST=\@empty \let\dg@ALIST=\@empty
+ \let\dg@PASS=\dg@savepass
+}{%\enddiagram
+ % Compute size of diagram.
+ \dg@VERT=-\dg@Y\relax
+ %
+ % PASS (2): CALCULATE GRID GEOMETRY.
+ % Since arrows may terminate at nodes later in the diagram,
+ % this requires node data to be saved up in an earlier pass.
+ % Don't need geom pass in compatibility mode.
+ %
+ \ifdgVERBOSE \message{.}\fi
+ \ifx\dg@BIGNODE\@empty
+ % Accumulate data.
+ \dg@XGRID=\z@ \dg@YGRID=\z@
+ \dg@XLPAD=\z@ \dg@XRPAD=\z@ \dg@YBPAD=\z@ \dg@YTPAD=\z@
+ \let\dg@PASS=\dg@geompass
+ \dg@NLIST \dg@ALIST
+ % Calculate \unitlength and normalized XGRID,YGRID.
+ % catch any bogus results along the way
+ \ifnum\dg@XGRID>\z@\else \dg@XGRID=\dgHORIZPAD \fi
+ \ifnum\dg@YGRID>\z@\else \dg@YGRID=\dgVERTPAD \fi
+ \dggeometry
+ \ifdim\unitlength>\z@\else
+ \unitlength=\dgARROWLENGTH \divide\unitlength\@m \fi
+ \ifnum\dg@XGRID>\z@\else \dg@XGRID=\@ne \fi
+ \ifnum\dg@YGRID>\z@\else \dg@YGRID=\@ne \fi
+ \fi
+ % Now convert drawing dimensions to \unitlength's.
+ \dg@LBLOFF=\dgLABELOFFSET \divide\dg@LBLOFF\unitlength
+ \multiply\dg@HORIZ\@m \multiply\dg@HORIZ\dg@XGRID
+ \multiply\dg@VERT\@m \multiply\dg@VERT\dg@YGRID
+ \divide\dg@XLPAD\unitlength \divide\dg@XRPAD\unitlength
+ \divide\dg@YBPAD\unitlength \divide\dg@YTPAD\unitlength
+ %
+ % PASS (3): DRAW SAVED NODES AND ARROWS USING GRID GEOMETRY.
+ %
+ \ifdgVERBOSE \message{.}\fi
+ \let\dg@PASS=\dg@drawpass
+ \hspace*{\dg@XLPAD\unitlength}%
+ \vcenter{%
+ \hsize=0pt\relax\parindent=0pt\relax
+ \parskip=0pt\relax\baselineskip=0pt\relax
+ \vspace*{\dg@YTPAD\unitlength}%
+ \begin{picture}(0,0)(0,0)\dg@NLIST\dg@ALIST\end{picture}%
+ % Tell TeX how high diagram is.
+ \raisebox{\z@}[\z@][\dg@VERT\unitlength]{}%
+ \vspace*{\dg@YBPAD\unitlength}%
+ }
+ % Tell TeX how wide diagram is.
+ \hspace*{\dg@HORIZ\unitlength}%
+ \hspace*{\dg@XRPAD\unitlength}%
+ \ifdgVERBOSE \message{]}\fi
+}%
+
+\def\dg@savepass{s}
+\def\dg@geompass{g}
+\def\dg@drawpass{d}
+
+%
+%
+% ---MAKING NODES---
+%
+% In draw pass, just place centered FORMULA at current coords.
+%
+% In geometry pass, find how far nodes at boundary of diagram
+% stick out over the edge; update XLPAD, XRPAD, YBPAD, YTPAD.
+%
+% In save pass, measure FORMULA, saving incremented position and
+% padded width and height (in scaled points) on \dg@SLIST like so:
+% ...,\dg@XNODE=<X coord>\relax\dg@YNODE=<Y coord>\relax
+% \dg@XTEMP=<node width>\relax\dg@YTEMP=<node height>\relax,...
+% and saving node itself (for later drawing) on \dg@NLIST like so:
+% ...\dg@X=<X coord>\relax\dg@Y=<Y coord>\relax
+% \dg@node{FORMULA}...
+% Also update HORIZ (horizontal size of diagram).
+%
+% Usage: \dg@node[NCOLS]{FORMULA}
+\newoptcommand{\dg@node}{\@ne}[2]{%
+ \ifx\dg@PASS\dg@savepass
+ %
+ % Update coordinates and XMAX.
+ \dg@XTEMP=#1\relax
+ \ifnum\dg@XTEMP<\@ne \dg@XTEMP=\@ne\fi
+ \advance\dg@X\dg@XTEMP
+ \ifnum\dg@HORIZ<\dg@X \dg@HORIZ=\dg@X \fi
+ %
+ % Measure padded node.
+ \setbox\dg@NODEBOX=\hbox{$\dgeverynode{#2}$}%
+ \dg@XTEMP=\wd\dg@NODEBOX \advance\dg@XTEMP\dgHORIZPAD
+ \dg@YTEMP=\ht\dg@NODEBOX \advance\dg@YTEMP\dp\dg@NODEBOX
+ \advance\dg@YTEMP\dgVERTPAD
+ %
+ % Save up info in NLIST and SLIST.
+ \toks\z@=\expandafter{\dg@SLIST}%
+ \edef\dg@SLIST{\the\toks\z@
+ ,\noexpand\dg@XNODE=\number\dg@X\noexpand\relax
+ \noexpand\dg@YNODE=\number\dg@Y\noexpand\relax
+ \noexpand\dg@XTEMP=\number\dg@XTEMP\noexpand\relax
+ \noexpand\dg@YTEMP=\number\dg@YTEMP\noexpand\relax}%
+ \toks\z@=\expandafter{\dg@NLIST}%
+ \toks\tw@={\dg@node{#2}}%
+ \edef\dg@NLIST{\the\toks\z@
+ \noexpand\dg@X=\number\dg@X\noexpand\relax
+ \noexpand\dg@Y=\number\dg@Y\noexpand\relax
+ \the\toks\tw@}%
+ \else\ifx\dg@PASS\dg@geompass
+ %
+ % If on boundary, compare padding against half of
+ % padded node size saved in SLIST.
+ \ifnum\dg@X=\z@
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@WEND\tw@
+ \ifnum\dg@XLPAD<\dg@WEND \dg@XLPAD=\dg@WEND \fi\fi
+ \ifnum\dg@X=\dg@HORIZ
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@WEND\tw@
+ \ifnum\dg@XRPAD<\dg@WEND \dg@XRPAD=\dg@WEND \fi\fi
+ \ifnum\dg@Y=\z@
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@HEND\tw@
+ \ifnum\dg@YTPAD<\dg@HEND \dg@YTPAD=\dg@HEND \fi\fi
+ \ifnum\dg@Y=-\dg@VERT\relax
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@HEND\tw@
+ \ifnum\dg@YBPAD<\dg@HEND \dg@YBPAD=\dg@HEND \fi\fi
+ \else\ifx\dg@PASS\dg@drawpass
+ %
+ % Get scaled picture coords from grid coords.
+ \dg@XNODE=\dg@X \multiply\dg@XNODE\@m
+ \multiply\dg@XNODE\dg@XGRID
+ \dg@YNODE=\dg@Y \multiply\dg@YNODE\@m
+ \multiply\dg@YNODE\dg@YGRID
+ %
+ % Place centered formula.
+ \setbox\dg@NODEBOX=\hbox{$\dgeverynode{#2}$}%
+ \put(\dg@XNODE,\dg@YNODE){\dg@makebox{\box\dg@NODEBOX}}%
+ \fi\fi\fi}%
+
+% Increment coordinates to beginning of NROWS-th next
+% grid row (only in save pass).
+% Usage: \dg@cr[NROWS]
+\newoptcommand{\dg@cr}{\@ne}[1]{%
+ \ifx\dg@PASS\dg@savepass
+ \dg@YTEMP=#1\relax
+ \ifnum\dg@YTEMP<\@ne \dg@YTEMP=\@ne \fi
+ \advance\dg@Y -\dg@YTEMP\relax
+ \dg@X=-\@ne\relax\fi}%
+%
+%
+% ---ARROW COMMAND FRONT ENDS---
+%
+% Usage: \dg@arrow[USERSIZE]{ARROW_SPECS}LABELS...
+\newoptcommand{\dg@arrow}{\@ne}[2]{%
+ % Keep all arrow geometry parameters local.
+ % The \endgroup is in each \dg@process command.
+ \begingroup
+ % Get optional arrow USERSIZE.
+ \dg@USERSIZE=#1\relax
+ \ifnum\dg@USERSIZE<\@ne \dg@USERSIZE=\@ne \fi
+ % Parse arrow specification.
+ \dg@parse{#2}%
+ % In draw pass, calculate all the arrow geometry parameters
+ % and draw the arrow.
+ % In geometry pass, calculate minimum size of grid rectangle
+ % which gives all arrows ARROWLENGTH of room.
+ % In save mode, just save up the arrow in ALIST.
+ \ifx\dg@PASS\dg@savepass
+ % Arrow saved with orig LBLTYPE, so don't re-position args.
+ \ifx\dg@label\dgl@b \let\dg@label=\dgl@t \fi
+ \ifx\dg@label\dgl@r \let\dg@label=\dgl@l \fi
+ \let\dg@process=\dg@save
+ \else\ifx\dg@PASS\dg@geompass
+ \let\dg@process=\dg@ignore
+ \dg@geomcalc
+ \else\ifx\dg@PASS\dg@drawpass
+ \let\dg@process=\dg@draw
+ \dg@drawcalc
+ \fi\fi\fi
+ \dg@label{\dg@process{#1}{#2}}}%
+
+% Also make \arrow command available for use outside of diagrams.
+\newoptcommand{\arrow}{\@ne}[2]{%
+ % Parse arrow specification just to check how many labels.
+ \dg@parse{#2}%
+ % Text arrow uses original LBLTYPE, so don't re-position args.
+ \ifx\dg@label\dgl@b \let\dg@label=\dgl@t \fi
+ \ifx\dg@label\dgl@r \let\dg@label=\dgl@l \fi
+ \dg@label{\dg@textarrow{#1}{#2}}}%
+
+\def\dg@textarrow#1#2#3#4{%
+ \mathrel{{%
+ \dgHORIZPAD=0pt\relax\dgVERTPAD=0pt\relax
+ \dgARROWLENGTH=\dgTEXTARROWLENGTH\relax
+ \dgVERBOSEfalse
+ \begin{diagram}
+ \node{}\arrow[#1]{#2}{#3}{#4}\node{}
+ \end{diagram}}}}
+
+% Parse arrow specification: comma-separated list of features.
+% Usage: \dg@parse{TYPE,ONEORTWOLABEL,OPTION,...}
+\def\dg@parse#1{%
+ % Set default labeling and options.
+ \let\dg@label=\dgl@ \dgo@
+ % Scan list, reading TYPE, LBLTYPE, and OPTIONs in turn.
+ \let\dg@type=\@empty \let\dg@lbltype=\@empty
+ \@for\dg@list:=#1\do{%
+ \ifx\dg@type\@empty \let\dg@type=\dg@list
+ \else\ifx\dg@lbltype\@empty \let\dg@lbltype=\dg@list
+ % In case LBLTYPE not given, try it as an OPTION.
+ % Note: LBLTYPE and OPTION names must not conflict.
+ \@ifundefined{dgo@\dg@list}{}{\@nameuse{dgo@\dg@list}}%
+ \else
+ % Process OPTIONs in turn; ignore bad OPTIONs.
+ \@ifundefined{dgo@\dg@list}{}{\@nameuse{dgo@\dg@list}}%
+ \fi\fi}%
+ % TYPE must be specified (default to "e" on error).
+ % Get raw geometry parameters from TYPE.
+ \@ifundefined{dgt@\dg@type}{\dgt@e}{\@nameuse{dgt@\dg@type}}%
+ % If LBLTYPE valid, get arg handler.
+ \@ifundefined{dgl@\dg@lbltype}{}{%
+ \dg@letname\dg@label{dgl@\dg@lbltype}}}
+
+%
+%
+% ---ARROW PROCESSORS (draw, save, ignore)---
+%
+% Draw labelled arrow, using computed arrow geometry parameters.
+% The \endgroup matches \dg@arrow's \begingroup.
+% Usage: \dg@draw{IGNORE}{IGNORE}{LABEL1}{LABEL2}
+\def\dg@draw#1#2#3#4{%
+ % Typeset labels in advance of all the positioning yoga,
+ % since TeX only allows boxes to nest 40 deep by default.
+ \setbox\dg@LABONEBOX=\hbox{$\dgeverylabel{#3}$}%
+ \setbox\dg@LABTWOBOX=\hbox{$\dgeverylabel{#4}$}%
+ \put(\dg@X,\dg@Y){\dg@makebox{%
+ \begin{picture}(0,0)%
+ \thinlines
+ \put(\dg@XOFFSET,\dg@YOFFSET){%
+ \dg@VECTOR(\dg@DX,\dg@DY){\dg@SIZE}}%
+ \put(\dg@XLBL,\dg@YLBL){\dg@makebox{%
+ \begin{picture}(0,0)%
+ \put(\dg@XLBLOFF,\dg@YLBLOFF){%
+ \dg@makebox[\dg@LBLONE]{\box\dg@LABONEBOX}}%
+ \put(-\dg@XLBLOFF,-\dg@YLBLOFF){%
+ \dg@makebox[\dg@LBLTWO]{\box\dg@LABTWOBOX}}%
+ \end{picture}}}%
+ \end{picture}}}%
+ \endgroup}%
+
+% Instead of drawing arrow now, save it on \dg@ALIST, like so:
+% ...\dg@X=<X coord>\relax\dg@Y=<Y coord>\relax
+% \dg@arrow[<size>]{<arrow specs>}<labels>...
+% If either LABEL1 or LABEL2 is empty, it will simply be ignored.
+% Usage: \dg@save{SIZE}{SPEC}{LABEL1}{LABEL2}
+\def\dg@save#1#2#3#4{%
+ \endgroup % to match \dg@arrow's \begingroup
+ \toks\z@=\expandafter{\dg@ALIST}%
+ \toks\tw@={\dg@arrow[#1]{#2}{#3}{#4}}%
+ \edef\dg@ALIST{\the\toks\z@%
+ \noexpand\dg@X=\number\dg@X\noexpand\relax
+ \noexpand\dg@Y=\number\dg@Y\noexpand\relax
+ \the\toks\tw@}}%
+
+% No-op arrow processor.
+% Usage: \dg@ignore{SIZE}{SPEC}{LABEL1}{LABEL2}
+\def\dg@ignore#1#2#3#4{\endgroup}
+
+%
+%
+% ---ARROW GEOMETRY CALCULATIONS---
+%
+% Calc minimum size of grid rectangle (in sp's) so that all
+% arrows will have horizontal extent at least ARROWMINX :=
+% ( |DX|/(|DX|+|DY|) )*ARROWLENGTH and the vertical extent
+% at least ARROWMINY := ( |DY|/(|DX|+|DY|) )*ARROWLENGTH.
+% We estimate the horizontal and vertical extents from node
+% corner to node corner (which indeed gives lower bounds).
+% Thus for example XGRID must be at least
+% ( (WSOURCE+WTARGET)/2 + ARROWMINX ) / (SIZE*USERSIZE)
+% where the width of source (target) node is WSOURCE (WTARGET).
+% There is a similar formula for YGRID.
+%
+% Updates (globally so we see it later!!!):
+% XGRID, YGRID
+% using these arrow parameters:
+% X, Y, USERSIZE, SIZE, DX, DY
+% using also the stored node dims in SLIST.
+% Uses temp vars XOFFSET, YOFFSET, XTEMP, YTEMP, ZTEMP,
+% XEND, YEND, WEND, HEND. No args.
+%
+\def\dg@geomcalc{%
+ % Find other end of arrow (in grid coords).
+ \dg@XEND=\dg@SIZE \multiply\dg@XEND\dg@USERSIZE
+ \ifnum\dg@DX=\z@
+ \dg@YEND=\dg@XEND \dg@XEND=\z@
+ \dg@changesign\dg@YEND\dg@DY
+ \else
+ \dg@changesign\dg@XEND\dg@DX \dg@YEND=\dg@XEND
+ \multiply\dg@YEND\dg@DY \divide\dg@YEND\dg@DX
+ \fi
+ \advance\dg@XEND\dg@X \advance\dg@YEND\dg@Y
+ % Get size of node there.
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@XEND}{\dg@YEND}{\dg@WEND}{\dg@HEND}%
+ \dg@XOFFSET=\dg@WEND \dg@YOFFSET=\dg@HEND
+ % Now average in size of current node.
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \advance\dg@XOFFSET\dg@WEND \divide\dg@XOFFSET\tw@
+ \advance\dg@YOFFSET\dg@HEND \divide\dg@YOFFSET\tw@
+ % Now add in required arrow length.
+ \dg@XTEMP=\dgARROWLENGTH \dg@YTEMP=\dgARROWLENGTH
+ \ifnum\dg@DX>\z@
+ \dg@ZTEMP=\dg@DX \multiply\dg@XTEMP\dg@DX
+ \else \dg@ZTEMP=-\dg@DX \multiply\dg@XTEMP -\dg@DX \fi
+ \ifnum\dg@DY>\z@
+ \advance\dg@ZTEMP\dg@DY \multiply\dg@YTEMP\dg@DY
+ \else \advance\dg@ZTEMP -\dg@DY \multiply\dg@YTEMP -\dg@DY\fi
+ \ifnum\dg@ZTEMP=\z@\else
+ \divide\dg@XTEMP\dg@ZTEMP \divide\dg@YTEMP\dg@ZTEMP
+ \advance\dg@XOFFSET\dg@XTEMP \advance\dg@YOFFSET\dg@YTEMP
+ \fi
+ % Divide by number of grid units to get unit size.
+ \divide\dg@XOFFSET\dg@SIZE \divide\dg@XOFFSET\dg@USERSIZE
+ \divide\dg@YOFFSET\dg@SIZE \divide\dg@YOFFSET\dg@USERSIZE
+ \ifnum\dg@DX=\z@ \dg@XOFFSET=\z@ \fi
+ \ifnum\dg@DY=\z@ \dg@YOFFSET=\z@ \fi
+ \ifnum\dg@XGRID<\dg@XOFFSET \global\dg@XGRID=\dg@XOFFSET\fi
+ \ifnum\dg@YGRID<\dg@YOFFSET \global\dg@YGRID=\dg@YOFFSET\fi
+ \relax}
+
+% Calculate all the arrow geometry parameters for drawing:
+% X, Y, DX, DY, SIZE, XOFFSET, YOFFSET, VECTOR,
+% XLBL, YLBL, XLBLOFF, YLBLOFF, LBLONE, LBLTWO,
+% from the (preliminary) values of these basic arrow parameters:
+% X, Y, USERSIZE, SIZE, DX, DY, VECTOR, LBLPOS
+% using also the grid geom and diagram parameters:
+% XGRID, YGRID, LBLOFF, SLIST, ARROWPARTS.
+% No args. Uses temp vars XTEMP, YTEMP, ZTEMP, XEND, WEND.
+\def\dg@drawcalc{%
+ % Get size of node at other end of arrow (in picture coords).
+ \dg@XEND=\dg@SIZE \multiply\dg@XEND\dg@USERSIZE
+ \ifnum\dg@DX=\z@
+ \dg@YEND=\dg@XEND \dg@XEND=\z@
+ \dg@changesign\dg@YEND\dg@DY
+ \else
+ \dg@changesign\dg@XEND\dg@DX \dg@YEND=\dg@XEND
+ \multiply\dg@YEND\dg@DY \divide\dg@YEND\dg@DX
+ \fi
+ \advance\dg@XEND\dg@X \advance\dg@YEND\dg@Y
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@XEND}{\dg@YEND}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@WEND\unitlength \divide\dg@HEND\unitlength
+ % Now adjust arrow dir to grid aspect ratio (XGRID:YGRID).
+ \multiply\dg@DX\dg@XGRID \multiply\dg@DY\dg@YGRID
+ \dg@rmcommondiv\tw@\dg@DX\dg@DY
+ \dg@rmcommondiv\tw@\dg@DX\dg@DY %[sic]
+ \dg@rmcommondiv\thr@@\dg@DX\dg@DY
+ % Scale arrow to requested USERSIZE.
+ % Prepare to convert size from grid to picture coords.
+ \multiply\dg@SIZE\dg@USERSIZE \multiply\dg@SIZE\@m
+ \ifnum\dg@DX=\z@
+ %
+ % Vertical arrow.
+ %
+ % SIZE measures vertical extent in \unitlengths. Arrow
+ % shortened by (HSOURCE+HTARGET)/2, offset by HSOURCE/2.
+ % Labels at (HSOURCE/2 + SIZE*LBLPOS/ARROWPARTS).
+ \multiply\dg@SIZE\dg@YGRID
+ \divide\dg@HEND\tw@ \advance\dg@SIZE -\dg@HEND
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@YOFFSET}%
+ \divide\dg@YOFFSET\unitlength \divide\dg@YOFFSET\tw@
+ \advance\dg@SIZE -\dg@YOFFSET
+ \dg@XOFFSET=\z@
+ \def\dg@LBLONE{r}\def\dg@LBLTWO{l}%
+ \dg@XLBL=\z@ \dg@YLBL=\dg@SIZE
+ \multiply\dg@YLBL\dg@LBLPOS
+ \divide\dg@YLBL\dgARROWPARTS\relax
+ \advance\dg@YLBL\dg@YOFFSET
+ \dg@changesign\dg@YLBL\dg@DY
+ \dg@changesign\dg@YOFFSET\dg@DY
+ \else
+ % Nonvertical arrow.
+ % SIZE measures horizontal extent in \unitlengths.
+ \multiply\dg@SIZE\dg@XGRID
+ \ifnum\dg@DY=\z@
+ %
+ % Horizontal arrow.
+ %
+ % Arrow shortened by (WSOURCE+WTARGET)/2,
+ % and offset by WSOURCE/2. Labels at
+ % (WSOURCE/2 + SIZE*LBLPOS/ARROWPARTS).
+ \divide\dg@WEND\tw@ \advance\dg@SIZE -\dg@WEND
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@XOFFSET}{\dg@HEND}%
+ \divide\dg@XOFFSET\unitlength \divide\dg@XOFFSET\tw@
+ \advance\dg@SIZE -\dg@XOFFSET
+ \dg@YOFFSET=\z@
+ \def\dg@LBLONE{b}\def\dg@LBLTWO{t}%
+ \dg@YLBL=\z@ \dg@XLBL=\dg@SIZE
+ \multiply\dg@XLBL\dg@LBLPOS
+ \divide\dg@XLBL\dgARROWPARTS\relax
+ \advance\dg@XLBL\dg@XOFFSET
+ \dg@changesign\dg@XLBL\dg@DX
+ \dg@changesign\dg@XOFFSET\dg@DX
+ \else
+ %
+ % Diagonal arrow.
+ %
+ % Arrow offset in its own direction, with horiz comp
+ % XOFFSET := MIN( WSOURCE/2, |DX/DY|*HSOURCE/2 ), and
+ % shortened in its own direction, with horiz comp
+ % XOFFSET + MIN( WTARGET/2, |DX/DY|*HTARGET/2 ).
+ % Labels at ( XOFFSET+-SIZE*LBLPOS/ARROWPARTS ,
+ % YOFFSET+-SIZE*LBLPOS*DY/(ARROWPARTS*DX) )
+ \divide\dg@WEND\tw@ \divide\dg@HEND\tw@
+ \multiply\dg@HEND\dg@DX \divide\dg@HEND\dg@DY
+ \ifnum\dg@HEND<\z@ \multiply\dg@HEND\m@ne \fi
+ \ifnum\dg@WEND<\dg@HEND \advance\dg@SIZE -\dg@WEND
+ \else \advance\dg@SIZE -\dg@HEND \fi
+ \dg@getnodesize
+ {\dg@SLIST}{\dg@X}{\dg@Y}{\dg@WEND}{\dg@HEND}%
+ \divide\dg@WEND\unitlength \divide\dg@WEND\tw@
+ \divide\dg@HEND\unitlength \divide\dg@HEND\tw@
+ \multiply\dg@HEND\dg@DX \divide\dg@HEND\dg@DY
+ \ifnum\dg@HEND<\z@ \multiply\dg@HEND\m@ne \fi
+ \ifnum\dg@WEND<\dg@HEND \dg@XOFFSET=\dg@WEND
+ \else \dg@XOFFSET=\dg@HEND \fi
+ \advance\dg@SIZE -\dg@XOFFSET
+ \dg@changesign\dg@XOFFSET\dg@DX
+ \dg@YOFFSET=\dg@XOFFSET
+ \multiply\dg@YOFFSET\dg@DY \divide\dg@YOFFSET\dg@DX
+ \def\dg@LBLONE{br}\def\dg@LBLTWO{tl}%
+ \ifnum\dg@DX<\z@ \ifnum\dg@DY>\z@
+ \def\dg@LBLONE{bl}\def\dg@LBLTWO{tr}\fi\fi
+ \ifnum\dg@DX>\z@ \ifnum\dg@DY<\z@
+ \def\dg@LBLONE{bl}\def\dg@LBLTWO{tr}\fi\fi
+ \dg@XLBL=\dg@SIZE
+ \multiply\dg@XLBL\dg@LBLPOS
+ \divide\dg@XLBL\dgARROWPARTS\relax
+ \dg@changesign\dg@XLBL\dg@DX
+ \dg@YLBL=\dg@XLBL
+ \multiply\dg@YLBL\dg@DY \divide\dg@YLBL\dg@DX
+ \advance\dg@XLBL\dg@XOFFSET
+ \advance\dg@YLBL\dg@YOFFSET
+ \fi
+ \fi
+ % (XLBL,YLBL) is the displacement from the source NODE
+ % to the point along the arrow where the labels will be
+ % attached. The offset of first label from this attachment
+ % point is the vector
+ % (XLBLOFF,YLBLOFF) = LBLOFF*sgn(DX)*(-DY,DX)/max(|DX|,|DY|)
+ % if DX is nonzero, and otherwise
+ % (XLBLOFF,YLBLOFF) = LBLOFF*(-1,0);
+ % The 2nd label is offset by the vector (-XLBLOFF,-YLBLOFF).
+ \dg@XLBLOFF=-\dg@DY \dg@changesign\dg@XLBLOFF\dg@DX
+ \dg@YLBLOFF=\dg@DX \dg@changesign\dg@YLBLOFF\dg@DX
+ \ifnum\dg@DX=\z@ \dg@XLBLOFF=\m@ne \fi
+ \dg@XTEMP=\dg@DX \dg@changesign\dg@XTEMP\dg@DX
+ \dg@YTEMP=\dg@DY \dg@changesign\dg@YTEMP\dg@DY
+ \ifnum\dg@YTEMP>\dg@XTEMP \dg@XTEMP=\dg@YTEMP \fi
+ \ifnum\dg@XTEMP=\z@ \dg@XTEMP=\@ne \fi
+ \multiply\dg@XLBLOFF\dg@LBLOFF \divide\dg@XLBLOFF\dg@XTEMP
+ \multiply\dg@YLBLOFF\dg@LBLOFF \divide\dg@YLBLOFF\dg@XTEMP
+ %
+ % Change node location from grid coords to picture coords.
+ \multiply\dg@X\@m \multiply\dg@X\dg@XGRID
+ \multiply\dg@Y\@m \multiply\dg@Y\dg@YGRID
+ \relax}%
+
+%
+%
+% ---UTILITY ROUTINES---
+%
+% Remove common divisor DIV from two number registers
+% \NUM1 and \NUM2.
+% Usage: \dg@rmcommondiv{DIV}{\NUM1}{\NUM2}
+% NOTE: uses XTEMP and YTEMP.
+\def\dg@rmcommondiv#1#2#3{%
+ \dg@XTEMP=#2\relax
+ \divide\dg@XTEMP #1\relax \multiply\dg@XTEMP #1\relax
+ \dg@YTEMP=#3\relax
+ \divide\dg@YTEMP #1\relax \multiply\dg@YTEMP #1\relax
+ \ifnum\dg@XTEMP=#2\relax \ifnum\dg@YTEMP=#3\relax
+ \divide#2#1\relax \divide#3#1\relax \fi\fi}%
+
+% Multiply number register \NUM1 by sign of \NUM2.
+% Usage: \dg@changesign\NUM1\NUM2
+\def\dg@changesign#1#2{%
+ \ifnum #2<\z@ \multiply#1\m@ne
+ \else\ifnum #2=\z@ #1=\z@ \fi\fi}%
+
+% Determine from SLIST the padded width and height (in scaled
+% points) of the node at (XCOORD,YCOORD). Place the answer
+% in number registers \WIDTH and \HEIGHT, resp (if no such
+% node, set \WIDTH=\HEIGHT=0). SLIST must be comma-separated
+% list of TeX code segments, each of which puts the node
+% coords in (XNODE,YNODE) and the node dims in(XTEMP,YTEMP).
+% Uses temp vars XTEMP, YTEMP.
+% Usage: \dg@getnodesize{SLIST}{XCOORD}{YCOORD}{\WIDTH}{\HEIGHT}
+\def\dg@getnodesize#1#2#3#4#5{%
+ #4=\z@\relax #5=\z@\relax
+ % loop through saved nodes
+ \expandafter\@for\expandafter\dg@trynode
+ \expandafter:\expandafter=#1\do{%
+ \dg@XNODE=\m@ne % impossible (in case \dg@trynode is empty)
+ \dg@trynode
+ \ifnum #2=\dg@XNODE \ifnum #3=\dg@YNODE
+ #4=\dg@XTEMP\relax #5=\dg@YTEMP\relax\fi\fi}}%
+
+% Like \makebox(0,0)[POS]{TEXT}, with POS expanded beforehand
+% and bottom alignment at true bottom rather than baseline.
+%
+% Usage: \dg@makebox[POS]{TEXT}
+\long\def\dg@sinkbaseline#1{%
+ \leavevmode\hbox{\vbox{%
+ \lineskiplimit=16383pt\relax\lineskip=0pt\relax
+ \baselineskip=-1000pt\relax
+ \parindent=0pt\relax\parskip=0pt\relax
+ \hbox{#1}\rule{0pt}{0pt}}}}%
+\newoptcommand{\dg@makebox}{}[2]{\dg@sinkbaseline{%
+ \expandafter\makebox\expandafter(\expandafter
+ 0\expandafter,\expandafter0\expandafter)\expandafter
+ [#1]{#2}}}%
+
+% Produces nothing.
+% Usage:\dg@novector(X,Y){LaTeX_LENGTH}
+\def\dg@novector(#1,#2)#3{}%
+
+% \let command \CMD equal funny-name command \NAME.
+% Usage: \dg@letname{\CMD}{NAME}.
+\def\dg@letname#1#2{%
+ \relax\expandafter
+ \let\expandafter #1\csname #2\endcsname\relax}%
+
+% Arg handlers, one for each LBLTYPE.
+% Grab labels from following input and feed them to \PROCESS.
+% Usage: \dgl@LBLTYPE{\PROCESS}...
+\def\dgl@#1{#1{}{}}%
+\def\dgl@t#1#2{#1{#2}{}}%
+\def\dgl@b#1#2{#1{}{#2}}%
+\def\dgl@tb#1#2#3{#1{#2}{#3}}%
+\def\dgl@l#1#2{#1{#2}{}}%
+\def\dgl@r#1#2{#1{}{#2}}%
+\def\dgl@lr#1#2#3{#1{#2}{#3}}%
+
diff --git a/macros/latex/contrib/pb-diagram/pb-examples.tex b/macros/latex/contrib/pb-diagram/pb-examples.tex
new file mode 100644
index 0000000000..ed9338e34a
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-examples.tex
@@ -0,0 +1,245 @@
+% pb-examples.tex: nifty example using pb-diagram.sty
+% Authors: Bill Richter et al.
+% Version Number: 5.0
+% Version Date: 20 Oct 1998
+%
+\def\tooee{LaTeX2e}
+\ifx\fmtname\tooee
+ \documentclass[12pt]{article}\usepackage{pb-diagram}
+\else
+ \documentstyle[12pt,pb-diagram]{article}
+\fi
+\title{Examples of the Diagram Environment}
+\author{Stolen from Various Sources}
+\begin{document}
+\maketitle
+
+\setlength{\fboxsep}{0pt}
+
+This ridiculous example shows how the package fits
+arrows in between the formulas, taking into account the
+exact size of every formula. (The box around the diagram
+shows how the shape of the entire diagram is made known to
+\LaTeX.) Note that diagonal arrows are fitted to either
+the tops or sides of the formulas, depending individual
+circumstances.
+\begin{center}\fbox{$
+\begin{diagram}
+\node{\left[\begin{array}{cc} A_{00} & A_{01} \\
+ A_{10} & A_{11}\end{array}\right]}
+ \arrow{e,t}{a} \arrow{s,l}{c} \arrow{ese,b,1}{u}
+ \node{B^*} \arrow{e,t}{b^*}
+ \node{C} \arrow{s,r}{d} \arrow{wsw,b,1}{v}
+\\
+\node{D} \arrow[2]{e,b}{e}
+ \node[2]{H^2(X,\, \omega_X \otimes L^{\otimes(-n^2+n)})}
+\end{diagram}
+$}\end{center}
+
+% Catcode hack to get typewriter `\' inside arg of another command
+% where \verb is illegal.
+\begingroup \catcode`|=0 \catcode`\\=12
+ |gdef|bbb{{|tt\}}%
+|endgroup
+%
+\makeatletter
+\@ifundefined{lamsvector}{%
+ (There are some additional diagrams at this point in the file,
+ which you can see if you add
+ \ifx\fmtname\tooee
+ {\tt\bbb usepackage\{lamsarrow\}\bbb usepackage\{pb-lams\}}
+ at the end of the list of included packages.)
+ \else
+ \mbox{\tt lamsarrow,pb-lams} at the end of the
+ document style options.)
+ \fi
+}{%
+\newpage
+This diagram shows off the fancy arrows fonts from LamS-\TeX.
+\[
+\begin{diagram}
+\node{A} \arrow{e,t,V}{a} \arrow{s,l,'}{c} \arrow{ese,b,1,`}{u}
+ \node{B} \arrow{e,t,A}{b}
+ \node{C} \arrow{s,r,J}{d} \arrow{wsw,b,1,L}{v} \\
+\node{D} \arrow[2]{e,b,S}{e}
+ \node[2]{E}
+\end{diagram}
+\]
+
+The two diagrams below differ only in that the second has an extra diagonal
+arrow. Because the first diagram is naturally very long, this diagonal arrow
+could not be drawn into the first diagram even with the LamS-\TeX\ fonts. So
+the diagram automatically compromises the diagram's aspect ratio to make the
+arrow possible.
+\[
+\begin{diagram}
+\node{\rule{80pt}{1pt}} \arrow[3]{e} % remove arrow: \arrow{seee,..}
+ \node[3]{\rule{80pt}{1pt}} \arrow{s}\\
+\node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}}
+\end{diagram}
+\]
+\[
+\begin{diagram}
+\node{\rule{80pt}{1pt}} \arrow[3]{e} \arrow{seee,..}
+ \node[3]{\rule{80pt}{1pt}} \arrow{s}\\
+\node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}} \arrow{e}
+ \node{\rule{80pt}{1pt}}
+\end{diagram}
+\]}
+\makeatother
+
+\newpage
+These examples show how to simulate split arrows by placing the diagram on a finer grid than logically necessary.
+\[
+ \dgARROWLENGTH=0.6\dgARROWLENGTH
+ \begin{diagram}
+ \node[2]{A}\arrow[2]{s}\\
+ \node{B}\arrow{e,-} \node{}\arrow{e,t}{\alpha} \node{C} \\
+ \node[2]{D}\arrow{ne,b}{\beta}
+ \end{diagram}
+\]
+
+\[
+\begin{diagram}
+\node{A} \arrow[2]{e,t}{a} \arrow[2]{s,l}{c} \arrow[2]{ese,t,3}{u}
+ \node[2]{B^*} \arrow[2]{e,t}{b^*}
+ \node[2]{C} \arrow[2]{s,r}{d} \arrow{wsw,-}
+\\
+ \node[3]{} \arrow{wsw,t}{v}
+\\
+\node{D} \arrow[4]{e,b}{e}
+ \node[4]{E}
+\end{diagram}
+\]
+
+
+\newpage
+Here are several ``real life'' examples from Bill Richter's work:
+%%%% Note: for ease of tex-ing we don't assume extra fonts.
+\let\frak\relax
+\let\Bbb=\relax
+%%%%
+%\font\tenfrak=eufm10 scaled \magstep1
+%\font\sevenfrak=eufm7 scaled \magstep1
+%\font\fivefrak=eufm5 scaled \magstep1
+%\newfam\frakfam \def\frak{\fam\frakfam\tenfrak} \textfont\frakfam=\tenfrak
+%\scriptfont\frakfam=\sevenfrak \scriptscriptfont\frakfam=\fivefrak
+%%%%
+%%%%
+\def\a{ \alpha }
+\def\d{ \delta }
+\def\s{ \sigma }
+\def\l{ \lambda }
+\def\p{ \partial }
+\def\st{{\tilde\s}}
+\def\O{ \Omega }
+\def\S{\Sigma}
+\def\Z{{\Bbb Z }}
+\def\@{ \otimes }
+\def\^{ \wedge }
+\def\({ \left( }
+\def\){ \right) }
+\def\K#1{{ K\(\Z/2,#1\) }}
+\def\KZ#1{{K\(\Z/4,#1\) }}
+\def\id{ \mathop{id}\nolimits }
+\def\h{ {\frak h} }
+\def\e{ {\frak e} }
+\def\G{ G }
+\def\pinch{{ \mathop{{\rm pinch}} }}
+\def\tuber{{ \bar\tau }}
+%%%%
+%%%%
+\[
+\begin{diagram}
+\node[4]{ \K{8n+1} }
+\\
+\node[2]{ \KZ{8n-1} } \arrow{e} \arrow{ene,t}{Sq^2}
+ \node{E} \arrow{ne,b}{\Theta} \arrow{s,l}{\pi}
+\\
+\node{ \S\O X \^ \O X } \arrow{e,t}{H_\mu} \arrow{ne,t}{\s(\a\@\a)}
+ \node{ \Sigma \O X } \arrow{e,t}{\sigma} \arrow{ne,t}{\st}
+ \node{ X } \arrow{e,t}{\a^2}
+ \node{ \KZ{8n}. }
+\end{diagram}
+\]
+
+\[
+\begin{diagram}
+\node[3]{\O\S A} \arrow[2]{e,t}{\l_2}
+ \node[2]{\O^2 \( \S A \^ \S A \)}
+\\
+\node[4]{\#}
+\\
+% Note: the next two lines are like
+% \node{\O B} \arrow[2]{e,t,1}{\d} \arrow[2]{ne,t}{\O\(\p\)}
+% but put a gap in first arrow to make room for crossing arrow
+\node{\O B} \arrow{e,t,-}{\d} \arrow[2]{ne,t}{\O\(\p\)}
+ \node{} \arrow{e}
+ \node{F} \arrow[2]{e,t}{\h} \arrow[2]{s,r}{\pi} \arrow[2]{n,r}{J}
+ \node[2]{\O^2 \( B \^ \S A \)} \arrow[2]{n,r}{\O^2\(\p\^\id\)}
+\\
+\\
+\node{A} \arrow[2]{ne,t}{\e} \arrow[2]{e,t}{f} \arrow[2]{nne,t,1}{E}
+ \node[2]{X} \arrow[2]{e,t}{h}
+ \node[2]{B.}
+\end{diagram}
+\]
+
+\[
+\divide\dgARROWLENGTH by3
+\begin{diagram}
+\node[9]{\O S^5}
+\\
+\\
+\\
+\node[8]{\scriptstyle\quad (\beta)}
+\\
+\node{\O\( M^5_{2\iota}\)} \arrow[4]{e,t}{\O\(\pinch\)}
+ \node[4]{\O S^5} \arrow[2]{e,t,-}{\d} \arrow[4]{ne,t}{\O\(2\iota\)}
+ \node[2]{} \arrow[2]{e}
+ \node[2]{\G} \arrow[4]{e,t}{\h_2}
+ \arrow[2]{s,r,-}{\pi} \arrow[4]{n,r}{J}
+ \node[4]{J\(S^4\^S^4\)}
+\\
+\\
+\node[3]{J_2\( M^4_{2\iota}\)} \arrow[3]{e,t,3,-}{\d_2} \arrow[2]{ne,t}{\iota}
+ \node[3]{} \arrow{e}
+ \node{\G_2} \arrow[4]{e,t,3}{\h_2} \arrow[2]{ne,t}{\iota}
+ \node[2]{} \arrow[2]{s}
+ \node[2]{S^8} \arrow[2]{ne,b}{E}
+\\
+\node[4]{\scriptstyle (\alpha)}
+\\
+\node{M^{12}_{2\iota}} \arrow[4]{e,t}{\tuber} \arrow[2]{ne,t}{\tau}
+ \node[4]{S^4} \arrow[4]{e,t}{\iota} \arrow[2]{ne,t}{\e} \arrow[4]{nne,t,3}{E}
+ \node[4]{M^5_{2\iota}} \arrow[4]{e,t}{\pinch}
+ \node[4]{S^5}
+\end{diagram}
+\]
+
+\newpage
+Example by Anders Thorup (thorup@math.ku.dk), originally done with a
+package developed by himself and Steven Kleiman
+(kleiman@math.mit.edu):
+\[
+\begin{diagram}
+\node{H^k(B_G\times N;Q)=H^k_G(N;Q)}
+ \arrow[2]{e,t}{f^*_j} \arrow[2]{s,l}{p^*} \arrow{se,t}{\tilde f^*}
+ \node[2]{H^k_G(F_j;Q)} \arrow[2]{s,r}{q^*_j}
+\\
+\node[2]{H^k_G(M;Q)} \arrow{ne,t}{i^*_j} \arrow[2]{s,l,1}{i^*}
+\\
+\node{H^k(N;Q)}\arrow{e,t,-}{\tilde f^*_j=f^*_j}\arrow{se,b}{\tilde f^*=f^*}
+ \node{} \arrow{e}
+ \node{H^k(F_j;Q)}
+\\
+\node[2]{H^k(M;Q)} \arrow{ne,b}{i^*_j}
+\end{diagram}
+\]
+
+\end{document}
diff --git a/macros/latex/contrib/pb-diagram/pb-lams.sty b/macros/latex/contrib/pb-diagram/pb-lams.sty
new file mode 100644
index 0000000000..33d802966f
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-lams.sty
@@ -0,0 +1,142 @@
+% pb-lams.sty: LAMS-TeX font enhancements for pb-diagram.sty
+% Author: Paul Burchard <burchard@pobox.com>
+% Version Number: 5.0
+% Version Date: 20 Oct 1998
+%
+% Copyright (c) 1997, 1998 by Paul Burchard
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%
+% This style file should be loaded *AFTER* pb-diagram.sty and
+% lamsarrow.sty. It should be loaded as follows:
+% \usepackage{pb-diagram,lamsarrow,pb-lams}
+%
+% This code adds to the "diagram" environment the use of
+% fancy arrow heads and tails, as well as additional arrow
+% directions. Most of the options defined here can be
+% combined arbitrarily.
+%
+
+\@ifundefined{diagram}{%
+ \@latexerr{The pb-lams style option requires pb-diagram}%
+ {You must include the pb-diagram package prior to pb-lams.}}{}
+\@ifundefined{lamsvector}{%
+ \@latexerr{The pb-lams style option requires lamsarrow}%
+ {You must include the lamsarrow package prior to pb-lams.}}{}
+
+\newif\ifdg@LATEXGEOM \dg@LATEXGEOMfalse
+
+\@namedef{dgo@}{%
+ \let\dg@VECTOR=\lamsvector
+ \lamsshaft{?}\lamssource{?}\lamstarget{?}%
+ \dg@LBLPOS=\dgARROWPARTS \divide\dg@LBLPOS\tw@\relax}%
+\@namedef{dgo@..}{\lamsshaft{.}}%
+\@namedef{dgo@<>}{\lamssource{^}\lamstarget{^}}%
+\@namedef{dgo@=}{\lamsshaft{=}}%
+\@namedef{dgo@-}{\lamstarget{0}}%
+\@namedef{dgo@'}{\lamstarget{'}}%
+\@namedef{dgo@`}{\lamstarget{`}}%
+\@namedef{dgo@A}{\lamstarget{A}}%
+\@namedef{dgo@V}{\lamssource{V}}%
+\@namedef{dgo@J}{\lamssource{J}}%
+\@namedef{dgo@L}{\lamssource{L}}%
+\@namedef{dgo@S}{\lamssource{S}}%
+%
+% approximate aspect ratio by half-integer betw 1/2 and 3
+% (or betw 1/2 and 2 if 3:1 arrow detected)
+%
+\def\dggeometry{
+ \dg@ZTEMP=\dg@XGRID \multiply\dg@ZTEMP\tw@
+ \ifnum\dg@YGRID=\z@ \dg@ZTEMP=\tw@
+ \else \divide\dg@ZTEMP\dg@YGRID \fi
+ % font limit cutoffs
+ \ifnum\dg@ZTEMP>6\relax \dg@ZTEMP=6\relax \fi
+ \ifdg@LATEXGEOM\ifnum\dg@ZTEMP>\f@ur \dg@ZTEMP=\f@ur \fi\fi
+ \ifnum\dg@ZTEMP<\@ne \dg@ZTEMP=\@ne \fi
+ \unitlength=1sp\relax
+ \ifnum\dg@ZTEMP<\tw@
+ % round aspect ratio up toward 2:2, widen rect
+ \advance\dg@ZTEMP\@ne
+ \multiply\unitlength\dg@YGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@YGRID
+ \else
+ % round aspect ratio down toward 2:2, tallen rect
+ \multiply\unitlength\dg@XGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@XGRID
+ \fi
+ \divide\unitlength\@m\relax
+ \dg@LATEXGEOMfalse}
+%
+% Bugwards-compatibility mode for versions 3.6 and earlier.
+% Enable it with \let\dggeometry=\dgoldgeometry
+%
+\def\dgoldgeometry{
+ \dg@ZTEMP=\dg@XGRID \multiply\dg@ZTEMP\tw@
+ \ifnum\dg@YGRID=\z@ \dg@ZTEMP=\tw@
+ \else \divide\dg@ZTEMP\dg@YGRID \fi
+ % font limit cutoffs
+ \ifnum\dg@ZTEMP>6\relax \dg@ZTEMP=6\relax \fi
+ \ifdg@LATEXGEOM\ifnum\dg@ZTEMP>\f@ur \dg@ZTEMP=\f@ur \fi\fi
+ \ifnum\dg@ZTEMP<\@ne \dg@ZTEMP=\@ne \fi
+ % The following calculation is garbled!
+ \unitlength=2sp\relax
+ \ifnum\dg@ZTEMP<\tw@
+ % round aspect ratio up toward 2:2, widen rect
+ \advance\dg@ZTEMP\@ne
+ \multiply\unitlength\dg@YGRID \divide\unitlength\tw@
+ \else
+ % round aspect ratio down toward 2:2, tallen rect
+ \multiply\unitlength\dg@XGRID \divide\unitlength\dg@ZTEMP
+ \fi
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@YGRID \divide\unitlength\@m
+ \dg@LATEXGEOMfalse}
+%
+% new directions
+\def\dgt@nee{\dg@DX=\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@see{\dg@DX=\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+\def\dgt@nww{\dg@DX=-\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@sww{\dg@DX=-\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+\def\dgt@nnne{\dg@DX=\@ne \dg@DY=\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@nnnw{\dg@DX=\m@ne \dg@DY=\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@sssw{\dg@DX=\m@ne \dg@DY=-\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@ssse{\dg@DX=\@ne \dg@DY=-\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@nnnee{\dg@DX=\tw@ \dg@DY=\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@nnnww{\dg@DX=-\tw@ \dg@DY=\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@sssww{\dg@DX=-\tw@ \dg@DY=-\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@sssee{\dg@DX=\tw@ \dg@DY=-\thr@@ \dg@SIZE=\tw@}%
+%
+% these are only drawn approx correct in some aspect ratios:
+\def\dgt@nneee{\dg@DX=\thr@@ \dg@DY=\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@nnwww{\dg@DX=-\thr@@ \dg@DY=\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@sswww{\dg@DX=-\thr@@ \dg@DY=-\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@sseee{\dg@DX=\thr@@ \dg@DY=-\tw@ \dg@SIZE=\thr@@}%
+%
+% these only work with LaTeX-compatible aspect ratios:
+% must set this globally to see it later!!!
+\def\dgt@neee{\dg@DX=\thr@@ \dg@DY=\@ne \dg@SIZE=\thr@@
+ \global\dg@LATEXGEOMtrue}%
+\def\dgt@nwww{\dg@DX=-\thr@@ \dg@DY=\@ne \dg@SIZE=\thr@@
+ \global\dg@LATEXGEOMtrue}%
+\def\dgt@swww{\dg@DX=-\thr@@ \dg@DY=\m@ne \dg@SIZE=\thr@@
+ \global\dg@LATEXGEOMtrue}%
+\def\dgt@seee{\dg@DX=\thr@@ \dg@DY=\m@ne \dg@SIZE=\thr@@
+ \global\dg@LATEXGEOMtrue}%
+
diff --git a/macros/latex/contrib/pb-diagram/pb-manual.pdf b/macros/latex/contrib/pb-diagram/pb-manual.pdf
new file mode 100644
index 0000000000..b74f947163
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-manual.pdf
Binary files differ
diff --git a/macros/latex/contrib/pb-diagram/pb-manual.tex b/macros/latex/contrib/pb-diagram/pb-manual.tex
new file mode 100644
index 0000000000..d0a25612cc
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-manual.tex
@@ -0,0 +1,574 @@
+% pb-manual.tex: user's manual for pb-diagram.sty macros
+% Author: Paul Burchard <burchard@pobox.com>
+% Version Number: 5.0
+% Version Date: 20 Oct 1998
+%
+% Copyright (c) 1990, 1992, 1995, 1998 by Paul Burchard
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%
+\def\tooee{LaTeX2e}
+\ifx\fmtname\tooee
+ \documentclass[12pt]{article}\usepackage{pb-diagram}
+\else
+ \documentstyle[12pt,pb-diagram]{article}
+\fi
+\def\diagramversion{5.0}
+\title{User's Guide to the Diagram Environment,
+ Version \diagramversion}
+\author{Paul Burchard (burchard@pobox.com)}
+\def\tfrac#1#2{{\textstyle\frac{#1}{#2}}}
+\begin{document}
+\maketitle
+
+\section{Introduction}
+
+The \verb"diagram" environment allows the
+\ifx\fmtname\tooee\LaTeXe\else\LaTeX\fi{} user to easily
+create complex commutative diagrams, by placing formula nodes
+on a conceptual grid and attaching arrows to them.
+
+The grid used in these diagrams is not a fixed square grid.
+Instead, the environment automatically generates a correctly scaled
+and shaped rectangular grid which will compactly hold the formulas,
+while leaving room for the arrows between them. Moreover, the
+arrows automatically adapt to the spaces between the formulas
+being connected. These features are accomplished with a
+three-pass algorithm that takes into account the width
+and height of every formula.
+
+The arrows in these diagrams are quite flexible.
+Arrows may, in any combination,
+\begin{itemize}
+ \item point in any of a large number of lattice directions;
+ \item span multiple rows and columns of the grid;
+ \item cross other arrows;
+ \item have labels on either or both sides,
+ with adjustable positioning;
+ \item have a variety of head, tail, and shaft styles.
+\end{itemize}
+The fancier arrow styles are made possible by special fonts,
+either from Xy-pic or {\sc LamS}-\TeX, but the package can be used
+without them if necessary.
+
+\pagebreak[3]
+To get a feel for how the package works, here are some examples of
+commands for producing arrows:
+\begin{flushright}
+%
+% Catcode hack to get typewriter `\' `{' `}' inside arg of command
+% where \verb is illegal.
+\begingroup
+ \catcode`|=0 \catcode`[=1 \catcode`]=2
+ \catcode`\{=12 \catcode`\}=12 \catcode`\\=12
+ |gdef|bbb[\]|gdef|lll[{]|gdef|rrr[}]%
+|endgroup
+\def\ttt{\ifx\fmtname\tooee\fontfamily{cmtt}\selectfont\else\tt\fi}%
+%
+% tighten it up a bit to fit on page in 12pt
+\setlength{\dgARROWLENGTH}{1.5em}%
+\noindent
+$\begin{diagram}
+ \node{\makebox[0pt][r]{\ttt\bbb arrow\lll e\rrr \quad}+}
+ \arrow{e} \node{+} \node{+} \node{+} \node{+} \\
+ \node{+} \arrow{s,lr}{\makebox[0pt][r]{\ttt\bbb
+ arrow\lll s,lr\rrr\lll\bbb alpha\rrr\lll\bbb beta\rrr\quad}
+ \alpha}{\beta}
+ \node{+} \node{+} \node{+} \node{+} \\
+ \node{+} \node{+} \node{+} \node{+} \node{+} \\
+ \node{\makebox[0pt][r]{\ttt\bbb
+ arrow[2]\lll ene,t,3,..\rrr\lll f\_0\rrr\quad}+}
+ \arrow[2]{ene,t,3,..}{f_0} \node{+}
+ \node{+} \node{+} \node{+}
+\end{diagram}$
+\end{flushright}
+And here is a simple example diagram:
+\[
+ \begin{diagram}
+ \node{A} \arrow{e,t}{a} \arrow{s,l}{c} \arrow{ese}
+ \node{B^*} \arrow{e,t}{b^*}
+ \node{C} \arrow{s,r}{d} \arrow{wsw} \\
+ \node{D} \arrow[2]{e,b}{e} \node[2]{E}
+ \end{diagram}
+\]
+\begin{verbatim}
+ \[
+ \begin{diagram}
+ \node{A} \arrow{e,t}{a} \arrow{s,l}{c} \arrow{ese}
+ \node{B^*} \arrow{e,t}{b^*}
+ \node{C} \arrow{s,r}{d} \arrow{wsw} \\
+ \node{D} \arrow[2]{e,b}{e} \node[2]{E}
+ \end{diagram}
+ \]
+\end{verbatim}
+
+\pagebreak[4]
+\section{Loading the Diagram Package}
+
+To use the \verb"diagram" environment, begin your
+\ifx\fmtname\tooee\LaTeXe\else\LaTeX2e\fi{} file with:
+\begin{verbatim}
+ \documentclass{DOCSTYLE}\usepackage{pb-diagram}
+\end{verbatim}
+where \verb"DOCSTYLE" is your document style (e.g.,
+\verb"article"). The style file \verb"pb-diagram.sty" needs to
+be placed in one of your system's \TeX{} input directories.
+
+If you are using older versions of \LaTeX{} (2.09 or older), then
+you would begin instead with:
+\begin{verbatim}
+ \documentstyle[pb-diagram]{DOCSTYLE}
+\end{verbatim}
+
+If you have {\em METAFONT\/} available on your system,
+and would like to make use of the additional features
+of the Xy-pic fonts (highly recommended!), then you should
+instead begin your
+\ifx\fmtname\tooee\LaTeXe\else\LaTeX2e\fi{} file with:
+\begin{verbatim}
+ \documentclass{DOCSTYLE}
+ \usepackage[cmtip,arrow]{xy}
+ \usepackage{pb-diagram,pb-xy}
+\end{verbatim}
+This option requires that you have Xy-pic installed on your
+system. Xy-pic is available from your nearest CTAN archive
+(e.g. {\tt http://ctan.tug.org/}) in the CTAN directory
+{\tt macros/generic/diagrams/xypic/}.
+
+An alternative set of fonts which enables some of the
+fancier features is the {\sc LamS}-\TeX{} font set; to
+use it, begin your
+\ifx\fmtname\tooee\LaTeXe\else\LaTeX2e\fi{} file with:
+\begin{verbatim}
+ \documentclass{DOCSTYLE}
+ \usepackage{pb-diagram,lamsarrow,pb-lams}
+\end{verbatim}
+This option requires the {\em METAFONT\/} source files
+\verb"lams1.mf" through \verb"lams5.mf" to be installed.
+
+Installation of additional fonts is system-dependent,
+but will involve moving the \verb".mf" files into the system's
+{\em METAFONT\/} input directory, and then running the
+{\em METAFONT\/} program. This program will generate the
+\verb".tfm" files required for \TeX, and the \verb".pk" or
+\verb".gf" files required for printing and previewing.
+On {\sc unix} systems, the relevant files are typically
+located in \verb"/usr/lib/mf" and \verb"/usr/lib/tex", or
+\verb"/usr/local/lib/mf" and \verb"/usr/local/lib/tex".
+
+If you are having troubling getting \LaTeX{} to properly
+process an older paper which uses this package, check the
+later section, ``Upgrading Papers from Previous Versions.''
+
+\pagebreak[4]
+\section{Using the Diagram Environment}
+\subsection{Overall Structure of the Environment}
+
+The \verb"diagram" environment should be used in
+{\em math mode only}. Its usage is as follows:\footnote{For
+compatibility reasons, the diagram environment accepts and
+optional argument. When this argument is supplied, the grid
+geometry is calculated in exactly the same way as in version~1.0
+of this package. Therefore, manuscripts written with version~1.0
+require no changes to be processed with version~\diagramversion.}
+\begin{verbatim}
+ \begin{diagram}
+ NODE ARROW ARROW ... NODE ARROW ARROW ... .... \\
+ NODE ARROW ARROW ... NODE ARROW ARROW ... .... \\
+ ...
+ NODE ARROW ARROW ... NODE ARROW ARROW ... ....
+ \end{diagram}
+\end{verbatim}
+
+Each \verb"NODE" places a centered formula at a new grid point, and
+each \verb"ARROW" which follows this \verb"NODE" (but precedes the
+next \verb"NODE") will be attached by its tail to the same grid
+point. The diagram will be automatically be given a geometry which
+accomodates these elements, but you can also fine-tune it afterwards
+by hand if it didn't turn out like you imagined
+(see the section on ``Fine-Tuning'' below). We now explain
+how to specify the \verb"NODE"s and \verb"ARROW"s.
+
+\subsection{Formula Nodes}
+
+A \verb"NODE" is specified by the comand:
+\begin{verbatim}
+ \node[NCOLS]{FORMULA}
+\end{verbatim}
+where the optional argument \verb"NCOLS" tells how many grid columns
+to move forward from the previous node (the default is 1). The
+\verb"FORMULA" is the math mode material which you want to place at
+that node in the grid.
+
+The \verb"\\" command moves to the next grid row. As is usual in
+\LaTeX{} arrays, the final row should not end with a \verb"\\", and
+any blank columns at the end of a row need not be entered. More
+generally, it is possible to move \verb"NROWS" rows down at once
+using the command:
+\begin{verbatim}
+ \\[NROWS]
+\end{verbatim}
+
+\subsection{Arrows and their Embellishments}
+
+An \verb"ARROW" is specified by the \verb"\arrow" command, which may
+also be used anywhere in math mode, independent of the
+\verb"diagram" environment. Its usage depends on the number of
+labels desired:
+\begin{verbatim}
+ \arrow[SIZE]{DIRECTION,OPTIONS}
+ \arrow[SIZE]{DIRECTION,ONELABEL,OPTIONS}{LABEL}
+ \arrow[SIZE]{DIRECTION,TWOLABEL,OPTIONS}{LABEL1}{LABEL2}
+\end{verbatim}
+The commas should not have any spaces before or after them, and there
+should not be any extra spaces or commas at the beginning or end of
+the list. The optional integer argument \verb"SIZE" tells how many
+times its normal length the arrow should be made. For example,
+\verb"\arrow[2]{e}" will span two columns, while \verb"\arrow[2]{s}"
+will span two rows.
+
+The arrow \verb"DIRECTION" may be chosen from the compass point
+directions:
+\begin{verbatim}
+ n,e,s,w,ne,nw,se,sw,nne,nnw,sse,ssw,ene,ese,wnw,wsw
+\end{verbatim}
+If the \verb"pb-lams" style has been loaded, the \verb"DIRECTION"
+may also be chosen from this list:
+\begin{verbatim}
+ nee,see,nww,sww,
+ neee,nnne,nnnw,nwww,swww,sssw,ssse,seee,
+ nnnee,nnnww,sssww,sssee,nneee,nnwww,sswww,sseee
+\end{verbatim}
+(For more information about arrow directions, see the sections
+on ``Fine Tuning'' and ``Customizing'' below.)
+
+Any \verb"LABEL"s present are math mode material. The
+\verb"ONELABEL" specifier may be chosen from:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt t}\> top\\
+ \>{\tt b}\> bottom\\
+ \>{\tt l}\> left (only for use with vertical arrows)\\
+ \>{\tt r}\> right (only for use with vertical arrows)
+\end{tabbing}
+The \verb"TWOLABEL" specifier may be chosen from:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt tb}\> top and bottom\\
+ \>{\tt lr}\> left and right (only for use with vertical arrows)
+\end{tabbing}
+
+The \verb"OPTION"s describe the style of the arrow shaft, the symbols
+to be used at the head and tail of the arrow, and the positions of
+the labels. The defaults are: a simple line shaft, a single simple
+arrowhead, no special tail symbol, and labels positioned at the
+midpoint of the arrow shaft. The \verb"OPTION"s may be selected from
+the lists which follow. Most of the options can be combined with
+others; however, not all combinations make sense. In addition,
+options marked with~(*) are only available with
+either \verb"pb-xy" or \verb"pb-lams" loaded;
+and options marked with~(**) are only available with \verb"pb-xy" loaded.
+Shaft options are:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt ..}\> dotted or dashed arrow shaft\\
+ \>{\tt =}\> double line shaft* (``equals sign'')\\
+ \>{\tt !}\> invisible arrow shaft
+\end{tabbing}
+Arrow head options are:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt -}\> no arrow heads\\
+ \>{\tt <>}\> arrow heads on both ends\\
+ \>{\tt A}\> double arrow head*\\
+ \>{\tt '}\> left half of arrow head*\\
+ \>{\tt `}\> right half of arrow head*
+\end{tabbing}
+Arrow tail options are:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt V}\> single arrow tail*\\
+ \>{\tt J}\> left fish hook arrow tail*\\
+ \>{\tt L}\> right fish hook arrow tail*\\
+ \>{\tt S}\> squiggle arrow tail*
+ \>{\tt T}\> ``mapsto'' arrow tail**
+\end{tabbing}
+In the default configuration, the label positioning options are:
+\begin{tabbing}
+ {\tt xxx}\={\tt x}\qquad\=\kill
+ \>{\tt 1}\> 1/4 of way from tail end\\
+ \>{\tt 2}\> 2/4 of way from tail end (the default)\\
+ \>{\tt 3}\> 3/4 of way from tail end
+\end{tabbing}
+However, if more flexibility is needed, there is an
+\verb"ARROWPARTS" parameter which specifies how many pieces the arrow
+will be divided into to determine the meaning of the label
+positioning option. (In general, the positioning option may be any
+single digit.) For example, to position a label 5/6 of the way from
+the tail end of the arrow, you would use commands like these:
+\begin{verbatim}
+ \dgARROWPARTS=6
+ \begin{diagram}
+ ... \arrow{e,t,5}{MYLABEL} ...
+ \end{diagram}
+\end{verbatim}
+\verb"ARROWPARTS" should be even, so that ordinary labels can
+be properly positioned at the half-way point.
+
+
+\section{Fine Tuning the Diagrams}
+
+Many of the parameters used by the \verb"diagram" environment are
+accessible to you and documented here so that the existing features
+can be fine-tuned.
+
+The most important parameter is \verb"\dgARROWLENGTH", which
+specifies the minimum length for all arrows. The \verb"diagram"
+environment will independently adjust the horizontal and vertical
+scales of its rectangular grid until at least that much room is
+available for each arrow. This calculation takes into account
+the room that must be set aside for the each of the two formulas
+being connected by an arrow. The default minimum arrow length is
+\begin{verbatim}
+ \dgARROWLENGTH=2.5em
+\end{verbatim}
+The \verb"\arrow" command may also be used outside of the diagram
+environment; in that case, its length is instead controlled by
+the parameter
+\begin{verbatim}
+ \dgTEXTARROWLENGTH=1.1em
+\end{verbatim}
+
+Some anomalies you may encounter: the collision of formulas is not
+checked unless an arrow connects them. Therefore, if two formulas
+turn out to overlap you can just connect them with an invisible arrow.
+
+Another problem may occur when you simulate ``arrow fragments''
+using a finer grid. The arrow-length checker does not know what
+is a ``fragment'' and so it will force each fragment to be
+\verb"\dgARROWLENGTH" long. The easiest way to fix this is to
+locally divide \verb"\dgARROWLENGTH" by the scale factor between
+the coarse and fine grids. For example:
+{\samepage
+\begin{verbatim}
+ \divide\dgARROWLENGTH by2
+ \begin{diagram}
+ \node[2]{A}\arrow[2]{s}\\
+ \node{B}\arrow{e,-} \node{}\arrow{e,t}{\alpha} \node{C}\\
+ \node[2]{D}
+ \end{diagram}
+\end{verbatim}
+\[
+ \divide\dgARROWLENGTH by2
+ \begin{diagram}
+ \node[2]{A}\arrow[2]{s}\\
+ \node{B}\arrow{e,-} \node{}\arrow{e,t}{\alpha} \node{C}\\
+ \node[2]{D}
+ \end{diagram}
+\]
+}
+
+The space set aside for a formula
+further includes padding to keep the arrows from actually touching the
+formulas. The padding increases the apparent horizontal size of
+each formula by \verb"\dgHORIZPAD" and the apparent vertical size
+by \verb"\dgVERTPAD". The default values of these parameters are:
+\begin{verbatim}
+ \dgHORIZPAD=1em
+ \dgVERTPAD=2ex
+\end{verbatim}
+
+The ratio of the horizontal and vertical scales of the grid,
+known as the {\em aspect ratio\/}, cannot be completely
+arbitrary because of the slope limitations of font-based arrows.
+In order that the full required set of compass-point directions be
+available, the optimal calculated aspect ratio will be approximated
+so as to be compatible with the available fonts. In plain
+\LaTeX{} mode the possibile aspect ratios are half-integers up to~2,
+while in {\sc LamS}-\TeX{} mode they are half-integers up to~3.
+
+\verb"\dgLABELOFFSET" is the (approximate) distance which will
+separate labels from their arrows. An arrow is divided into
+\verb"\dgARROWPARTS" parts for custom positioning of labels along the
+arrow (the only sensible choices for this number are 2,4,6,8,10). By
+default,
+\begin{verbatim}
+ \dgLABELOFFSET=.7ex
+ \dgARROWPARTS=4
+\end{verbatim}
+
+The following two parameters regulate the appearance of dotted arrows
+in plain \LaTeX{} mode:
+\begin{verbatim}
+ \dgDOTSPACING=0.35em
+ \dgDOTSIZE=1.5\fontdimen8\tenln
+\end{verbatim}
+
+By default, nodes are typeset \verb"\displaystyle", and labels
+\verb"\scriptstyle". This is controlled by the commands
+\verb"\dgeverynode" (which is executed prior to the formula of each
+node) and \verb"\dgeverylabel" (which is executed prior to the
+formula of each label). They can be changed with
+\verb"\renewcommand", like this:
+\begin{verbatim}
+ \renewcommand{\dgeverynode}{\displaystyle}
+ \renewcommand{\dgeverylabel}{\scriptstyle}
+\end{verbatim}
+These commands may alternatively be defined to take one argument,
+which will be the content of the node or label.
+
+
+\section{Customizing the Package}
+
+The \verb"diagram" environment was designed in a modular way to make
+it easy to add features.
+
+To add a new option to the \verb"\arrow" command---say
+\verb"**"---you need only define a command named \verb"\dgo@**" which
+sets the desired parameters. Let's say you want the \verb"**" option
+to make \verb"\arrow" use a custom arrow design of yours. Since
+\verb"\dg@VECTOR" is the parameter that governs the arrow-drawing
+code, you would say
+\begin{verbatim}
+ \@namedef{dgo@**}{\let\dg@VECTOR=\myamazingvector}
+\end{verbatim}
+where \verb"\myamazingvector" is your custom arrow code (analogous
+to \LaTeX's \verb"\vector" command). Note that if this definition is
+not in a style file, it needs to be bracketed with
+\verb"\makeatletter...\makeatother". You can then use your custom
+arrow style like any other option:
+\begin{verbatim}
+ \arrow{sw,t,**}{\Gamma}
+\end{verbatim}
+
+Adding new arrow direction codes is done by defining commands of the
+form \verb"\dgt@DIRCODE". These commands set \verb"\vector"-like
+parameters to specify the arrow direction (thinking of the arrow as
+laid out on a grid where the basic rectangle is unit wide and one
+unit high). For example:
+\begin{verbatim}
+ \@namedef{dgt@sse}{\dg@DX=1 \dg@DY=-2 \dg@SIZE=1 }
+\end{verbatim}
+
+You can also customize the way the grid geometry is computed by
+redefining the \verb"\dggeometry" command. It must set
+the integer parameters \verb"\dg@XGRID" and \verb"\dg@YGRID" and
+the length parameter \verb"\unitlength". Each grid rectangle
+will then be 1000\verb"\dg@XGRID" by 1000\verb"\dg@YGRID"
+\verb"\unitlength"s in size. The assigned values of
+\verb"\dg@XGRID" and \verb"\dg@YGRID" should be smallish numbers
+(to avoid arithmetic overflow) with \verb"XGRID":\verb"YGRID"
+as the desired aspect ratio. As inputs,
+you should use the pre-supplied values of \verb"\dg@XGRID" and
+\verb"\dg@YGRID", which are the calculated minimum width and
+height that grid rectangles must have, measured in scaled
+points (sp).
+
+In plain \LaTeX{} mode, the aspect ratio must be a half-integer
+between~$\tfrac12$ and~2 (or the inverse of such) in order to
+support the basic 16 compass directions. In {\sc LamS}-\TeX{} mode,
+the aspect ratio need only be a half-integer between~$\tfrac12$
+and~3 in order to support these same basic directions; and when
+the aspect ratio is chosen from these values, almost all the
+arrow directions $(p,q)$ with $\max(|p|,|q|)\le 3$ are supported.
+The exceptions are that arrows of type $(\pm 3,\,\pm 2)$ are
+only rendered approximately in some aspect ratios, and that
+arrows of type $(\pm 3,\,\pm 1)$ are not supported unless
+the aspect ratio is a half-integer between~$\tfrac12$ and~2.
+The \verb"\dggeometry" macro for {\sc LamS}-\TeX{} mode
+{\em automatically\/} detects when it needs to restrict the
+aspect ratio because of a type $(\pm 3,\,\pm 1)$ arrow in
+the diagram.
+
+
+\section{Upgrading Papers from Previous Versions}
+
+Some slightly incompatible changes have been made during
+the evolution of this package.
+
+Beginning with version~3.5, the files and names of the packages
+were reorganized to simplify electronic publication. Here is a
+dictionary to make the translation:
+\begin{center}
+\begin{tabular}{|l|l|} \hline
+ Old Packages & New Packages \\ \hline
+ \tt diagram & \tt pb-diagram \\
+ \tt lamsarrow,diagram & \tt pb-diagram,lamsarrow,pb-lams \\ \hline
+\end{tabular}
+\end{center}
+The order of the packages must be as shown in the table.
+
+Beginning with version~4.0, a bug which caused occasional diagrams
+to come out twice too large was eliminated. If you have an old paper
+which was tuned for the earlier geometry calculation, you can get
+the previous behavior back by including the command
+\verb"\let\dggeometry=\dgoldgeometry" in the document's preamble.
+
+
+\section{Implementation Notes}
+
+All command names defined in the \verb"pb-diagram.sty" style file
+begin with ``\verb"\dg"'', except \verb"\diagram",
+\verb"\enddiagram", \verb"\node", \verb"\arrow",
+\verb"\\", and the \LaTeX{} enhancements \verb"\newoptcommand",
+\verb"\newoptenvironment", \verb"\renewoptcommand", and
+\verb"\renewoptenvironment". All private commands contain an `@' in
+their names. The commands \verb"\node" and \verb"\\" are only defined
+within the \verb"diagram" environment. Spaces following the
+\verb"\end{diagram}" are ignored.
+
+In all the macro files in this package, lines have been limited to
+less than~70 characters to avoid problems with electronic mailing.
+
+
+\section{Copyright and Acknowledgments}
+
+The \verb"pb-diagram" package is
+copyright \copyright\ 1990, 1992, 1995, 1998 by Paul Burchard.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+The file \verb"pb-xy.sty" is
+copyright \copyright\ 1998 by Bill Richter,
+and is also distributed under the terms of the GNU General Public License.
+
+The fonts \verb"lams1.mf" through \verb"lams5.mf", as well as the
+macros in \verb"lamsarrow.sty", are copyright \copyright\ 1989,
+1990, 1991 by The Texplorators Corporation, 1572 West Gray \#377,
+Houston, TX 77019--4948. Beginning with version 4.1 of this package,
+the fonts include a patch by Ingo Hadan which makes them compatible
+with recent versions of \verb"cmbase.mf", and in particular, eliminating
+a division-by-zero error that caused certain glyphs to appear wildly deformed.
+
+I would like to acknowledge inspiration from a macro package of
+Marc-Paul van der Hulst. Bill Richter was of major help to me with
+his topological torture-testing of this package, and he provided
+some spectacular example diagrams for distribution with this package.
+Dan Christensen made many good suggestions which were incorporated
+into version 4.0.
+
+\end{document}
diff --git a/macros/latex/contrib/pb-diagram/pb-xy.sty b/macros/latex/contrib/pb-diagram/pb-xy.sty
new file mode 100644
index 0000000000..f5cadd5a51
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/pb-xy.sty
@@ -0,0 +1,133 @@
+% pb-xy.sty: Xypic arrow enhancements for pb-diagram.sty
+% Author: Bill Richter <richter@math.nwu.edu>
+% Version Number: 5.0
+% Version Date: 20 Oct 1998
+%
+% Copyright (c) 1998 by Bill Richter
+%
+% This program is free software; you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation; either version 2 of the License, or
+% (at your option) any later version.
+%
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with this program; if not, write to the Free Software
+% Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+%
+% This style file should be loaded as follows:
+% \usepackage[cmtip,arrow]{xy}
+% \usepackage{pb-diagram,pb-xy}
+%
+% This code adds to the "diagram" environment the use of
+% Xypic fancy arrow heads and tails, as well as additional arrow
+% directions. Most of the options defined here can be
+% combined arbitrarily.
+%
+
+\makeatother
+\def\PBXYarat{\ar@}%
+\makeatletter
+
+\newcount\PBXYxsize
+\newcount\PBXYysize
+
+\def\pbxy@tail{{}}%
+\def\pbxy@mid{-}%
+\def\pbxy@head{>}%
+
+\@namedef{dgo@}{%
+ \let\dg@VECTOR=\PBXYvector
+ \def\pbxy@tail{{}}\def\pbxy@mid{-}\def\pbxy@head{>}%
+ \dg@LBLPOS=\dgARROWPARTS \divide\dg@LBLPOS\tw@}% from pb-diagram.sty
+
+\@namedef{dgo@-}{\def\pbxy@head{{}}}%
+\@namedef{dgo@!}{\def\pbxy@mid{{}}\def\pbxy@head{{}}%
+ \let\dg@VECTOR=\dg@novector}% from pb-diagram.sty
+\@namedef{dgo@..}{\def\pbxy@mid{.}}%
+\@namedef{dgo@--}{\def\pbxy@mid{--}}%
+\@namedef{dgo@<>}{\def\pbxy@tail{<}\def\pbxy@head{>}}%
+\@namedef{dgo@=}{\def\pbxy@mid{2{-}}\def\pbxy@head{{}}}%
+\@namedef{dgo@'}{\def\pbxy@head{^{>}}}%
+\@namedef{dgo@`}{\def\pbxy@head{_{>}}}%
+\@namedef{dgo@A}{\def\pbxy@head{>>}}%
+\@namedef{dgo@V}{\def\pbxy@tail{>}}%
+\@namedef{dgo@J}{\def\pbxy@tail{^{(}}}%
+\@namedef{dgo@L}{\def\pbxy@tail{_{(}}}%
+\@namedef{dgo@S}{\def\pbxy@mid{~}}%
+\@namedef{dgo@T}{\def\pbxy@tail{|}}%
+
+\def\PBXYvector(#1,#2)#3{%
+ \PBXYxsize#3\relax
+ \ifnum#1<\z@\multiply\PBXYxsize\m@ne\fi
+ \PBXYysize\PBXYxsize\relax
+ \ifnum#1=\z@
+ \PBXYxsize\z@
+ \ifnum#2<\z@\multiply\PBXYysize\m@ne\fi
+ \else
+ \multiply\PBXYysize#2\relax\divide\PBXYysize#1\relax
+ \fi
+ \edef\PBXYarrow{\noexpand\PBXYarat{\pbxy@tail\pbxy@mid\pbxy@head}}%
+ \ifnum#1<\z@
+ \makebox(\PBXYxsize,\PBXYysize){%
+ \begin{xy} 0;<\unitlength,\z@>:%
+ \PBXYarrow(\PBXYxsize,\PBXYysize)%
+ \end{xy}%
+ }%
+ \else
+ {\begin{xy} <\unitlength,\z@>:%
+ \PBXYarrow(\PBXYxsize,\PBXYysize)%
+ \end{xy}}%
+ \fi
+}
+
+\def\dgt@nee{\dg@DX=\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@see{\dg@DX=\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+\def\dgt@nww{\dg@DX=-\tw@ \dg@DY=\@ne \dg@SIZE=\tw@}%
+\def\dgt@sww{\dg@DX=-\tw@ \dg@DY=\m@ne \dg@SIZE=\tw@}%
+\def\dgt@neee{\dg@DX=\thr@@ \dg@DY=\@ne \dg@SIZE=\thr@@}%
+\def\dgt@nnne{\dg@DX=\@ne \dg@DY=\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@nnnw{\dg@DX=\m@ne \dg@DY=\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@nwww{\dg@DX=-\thr@@ \dg@DY=\@ne \dg@SIZE=\thr@@}%
+\def\dgt@swww{\dg@DX=-\thr@@ \dg@DY=\m@ne \dg@SIZE=\thr@@}%
+\def\dgt@sssw{\dg@DX=\m@ne \dg@DY=-\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@ssse{\dg@DX=\@ne \dg@DY=-\thr@@ \dg@SIZE=\@ne}%
+\def\dgt@seee{\dg@DX=\thr@@ \dg@DY=\m@ne \dg@SIZE=\thr@@}%
+\def\dgt@nneee{\dg@DX=\thr@@ \dg@DY=\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@nnnee{\dg@DX=\tw@ \dg@DY=\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@nnnww{\dg@DX=-\tw@ \dg@DY=\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@nnwww{\dg@DX=-\thr@@ \dg@DY=\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@sswww{\dg@DX=-\thr@@ \dg@DY=-\tw@ \dg@SIZE=\thr@@}%
+\def\dgt@sssww{\dg@DX=-\tw@ \dg@DY=-\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@sssee{\dg@DX=\tw@ \dg@DY=-\thr@@ \dg@SIZE=\tw@}%
+\def\dgt@sseee{\dg@DX=\thr@@ \dg@DY=-\tw@ \dg@SIZE=\thr@@}%
+
+% approximate aspect ratio by half-integer betw 1/2 and 4
+%
+\def\dggeometry{
+ \dg@ZTEMP=\dg@XGRID \multiply\dg@ZTEMP\tw@
+ \ifnum\dg@YGRID=\z@ \dg@ZTEMP=\tw@
+ \else \divide\dg@ZTEMP\dg@YGRID \fi
+ \ifnum\dg@ZTEMP>8\relax \dg@ZTEMP=8\relax \fi
+ \ifnum\dg@ZTEMP<\@ne \dg@ZTEMP=\@ne \fi
+ \unitlength=1sp\relax
+ \ifnum\dg@ZTEMP<\tw@
+ % round aspect ratio up toward 2:2, widen rect
+ \advance\dg@ZTEMP\@ne
+ \multiply\unitlength\dg@YGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@YGRID
+ \else
+ % round aspect ratio down toward 2:2, tallen rect
+ \multiply\unitlength\dg@XGRID
+ \dg@XGRID=\dg@ZTEMP \dg@YGRID=\tw@
+ \dg@rmcommondiv\tw@\dg@XGRID\dg@YGRID
+ \divide\unitlength\dg@XGRID
+ \fi
+ \divide\unitlength\@m\relax}%
+
diff --git a/macros/latex/contrib/pb-diagram/tfm b/macros/latex/contrib/pb-diagram/tfm
new file mode 120000
index 0000000000..54c9ef43ec
--- /dev/null
+++ b/macros/latex/contrib/pb-diagram/tfm
@@ -0,0 +1 @@
+../../../lamstex/tfm \ No newline at end of file