% Copyright 2011, 2012 by Florêncio Neves
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
\ProvidesPackage{tikz-cd}[2012/07/17 v0.2c Commutative diagrams with tikz.]
\RequirePackage{tikz}
\AtBeginDocument{% \fontdimen's can't be read reliably inside a tikzpicture
  \setbox\pgfutil@tempboxa\hbox{$ $}%
  \pgfmathparse{\the\fontdimen8\textfont3/1ex}\edef\tikzcdrulethickness{\pgfmathresult ex}%
  \pgfmathparse{\the\fontdimen22\textfont2/1ex}\edef\tikzcdaxisheight{\pgfmathresult ex}}

\usetikzlibrary{matrix}

\newif\iftikzcd@mathmode
\newcount\tikzcd@targetrow
\newcount\tikzcd@targetcol

\pgfqkeys{/tikz/commutative diagrams}{
  /tikz/commutative diagrams/.search also={/tikz},
  arrows/.style={
    /tikz/commutative diagrams/every arrow/.append style={#1}},
  labels/.style={
    /tikz/commutative diagrams/every label/.append style={#1}},
  diagrams/.style={
    /tikz/commutative diagrams/every diagram/.append style={#1}},
  description/.style={
    /tikz/anchor=center,
    /tikz/fill=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
    /tikz/inner sep=%
      \pgfkeysvalueof{/tikz/commutative diagrams/description clearance}},
  crossing over/.style={
    /tikz/preaction={
      /tikz/draw=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
      /tikz/arrows=-,
      /tikz/line width=%
        \pgfkeysvalueof{/tikz/commutative diagrams/crossing over clearance}}},
  row sep/.code={\tikzcd@sep{row}{#1}},
  column sep/.code={\tikzcd@sep{column}{#1}},
  math mode/.is if=tikzcd@mathmode,
  matrix of math nodes maybe/.style={%
    /tikz/matrix of nodes,
    /tikz/nodes={
      execute at begin node=\iftikzcd@mathmode$\fi, %$
      execute at end node=\iftikzcd@mathmode$\fi}}, %$
  start anchor/.code={%
    \ifx#1\pgfkeysnovalue\let\tikzcd@sourceanchor\empty%
    \else\def\tikzcd@sourceanchor{.#1}\fi},
  end anchor/.code={%
    \ifx#1\pgfkeysnovalue\let\tikzcd@targetanchor\empty%
    \else\def\tikzcd@targetanchor{.#1}\fi},
  arrow style/.is choice}

% generic arrow tip selection styles
\pgfqkeys{/tikz/commutative diagrams}{
  dashrightarrow/.style={/tikz/commutative diagrams/.cd,rightarrow,dashed},
  dashleftarrow/.style={/tikz/commutative diagrams/.cd,leftarrow,dashed},
  rightsquigarrow/.style={
    /tikz/commutative diagrams/.cd,rightarrow,squiggly},
  leftsquigarrow/.style={/tikz/commutative diagrams/.cd,leftarrow,squiggly},
  leftrightsquigarrow/.style={
    /tikz/commutative diagrams/.cd,leftrightarrow,squiggly},
  squiggly/.code={%
    \expandafter\ifx\csname tikz@library@decorations.pathmorphing@loaded\endcsname\pgfutil@empty%
    \else\PackageError{tikz-cd}{To use squiggly arrows, include %
      \protect\usetikzlibrary{decorations.pathmorphing} in the document preamble}{}\fi},
  squiggly/.append style={
    decorate,
    decoration={
      zigzag,
      segment length=4,
      amplitude=.9,
      post=lineto, post length=2pt,
      pre=lineto, pre length=2pt}}}

% The Computer Modern arrow style
\pgfqkeys{/tikz/commutative diagrams/arrow style}{
  computer modern/.style={
    /tikz/commutative diagrams/.cd,
    default arrow/.style={
      /tikz/line join=round,
      /tikz/arrows=cm cap-cm to,
      /tikz/line width=\tikzcdrulethickness},
    rightarrow/.style={/tikz/arrows=cm cap-cm to},
    Rightarrow/.style={
      /tikz/arrows=cm implies cap-cm implies,
      /tikz/commutative diagrams/double line},
    leftarrow/.style={/tikz/arrows=cm to-cm cap},
    Leftarrow/.style={
      /tikz/arrows=cm implies-cm implies cap,
      /tikz/commutative diagrams/double line},
    leftrightarrow/.style={/tikz/arrows=cm to-cm to},
    Leftrightarrow/.style={
      /tikz/arrows=cm implies-cm implies,
      /tikz/commutative diagrams/double line},
    mapsto/.style={/tikz/arrows=cm |-cm to},
    hookrightarrow/.style={/tikz/arrows=cm right hook-cm to},
    hookleftarrow/.style={/tikz/arrows=cm to-cm left hook},
    rightharpoonup/.style={/tikz/arrows=cm cap-cm left to},
    rightharpoondown/.style={/tikz/arrows=cm cap-cm right to},
    leftharpoonup/.style={/tikz/arrows=cm right to-cm cap},
    leftharpoondown/.style={/tikz/arrows=cm left to-cm cap},
    rightarrowtail/.style={/tikz/arrows=cm to reversed-cm to},
    leftarrowtail/.style={/tikz/arrows=cm to-cm to reversed},
    twoheadrightarrow/.style={/tikz/arrows=cm cap-cm double to},
    twoheadleftarrow/.style={/tikz/arrows=cm double to-cm cap},
    equals/.style={
      /tikz/arrows=cm implies cap-cm implies cap,
      /tikz/commutative diagrams/double line},
    maps to/.code={\pgfsetarrowsstart{cm |}},
    hook/.code={\pgfsetarrowsstart{cm right hook}},
    two heads/.code={\pgfsetarrowsend{cm double to}},
    tail/.code={\pgfsetarrowsstart{cm to reversed}},
    double line/.style={
      /tikz/double=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
      /tikz/double distance=3.643\pgflinewidth},
    dashed/.style={/tikz/densely dashed}}}

% The tikz arrow style
\pgfqkeys{/tikz/commutative diagrams/arrow style}{
  tikz/.code={%
    \expandafter\ifx\csname tikz@library@arrows@loaded\endcsname\pgfutil@empty%
    \else\PackageError{tikz-cd}{To use the `tikz' arrow style, include %
           \protect\usetikzlibrary{arrows} in the document preamble}{}\fi},
  tikz/.append style={
    /tikz/commutative diagrams/.cd,
    default arrow/.style={/tikz/arrows=->},
    rightarrow/.style={/tikz/arrows=->},
    Rightarrow/.style={
      /tikz/arrows=-implies,
      /tikz/commutative diagrams/double line},
    leftarrow/.style={/tikz/arrows=<-},
    Leftarrow/.style={
      /tikz/arrows=implies-,
      /tikz/commutative diagrams/double line},
    leftrightarrow/.style={/tikz/arrows=<->},
    Leftrightarrow/.style={
      /tikz/arrows=implies-implies,
      /tikz/commutative diagrams/double line},
    mapsto/.style={/tikz/arrows=|->},
    hookrightarrow/.style={/tikz/arrows=right hook->},
    hookleftarrow/.style={/tikz/arrows=<-left hook},
    rightharpoonup/.style={/tikz/arrows=-left to},
    rightharpoondown/.style={/tikz/arrows=-right to},
    leftharpoonup/.style={/tikz/arrows=right to-},
    leftharpoondown/.style={/tikz/arrows=left to-},
    rightarrowtail/.style={/tikz/arrows=>->},
    leftarrowtail/.style={/tikz/arrows=<-<},
    twoheadrightarrow/.style={/tikz/arrows=->>},
    twoheadleftarrow/.style={/tikz/arrows=<<-}, %>>
    equals/.style={
      /tikz/arrows=-,
      /tikz/commutative diagrams/double line},
    maps to/.code={\pgfsetarrowsstart{|}},
    hook/.code={\pgfsetarrowsstart{right hook}},
    two heads/.code={
      \pgfsetarrowsend{\csname tikz@special@arrow@end>>\endcsname}},
    tail/.code={
      \pgfsetarrowsstart{\csname tikz@special@arrow@start>\endcsname}},
    dashed/.style={/tikz/dashed},
    double line/.style={
      /tikz/double equal sign distance,
      /tikz/double=\pgfkeysvalueof{/tikz/commutative diagrams/background color}}}}

% Default settings
\pgfqkeys{/tikz/commutative diagrams}{
  every arrow/.style={
    /tikz/commutative diagrams/.cd,
    /tikz/draw,
    /tikz/commutative diagrams/default arrow},
  every label/.style={
    /tikz/commutative diagrams/.cd,
    /tikz/auto,
    /tikz/font=\scriptsize,
    /tikz/inner sep=0.5ex},
  every diagram/.style={
    /tikz/commutative diagrams/.cd,
    /tikz/cells={/tikz/nodes={/tikz/shape={asymmetrical rectangle}}},
    row sep=normal,
    column sep=normal,
    /tikz/baseline=0pt},
  math mode=true,
  center shift/.initial=\tikzcdaxisheight,
  row sep/huge/.initial=10ex,
  row sep/large/.initial=7.5ex,
  row sep/normal/.initial=5ex,
  row sep/scriptsize/.initial=3.75ex,
  row sep/small/.initial=2.5ex,
  row sep/tiny/.initial=1.25ex,
  column sep/huge/.initial=12ex,
  column sep/large/.initial=9ex,
  column sep/normal/.initial=6ex,
  column sep/scriptsize/.initial=4.5ex,
  column sep/small/.initial=3ex,
  column sep/tiny/.initial=1.5ex,
  arrow style=computer modern,
  start anchor,
  end anchor,
  description clearance/.initial=1.5pt,
  crossing over clearance/.initial=6pt,
  background color/.initial=white}

% The shape used inside matrices
\pgfdeclareshape{asymmetrical rectangle} {
  \inheritsavedanchors[from={rectangle}]
  \inheritanchor[from={rectangle}]{base}
  \inheritanchor[from={rectangle}]{north}
  \inheritanchor[from={rectangle}]{south}
  \inheritanchor[from={rectangle}]{base west}
  \inheritanchor[from={rectangle}]{north west}
  \inheritanchor[from={rectangle}]{south west}
  \inheritanchor[from={rectangle}]{base east}
  \inheritanchor[from={rectangle}]{north east}
  \inheritanchor[from={rectangle}]{south east}
  \inheritanchor[from={rectangle}]{mid}
  \inheritanchor[from={rectangle}]{mid west}
  \inheritanchor[from={rectangle}]{mid east}
  \inheritbackgroundpath[from={rectangle}]
  \anchor{center}{\pgf@anchor@rectangle@center\pgfmathsetlength\pgf@y%
    {\pgfkeysvalueof{/tikz/commutative diagrams/center shift}}}
  \anchor{west}{\pgf@anchor@rectangle@west\pgfmathsetlength\pgf@y%
    {\pgfkeysvalueof{/tikz/commutative diagrams/center shift}}}
  \anchor{east}{\pgf@anchor@rectangle@east\pgfmathsetlength\pgf@y%
    {\pgfkeysvalueof{/tikz/commutative diagrams/center shift}}}
  \anchor{real center}{\pgf@anchor@rectangle@center}
  \anchor{real west}{\pgf@anchor@rectangle@west}
  \anchor{real east}{\pgf@anchor@rectangle@east}
  \anchorborder{%
    \pgfmathsetlength\pgfutil@tempdima%
      {\pgfkeysvalueof{/tikz/commutative diagrams/center shift}}%
    \pgf@xb=\pgf@x% xb/yb is target
    \pgf@yb=\pgf@y%
    \southwest%
    \pgf@xa=\pgf@x% xa/ya is se
    \pgf@ya=\pgf@y%
    \northeast%
    \advance\pgf@x by-\pgf@xa%
    \advance\pgf@y by-\pgf@ya%
    \pgf@xc=.5\pgf@x% x/y is half width/height
    \pgf@yc=.5\pgf@y%
    \advance\pgf@xa by\pgf@xc% xa/ya becomes center
    \advance\pgf@ya by\pgf@yc%
    \ifdim\pgf@yb>0pt%
      \northeast%
      \pgf@yc=\pgf@y%
      \advance\pgf@yc by-\pgfutil@tempdima%
    \else%
      \southwest%
      \pgf@yc=-\pgf@y%
      \advance\pgf@yc by\pgfutil@tempdima%
    \fi
    \edef\pgf@marshal{%
      \noexpand\pgfpointborderrectangle
      {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
      {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
    }%
    \pgf@process{\pgf@marshal}%
    \advance\pgf@x by\pgf@xa%
    \advance\pgf@y by\pgfutil@tempdima%
  }%
}%

% Branch depending on whether the next character is [, { or none of those.
\def\tikzcd@threefold#1#2#3{%
  \def\tikzcd@tempa{#1}%
  \def\tikzcd@tempb{#2}%
  \def\tikzcd@tempc{#3}%
  \futurelet\next\tikzcd@@threefold}

\def\tikzcd@@threefold{%
  \ifx[\next\let\tikzcd@tempc\tikzcd@tempa%
    \else\ifx\bgroup\next\let\tikzcd@tempc\tikzcd@tempb\fi\fi%
  \tikzcd@tempc}

%The arrow commands
\def\tikzcd@arrow{\tikzcd@threefold{\tikzcd@ar@getdir}{\tikzcd@ar@getdir[]}{}}

\def\tikzcd@ar@getdir[#1]#2{%
  \tikzcd@targetrow\pgfmatrixcurrentrow%
  \tikzcd@targetcol\pgfmatrixcurrentcolumn%
  \tikzcd@parse#2\relax%
  \toks@\expandafter{\tikzcd@savedpaths\path[/tikz/commutative diagrams/every arrow,#1]}%
  \global\edef\tikzcd@savedpaths{\the\toks@%
    (\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn%
    \noexpand\tikzcd@sourceanchor) to }%
  \tikzcd@threefold{\tikzcd@ar@getlabel}{\tikzcd@ar@getlabel[]}{\tikzcd@ar@final}}

\def\tikzcd@ar@getlabel[#1]#2{%
  \expandafter\def\expandafter\tikzcd@savedpaths\expandafter{\tikzcd@savedpaths%
    node[/tikz/commutative diagrams/every label,#1]{\tikzcd@mathmaybe{#2}}}%
  \tikzcd@threefold{\tikzcd@ar@getlabel}{\tikzcd@ar@getlabel[]}{\tikzcd@ar@final}}

\def\tikzcd@ar@final{%
  \toks@\expandafter{\tikzcd@savedpaths}
  \global\edef\tikzcd@savedpaths{%
    \the\toks@%
    (\tikzmatrixname-\the\tikzcd@targetrow-\the\tikzcd@targetcol%
    \noexpand\tikzcd@targetanchor); }}

\def\tikzcd@xar#1{\tikzcd@threefold{\tikzcd@@xar{#1}}{\tikzcd@arrow[]{#1}}{\tikzcd@arrow[]{#1}}}

\def\tikzcd@@xar#1[#2]{\tikzcd@arrow[#2]{#1}}

\def\tikzcd@parse#1{% Parser for arrow direction argument
  \def\tikzcd@tempa{\tikzcd@parse}%
  \ifx#1r\advance\tikzcd@targetcol by1\else%
   \ifx#1d\advance\tikzcd@targetrow by1\else%
    \ifx#1l\advance\tikzcd@targetcol by-1\else%
     \ifx#1u\advance\tikzcd@targetrow by-1\else%
      \ifx#1\relax\let\tikzcd@tempa\empty%
       \else\PackageError{tikz-cd}{Arrow direction argument must contain %
                        only the characters l, r, u or d}{}\fi\fi\fi\fi\fi%
  \tikzcd@tempa}

%The tikzcd environment
\def\tikzcd{\tikzcd@threefold{\tikzcd@}{\tikzcd@[]}{\tikzcd@[]}}

\def\tikzcd@[#1]{%
  \tikzpicture[/tikz/commutative diagrams/every diagram,#1]%
  \tikzcd@initialize%
  \matrix[/tikz/commutative diagrams/matrix of math nodes maybe]\bgroup}

\def\endtikzcd{%
  \pgfmatrixendrow\egroup;%
  \tikzcd@finalize%
  \endtikzpicture}

\def\tikzcd@initialize{%
  \def\arrow{\tikzcd@arrow}%
  \def\ar{\tikzcd@arrow}%
  \def\rar{\tikzcd@xar{r}}%
  \def\lar{\tikzcd@xar{l}}%
  \def\dar{\tikzcd@xar{d}}%
  \def\uar{\tikzcd@xar{u}}%
  \def\urar{\tikzcd@xar{ur}}%
  \def\ular{\tikzcd@xar{ul}}%
  \def\drar{\tikzcd@xar{dr}}%
  \def\dlar{\tikzcd@xar{dl}}%
  \def\rowsep##1{\pgfkeysvalueof{/tikz/commutative diagrams/row sep/##1}}%
  \def\colsep##1{\pgfkeysvalueof{/tikz/commutative diagrams/column sep/##1}}%
  \global\let\tikzcd@savedpaths\empty}

\def\tikzcd@finalize{\tikzcd@savedpaths}

\def\tikzcd@mathmaybe#1{\iftikzcd@mathmode$ #1$\else#1\fi}

\def\tikzcd@sep#1#2{
  \pgfkeysifdefined{/tikz/commutative diagrams/#1 sep/#2}%
    {\tikzset{#1 sep=\pgfkeysvalueof{/tikz/commutative diagrams/#1 sep/#2}}}%
    {\tikzset{#1 sep=#2}}}

%Computer modern arrow tips
\pgfarrowsdeclare{cm to}{cm to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm implies}{cm implies}
{
  \pgfmathsetlength{\pgfutil@tempdima}{-0.729\pgflinewidth+.25*\pgfinnerlinewidth}
  \pgfarrowsleftextend{\pgfutil@tempdima}
  \pgfmathsetlength{\pgfutil@tempdima}{1.094\pgflinewidth-.25*\pgfinnerlinewidth}
  \pgfarrowsrightextend{\pgfutil@tempdima}
}
{
  \pgfmathsetlength{\pgfutil@tempdimb}{.5\pgflinewidth-.5*\pgfinnerlinewidth}
  \pgfutil@tempdima\pgflinewidth
  \pgfsetlinewidth{\pgfutil@tempdimb}
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-0.542\pgfutil@tempdima}{1.142\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-0.247\pgfutil@tempdima}{0.476\pgfutil@tempdima}}
  {\pgfqpoint{0.29\pgfutil@tempdima}{0.114\pgfutil@tempdima}}
  {\pgfqpoint{0.844\pgfutil@tempdima}{0pt}}
  \pgfpathcurveto
  {\pgfqpoint{0.29\pgfutil@tempdima}{-0.114\pgfutil@tempdima}}
  {\pgfqpoint{-0.247\pgfutil@tempdima}{-0.476\pgfutil@tempdima}}
  {\pgfqpoint{-0.542\pgfutil@tempdima}{-1.142\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm bold to}{cm bold to}
{
  \pgfarrowsleftextend{-4.055\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=0.667\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm left to}{cm left to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfqpoint{-5.333\pgfutil@tempdima}{6\pgfutil@tempdima}}
  \pgfpathcurveto
  {\pgfqpoint{-4.2\pgfutil@tempdima}{2.5\pgfutil@tempdima}}
  {\pgfqpoint{-2.133\pgfutil@tempdima}{0.6\pgfutil@tempdima}}
  {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm right to}{cm right to}
{
  \pgfarrowsleftextend{-5.833\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfutil@tempdima=\pgflinewidth
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfsetroundjoin
  \pgfpathmoveto{\pgfpointorigin}
  \pgfpathcurveto
  {\pgfqpoint{-2.133\pgfutil@tempdima}{-0.6\pgfutil@tempdima}}
  {\pgfqpoint{-4.2\pgfutil@tempdima}{-2.5\pgfutil@tempdima}}
  {\pgfqpoint{-5.333\pgfutil@tempdima}{-6\pgfutil@tempdima}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm |}{cm |}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{0.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{-4\pgflinewidth}}
  \pgfpathlineto{\pgfqpoint{0pt}{4\pgflinewidth}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm left hook}{cm left hook}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{3.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{4.667\pgflinewidth}}
  \pgfpathcurveto
    {\pgfqpoint{4\pgflinewidth}{4.667\pgflinewidth}}
    {\pgfqpoint{4\pgflinewidth}{0pt}}
    {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm right hook}{cm right hook}
{
  \pgfarrowsleftextend{-0.5\pgflinewidth}
  \pgfarrowsrightextend{3.5\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{-4.667\pgflinewidth}}
  \pgfpathcurveto
    {\pgfqpoint{4\pgflinewidth}{-4.667\pgflinewidth}}
    {\pgfqpoint{4\pgflinewidth}{0pt}}
    {\pgfpointorigin}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm o}{cm o}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \pgfarrowsrightextend{7.167\pgflinewidth}
}
{
  \pgfpathcircle{\pgfqpoint{3.333\pgflinewidth}{0pt}}{3.333\pgflinewidth}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm *}{cm *}
{
  \pgfarrowsleftextend{+-.5\pgflinewidth}
  \pgfarrowsrightextend{7.167\pgflinewidth}
}
{
  \pgfpathcircle{\pgfqpoint{3.333\pgflinewidth}{0pt}}{3.333\pgflinewidth}
  \pgfusepathqfillstroke
}

\pgfarrowsdeclare{cm cap}{cm cap}
{
  \pgfarrowsleftextend{+0pt}
  \pgfarrowsrightextend{+\pgflinewidth}
}
{
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfpointorigin}
  \pgfpathlineto{\pgfqpoint{0.5\pgflinewidth}{0pt}}
  \pgfusepathqstroke
}

\pgfarrowsdeclare{cm implies cap}{cm implies cap}
{
  \pgfmathsetlength{\pgfutil@tempdima}{.5\pgflinewidth-.5*\pgfinnerlinewidth}
  \pgfarrowsleftextend{+0pt}
  \pgfarrowsrightextend{+\pgfutil@tempdima}
}
{
  \pgfmathsetlength{\pgfutil@tempdima}{.5\pgflinewidth-.5*\pgfinnerlinewidth}
  \pgfmathsetlength{\pgfutil@tempdimb}{.5\pgflinewidth-.5*\pgfutil@tempdima}
  \pgfsetlinewidth{\pgfutil@tempdima}
  \pgfsetdash{}{+0pt}
  \pgfsetroundcap
  \pgfpathmoveto{\pgfqpoint{0pt}{+1\pgfutil@tempdimb}}
  \pgfpathlineto{\pgfqpoint{0.5\pgfutil@tempdima}{+1\pgfutil@tempdimb}}
  \pgfpathmoveto{\pgfqpoint{0pt}{-1\pgfutil@tempdimb}}
  \pgfpathlineto{\pgfqpoint{0.5\pgfutil@tempdima}{-1\pgfutil@tempdimb}}
  \pgfusepathqstroke
}

\pgfarrowsdeclarereversed{cm to reversed}{cm to reversed}{cm to}{cm to}
\pgfarrowsdeclarereversed{cm left to reversed}{cm left to reversed}{cm left to}{cm left to}
\pgfarrowsdeclarereversed{cm right to reversed}{cm right to reversed}{cm right to}{cm right to}

\pgfarrowsdeclaredouble{cm double to}{cm double to}{cm to}{cm to}
\pgfarrowsdeclaredouble{cm double to reversed}{cm double to reversed}{cm to reversed}{cm to reversed}

%Font arrows (experimental)

\tikzset{
  /tikz/commutative diagrams/enable font arrows/.code={%
    % A little surgery on pgf's arrow selection commands
    \pgfutil@ifundefined{tikzcd@orig@pgfsetarrowsend}%
      {\let\tikzcd@orig@pgfsetarrowsend\pgfsetarrowsend
       \let\tikzcd@orig@pgfsetarrowsstart\pgfsetarrowsstart
       \def\pgfsetarrowsend##1{%
         \pgfutil@ifundefined{tikzcd@arrows@cmd@##1}%
           {\tikzcd@orig@pgfsetarrowsend{##1}}
           {\tikzcd@arrowset{end}{##1}}}%
       \def\pgfsetarrowsstart##1{%
         \pgfutil@ifundefined{tikzcd@arrows@cmd@##1}%
           {\tikzcd@orig@pgfsetarrowsstart{##1}}
           {\tikzcd@arrowset{start}{##1}}}%
         }{}},
  /tikz/commutative diagrams/font arrows/.cd,
  double distance/.store in={\tikzcdfontarrowsdoubledistance},
  declare head/.code n args={4}{\tikzcd@arrowsdeclare{#1}{#2}{#3}{#4}{\iftrue}},
  declare tail/.code n args={4}{\tikzcd@arrowsdeclare{#1}{#2}{#3}{#4}{\iffalse}},
}

% #1 = name
% #2 = command
% #3 = axis height
% #4 = width of clip box
% #5 = \iftrue for head, \iffalse for tail
\def\tikzcd@arrowsdeclare#1#2#3#4#5{%
  \expandafter\def\csname tikzcd@arrows@cmd@#1\endcsname{#2}%
  \expandafter\def\csname tikzcd@arrows@ifhead@#1\endcsname{#5}%
  \expandafter\def\csname tikzcd@arrows@axheight@#1\endcsname{#3}%
  \expandafter\def\csname tikzcd@arrows@length@#1\endcsname{#4}}

% Select the pdfTeX or generic backend according to pgf's setting.
%
% The generic backend uses a rectangle to clip the font glyph, and the
% pdfTeX backend uses the font glyph as the clipping path for a big
% black box.  The latter method seems to trick pdf viewers and
% printers to treat the resulting arrow tip as a graphic element
% instead of text, making the transition between line and arrow tip
% less noticeable.
\def\tikzcd@tempa{pgfsys-pdftex.def}
\ifx\pgfsysdriver\tikzcd@tempa
  \def\tikzcd@arrowset{\tikzcd@arrowset@pdftex}
\else
  \def\tikzcd@arrowset{\tikzcd@arrowset@generic}
\fi

% #1 `start' or `end'
% #2 arrow name
\def\tikzcd@arrowset@pdftex#1#2{%
  \expandafter\def\csname pgf@#1arrow\endcsname{%
    \pgfinterruptpath%
    \pgf@relevantforpicturesizefalse%
    \pgftransformreset%
    \pgfsys@beginscope%
    \pgfmathsetlengthmacro\tikzcd@len{\csname tikzcd@arrows@length@#2\endcsname}%
    \setbox\pgfutil@tempboxa=\hbox{\pgfinterruptpicture %
                 \csname tikzcd@arrows@cmd@#2\endcsname\endpgfinterruptpicture}%
    \csname tikzcd@arrows@ifhead@#2\endcsname%
      \pgftransformxshift{\tikzcd@len-\wd\pgfutil@tempboxa}%
    \else%
      \pgftransformrotate{180}%
      \pgftransformxshift{-\tikzcd@len}%
    \fi%
    \pgftransformyshift{-\csname tikzcd@arrows@axheight@#2\endcsname}%
    \pdfliteral{7 Tr}%
    \pgflowlevelsynccm\copy\pgfutil@tempboxa%
    \csname tikzcd@arrows@ifhead@#2\endcsname\else%
       \pgftransformxshift{\tikzcd@len-\wd\pgfutil@tempboxa}%
    \fi%
    \pgfpathrectangle{\pgfpoint{0pt}{-1ex}}{\pgfpoint{-\tikzcd@len}{3ex}}%
    \pgfusepathqfill%
    \pgfsys@endscope%
    \endpgfinterruptpath}%
  \expandafter\def\csname pgf@shorten@#1\endcsname{%
    \pgfmathsetlength\pgf@xa{\csname tikzcd@arrows@length@#2\endcsname}%
    \advance\pgf@x by\pgf@xa}}%

% #1 `start' or `end'
% #2 arrow name
\def\tikzcd@arrowset@generic#1#2{%
  \expandafter\def\csname pgf@#1arrow\endcsname{%
    \pgfinterruptpath%
    \pgf@relevantforpicturesizefalse%
    \pgftransformreset%
    \pgfsys@beginscope%
    \pgfmathsetlengthmacro\tikzcd@len{\csname tikzcd@arrows@length@#2\endcsname}%
    \pgfpathrectangle{\pgfpoint{0pt}{-1.5ex}}{\pgfpoint{\tikzcd@len}{3ex}}%
    \pgfusepathqclip%
    \csname tikzcd@arrows@ifhead@#2\endcsname%
      \pgftransformxshift{\tikzcd@len}%
    \else%
      \pgftransformrotate{180}%
      \pgftransformxshift{-\tikzcd@len}%
    \fi%
    \pgftransformyshift{-\csname tikzcd@arrows@axheight@#2\endcsname}%
    \pgftext[\csname tikzcd@arrows@ifhead@#2\endcsname right\else left\fi,base]%
            {\csname tikzcd@arrows@cmd@#2\endcsname}%
    \pgfsys@endscope%
    \endpgfinterruptpath}%
  \expandafter\def\csname pgf@shorten@#1\endcsname{%
    \pgfmathsetlength\pgf@xa{\csname tikzcd@arrows@length@#2\endcsname}%
    \advance\pgf@x by\pgf@xa}}%

% The arguments for `declare head' and `declare tail' are 1. name of
% the arrow tip, 2. TeX command corresponding to an arrow, 3. distance
% from baseline to arrow stem, 4. width of the clip box, which should
% be big enough to contain the whole tip.
\tikzset{/tikz/commutative diagrams/font arrows/.cd,
  double distance={3.8\pgflinewidth},
  declare head={math to}{$\to$}{\tikzcdaxisheight}{1ex},
  declare head={math to reversed}{$\leftarrowtail$}{\tikzcdaxisheight}{1ex},
  declare tail={math cap}{$\to$}{\tikzcdaxisheight}{1ex},
  declare tail={math |}{$\mapsto$}{\tikzcdaxisheight}{1ex},
  declare head={math o}{$\multimap$}{\tikzcdaxisheight}{1.4ex},
  declare head={math implies}{$\Rightarrow$}{\tikzcdaxisheight}{1.4ex},
  declare tail={math implies cap}{$\Rightarrow$}{\tikzcdaxisheight}{1ex},
  declare head={math left hook}{$\hookleftarrow$}{\tikzcdaxisheight}{1ex},
  declare tail={math right hook}{$\hookrightarrow$}{\tikzcdaxisheight}{1ex},
  declare head={math double to}{$\twoheadrightarrow$}{\tikzcdaxisheight}{1.4ex},
  declare head={math left to}{$\rightharpoonup$}{\tikzcdaxisheight}{1ex},
  declare head={math right to}{$\rightharpoondown$}{\tikzcdaxisheight}{1ex},
}

% The `math font' arrow style
\pgfkeys{/tikz/commutative diagrams/arrow style/math font/.style={
    /tikz/commutative diagrams/.cd,
    enable font arrows,
    default arrow/.style={
      /tikz/arrows=math cap-math to,
      /tikz/line width=\tikzcdrulethickness},
    rightarrow/.style={/tikz/arrows=math cap-math to},
    Rightarrow/.style={
      /tikz/arrows=math implies cap-math implies,
      /tikz/commutative diagrams/double line},
    leftarrow/.style={/tikz/arrows=math to-math cap},
    Leftarrow/.style={
      /tikz/arrows=math implies-math implies cap,
      /tikz/commutative diagrams/double line},
    leftrightarrow/.style={/tikz/arrows=math to-math to},
    Leftrightarrow/.style={
      /tikz/arrows=math implies-math implies,
      /tikz/commutative diagrams/double line},
    mapsto/.style={/tikz/arrows=math |-math to},
    hookrightarrow/.style={/tikz/arrows=math right hook-math to},
    hookleftarrow/.style={/tikz/arrows=math to-math left hook},
    rightharpoonup/.style={/tikz/arrows=math cap-math left to},
    rightharpoondown/.style={/tikz/arrows=math cap-math right to},
    leftharpoonup/.style={/tikz/arrows=math right to-math cap},
    leftharpoondown/.style={/tikz/arrows=math left to-math cap},
    rightarrowtail/.style={/tikz/arrows=math to reversed-math to},
    leftarrowtail/.style={/tikz/arrows=math to-math to reversed},
    twoheadrightarrow/.style={/tikz/arrows=math cap-math double to},
    twoheadleftarrow/.style={/tikz/arrows=math double to-math cap},
    equals/.style={
      /tikz/arrows=math implies cap-math implies cap,
      /tikz/commutative diagrams/double line},
    maps to/.code={\pgfsetarrowsstart{math |}},
    hook/.code={\pgfsetarrowsstart{math right hook}},
    two heads/.code={\pgfsetarrowsend{math double to}},
    tail/.code={\pgfsetarrowsstart{math to reversed}},
    double line/.style={
      /tikz/double=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
      /tikz/double distance=\tikzcdfontarrowsdoubledistance},
    dashed/.style={/tikz/densely dashed}}}

\endinput
