%  This should appear in a file named catmac.sty
%         Copyright 1988,1989 Michael Barr
%         Department of Mathematics and Statistics
%         McGill University
%         805 Sherbrooke St., W
%         Montreal, Quebec, Canada
%         H3P 1S4
%
%         inhb@mcgillb.bitnet
%
%         All commercial rights reserved.  May be freely distributed
%         and used with the following exceptions:
%         1. No commercial use without explicit permission.
%         2. It may not be used by any employee of a telephone
%         company.
%         3. It may not be distributed without this notice.
%
%         Last revised 89-12-11


\newcount \coefa
\newcount \coefb
\newcount \coefc
\newcount\tempcounta
\newcount\tempcountb
\newcount\tempcountc
\newcount\tempcountd
\newcount\xext
\newcount\yext
\newcount\xoff
\newcount\yoff
\newcount\gap%
\newcount\arrowtypea
\newcount\arrowtypeb
\newcount\arrowtypec
\newcount\arrowtyped
\newcount\arrowtypee
\newcount\height
\newcount\width
\newcount\xpos
\newcount\ypos
\newcount\run
\newcount\rise
\newcount\arrowlength
\newcount\halflength
\newcount\arrowtype
\newdimen\tempdimen
\newdimen\xlen
\newdimen\ylen
\newsavebox{\tempboxa}%
\newsavebox{\tempboxb}%
\newsavebox{\tempboxc}%


\newcount \repetitions
\def\repto#1{%
\mathrel{
\hbox{$
\repetitions=0%
\loop\ifnum\repetitions<#1%
    \advance \repetitions by 1%
    \relbar\joinrel
\repeat
\rightarrow
$}}}
\def\to{\repto0}
\def\To{\repto1}
\def\two{\reptwo0}
\def\Two{\reptwo1}
\def\tofro{\mathrel{\vcenter{\hbox{\oalign
{$\longrightarrow$\crcr$\longleftarrow$}}}}}

\def\epi{\mathrel{\mathchar"221\mkern -12mu\mathchar"221}}
\def\leftepi{\mathrel{\mathchar"220\mkern -12mu\mathchar"220}}
\def\mon{\mathrel{\m@th\hbox to
      14.6pt{\lasyb\char'51\hskip-2.1pt$\arrext$\hss
$\mathord\rightarrow$}}} % width of \epi
\def\leftmono{\mathrel{\m@th\hbox to
14.6pt{$\mathord\leftarrow$\hss$\arrext$\hskip-2.1pt\lasyb\char'50%
}}} % width of \epi
\font\lasyb=lasyb10 scaled \magstephalf % for \mon
\mathchardef\arrext="0200       % amr minus for arrow extension (see \into)


\setlength{\unitlength}{.01em}%
\def\settypes(#1,#2,#3){\arrowtypea#1 \arrowtypeb#2 \arrowtypec#3}
\def\settoheight#1#2{\setbox\@tempboxa\hbox{#2}#1\ht\@tempboxa\relax}%
\def\settodepth#1#2{\setbox\@tempboxa\hbox{#2}#1\dp\@tempboxa\relax}%
\def\settokens[#1`#2`#3`#4]{%
     \def\tokena{#1}\def\tokenb{#2}\def\tokenc{#3}\def\tokend{#4}}
\def\setsqparms[#1`#2`#3`#4;#5`#6]{%
\arrowtypea #1
\arrowtypeb #2
\arrowtypec #3
\arrowtyped #4
\width #5
\height #6
}
\def\setpos(#1,#2){\xpos=#1 \ypos#2}

\def\bfig{\begin{picture}(\xext,\yext)(\xoff,\yoff)}
\def\efig{\end{picture}}

\def\putbox(#1,#2)#3{\put(#1,#2){\makebox(0,0){$#3$}}}

\def\settriparms[#1`#2`#3;#4]{\settripairparms[#1`#2`#3`1`1;#4]}%

\def\settripairparms[#1`#2`#3`#4`#5;#6]{%
\arrowtypea #1
\arrowtypeb #2
\arrowtypec #3
\arrowtyped #4
\arrowtypee #5
\width #6
\height #6
}

\def\resetparms{\settripairparms[1`1`1`1`1;500]\width 500}%default values%

\resetparms

\def\mvector(#1,#2)#3{%%
\put(0,0){\vector(#1,#2){#3}}%
\put(0,0){\vector(#1,#2){30}}%
}
\def\evector(#1,#2)#3{{%%
\arrowlength #3
\put(0,0){\vector(#1,#2){\arrowlength}}%
\advance \arrowlength by-30
\put(0,0){\vector(#1,#2){\arrowlength}}%
}}

\def\horsize#1#2{%
\settowidth{\tempdimen}{$#2$}%
#1=\tempdimen
\divide #1 by\unitlength
}

\def\vertsize#1#2{%
\settoheight{\tempdimen}{$#2$}%
#1=\tempdimen
\settodepth{\tempdimen}{$#2$}%
\advance #1 by\tempdimen
\divide #1 by\unitlength
}

\def\vertadjust[#1`#2`#3]{%
\vertsize{\tempcounta}{#1}%
\vertsize{\tempcountb}{#2}%
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
\divide\tempcounta by2
\vertsize{\tempcountb}{#3}%
\ifnum \tempcountb>0 \advance \tempcountb by20 \fi
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
}

\def\horadjust[#1`#2`#3]{%
\horsize{\tempcounta}{#1}%
\horsize{\tempcountb}{#2}%
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
\divide\tempcounta by20
\horsize{\tempcountb}{#3}%
\ifnum \tempcountb>0 \advance \tempcountb by60 \fi
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
}

% In this procedure, #1 is the paramater that sticks out all the way,
% #2 sticks out the least and #3 is a label sticking out half way.  #4 is
% the amount of the offset.

\def\sladjust[#1`#2`#3]#4{%
\tempcountc=#4
\horsize{\tempcounta}{#1}%
\divide \tempcounta by2
\horsize{\tempcountb}{#2}%
\divide \tempcountb by2
\advance \tempcountb by-\tempcountc
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb\fi
\divide \tempcountc by2
\horsize{\tempcountb}{#3}%
\advance \tempcountb by-\tempcountc
\ifnum \tempcountb>0 \advance \tempcountb by80\fi
\ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb\fi
\advance\tempcounta by20
}

\def\putvector(#1,#2)(#3,#4)#5#6{{%
\xpos=#1
\ypos=#2
\run=#3
\rise=#4
\arrowlength=#5
\arrowtype=#6
\ifnum \arrowtype<0
    \ifnum \run=0
        \advance \ypos by-\arrowlength
    \else
        \tempcounta \arrowlength
        \multiply \tempcounta by\rise
        \divide \tempcounta by\run
        \ifnum\run>0
            \advance \xpos by\arrowlength
            \advance \ypos by\tempcounta
        \else
            \advance \xpos by-\arrowlength
            \advance \ypos by-\tempcounta
        \fi
    \fi
    \multiply \arrowtype by-1
    \multiply \rise by-1
    \multiply \run by-1
\fi
\ifnum \arrowtype=1
    \put(\xpos,\ypos){\vector(\run,\rise){\arrowlength}}%
\else\ifnum \arrowtype=2
    \put(\xpos,\ypos){\mvector(\run,\rise)\arrowlength}%
\else\ifnum\arrowtype=3
    \put(\xpos,\ypos){\evector(\run,\rise){\arrowlength}}%
\fi\fi\fi
}}

\def\putsplitvector(#1,#2)#3#4{%%
\xpos #1
\ypos #2
\arrowtype #4
\halflength #3
\arrowlength #3
\gap 140
\advance \halflength by-\gap
\divide \halflength by2
\ifnum \arrowtype=1
    \put(\xpos,\ypos){\line(0,-1){\halflength}}%
    \advance\ypos by-\halflength
    \advance\ypos by-\gap
    \put(\xpos,\ypos){\vector(0,-1){\halflength}}%
\else\ifnum \arrowtype=2
    \put(\xpos,\ypos){\line(0,-1)\halflength}%
    \put(\xpos,\ypos){\vector(0,-1)3}%
    \advance\ypos by-\halflength
    \advance\ypos by-\gap
    \put(\xpos,\ypos){\vector(0,-1){\halflength}}%
\else\ifnum\arrowtype=3
    \put(\xpos,\ypos){\line(0,-1)\halflength}%
    \advance\ypos by-\halflength
    \advance\ypos by-\gap
    \put(\xpos,\ypos){\evector(0,-1){\halflength}}%
\else\ifnum \arrowtype=-1
    \advance \ypos by-\arrowlength
    \put(\xpos,\ypos){\line(0,1){\halflength}}%
    \advance\ypos by\halflength
    \advance\ypos by\gap
    \put(\xpos,\ypos){\vector(0,1){\halflength}}%
\else\ifnum \arrowtype=-2
    \advance \ypos by-\arrowlength
    \put(\xpos,\ypos){\line(0,1)\halflength}%
    \put(\xpos,\ypos){\vector(0,1)3}%
    \advance\ypos by\halflength
    \advance\ypos by\gap
    \put(\xpos,\ypos){\vector(0,1){\halflength}}%
\else\ifnum\arrowtype=-3
    \advance \ypos by-\arrowlength
    \put(\xpos,\ypos){\line(0,1)\halflength}%
    \advance\ypos by\halflength
    \advance\ypos by\gap
    \put(\xpos,\ypos){\evector(0,1){\halflength}}%
\fi\fi\fi\fi\fi\fi
}

\def\putmorphism(#1)(#2,#3)[#4`#5`#6]#7#8#9{{%
\run #2
\rise #3
\ifnum\rise=0
  \puthmorphism(#1)[#4`#5`#6]{#7}{#8}{#9}%
\else\ifnum\run=0
  \putvmorphism(#1)[#4`#5`#6]{#7}{#8}{#9}%
\else
\setpos(#1)%
\arrowlength #7
\arrowtype #8
\ifnum\run=0
\else\ifnum\rise=0
\else
\ifnum\run>0
    \coefa=1
\else
   \coefa=-1
\fi
\ifnum\arrowtype>0
   \coefb=0
   \coefc=-1
\else
   \coefb=\coefa
   \coefc=1
   \arrowtype=-\arrowtype
\fi
\width=2
\multiply \width by\run
\divide \width by\rise
\ifnum \width<0  \width=-\width\fi
\advance\width by60
\if l#9 \width=-\width\fi
\putbox(\xpos,\ypos){#4}%            %node 1
{\multiply \coefa by\arrowlength%      %node 2
\advance\xpos by\coefa
\multiply \coefa by\rise
\divide \coefa by\run
\advance \ypos by\coefa
\putbox(\xpos,\ypos){#5} }%
{\multiply \coefa by\arrowlength%      %label
\divide \coefa by2
\advance \xpos by\coefa
\advance \xpos by\width
\multiply \coefa by\rise
\divide \coefa by\run
\advance \ypos by\coefa
\if l#9%
   \put(\xpos,\ypos){\makebox(0,0)[r]{$#6$}}%
\else\if r#9%
   \put(\xpos,\ypos){\makebox(0,0)[l]{$#6$}}%
\fi\fi }%
{\multiply \rise by-\coefc%             %arrow
\multiply \run by-\coefc
\multiply \coefb by\arrowlength
\advance \xpos by\coefb
\multiply \coefb by\rise
\divide \coefb by\run
\advance \ypos by\coefb
\multiply \coefc by70
\advance \ypos by\coefc
\multiply \coefc by\run
\divide \coefc by\rise
\advance \xpos by\coefc
\multiply \coefa by140
\multiply \coefa by\run
\divide \coefa by\rise
\advance \arrowlength by\coefa
\ifnum \arrowtype=1
   \put(\xpos,\ypos){\vector(\run,\rise){\arrowlength}}%
\else\ifnum\arrowtype=2
   \put(\xpos,\ypos){\mvector(\run,\rise){\arrowlength}}%
\else\ifnum\arrowtype=3
   \put(\xpos,\ypos){\evector(\run,\rise){\arrowlength}}%
\fi\fi\fi}\fi\fi\fi\fi}}

\def\puthmorphism(#1,#2)[#3`#4`#5]#6#7#8{{%
\xpos #1
\ypos #2
\width #6
\arrowlength #6
\putbox(\xpos,\ypos){#3\vphantom{#4}}%
{\advance \xpos by\arrowlength
\putbox(\xpos,\ypos){\vphantom{#3}#4}}%
\horsize{\tempcounta}{#3}%
\horsize{\tempcountb}{#4}%
\divide \tempcounta by2
\divide \tempcountb by2
\advance \tempcounta by30
\advance \tempcountb by30
\advance \xpos by\tempcounta
\advance \arrowlength by-\tempcounta
\advance \arrowlength by-\tempcountb
\putvector(\xpos,\ypos)(1,0){\arrowlength}{#7}%
\divide \arrowlength by2
\advance \xpos by\arrowlength
\vertsize{\tempcounta}{#5}%
\divide\tempcounta by2
\advance \tempcounta by20
\if a#8 %
   \advance \ypos by\tempcounta
   \putbox(\xpos,\ypos){#5}%
\else
   \advance \ypos by-\tempcounta
   \putbox(\xpos,\ypos){#5}%
\fi}}

\def\putvmorphism(#1,#2)[#3`#4`#5]#6#7#8{{%
\xpos #1
\ypos #2
\arrowlength #6
\arrowtype #7
\settowidth{\xlen}{$#5$}%
\putbox(\xpos,\ypos){#3}%
{\advance \ypos by-\arrowlength
\putbox(\xpos,\ypos){#4}}%
{\advance\arrowlength by-140
\advance \ypos by-70
\ifdim\xlen>0pt
   \if m#8%
      \putsplitvector(\xpos,\ypos){\arrowlength}{\arrowtype}%
   \else
      \putvector(\xpos,\ypos)(0,-1){\arrowlength}{\arrowtype}%
   \fi
\else
   \putvector(\xpos,\ypos)(0,-1){\arrowlength}{\arrowtype}%
\fi}%
\ifdim\xlen>0pt
   \divide \arrowlength by2
   \advance\ypos by-\arrowlength
   \if l#8%
      \advance \xpos by-40
      \put(\xpos,\ypos){\makebox(0,0)[r]{$#5$}}%
   \else\if r#8%
      \advance \xpos by40
      \put(\xpos,\ypos){\makebox(0,0)[l]{$#5$}}%
   \else
      \putbox(\xpos,\ypos){#5}%
   \fi\fi
\fi
}}

\def\topadjust[#1`#2`#3]{%
\yoff=10
\vertadjust[#1`#2`{#3}]%
\advance \yext by\tempcounta
\advance \yext by 10
}
\def\botadjust[#1`#2`#3]{%
\vertadjust[#1`#2`{#3}]%
\advance \yext by\tempcounta
\advance \yoff by-\tempcounta
}
\def\leftadjust[#1`#2`#3]{%
\xoff=0
\horadjust[#1`#2`{#3}]%
\advance \xext by\tempcounta
\advance \xoff by-\tempcounta
}
\def\rightadjust[#1`#2`#3]{%
\horadjust[#1`#2`{#3}]%
\advance \xext by\tempcounta
}
\def\rightsladjust[#1`#2`#3]{%
\sladjust[#1`#2`{#3}]{\width}%
\advance \xext by\tempcounta
}
\def\leftsladjust[#1`#2`#3]{%
\xoff=0
\sladjust[#1`#2`{#3}]{\width}%
\advance \xext by\tempcounta
\advance \xoff by-\tempcounta
}
\def\adjust[#1`#2;#3`#4;#5`#6;#7`#8]{%
\topadjust[#1``{#2}]
\leftadjust[#3``{#4}]
\rightadjust[#5``{#6}]
\botadjust[#7``{#8}]}

\def\putsquarep<#1>(#2)[#3;#4`#5`#6`#7]{{%
\setsqparms[#1]%
\setpos(#2)%
\settokens[#3]%
\puthmorphism(\xpos,\ypos)[\tokenc`\tokend`{#7}]{\width}{\arrowtyped}b%
\advance\ypos by \height
\puthmorphism(\xpos,\ypos)[\tokena`\tokenb`{#4}]{\width}{\arrowtypea}a%
\putvmorphism(\xpos,\ypos)[``{#5}]{\height}{\arrowtypeb}l%
\advance\xpos by \width
\putvmorphism(\xpos,\ypos)[``{#6}]{\height}{\arrowtypec}r%
}}

\def\putsquare{\@ifnextchar <{\putsquarep}{\putsquarep%
   <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped;\width`\height>}}
\def\square{\@ifnextchar< {\squarep}{\squarep
   <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped;\width`\height>}}
                                                      %         #6
\def\squarep<#1>[#2`#3`#4`#5;#6`#7`#8`#9]{{%          %     #2------>#3
\setsqparms[#1]%                                      %      |       |
\xext=\width                                          %      |       |
\yext=\height                                         %    #7|       |#8
\topadjust[#2`#3`{#6}]%                               %      |       |
\botadjust[#4`#5`{#9}]%                               %      |       |
\leftadjust[#2`#4`{#7}]%                              %      v       v
\rightadjust[#3`#5`{#8}]%                             %     #4------>#5
\begin{picture}(\xext,\yext)(\xoff,\yoff)%                      #9
\putsquarep<\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped;\width`\height>%
(0,0)[#2`#3`#4`#5;#6`#7`#8`{#9}]%
\end{picture}%
}}

\def\putptrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\advance\ypos by \height
\puthmorphism(\xpos,\ypos)[#4`#5`{#7}]{\height}{\arrowtypea}a%
\putvmorphism(\xpos,\ypos)[`#6`{#8}]{\height}{\arrowtypeb}l%
\advance\xpos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[``{#9}]{\height}{\arrowtypec}r%
}}

\def\putptriangle{\@ifnextchar <{\putptrianglep}{\putptrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\ptriangle{\@ifnextchar <{\ptrianglep}{\ptrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\ptrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%       #5
\settriparms[#1]%
\width=\height                         %      #2----->#3
\xext=\width                           %      |      /
\yext=\width                           %      |     /
\topadjust[#2`#3`{#5}]%                %    #6|    /#7
\botadjust[#3``]%                      %      |   /
\leftadjust[#2`#4`{#6}]%               %      |  /
\rightsladjust[#3`#4`{#7}]%            %      v v
\begin{picture}(\xext,\yext)(\xoff,\yoff)%    #4
\putptrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putqtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\advance\ypos by\height
\puthmorphism(\xpos,\ypos)[#4`#5`{#7}]{\height}{\arrowtypea}a%
\putmorphism(\xpos,\ypos)(1,-1)[``{#8}]{\height}{\arrowtypeb}l%
\advance\xpos by\height
\putvmorphism(\xpos,\ypos)[`#6`{#9}]{\height}{\arrowtypec}r%
}}

\def\putqtriangle{\@ifnextchar <{\putqtrianglep}{\putqtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\qtriangle{\@ifnextchar <{\qtrianglep}{\qtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\qtrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                  #5
\width=\height                         %        #2----->#3
\xext=\width                           %         \      |
\yext=\height                          %          \     |
\topadjust[#2`#3`{#5}]%                %         #6\    |#7
\botadjust[#4``]%                      %            \   |
\leftsladjust[#2`#4`{#6}]%             %             \  |
\rightadjust[#3`#4`{#7}]%              %              v v
\begin{picture}(\xext,\yext)(\xoff,\yoff)%             #4
\putqtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putdtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\puthmorphism(\xpos,\ypos)[#5`#6`{#9}]{\height}{\arrowtypec}b%
\advance\xpos by \height \advance\ypos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[``{#7}]{\height}{\arrowtypea}l%
\putvmorphism(\xpos,\ypos)[#4``{#8}]{\height}{\arrowtypeb}r%
}}

\def\putdtriangle{\@ifnextchar <{\putdtrianglep}{\putdtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\dtriangle{\@ifnextchar <{\dtrianglep}{\dtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\dtrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                          #2
\width=\height                         %                  / |
\xext=\width                           %                 /  |
\yext=\height                          %              #5/   |#6
\topadjust[#2``]%                      %               /    |
\botadjust[#3`#4`{#7}]%                %              /     |
\leftsladjust[#3`#2`{#5}]%             %             v      v
\rightadjust[#2`#4`{#6}]%              %            #3----->#4
\begin{picture}(\xext,\yext)(\xoff,\yoff)%              #7
\putdtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putbtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\puthmorphism(\xpos,\ypos)[#5`#6`{#9}]{\height}{\arrowtypec}b%
\advance\ypos by\height
\putmorphism(\xpos,\ypos)(1,-1)[``{#8}]{\height}{\arrowtypeb}r%
\putvmorphism(\xpos,\ypos)[#4``{#7}]{\height}{\arrowtypea}l%
}}

\def\putbtriangle{\@ifnextchar <{\putbtrianglep}{\putbtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\btriangle{\@ifnextchar <{\btrianglep}{\btrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\btrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                     #2
\width=\height                         %              | \
\xext=\width                           %              |  \
\yext=\height                          %            #5|   \#6
\topadjust[#2``]%                      %              |    \
\botadjust[#3`#4`{#7}]%                %              |     \
\leftadjust[#2`#3`{#5}]%               %              v      v
\rightsladjust[#4`#2`{#6}]%            %              #3----->#4
\begin{picture}(\xext,\yext)(\xoff,\yoff)%                #7
\putbtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putAtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
{\multiply \height by2
\puthmorphism(\xpos,\ypos)[#5`#6`{#9}]{\height}{\arrowtypec}b}%
\advance\xpos by\height \advance\ypos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[#4``{#7}]{\height}{\arrowtypea}l%
\putmorphism(\xpos,\ypos)(1,-1)[``{#8}]{\height}{\arrowtypeb}r%
}}

\def\putAtriangle{\@ifnextchar <{\putAtrianglep}{\putAtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\Atriangle{\@ifnextchar <{\Atrianglep}{\Atrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\Atrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                 #2
\width=\height                         %         /   \
\xext=\width                           %        /     \
\yext=\height                          %     #5/       \#6
\topadjust[#2``]%                      %      /         \
\botadjust[#3`#4`{#7}]%                %     /           \
\multiply \xext by2 %                  %    v             v
\leftsladjust[#3`#2`{#5}]%             %   #3------------>#4
\rightsladjust[#4`#2`{#6}]%            %          #7
\begin{picture}(\xext,\yext)(\xoff,\yoff)%
\putAtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putAtrianglepairp<#1>(#2)[#3;#4`#5`#6`#7`#8]{{%
\settripairparms[#1]%
\setpos(#2)%
\settokens[#3]%
\puthmorphism(\xpos,\ypos)[\tokenb`\tokenc`{#7}]{\height}{\arrowtyped}b%
\advance\xpos by\height
\advance\ypos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[\tokena``{#4}]{\height}{\arrowtypea}l%
\putvmorphism(\xpos,\ypos)[``{#5}]{\height}{\arrowtypeb}m%
\putmorphism(\xpos,\ypos)(1,-1)[``{#6}]{\height}{\arrowtypec}r%
}}

\def\putAtrianglepair{\@ifnextchar <{\putAtrianglepairp}{\putAtrianglepairp%
   <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>}}
\def\Atrianglepair{\@ifnextchar <{\Atrianglepairp}{\Atrianglepairp%
   <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>}}

\def\Atrianglepairp<#1>[#2;#3`#4`#5`#6`#7]{{%
\settripairparms[#1]%
\settokens[#2]%
\width=\height
\xext=\width
\yext=\height
\topadjust[\tokena``]%
\vertadjust[\tokenb`\tokenc`{#6}]%                      %  #2a
\tempcountd=\tempcounta                       %           / | \
\vertadjust[\tokenc`\tokend`{#7}]%            %          /  |  \
\ifnum\tempcounta<\tempcountd                 %       #3/  #4   \#5
\tempcounta=\tempcountd\fi                    %        /    |    \
\advance \yext by\tempcounta                  %       /     |     \
\advance \yoff by-\tempcounta                 %      v      v      v
\multiply \xext by2 %                         %     #2b---->#2c---->#2d
\leftsladjust[\tokenb`\tokena`{#3}]%          %         #6     #7
\rightsladjust[\tokend`\tokena`{#5}]%
\begin{picture}(\xext,\yext)(\xoff,\yoff)%
\putAtrianglepairp
<\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>%
(0,0)[#2;#3`#4`#5`#6`{#7}]%
\end{picture}%
}}

\def\putVtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\advance\ypos by\height
{\multiply\height by2
\puthmorphism(\xpos,\ypos)[#4`#5`{#7}]{\height}{\arrowtypea}a}%
\putmorphism(\xpos,\ypos)(1,-1)[`#6`{#8}]{\height}{\arrowtypeb}l%
\advance\xpos by\height
\advance\xpos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[``{#9}]{\height}{\arrowtypec}r%
}}

\def\putVtriangle{\@ifnextchar <{\putVtrianglep}{\putVtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\Vtriangle{\@ifnextchar <{\Vtrianglep}{\Vtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\Vtrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                      #5
\width=\height                         %        #2------------->#3
\xext=\width                           %         \             /
\yext=\height                          %          \           /
\topadjust[#2`#3`{#5}]%                %         #6\         /#7
\botadjust[#4``]%                      %            \       /
\multiply \xext by2 %                  %             \     /
\leftsladjust[#2`#3`{#6}]%             %              v   v
\rightsladjust[#3`#4`{#7}]%            %               #4
\begin{picture}(\xext,\yext)(\xoff,\yoff)%
\putVtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putVtrianglepairp<#1>(#2)[#3;#4`#5`#6`#7`#8]{{
\settripairparms[#1]%
\setpos(#2)%
\settokens[#3]%
\advance\ypos by\height
\putmorphism(\xpos,\ypos)(1,-1)[`\tokend`{#6}]{\height}{\arrowtypec}l%
\puthmorphism(\xpos,\ypos)[\tokena`\tokenb`{#4}]{\height}{\arrowtypea}a%
\advance\xpos by\height
\putvmorphism(\xpos,\ypos)[``{#7}]{\height}{\arrowtyped}m%
\advance\xpos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[``{#8}]{\height}{\arrowtypee}r%
}}

\def\putVtrianglepair{\@ifnextchar <{\putVtrianglepairp}{\putVtrianglepairp%
    <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>}}
\def\Vtrianglepair{\@ifnextchar <{\Vtrianglepairp}{\Vtrianglepairp%
    <\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>}}

\def\Vtrianglepairp<#1>[#2;#3`#4`#5`#6`#7]{{%
\settripairparms[#1]%
\settokens[#2]%                            #3      #4
\xext=\height                  %        #2a---->#2b---->#2c
\width=\height                 %         \      |      /
\yext=\height                  %          \     |     /
\vertadjust[\tokena`\tokenb`{#4}]%       #5\   #6    /#7
\tempcountd=\tempcounta        %            \   |   /
\vertadjust[\tokenb`\tokenc`{#5}]%           \  |  /
\ifnum\tempcounta<\tempcountd%                v v v
\tempcounta=\tempcountd\fi%                    #2d
\advance \yext by\tempcounta
\botadjust[\tokend``]%
\multiply \xext by2
\leftsladjust[\tokena`\tokend`{#6}]%
\rightsladjust[\tokenc`\tokend`{#7}]%
\begin{picture}(\xext,\yext)(\xoff,\yoff)%
\putVtrianglepairp
<\arrowtypea`\arrowtypeb`\arrowtypec`\arrowtyped`\arrowtypee;\height>%
(0,0)[#2;#3`#4`#5`#6`{#7}]%
\end{picture}%
}}


\def\putCtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\advance\ypos by\height
\putmorphism(\xpos,\ypos)(1,-1)[``{#9}]{\height}{\arrowtypec}l%
\advance\xpos by\height
\advance\ypos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[#4`#5`{#7}]{\height}{\arrowtypea}l%
{\multiply\height by 2
\putvmorphism(\xpos,\ypos)[`#6`{#8}]{\height}{\arrowtypeb}r}%
}}

\def\putCtriangle{\@ifnextchar <{\putCtrianglep}{\putCtrianglep
    <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\Ctriangle{\@ifnextchar <{\Ctrianglep}{\Ctrianglep
    <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\Ctrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                         #2
\width=\height                          %                / |
\xext=\width                            %               /  |
\yext=\height                           %            #5/   |
\multiply \yext by2 %                   %             /    |
\topadjust[#2``]%                       %            /     |
\botadjust[#4``]%                       %           v      |
\sladjust[#3`#2`{#5}]{\width}%          %          #3      |#6
\tempcountd=\tempcounta                 %           \      |
\sladjust[#3`#4`{#7}]{\width}%          %            \     |
\ifnum \tempcounta<\tempcountd          %           #7\    |
\tempcounta=\tempcountd\fi              %              \   |
\advance \xext by\tempcounta            %               \  |
\advance \xoff by-\tempcounta           %                v v
\rightadjust[#2`#4`{#6}]%               %                 #4
\begin{picture}(\xext,\yext)(\xoff,\yoff)%
\putCtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\putDtrianglep<#1>(#2,#3)[#4`#5`#6;#7`#8`#9]{{%
\settriparms[#1]%
\xpos=#2 \ypos=#3
\advance\xpos by\height \advance\ypos by\height
\putmorphism(\xpos,\ypos)(-1,-1)[``{#9}]{\height}{\arrowtypec}r%
\advance\xpos by-\height \advance\ypos by\height
\putmorphism(\xpos,\ypos)(1,-1)[`#5`{#8}]{\height}{\arrowtypeb}r%
{\multiply\height by 2
\putvmorphism(\xpos,\ypos)[#4`#6`{#7}]{\height}{\arrowtypea}l}%
}}

\def\putDtriangle{\@ifnextchar <{\putDtrianglep}{\putDtrianglep
    <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}
\def\Dtriangle{\@ifnextchar <{\Dtrianglep}{\Dtrianglep
   <\arrowtypea`\arrowtypeb`\arrowtypec;\height>}}

\def\Dtrianglep<#1>[#2`#3`#4;#5`#6`#7]{{%%
\settriparms[#1]%                                 #2
\width=\height                         %          | \
\xext=\height                          %          |  \
\yext=\height                          %          |   \#6
\multiply \yext by2 %                  %          |    \
\topadjust[#2``]%                      %          |     \
\botadjust[#4``]%                      %          |      v
\leftadjust[#2`#4`{#5}]%               %        #5|      #3
\sladjust[#3`#2`{#5}]{\height}%        %          |      /
\tempcountd=\tempcountd                %          |     /
\sladjust[#3`#4`{#7}]{\height}%        %          |    /#7
\ifnum \tempcounta<\tempcountd         %          |   /
\tempcounta=\tempcountd\fi             %          |  /
\advance \xext by\tempcounta           %          v v
\begin{picture}(\xext,\yext)(\xoff,\yoff)%        #4
\putDtrianglep<\arrowtypea`\arrowtypeb`\arrowtypec;\height>%
(0,0)[#2`#3`#4;#5`#6`{#7}]%
\end{picture}%
}}

\def\setrecparms[#1`#2]{\width=#1 \height=#2}%
%              #4
%        #3b<-------#3a x #3b
%       ^ |             |
%      /  |             |
%   #5/   |             |
%    /    |             |
%   /     |             |
%  /      |             |
% #3c     |#6           |#3a x #5
%  \      |             |
%   \     |             |
%  #8\    |             |
%     \   |             |
%      \  |             |
%       v v             v
%        #3d<-------#3a x #3d
%              #8

\def\recursep<#1`#2>[#3;#4`#5`#6`#7`#8]{{%
\width=#1 \height=#2
\settokens[#3]
\settowidth{\tempdimen}{$\tokena$}
\ifdim\tempdimen=0pt
  \savebox{\tempboxa}{\hbox{$\tokenb$}}%
  \savebox{\tempboxb}{\hbox{$\tokend$}}%
  \savebox{\tempboxc}{\hbox{$#6$}}%
\else
  \savebox{\tempboxa}{\hbox{$\hbox{$\tokena$}\times\hbox{$\tokenb$}$}}%
  \savebox{\tempboxb}{\hbox{$\hbox{$\tokena$}\times\hbox{$\tokend$}$}}%
  \savebox{\tempboxc}{\hbox{$\hbox{$\tokena$}\times\hbox{$#6$}$}}%
\fi
\ypos=\height
\divide\ypos by 2
\xpos=\ypos
\advance\xpos by \width
\xext=\xpos \yext=\height
\topadjust[#3`\usebox{\tempboxa}`{#4}]%
\botadjust[#5`\usebox{\tempboxb}`{#8}]%
\sladjust[\tokenc`\tokenb`{#5}]{\ypos}%
\tempcountd=\tempcounta
\sladjust[\tokenc`\tokend`{#5}]{\ypos}%
\ifnum \tempcounta<\tempcountd
\tempcounta=\tempcountd\fi
\advance \xext by\tempcounta
\advance \xoff by-\tempcounta
\rightadjust[\usebox{\tempboxa}`\usebox{\tempboxb}`\usebox{\tempboxc}]%
\bfig
\putCtrianglep<-1`1`1;\ypos>(0,0)[`\tokenc`;#5`#6`{#7}]%
\puthmorphism(\ypos,0)[\tokend`\usebox{\tempboxb}`{#8}]{\width}{-1}b%
\puthmorphism(\ypos,\height)[\tokenb`\usebox{\tempboxa}`{#4}]{\width}{-1}a%
\advance\ypos by \width
\putvmorphism(\ypos,\height)[``\usebox{\tempboxc}]{\height}1r%
\efig
}}

\def\recurse{\@ifnextchar <{\recursep}{\recursep<\width`\height>}}

\def\puttwohmorphisms(#1,#2)[#3`#4;#5`#6]#7#8#9{{%
% 1 and 2 are position, 3 and 4 are the nodes, 5 and 6 the labels,
% 7 the distance between node centers and 8 & 9 are the arrow types.
%         #5
% #3 ===========> #4
%         #6
%
\puthmorphism(#1,#2)[#3`#4`]{#7}0a
\ypos=#2
\advance\ypos by 20
\puthmorphism(#1,\ypos)[\phantom{#3}`\phantom{#4}`#5]{#7}{#8}a
\advance\ypos by -40
\puthmorphism(#1,\ypos)[\phantom{#3}`\phantom{#4}`#6]{#7}{#9}b
}}

\def\puttwovmorphisms(#1,#2)[#3`#4;#5`#6]#7#8#9{{%
% 1 and 2 are position, 3 and 4 are the nodes, 5 and 6 the labels,
% 7 the distance between node centers and 8 & 9 are the arrow types.
%
%              #3
%              ||
%              ||
%           #5 || #6
%              ||
%              ||
%              vv
%              #4
%
\putvmorphism(#1,#2)[#3`#4`]{#7}0a
\xpos=#1
\advance\xpos by -20
\putvmorphism(\xpos,#2)[\phantom{#3}`\phantom{#4}`#5]{#7}{#8}l
\advance\xpos by 40
\putvmorphism(\xpos,#2)[\phantom{#3}`\phantom{#4}`#6]{#7}{#9}r
}}

\def\puthcoequalizer(#1)[#2`#3`#4;#5`#6`#7]#8#9{{%
% #1 is (\xpos,\ypos), the next 6 are the nodes and arrow labels
% #8 is the distance between each pair of nodes and #9 is the pos of #7
% either a (above) or b (below)
%         #5            #7
% #2 ===========> #3 --------> #4
%         #6
%
\setpos(#1)%
\puttwohmorphisms(\xpos,\ypos)[#2`#3;#5`#6]{#8}11%
\advance\xpos by #8
\puthmorphism(\xpos,\ypos)[\phantom{#3}`#4`#7]{#8}1{#9}
}}

\def\putvcoequalizer(#1)[#2`#3`#4;#5`#6`#7]#8#9{{%
% #1 is (\xpos,\ypos), the next 6 are the nodes and arrow labels
% #8 is the distance between each pair of nodes and #9 is the pos of #7
% either l (left) or r (right)
%
%              #2
%              | |
%              | |
%           #5 | | #6
%              | |
%              | |
%              v v
%              #3
%               |
%               |
%            #7 |
%               |
%               v
%              #4
%
\setpos(#1)%
\puttwovmorphisms(\xpos,\ypos)[#2`#3;#5`#6]{#8}11%
\advance\ypos by -#8
\putvmorphism(\xpos,\ypos)[\phantom{#3}`#4`#7]{#8}1{#9}
}}

\def\putthreehmorphisms(#1)[#2`#3;#4`#5`#6]#7(#8)#9{{%
% Use: \putthreehmorphisms(xpos,ypos)[lnode`rnode;toplabel`midlabel%
% botlabel]{distance}(toparrowtype,midarrowtype,botarrowtype){position}
\setpos(#1) \settypes(#8)
\if a#9 %
     \vertsize{\tempcounta}{#5}%
     \vertsize{\tempcountb}{#6}%
     \ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
\else
     \vertsize{\tempcounta}{#4}%
     \vertsize{\tempcountb}{#5}%
     \ifnum \tempcounta<\tempcountb \tempcounta=\tempcountb \fi
\fi
\advance \tempcounta by 60
\puthmorphism(\xpos,\ypos)[#2`#3`#5]{#7}{\arrowtypeb}{#9}
\advance\ypos by \tempcounta
\puthmorphism(\xpos,\ypos)[\phantom{#2}`\phantom{#3}`#4]{#7}{\arrowtypea}{#9}
\advance\ypos by -\tempcounta \advance\ypos by -\tempcounta
\puthmorphism(\xpos,\ypos)[\phantom{#2}`\phantom{#3}`#6]{#7}{\arrowtypec}{#9}
}}

%\def\putarc(#1,#2)[#3`#4`#5]#6#7#8{{%
%\xpos #1
%\ypos #2
%\width #6
%\arrowlength #6
%\putbox(\xpos,\ypos){#3\vphantom{#4}}%
%{\advance \xpos by\arrowlength
%\putbox(\xpos,\ypos){\vphantom{#3}#4}}%
%\horsize{\tempcounta}{#3}%
%\horsize{\tempcountb}{#4}%
%\divide \tempcounta by2
%\divide \tempcountb by2
%\advance \tempcounta by30
%\advance \tempcountb by30
%\advance \xpos by\tempcounta
%\advance \arrowlength by-\tempcounta
%\advance \arrowlength by-\tempcountb
%\halflength=\arrowlength \divide\halflength by 2
%\divide\arrowlength by 5
%\put(\xpos,\ypos){\bezier{\arrowlength}(0,0)(50,50)(\halflength,50)}
%\ifnum #7=-1 \put(\xpos,\ypos){\vector(-3,-2)0} \fi
%\advance\xpos by \halflength
%\put(\xpos,\ypos){\xpos=\halflength \advance\xpos by -50
%   \bezier{\arrowlength}(0,50)(\xpos,50)(\halflength,0)}
%\ifnum #7=1 {\advance \xpos by
%   \halflength \put(\xpos,\ypos){\vector(3,-2)0}} \fi
%\advance\ypos by 50
%\vertsize{\tempcounta}{#5}%
%\divide\tempcounta by2
%\advance \tempcounta by20
%\if a#8 %
%   \advance \ypos by\tempcounta
%   \putbox(\xpos,\ypos){#5}%
%\else
%   \advance \ypos by-\tempcounta
%   \putbox(\xpos,\ypos){#5}%
%\fi
%}}