% Copyright 2011, 2012 by Florêncio Neves
%
% 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 3 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, see <http://www.gnu.org/licenses/>.

% \ProvidesPackage{tikz-cd}[2012/12/30 v0.3c Commutative diagrams with tikz.]
% \RequirePackage{tikz}[2010/10/13] % pgf version 2.10 required

\usetikzlibrary{matrix}

\newif\iftikzcd@mathmode

\pgfqkeys{/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}},
  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}}, %$
  arrow style/.is choice}

% generic arrow tip selection styles
\pgfkeysdef{/tikz/commutative diagrams/arrow style/generic}{%
  \pgfqkeys{/tikz/commutative diagrams}{
    rightarrow/.style={/tikz/arrows=-#1 to},
    Rightarrow/.style={
      /tikz/arrows=-#1 implies,
      /tikz/commutative diagrams/double line},
    leftarrow/.style={/tikz/arrows=#1 to-},
    Leftarrow/.style={
      /tikz/arrows=#1 implies-,
      /tikz/commutative diagrams/double line},
    leftrightarrow/.style={/tikz/arrows=#1 to-#1 to},
    Leftrightarrow/.style={
      /tikz/arrows=#1 implies-#1 implies,
      /tikz/commutative diagrams/double line},
    mapsto/.style={/tikz/arrows=#1 |-#1 to},%|
    mapsfrom/.style={/tikz/arrows=#1 to-#1 |},%|
    hookrightarrow/.style={/tikz/arrows=#1 right hook-#1 to},
    hookleftarrow/.style={/tikz/arrows=#1 to-#1 left hook},
    rightharpoonup/.style={/tikz/arrows=-#1 left to},
    rightharpoondown/.style={/tikz/arrows=-#1 right to},
    leftharpoonup/.style={/tikz/arrows=#1 right to-},
    leftharpoondown/.style={/tikz/arrows=#1 left to-},
    rightarrowtail/.style={/tikz/arrows=#1 to reversed-#1 to},
    leftarrowtail/.style={/tikz/arrows=#1 to-#1 to reversed},
    twoheadrightarrow/.style={/tikz/arrows=-#1 double to},
    twoheadleftarrow/.style={/tikz/arrows=#1 double to-},
    maps to/.code={\pgfsetarrowsstart{#1 |}},%|
    hook/.code={\pgfsetarrowsstart{#1 right hook}},
    two heads/.code={\pgfsetarrowsend{#1 double to}},
    tail/.code={\pgfsetarrowsstart{#1 to reversed}}}}

\pgfqkeys{/tikz/commutative diagrams}{
  dash/.style={/tikz/arrows=-},
  dashrightarrow/.style={
    /tikz/commutative diagrams/rightarrow,
    /tikz/commutative diagrams/dashed},
  dashleftarrow/.style={
    /tikz/commutative diagrams/leftarrow,
    /tikz/commutative diagrams/dashed},
  equal/.style={
    /tikz/arrows=-,
    /tikz/commutative diagrams/double line},
  equals/.style={/tikz/commutative diagrams/equal},
  rightsquigarrow/.style={
    /tikz/commutative diagrams/rightarrow,
    /tikz/commutative diagrams/squiggly},
  leftsquigarrow/.style={
    /tikz/commutative diagrams/leftarrow,
    /tikz/commutative diagrams/squiggly},
  leftrightsquigarrow/.style={
    /tikz/commutative diagrams/leftrightarrow,
    /tikz/commutative diagrams/squiggly},
  squiggly/.code={%
    \expandafter\ifx\csname tikz@library@decorations.pathmorphing@loaded\endcsname\pgfutil@empty%
    \else\PackageError{tikz-cd}{You need to say %
      \string\usetikzlibrary{decorations.pathmorphing} to use squiggly arrows}{}\fi%
    \pgfkeysalso{
      /tikz/decorate,
      /tikz/decoration={
        zigzag,
        segment length=9.25\pgflinewidth,
        amplitude=1.9\pgflinewidth,
        post=lineto, post length=6\pgflinewidth,
        pre=lineto, pre length=6\pgflinewidth,
        #1}}}}

% The Computer Modern arrow style
\pgfkeysdef{/tikz/commutative diagrams/arrow style/computer modern}{%
  \pgfqkeys{/tikz/commutative diagrams}{
    arrow style/generic={cm},
    default arrow/.style={
      /tikz/line join=round,
      /tikz/commutative diagrams/rightarrow,
      /tikz/line width=0.0929ex},
    double line/.style={
      /tikz/double=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
      /tikz/double distance=3.643\pgflinewidth},
    dashed/.style={/tikz/dash pattern={on 7\pgflinewidth off 4\pgflinewidth}}}}

% The tikz arrow style
\pgfkeysdef{/tikz/commutative diagrams/arrow style/tikz}{%
  \expandafter\ifx\csname tikz@library@arrows@loaded\endcsname\pgfutil@empty%
  \else\PackageError{tikz-cd}{You need to say \string\usetikzlibrary{arrows} %
    to use the `tikz' arrow style}{}\fi
  \pgfqkeys{/tikz/commutative diagrams}{
    arrow style/generic={\pgfutil@firstofone},
    default arrow/.style={/tikz/commutative diagrams/rightarrow},
    rightarrow/.style={/tikz/arrows=->},
    leftarrow/.style={/tikz/arrows=<-},
    leftrightarrow/.style={/tikz/arrows=<->},
    mapsto/.style={/tikz/arrows=|->},%|
    mapsfrom/.style={/tikz/arrows=<-|},%|
    hookrightarrow/.style={/tikz/arrows=right hook->},
    hookleftarrow/.style={/tikz/arrows=<-left hook},
    rightarrowtail/.style={/tikz/arrows=>->},
    leftarrowtail/.style={/tikz/arrows=<-<},
    twoheadrightarrow/.style={/tikz/arrows=->>},
    twoheadleftarrow/.style={/tikz/arrows=<<-}, %>>
    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,
    @enablequotes,
    /tikz/draw,
    default arrow},
  every label/.style={
    /tikz/commutative diagrams/.cd,
    /tikz/auto,
    /tikz/font=\everymath\expandafter{\the\everymath\scriptstyle},
    /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},
  1-row diagram/.style={/tikz/baseline=(#1.base)},
  math mode=true,
  center yshift/.initial=tikzcdaxis,
  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,
  crossing over clearance/.initial=1.5ex,
  background color/.initial=white}

% pgfmath functions to obtain math fontdimens
\pgfmathdeclarefunction{tikzcdaxis}{0}{%
  \begingroup%
    $\relax$% update fontdimens
    \pgfutil@ifundefined{um_axis:N}% check if `unicode-math' is used
      {\pgf@x=\the\fontdimen22\textfont2\relax}%
      {\pgf@x=\expandafter\the\csname um_axis:N\endcsname\textstyle}%
    \pgfmathreturn\pgf@x%
  \endgroup}

\pgfmathdeclarefunction{tikzcdrule}{0}{%
  \begingroup%
    $\relax$%
    \pgfutil@ifundefined{um_fraction_rule:N}%
      {\pgf@x=\the\fontdimen8\textfont3\relax}%
      {\pgf@x=\expandafter\the\csname um_fraction_rule:N\endcsname\textstyle}%
    \pgfmathreturn\pgf@x%
  \endgroup}

% 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 yshift}}}
  \anchor{west}{\pgf@anchor@rectangle@west\pgfmathsetlength\pgf@y%
    {\pgfkeysvalueof{/tikz/commutative diagrams/center yshift}}}
  \anchor{east}{\pgf@anchor@rectangle@east\pgfmathsetlength\pgf@y%
    {\pgfkeysvalueof{/tikz/commutative diagrams/center yshift}}}
  \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 yshift}}%
    \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%
  }%
}%

% The arrow commands
\def\tikzcd@arrow{%
  \begingroup% 
  \pgfutil@ifnextchar[{\tikzcd@ar@getdir}{\tikzcd@ar@getdir[]}}

\def\tikzcd@ar@getdir[#1]#2{%
  \c@pgf@counta\pgfmatrixcurrentrow%
  \c@pgf@countb\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@startanchor) to }%
  \pgfutil@ifnextchar[{\tikzcd@ar@getlabel}{\pgfutil@ifnextchar\bgroup{\tikzcd@ar@getlabel[]}{\tikzcd@ar@final}}}

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

\def\tikzcd@ar@final{%
  \toks@\expandafter{\tikzcd@savedpaths}%
  \global\edef\tikzcd@savedpaths{%
    \the\toks@%
    (\tikzmatrixname-\the\c@pgf@counta-\the\c@pgf@countb\noexpand\tikzcd@endanchor); }%
  \endgroup}% restore pgf counters

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

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

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

% `quotes' library support
\def\tikzcd@passquotes#1{\tikzset{every to/.append style={#1}}}

\pgfqkeys{/tikz/commutative diagrams}{
  @enablequotes/.style={
    /handlers/first char syntax/the character "/.initial=\tikzcd@passquotes,
    /tikz/edge quotes mean/.try={%
      edge node={node [/tikz/commutative diagrams/every label,##2]{\tikzcd@mathmaybe{##1}}}}}}

% `start anchor', `end anchor', and `shift' keys
\def\tikzcd@setanchor#1[#2]#3\relax{%
  \ifx\relax#2\relax\else%
    \pgfqkeys{/tikz/commutative diagrams}{@#1transform/.append style={#2},@shiftabletopath}%
  \fi%
  \ifx\relax#3\relax%
    \expandafter\let\csname tikzcd@#1anchor\endcsname\empty%
  \else%
    \expandafter\def\csname tikzcd@#1anchor\endcsname{.#3}%
  \fi}

\pgfqkeys{/tikz/commutative diagrams}{
  @shiftabletopath/.style={
    /tikz/execute at begin to={%
      \begingroup%
        \def\tikz@tonodes{coordinate[pos=0,commutative diagrams/@starttransform/.try](tikzcd@nodea) %
                          coordinate[pos=1,commutative diagrams/@endtransform/.try](tikzcd@nodeb)}%
        \path (\tikztostart) \tikz@to@path;%
      \endgroup%
      \def\tikztostart{tikzcd@nodea}%
      \def\tikztotarget{tikzcd@nodeb}%
      \toks@\expandafter{\tikz@to@path}%
      \edef\tikz@to@path{(tikzcd@nodea) \the\toks@}
    },
    /tikz/commutative diagrams/@shiftabletopath/.code={}},
  start anchor/.code={%
    \pgfutil@ifnextchar[{\tikzcd@setanchor{start}}{\tikzcd@setanchor{start}[]}#1\relax},%]
  end anchor/.code={%
    \pgfutil@ifnextchar[{\tikzcd@setanchor{end}}{\tikzcd@setanchor{end}[]}#1\relax},%]
  start anchor=,
  end anchor=,
  shift left/.style={
    /tikz/commutative diagrams/@shiftabletopath,
    /tikz/execute at begin to={%
      \pgfpointnormalised{%
        \pgfpointdiff{\pgfpointanchor{tikzcd@nodeb}{center}}{\pgfpointanchor{tikzcd@nodea}{center}}}%
      \pgfgetlastxy{\tikzcd@x}{\tikzcd@y}%
      \pgfmathparse{(#1)/1pt}%
      \coordinate (tikzcd@nodea) at ([shift={(\pgfmathresult*\tikzcd@y,-\pgfmathresult*\tikzcd@x)}]tikzcd@nodea);%
      \coordinate (tikzcd@nodeb) at ([shift={(\pgfmathresult*\tikzcd@y,-\pgfmathresult*\tikzcd@x)}]tikzcd@nodeb);}},
  shift right/.style={
    /tikz/commutative diagrams/shift left={-(#1)}},
  transform nodes/.style={
    /tikz/commutative diagrams/@shiftabletopath,
    /tikz/commutative diagrams/@starttransform/.append style={#1},
    /tikz/commutative diagrams/@endtransform/.append style={#1}},
  shift/.style={
    /tikz/shift={#1},% we need this for labels to receive a shift
    /tikz/commutative diagrams/transform nodes={/tikz/shift={#1}}},
  xshift/.style={
    /tikz/xshift={#1},
    /tikz/commutative diagrams/transform nodes={/tikz/xshift={#1}}},
  yshift/.style={
    /tikz/yshift={#1},
    /tikz/commutative diagrams/transform nodes={/tikz/yshift={#1}}}}

% The `tikzcd' environment
\def\tikzcd{\pgfutil@ifnextchar[{\tikzcd@}{\tikzcd@[]}}

\def\tikzcd@[#1]{%
  \tikzpicture[/tikz/commutative diagrams/every diagram,#1]%
  \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}}%
  \global\let\tikzcd@savedpaths\empty
  \matrix[/tikz/commutative diagrams/matrix of math nodes maybe]\bgroup}

\def\endtikzcd{%
  \toks@\expandafter{\tikzcd@savedpaths}%
  \global\edef\tikzcd@savedpaths{%
    \noexpand\tikzset{commutative diagrams/\the\pgfmatrixcurrentrow-row diagram/.try=\tikzmatrixname}%
    \the\toks@}%
  \pgfmatrixendrow\egroup;%
  \tikzcd@savedpaths%
  \endtikzpicture}

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

\def\tikzcd@sep#1#2{
  \pgfkeysifdefined{/tikz/commutative diagrams/#1 sep/#2}%
    {\pgfkeysalso{/tikz/#1 sep=\pgfkeysvalueof{/tikz/commutative diagrams/#1 sep/#2}}}%
    {\pgfkeysalso{/tikz/#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)
\pgfkeysdef{/tikz/commutative diagrams/enable font arrows}{%
  % 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}}}}%
    {}}

\pgfqkeys{/tikz/commutative diagrams/font arrows}{
  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@temp{pgfsys-pdftex.def}
\ifx\pgfsysdriver\tikzcd@temp
  \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.
\pgfqkeys{/tikz/commutative diagrams/font arrows}{
  double distance={3.8\pgflinewidth},
  declare head={math to}{$\to$}{tikzcdaxis}{1ex},
  declare head={math to reversed}{$\leftarrowtail$}{tikzcdaxis}{1ex},
  declare tail={math cap}{$\to$}{tikzcdaxis}{1ex},
  declare tail={math |}{$\mapsto$}{tikzcdaxis}{1ex},%|
  declare head={math o}{$\multimap$}{tikzcdaxis}{1.4ex},
  declare head={math implies}{$\Rightarrow$}{tikzcdaxis}{1.4ex},
  declare tail={math implies cap}{$\Rightarrow$}{tikzcdaxis}{1ex},
  declare head={math left hook}{$\hookleftarrow$}{tikzcdaxis}{1ex},
  declare tail={math right hook}{$\hookrightarrow$}{tikzcdaxis}{1ex},
  declare head={math double to}{$\twoheadrightarrow$}{tikzcdaxis}{1.4ex},
  declare head={math left to}{$\rightharpoonup$}{tikzcdaxis}{1ex},
  declare head={math right to}{$\rightharpoondown$}{tikzcdaxis}{1ex},
}

% The `math font' arrow style
\pgfkeys{/tikz/commutative diagrams/arrow style/math font/.style={
    /tikz/commutative diagrams/.cd,
    enable font arrows,
    arrow style/generic={math},
    default arrow/.style={
      /tikz/commutative diagrams/rightarrow,
      /tikz/line width=tikzcdrule},
    double line/.style={
      /tikz/double=\pgfkeysvalueof{/tikz/commutative diagrams/background color},
      /tikz/double distance=\tikzcdfontarrowsdoubledistance},
    dashed/.style={/tikz/dash pattern=on 0.8ex off 0.4ex},
    squiggly/.default={pre length=1ex,post length=1ex}}}

\endinput
