%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Version: 2021/10/15
%%% License: MIT
%%% Author: Léo Colisson
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% A tikzlibrary[libraryName].code.tex is loaded automatically by tikz when using
% \usetikzlibrary{libraryName}. Therefore, you should just use
% \usetikzlibrary{zx} to load this library. We also provide a package to
% directly load this library using \usepackage{zx}.

\RequirePackage{amssymb} % For short minus
\RequirePackage{etoolbox}
\RequirePackage{ifthen} % For conditions
\RequirePackage{xparse} % For NewDocumentComments
\RequirePackage{bm} % For bold math fonts

\usetikzlibrary{cd,backgrounds,positioning,shapes,calc}
% Declare layers.
\pgfdeclarelayer{background} % Fox boxes using "fit" to group parts of the graph.
\pgfdeclarelayer{edgelayer} % For edges that are explicitely defined "wc"
\pgfdeclarelayer{nodelayer} % For nodes... in theory, this fails for now. https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd
\pgfdeclarelayer{main}
\pgfdeclarelayer{box} % For boxes using "fit" to fake multi-column boxes
\pgfdeclarelayer{labellayer} % For labels... in theory, this fails for now. https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd
\pgfdeclarelayer{foreground} % For the user, if they want to put anything really above everything.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% User modifiable variables
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Define colors, can be redefine by user
\definecolor{colorZxZ}{RGB}{204,255,204}
\definecolor{colorZxX}{RGB}{255,136,136}
\definecolor{colorZxH}{RGB}{255,255,0}

%%% Some wires (the one having an intermediate H, X, or S gate) may need some additional space for
%%% specific columns.
%%% Use these spaces like &[\zxHCol] or \\[\zxHRow] in that case
%% Defines the space to add for columns and rows containing a connection with Hadamard
% This is for "curved" wires
\newcommand{\zxHCol}{1mm}
\newcommand{\zxHRow}{1mm}
% This is for "flat" wires (usually takes more space)
\newcommand{\zxHColFlat}{1.5mm}
\newcommand{\zxHRowFlat}{1.5mm}
%% Defines the space to add for columns and rows containing a connection with small X/Z
\newcommand{\zxSCol}{1mm}
\newcommand{\zxSRow}{1mm}
\newcommand{\zxSColFlat}{1.5mm}
\newcommand{\zxSRowFlat}{1.5mm}
%% Defines the space to add for columns having both H and Spiders
\newcommand{\zxHSCol}{1mm}
\newcommand{\zxHSRow}{1mm}
\newcommand{\zxHSColFlat}{1mm}
\newcommand{\zxHSRowFlat}{1mm}
%% Wires only: when adding only wires with empty nodes, the space between columns can be too small. Useful not to shrink swap gates...
\newcommand{\zxWCol}{.55em}
\newcommand{\zxWRow}{.55em}
%% When vdots/dots are used in lines
\newcommand{\zxDotsCol}{3mm}
\newcommand{\zxDotsRow}{3mm}


% Angles by default for s and o related arrows
\def\zxDefaultSoftAngleS{30}
\def\zxDefaultSoftAngleN{60}
\def\zxDefaultSoftAngleO{40}
\def\zxDefaultSoftAngleChevron{60}

% Scale to use when scaling 3 dots
\def\zxScaleDots{.7}

% 0.4pt is default in tikz. Also used to ensure it has not been modified document wise by other libraries
% (quantikz notably changes this parameter).
\newcommand{\zxDefaultLineWidth}{0.4pt}

% For phase in content: How to convert sign ("-" for minus, nothing for "+", anything else should be inserted directly),
% above fraction (no parens), below fraction (no parens), above fraction (with parens), below fraction (with parens)
\NewExpandableDocumentCommand{\zxConvertToFracInContent}{mmmmm}{%
  \ifthenelse{\equal{#1}{-}}{\zxMinus}{#1}\frac{#2}{#3}%
}

% For phase in label: How to convert sign ("-" for minus, nothing for "+", anything else should be inserted directly),
% above fraction (no parens), below fraction (no parens), above fraction (with parens), below fraction (with parens)
\NewExpandableDocumentCommand{\zxConvertToFracInLabel}{mmmmm}{%
  \ifthenelse{\equal{#1}{-}}{\zxMinus}{#1}#4/#5%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Tikz styles
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Styles. User should not modify "wires definition", but is free to change:
% - "/zx/default style nodes/" to change completely the node style
% - "/zx/user overlay nodes" to add stuff on current node style
% - "/zx/default style wires" to change the wire style
% - "/zx/user overlay wires/" to add stuff on wire style
% The user is not supposed to use node styles directly (use \zxZ{}, \zxZ{\alpha+\beta}, \zxFrac-{\pi}{4}...)
% but is free (and encouraged) to use the styles in "wires definition" like \ar[r,o'].
\tikzset{
  /zx/wires definition/.style={
    %%% Basic default properties
    draw,
    -,
    line width=\zxDefaultLineWidth,
    %%% Useful shortcut (shorter lines means easy "align" of & symbols. Love M-x align in emacs btw.)
    ls/.style={looseness=##1},
    looseness wires only/.style={% Looseness used for wires only.
      looseness=1.2,
    },
    lw/.style={looseness wires only},
    % Use this when you are drawing lines between none nodes only (like swap gates...)
    between none/.style={
      looseness wires only,
      wire centered
    },
    bn/.style={
      between none
    },
    % ------------------------------
    % Practical stuff to draw lines easily:
    % Prefer to use these are they can be easily customized for each style and shorter to type.
    % Note that the letter is supposed to represent the shape of the link
    % dots/dashes are used to specify the position of the arrow.
    % Typically ' means top, . bottom, X- is right to X (or should arrive with angle 0),
    % -X is left to X (or should leave with angle zero). These shapes are usually designed to
    % work when the starting node is left most (or above of both nodes have the same column).
    % But they may work both way for some of them.
    % ------------------------------
    %%% Cup/Cap
    % Like a C shape (with without a perfect half circle). Useful maybe when perfect circles are too big.
    % If only tex was a functional language... https://tex.stackexchange.com/questions/618955
    C@generic/.style n args={8}{ % min/max, angle1, angle2, anchor, \x or \y, \y or \x, where to move,radius code (for circle should be "radius=\n3")
      to path={
        \pgfextra{ %% <- we will use def... so need to "exit" a few seconds pgf
          % Test if tikztostart is a point or a node, and define StartPoint accordingly.
          \ifPgfpointOrNode{\tikztostart}{%
            \def\StartPoint{\tikztostart}%
          }{%
            \def\StartPoint{\tikztostart.##4}%
          }%
          % Test if tikztostart is a point or a node, and define StartPoint accordingly.
          \ifPgfpointOrNode{\tikztotarget}{%
            \def\TargetPoint{\tikztotarget}%
          }{%
            \def\TargetPoint{\tikztotarget.##4}%
          }%
        }%
        (\StartPoint) % <- the path starts at StartPoint
        %%% Get x coordinate of left-most point
        let \p1=(\StartPoint),
        \p2=(\TargetPoint),
        \n1={##1(##51,##52)}, % coordinate of the most left part (when ##1=min and ##5=\x: ##52 goes to \x2)
        \n3={abs(##61-##62)/2} % Radius of circle
        in % Warning: no comma after last line before in
        %%%% We go on the left if needed (we check that we do move, otherwise we break the arrows tip if
        %%%% we stay on place
        %%%% First go to the left if needed
        \pgfextra{%
          %% We check if we are moving or not (required to preserve arrow tip direction)
          \pgfmathapproxequalto{##51}{\n1}%
        }%
        \ifpgfmathcomparison\else -- ##7\fi
        %%%% Version 1:
        \pgfextra{
          \pgfmathparse{
            ifthenelse(##61<##62, % if end angle < angle, draw clockwis
            "arc[start angle=##3,end angle=##2,##8]",%
            "arc[start angle=##2,end angle=##3,##8]"%
            )%
          }
        }
        \pgfmathresult
        \pgfextra{%
          %% We check if we are moving or not (required to preserve arrow tip direction)
          \pgfmathapproxequalto{##52}{\n1}%
        }%
        \ifpgfmathcomparison\else -- (\TargetPoint)\fi
        \tikztonodes % All to path finishes with that to deal with futur nodes I think
      }
    },
    %%
    C/.style={C@generic={min}{90}{180+90}{west}{\x}{\y}{(\n1,\y1)}{y radius=\n3, x radius=##1*\n3}},
    C/.default=1,
    % Like C, but rotated
    C-/.style={C@generic={max}{90}{-90}{east}{\x}{\y}{(\n1,\y1)}{y radius=\n3, x radius=##1*\n3}},
    C-/.default=1,
    C'/.style={C@generic={max}{0}{180}{north}{\y}{\x}{(\x1,\n1)}{x radius=\n3, y radius=##1*\n3}},
    C'/.default=1,
    C./.style={C@generic={min}{0}{-180}{south}{\y}{\x}{(\x1,\n1)}{x radius=\n3, y radius=##1*\n3}},
    C./.default=1,
    % Like a C shape (with without a perfect half circle). This was the old definition of C...
    % Hopefully not useful anymore.
    c/.style={/tikz/in=180,/tikz/out=180,looseness=2},
    % Like C, but symetric
    c-/.style={/tikz/in=0,/tikz/out=0,looseness=2},
    c'/.style={/tikz/in=90,/tikz/out=90,looseness=2},
    c./.style={/tikz/in=-90,/tikz/out=-90,looseness=2},
    % Similar to C, but with a softer angle. The '.- marker represents the portion of
    % the circle (hence the o) to keep (top, bottom,left/right).
    % Angle is customizable, for instance o'=50.
    o'/.style={/tikz/out=##1,/tikz/in=180-##1},
    o'/.default=\zxDefaultSoftAngleO,
    o./.style={/tikz/out=-##1,/tikz/in=180+##1},
    o./.default=\zxDefaultSoftAngleO,
    -o/.style={/tikz/out=-90-##1,/tikz/in=90+##1},
    -o/.default=\zxDefaultSoftAngleO,
    o-/.style={/tikz/out=-90+##1,/tikz/in=90-##1},
    o-/.default=\zxDefaultSoftAngleO,
    % Similar to o, but can be used also for diagonal items.
    % Why ()? Visualize fixing the top part and moving the bottom part.
    (/.style={bend right=##1},
    (/.default=30,
    )/.style={bend left=##1},
    )/.default=30,
    ('/.style={bend left=##1},
    ('/.default=30,
    (./.style={bend right=##1},
    (./.default=30,
    <'/.style={out=##1,in=180,looseness=0.65},
    <'/.default=\zxDefaultSoftAngleChevron,
    <./.style={out=-##1,in=180,looseness=0.65},
    <./.default=\zxDefaultSoftAngleChevron,
    '>/.style={out=0,in=180-##1,looseness=0.65},
    '>/.default=\zxDefaultSoftAngleChevron,
    .>/.style={out=0,in=180+##1,looseness=0.65},
    .>/.default=\zxDefaultSoftAngleChevron,
    ^./.style={out=-90+##1,in=90,looseness=0.65},
    ^./.default=\zxDefaultSoftAngleChevron,
    .^/.style={out=-90-##1,in=90,looseness=0.65},
    .^/.default=\zxDefaultSoftAngleChevron,
    'v/.style={out=90+##1,in=-90,looseness=0.65},
    'v/.default=\zxDefaultSoftAngleChevron,
    v'/.style={out=90-##1,in=-90,looseness=0.65},
    v'/.default=\zxDefaultSoftAngleChevron,
    % Links with a s-like shape.
    s/.style={/tikz/out=0,/tikz/in=180,looseness=0.6},
    % -s'.- shapes are like s, but with a soften (customizable like o) angle.
    % The '. say if you are going up or down, and - forces a sharp angle (- is flat) on the side of the -
    s'/.style={/tikz/out=##1,/tikz/in=180+##1},
    s'/.default=\zxDefaultSoftAngleS,
    s./.style={/tikz/out=-##1,/tikz/in=180-##1},
    s./.default=\zxDefaultSoftAngleS,
    -s'/.style={/tikz/out=0,/tikz/in=180+##1},
    -s'/.default=\zxDefaultSoftAngleS,
    -s./.style={/tikz/out=0,/tikz/in=180-##1},
    -s./.default=\zxDefaultSoftAngleS,
    s'-/.style={/tikz/out=##1,/tikz/in=180},
    s'-/.default=\zxDefaultSoftAngleS,
    s.-/.style={/tikz/out=-##1,/tikz/in=180},
    s.-/.default=\zxDefaultSoftAngleS,
    % Links with a s-like shape... but read from top to bottom
    ss/.style={/tikz/out=0-90,/tikz/in=180-90,looseness=0.6},
    % -s'.- shapes are like s, but with a soften (customizable like o) angle.
    % The '. say if you are going up or down, and - forces a sharp angle (- is flat) on the side of the -
    ss./.style={/tikz/out=##1-90,/tikz/in=180-90+##1},
    ss./.default=\zxDefaultSoftAngleS,
    .ss/.style={/tikz/out=-##1-90,/tikz/in=180-90-##1},
    .ss/.default=\zxDefaultSoftAngleS,
    sIs./.style={/tikz/out=0-90,/tikz/in=180-90+##1},
    sIs./.default=\zxDefaultSoftAngleS,
    .sIs/.style={/tikz/out=0-90,/tikz/in=180-90-##1},
    .sIs/.default=\zxDefaultSoftAngleS,
    ss.I/.style={/tikz/out=##1-90,/tikz/in=180-90},
    ss.I/.default=\zxDefaultSoftAngleS,
    I.ss/.style={/tikz/out=-##1-90,/tikz/in=180-90},
    I.ss/.default=\zxDefaultSoftAngleS,
    %%%% Links with a N-shape, i.e. like s shape, but symetric against the diagonal. Equivalently, it's a soft 's' shape with a much wider angle (>45).
    N'/.style={/tikz/out=##1,/tikz/in=180+##1},
    N'/.default=\zxDefaultSoftAngleN,
    N./.style={/tikz/out=-##1,/tikz/in=180-##1},
    N./.default=\zxDefaultSoftAngleN,
    -N'/.style={/tikz/out=0,/tikz/in=180+##1},
    -N'/.default=\zxDefaultSoftAngleN,
    -N./.style={/tikz/out=0,/tikz/in=180-##1},
    -N./.default=\zxDefaultSoftAngleN,
    N'-/.style={/tikz/out=##1,/tikz/in=180},
    N'-/.default=\zxDefaultSoftAngleN,
    N.-/.style={/tikz/out=-##1,/tikz/in=180},
    N.-/.default=\zxDefaultSoftAngleN,
    % No line but vdots/dots in between.
    3 vdots/.style={draw=none, "\makebox[0pt][r]{##1}\scalebox{\zxScaleDots}{$\cvdots$}" anchor=center},
    3 vdots/.default={},
    3 dots/.style={draw=none, "\makebox[0pt][r]{##1}\scalebox{\zxScaleDots}{$\chdots$}" anchor=center},
    3 dots/.default={},
    % Add a Hadmard/Z/X (no phase) in the middle of the line. Practical to add small nodes without creating
    % a new column/row. However, make sure the corresponding row/column is larger, using &[\zxHCol]
    % for columns and \\[\zxHRow] for rows (for Z/X style, use zxSCol and sxSRow), if you have both spiders
    % and Hadamard, use \zxHSCol and \zxHSRow.
    H/.style={"" {zxHSmall,anchor=center}},
    Z/.style={"" {zxNoPhaseSmallZ,anchor=center}},
    X/.style={"" {zxNoPhaseSmallX,anchor=center}},
    % Arrow will go out from the center of the shape instead of from the border. Useful
    % when connecting nodes with different shapes, it will give back a symetric connection.
    wire centered/.style={
      on layer=edgelayer,
      /tikz/commutative diagrams/start anchor=center,
      /tikz/commutative diagrams/end anchor=center,
    },
    wire centered start/.style={
      on layer=edgelayer,
      /tikz/commutative diagrams/start anchor=center,
    },
    wire centered end/.style={
      on layer=edgelayer,
      /tikz/commutative diagrams/end anchor=center,
    },
    wc/.style={wire centered},
    wcs/.style={wire centered start},
    wce/.style={wire centered end},
    wire not centered/.style={
      /tikz/commutative diagrams/start anchor=,
      /tikz/commutative diagrams/end anchor=,
    },
  },
  /zx/styles/rounded style/.style={
    %% Can be redefined by user
    % Style for empty nodes
    zxAllNodes/.style={
      shape=rectangle, % Otherwise nodes are asymetrical rectangle, which is not practical in our case. Gives notably anchor "center" which is really centered compared to asymatrical rectangles
      anchor=center,   % Center cells
      line width=\zxDefaultLineWidth,
      execute at begin node={\thinmuskip=0mu\medmuskip=0mu\thickmuskip=0mu}, % Reduce space around +/-...
    },
    % Use this to denote an empty diagram
    zxEmptyDiagram/.style={
      zxAllNodes,
      draw,
      dashed,
      minimum size=4mm,
    },
    % Style to use when no node is drawn
    zxNone/.style={
      zxAllNodes,
      shape=coordinate, % A coordinate has just a center. Nothing more.
    },
    % Style to use when no node is drawn, but a bit of space is required not to make the diagram too small
    zxNone+/.style={
      zxAllNodes,
      inner sep=1mm,
      outer sep=0mm
    },
    % Like zxNone+, but without width (wold prefer |, but special car in |[]|...
    zxNoneI/.style={
      zxNone+,
      inner xsep=0mm,
    },
    % Like zxNone+, but without height
    zxNone-/.style={
      zxNone+,
      inner ysep=0mm,
    },
    % Style to use when no node is drawn, but a large space must be reserved (typically used to fake two
    % nodes on a single line) (for +I- versions)
    zxNoneDouble/.style={
      shape=coordinate
    },
    % Style to use when no node is drawn, but a bit of space is required not to make the diagram too small
    zxNoneDouble+/.style={
      zxAllNodes,
      inner sep=.6em,
      outer sep=0mm
    },
    % Like zxNoneDouble+, but without width (wold prefer |, but special car in |[]|...
    zxNoneDoubleI/.style={
      zxNoneDouble+,
      inner xsep=0mm,
    },
    % Like zxNoneDouble+, but without height
    zxNoneDouble-/.style={
      zxNoneDouble+,
      inner ysep=0mm,
    },
    % Will be specific to all spiders
    zxSpiders/.style={
      draw=black,
    },
    % Will use this style when drawing a X/Z node without phase (not for end user directly)
    zxNoPhase/.style={
      zxAllNodes,
      zxSpiders,
      inner sep=0mm,
      minimum size=2mm,
      shape=circle,
    },
    % Used only in decoration of wires, to add small empty X/Z nodes.
    zxNoPhaseSmall/.style={
      zxNoPhase
    },
    % Style for nodes that are small enough to fit in a circle, like $\zxMinus \frac{\pi}{4}$
    zxShort/.style={
      zxAllNodes,
      zxSpiders,
      minimum size=5mm,
      font={\fontsize{8}{10}\selectfont\boldmath},
      rounded rectangle,
      inner sep=0.0mm,
      scale=0.8,
    }, % negative outer sep would draw lines from inside...
    % Style for nodes that are bigger, like $\alpha+\beta$ or $(a\oplus b)\pi$
    zxLong/.style={zxShort, inner xsep=1.2mm},
    %%% Styles of the label when |phase in label| is used
    stylePhaseInLabel/.style={
      font={\fontsize{8}{10}\selectfont\boldmath},
      inner sep=2pt,
      outer sep=0pt,
      rounded rectangle,
      % node on layer=labellayer, %% Fails in tikzcd: https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd
    },
    stylePhaseInLabelZ/.style={
      stylePhaseInLabel,
      fill=green!20!white
    },
    stylePhaseInLabelX/.style={
      stylePhaseInLabel,
      fill=red!20!white
    },
    %%%%%%%%%%% Style defined depending on above ones. Feel free to redefine.
    zxNoPhaseZ/.style={zxNoPhase,fill=colorZxZ},
    zxNoPhaseX/.style={zxNoPhase,fill=colorZxX},
    zxNoPhaseSmallZ/.style={zxNoPhaseSmall,fill=colorZxZ},
    zxNoPhaseSmallX/.style={zxNoPhaseSmall,fill=colorZxX},
    zxShortZ/.style={zxShort,fill=colorZxZ},
    zxShortX/.style={zxShort,fill=colorZxX},
    zxLongZ/.style={zxLong,fill=colorZxZ},
    zxLongX/.style={zxLong,fill=colorZxX},
    %%%%%%%%%%%
    %%% Instead of adding directly the style as the node's content (which would make
    %%% impossible styles that adds the phase in a label outside of the node)
    %%% add@Phase@Spider{,Z,X}={phase of the node} will be in charge of adding it.
    add@Phase@Spider/.style n args={4}{ % add@Phase@Spider{emptyStyle}{NotEmptyStyle}{node content}
      zx@emptyStyle/.style={##1},
      zx@notEmptyStyle/.style={##2},
      zx@labelStyle/.style={##3},
      /zx/zx@content/.initial={##4},
      phase in content,
    },
    add@Phase@Spider@Frac/.style n args={8}{ % add@Phase@Spider{emptyStyle}{NotEmptyStyle}{labelstyle}{sign}{above fraction (no parens)}{below fraction (no parens)}{above fraction (parens)}{below fraction (parens)}
      zx@emptyStyle/.style={##1},
      zx@notEmptyStyle/.style={##2},
      zx@labelStyle/.style={##3},
      % Useful to help "phase in content" to know if we are in Frac or not.
      /zx/zx@isInFrac/.initial={true},
      phase in content,
    },
    % #1 is the node content. Seems that storing it in /zx/zx@content is not enough because keys
    % seems to be local to nodes and are not transfered to label.
    zx@Execute@Very@End/.style n args={4}{
      zx@commandToExecuteVeryEnd/.try={##1}{##2}{##3}{##4},
    },
    zx@Execute@Very@End/.default={}{}{}{},
    %% zx@Execute@Very@End@Frac={emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)}
    zx@Execute@Very@End@Frac/.style n args={8}{
      zx@commandToExecuteVeryEndFrac/.try={##1}{##2}{##3}{##4}{##5}{##6}{##7}{##8},
    },
    zx@Execute@Very@End@Frac/.default={}{}{}{}{}{}{}{},
    %% /!\ WARNING: the following styles "phase..." must be loaded by or *after* add@Phase@Spider...
    %% To load it on the whole picture, prefer to do:
    %% \zx[/zx/user post preparation labels/.style={phase in label}]{
    %%   \zxZ{\alpha}
    %% }
    phase in content/.code={%
      % Check if we are in a Frac or not
      \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@isInFrac}}{true}}{%
        %%% ### We are in a fraction node!
        %% Modifies zx@commandToExecuteVeryEnd (which is executed at the very end by zx@Execute@Very@End)
        %% in order to add the good style
        \pgfkeysalso{
          % zx@commandToExecuteVeryEndFrac{emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)}
          zx@commandToExecuteVeryEndFrac/.style n args={8}{%
            execute at begin node={\zxConvertToFracInContent{####4}{####5}{####6}{####7}{####8}},%
          },%
          % Adds the style:
          zx@notEmptyStyle,
        }%
      }{ %%% ### We are NOT in a fraction node.
        %% Modifies zx@commandToExecuteVeryEnd (which is executed at the very end by zx@Execute@Very@End)
        %% in order to add the good style
        \pgfkeysalso{
          zx@commandToExecuteVeryEnd/.style n args={4}{%
            execute at begin node={####4},% ####4 = content
          }%
        }%
        % Checks if the content (stored by add@Phase@Spider in /zx/zx@content) is empty or not
        \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@content}}{}}{%
          \pgfkeysalso{%
            zx@emptyStyle,%
          }%
        }{%
          \pgfkeysalso{%
            zx@notEmptyStyle,%
          }%
        }%
      }%
    },
    phase in label/.code={
      % Check if we are in a Frac or not
      \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@isInFrac}}{true}}{%
        %%% ### We are in a fraction node!
        \pgfkeysalso{%
          % zx@commandToExecuteVeryEndFrac{emptystyle}{contentstyle}{labelstyle}{sign}{above frac (no parens)}{below frac (no parens)}{above frac (parens)}{below frac (parens)}
          zx@commandToExecuteVeryEndFrac/.code n args={8}{%
            \pgfkeysalso{
              label={[####3,##1] \zxConvertToFracInLabel{####4}{####5}{####6}{####7}{####8}},%
            }%
          },%
          zx@emptyStyle,
        }%
      }{%
        \pgfkeysalso{%
          % ##1 is the argument of "phase in label", i.e. the style of the label
          zx@commandToExecuteVeryEnd/.code n args={4}{% ####3: label style, ####4: content
            % Checks if the content (stored by add@Phase@Spider in /zx/zx@content) is empty or not
            \ifthenelse{\equal{####4}{}}{% Content is empty
            }{% Content is not empty
              \pgfkeysalso{
                label={[####3,##1] ####4},%
              }%
            }%
          },%
          zx@emptyStyle,
        }%
      }%
    },
    pil/.style={phase in label=##1},
    phase in label below/.style={
      phase in label={label position=below,##1}
    },
    pilb/.style={phase in label below=##1},
    phase in label above/.style={
      phase in label={label position=above,##1}
    },
    pila/.style={phase in label above=##1},
    phase in label right/.style={
      phase in label={label position=right,##1}
    },
    pilr/.style={phase in label right=##1},
    phase in label left/.style={
      phase in label={label position=left,##1}
    },
    pill/.style={phase in label left=##1},
    %%% Was supposed to automatically find the good style depending on content... Can't find how to do.
    % Styles zxLong{X/Z} zxNoPhase{X/Z} are automatically selected by \zxZ2{...} and \zxX2{...} commands
    % and zxShort is selected for fractions only like in \zxFracZ-{\pi}{4}
    % zxZ/.style={zxChoose={##1},fill=colorZxZ},
    % zxX/.style={zxChoose={##1},fill=colorZxX},
    %%% First argument is additional style. Second argument is content of node.
    zxZ2/.style 2 args={
      add@Phase@Spider={zxNoPhaseZ}{zxLongZ}{stylePhaseInLabelZ}{##2},
      /zx/post preparation labels,
      /zx/user post preparation labels,
      %/zx/user overlay nodes,
      ##1,
      zx@Execute@Very@End={zxNoPhaseZ}{zxLongZ}{stylePhaseInLabelZ}{##2},
    },
    %% ##1: other styles, ##2: content
    zxX2/.style 2 args={
      add@Phase@Spider={zxNoPhaseX}{zxLongX}{stylePhaseInLabelX}{##2},
      /zx/post preparation labels,
      /zx/user post preparation labels,
      ##1,
      zx@Execute@Very@End={zxNoPhaseX}{zxLongX}{stylePhaseInLabelX}{##2},
    },
    %% These take 6 arguments: additional style, sign (string "-" for minus, nothing for "+",
    %% otherwise inserted directly), above fraction (no parens), below fraction (no parens), above fraction (parens), below fraction (parens).
    zxFracZ6/.style n args={6}{
      add@Phase@Spider@Frac={zxNoPhaseZ}{zxShortZ}{stylePhaseInLabelZ}{##2}{##3}{##4}{##5}{##6},
      /zx/post preparation labels,
      /zx/user post preparation labels,
      ##1,
      zx@Execute@Very@End@Frac={zxNoPhaseZ}{zxShortZ}{stylePhaseInLabelZ}{##2}{##3}{##4}{##5}{##6},
    },
    zxFracX6/.style n args={6}{
      add@Phase@Spider@Frac={zxNoPhaseX}{zxShortX}{stylePhaseInLabelX}{##2}{##3}{##4}{##5}{##6},
      /zx/post preparation labels,
      /zx/user post preparation labels,
      ##1,
      zx@Execute@Very@End@Frac={zxNoPhaseX}{zxShortX}{stylePhaseInLabelX}{##2}{##3}{##4}{##5}{##6},
    },
    % For Hadamard
    zxH/.style={
      zxAllNodes,
      outer sep=0pt,
      fill=colorZxH,
      draw,
      inner sep=0.6mm,
      minimum height=1.5mm,
      minimum width=1.5mm,
      shape=rectangle},
    zxHSmall/.style={zxH},
  },
  % Default style. Can be changed by user
  /zx/default style nodes/.style={
    /zx/styles/rounded style
  },
  % User can put here any additional property
  /zx/user overlay nodes/.style={
  },
  % Any additional property that needs to be loaded after add@Phase@Spider (by script, not by user).
  /zx/post preparation labels/.style={
  },
  % User can put here any additional property that needs to be loaded after add@Phase@Spider
  /zx/user post preparation labels/.style={
  },
  % Default wire style. Can be changed by user.
  /zx/default style wires/.style={
  },
  % User can add stuff in this style to improve wire styles
  /zx/user overlay wires/.style={
  },
  /zx/defaultEnv/.style={
    column sep=tiny,
    row sep=tiny,
    % center on the math axis
    baseline={([yshift=-axis_height]current bounding box.center)},
    % Fix 1-row diagram baseline
    1-row diagram/.style={%
      /tikz/baseline={([yshift=-axis_height]current bounding box.center)}%
    },
    % Load (thanks ".search also") our own style
    /tikz/every node/.style={%
      % For quickly adding alias, and displaying this alias in debug mode.
      a/.code={%
        \pgfkeysalso{%
          alias=####1,%
        }%
        \ifdefined\zxDebugMode%
          \pgfkeysalso{%
            label={[inner sep=0pt,overlay,red,font={\fontsize{5}{6}}]-45:\scalebox{.5}{####1}}
          }%
        \fi%
      },
      /zx/default style nodes,
      /zx/user overlay nodes,
    },
    every arrow/.style={%
      /zx/wires definition,
      /zx/default style wires,
      /zx/user overlay wires,
    },
    %%% To be used only in \zx{...} environment.
    %%% Exemple:
    phase in content/.style={
      /zx/post preparation labels/.append style={
        phase in content,
      }
    },
    phase in label/.style={
      /zx/post preparation labels/.append style={
        phase in label=##1,
      }
    },
    phase in label above/.style={
      /zx/post preparation labels/.append style={
        phase in label above=##1,
      }
    },
    phase in label below/.style={
      /zx/post preparation labels/.append style={
        phase in label below=##1,
      }
    },
    phase in label right/.style={
      /zx/post preparation labels/.append style={
        phase in label right=##1,
      }
    },
    phase in label left/.style={
      /zx/post preparation labels/.append style={
        phase in label left=##1,
      }
    },
    % for "Phase In Label"
    pil/.style={phase in label=##1},
    pilb/.style={phase in label below=##1},
    pila/.style={phase in label above=##1},
    pilr/.style={phase in label right=##1},
    pill/.style={phase in label left=##1},
  },
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Helper functions
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Defines a "on layer=nameoflayer" style. TODO: check if better to move it in /zx/
% https://tex.stackexchange.com/questions/20425/z-level-in-tikz/20426#20426
% For path: on layer=namelayer, for nodes "node on layer=..."
% /!\ node on layer fails in tikzcd: https://tex.stackexchange.com/questions/618823/node-on-layer-style-in-tikz-matrix-tikzcd
\pgfkeys{%
  /tikz/on layer/.code={
    \pgfonlayer{#1}\begingroup
    \aftergroup\endpgfonlayer
    \aftergroup\endgroup
  },
  /tikz/node on layer/.code={
    \gdef\node@@on@layer{%
      \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{#1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}
    \aftergroup\node@on@layer
  },
  /tikz/end node on layer/.code={
    \endpgfonlayer\endgroup\endgroup
  }
}
\def\node@on@layer{\aftergroup\node@@on@layer}

%%% Declare a symbol for a short minus (useful in fractions)
\DeclareMathSymbol{\zxMinus}{\mathbin}{AMSa}{"39} % Requires amssymb

%%% Checks if a function is a point or a node.
%%% Not sure if best solution (needed to dig into source of TeX), but can't find anything better in manual
%%% https://tex.stackexchange.com/questions/6189553
\def\ifPgfpointOrNode#1#2#3{%
  \pgfutil@ifundefined{pgf@sh@ns@#1}{%
    #2%
  }{%
    #3%
  }%
}


%%% Create different kinds of dots...
%% https://tex.stackexchange.com/questions/617959
%% https://tex.stackexchange.com/questions/528774/excess-vertical-space-in-vdots/528775#528775
\DeclareRobustCommand\cvdotsAboveBaseline{%
  \vbox{\baselineskip4\p@ \lineskiplimit\z@%
    \hbox{.}\hbox{.}\hbox{.}}
}

\DeclareRobustCommand{\cvdotsCenterMathline}{%
  % vcenter is used to center the argument on the 'math axis', which is at half the height of an 'x', or about the position of a minus sign.
  \vcenter{\cvdotsAboveBaseline}%
}

\DeclareRobustCommand{\cvdotsCenterBaseline}{%
  \raisebox{-.5\height}{%
    $\cvdotsAboveBaseline$%
  }%
}

\DeclareRobustCommand{\chdots}{%
  \raisebox{-.5\height}{%
    \rotatebox{90}{% Maybe better options than rotatebox...
      $\cvdotsAboveBaseline$%
    }%
  }%
}

\DeclareRobustCommand{\cvdots}{\cvdotsCenterMathline}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Practical macros to automatically choose appropriate style and arrows
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% /!\ Warning: you should add {} at the end of all macros (except arrows)!
% Not using that may work for now, but it may break later...
% TODO: define them only in \zx environment.

% % Example: \leftManyDots{n}
% Useful to put on the left of a node like "n \vdots", linked to the next node.  Example: \leftManyDots{n}.
% First optional argument is scale of text, second is scale of =.
\NewExpandableDocumentCommand{\leftManyDots}{O{1}O{\zxScaleDots}m}{%
  |[zxNone+,inner xsep=0pt]| \scalebox{#1}{$#3$\,}\makebox[0pt][l]{\scalebox{#2}{$\cvdots$}} \ar[r,-s.,start anchor=north east] \ar[r,-s',start anchor=south east] \pgfmatrixnextcell%
}

% Useful to link two nodes and put a vdots in between.
\NewExpandableDocumentCommand{\middleManyDots}{}{%
  \ar[r,3 vdots] \ar[o',r] \ar[o.,r]%
}

% Like \leftManyDots but on the right. Do *not* create a new node, like in |[zxShortZ]| \alpha \rightManyDots{m}
\NewExpandableDocumentCommand{\rightManyDots}{O{1}O{\zxScaleDots}m}{%
  \ar[r,s'-,end anchor=north west] \ar[r,s.-,end anchor=south west] \pgfmatrixnextcell |[zxNone+,inner xsep=0pt]| \makebox[0pt][r]{\scalebox{#2}{$\cvdots$}}\scalebox{#1}{\,$#3$}
}

% A swap on one line... Practical mostly to gain space. Must be used with large nodes tough...
% \NewExpandableDocumentCommand{\OneLineSwap}{}{%
%   \ar[r,s,start anchor=south,end anchor=north] \ar[r,s,start anchor=north,end anchor=south]
% }


\NewExpandableDocumentCommand{\zxLoop}{O{90}O{20}O{}m}{%
  \ar[loop,in=#1-#2,out=#1+#2,looseness=8,min distance=3mm,#3]
}

\NewExpandableDocumentCommand{\zxLoopAboveDots}{O{20}O{}m}{%
  \ar[loop,in=90-#1,out=90+#1,looseness=8,min distance=3mm,"\cvdots" {scale=.6,anchor=north,yshift=-0.4mm},#2]
}

% Usage: node without any style, but may have space. Default is no space, \zxNone+{} is both horizontal
% and vertical, \zxNone-{} is only horizontal space, \zxNone|{} is only vertical space.
\NewExpandableDocumentCommand{\zxNone}{t+t-t|O{}m}{
  \IfBooleanTF{#1}{ % \zxNone+
    |[zxNone+,#4]| #5%
  }{
    \IfBooleanTF{#2}{ % \zxNone-
      |[zxNone-,#4]| #5%
    }{
      \IfBooleanTF{#3}{ % \zxNone
        |[zxNoneI,#4]| #5%
      }{% \zxNone
        |[zxNone,#4]| #5%
      }
    }
  }
}

% Usage: alias of \zxNone... To bad token can't be easily forwarded to another function.
\NewExpandableDocumentCommand{\zxN}{t+t-t|O{}m}{
  \IfBooleanTF{#1}{ % \zxNone+
    |[zxNone+,#4]| #5%
  }{
    \IfBooleanTF{#2}{ % \zxNone-
      |[zxNone-,#4]| #5%
    }{
      \IfBooleanTF{#3}{ % \zxNone
        |[zxNoneI,#4]| #5%
      }{% \zxNone
        |[zxNone,#4]| #5%
      }
    }
  }
}

% Cf \zxNone, but with larger space.
\NewExpandableDocumentCommand{\zxNoneDouble}{t+t-t|O{}m}{
  \IfBooleanTF{#1}{ % \zxNoneDouble+
    |[zxNoneDouble+,#4]| #5%
  }{
    \IfBooleanTF{#2}{ % \zxNoneDouble-
      |[zxNoneDouble-,#4]| #5%
    }{
      \IfBooleanTF{#3}{ % \zxNoneDouble
        |[zxNoneDoubleI,#4]| #5%
      }{% \zxNoneDouble
        |[zxNoneDouble,#4]| #5%
      }
    }
  }
}

%% For maximum styling liberty, the content is given directly to the style.
% It allows the style to put the phase in a label.
\NewExpandableDocumentCommand{\zxZ}{O{}m}{
  |[zxZ2={#1}{#2}]| %
}

%% For maximum styling liberty, the content is given directly to the style.
%% It allows the style to put the phase in a label.
\NewExpandableDocumentCommand{\zxX}{O{}m}{
  |[zxX2={#1}{#2}]| %
}

\NewExpandableDocumentCommand{\zxH}{O{}m}{
  |[zxH,#1]| {}%
}

% Use like: \zxFracX{\pi}{4} for positive values or for negative \zxFracX-{\pi}{4}
\NewExpandableDocumentCommand{\zxFracZ}{O{}t-moom}{%
  \IfNoValueTF{#5}{% 2 arguments like: \zxFracZ{\pi}{2}
    |[zxFracZ6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#3}{#6}]| %
  }{% 4 arguments like \zxFracZ{a+b}[(a+b)][(c+d)]{c+d}
    |[zxFracZ6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#4}{#5}]| %
  }%
}

% Use like: \zxFracX{\pi}{4} for positive values or for negative \zxFracX-{\pi}{4}
\NewExpandableDocumentCommand{\zxFracX}{O{}t-moom}{%
  \IfNoValueTF{#5}{% 2 arguments like: \zxFracZ{\pi}{2}
    |[zxFracX6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#3}{#6}]| %
  }{% 4 arguments like \zxFracZ{a+b}[(a+b)][(c+d)]{c+d}
    |[zxFracX6={#1}{\IfBooleanTF{#2}{\zxMinus}{}}{#3}{#6}{#4}{#5}]| %
  }%
}

\NewExpandableDocumentCommand{\zxEmptyDiagram}{}{
  |[zxEmptyDiagram]| {}%
}

% Quantikz has a bug which adds space automatically.
% https://tex.stackexchange.com/questions/618330
% Fixing that by copying the original (unpatched) functions, and reusing them later.
% Warning: you must load this package **before** quantikz otherwise the fix will not work.
\let\tikzcd@@originalCopyZx\tikzcd@
\let\endtikzcd@originalCopyZx\endtikzcd

%%%%% Main environment \begin{ZX}...\end{ZX}
\NewDocumentEnvironment{ZX}{O{}}{%
  \bgroup%
  % Add a switch in case someone really wants the current tikzcd version:
  \ifdefined\doNotPatchQuantikz% Do not patch tikzcd.
  \else% Restore locally original tikzcd.
    \let\tikzcd@\tikzcd@@originalCopyZx%
    \let\endtikzcd\endtikzcd@originalCopyZx%
  \fi%
  \pgfsetlayers{background,edgelayer,nodelayer,main,box,labellayer,foreground} % Layers are defined locally to avoid to disturb other drawings
  \begin{tikzcd}[%
    /zx/defaultEnv,%
    #1]%
  }{\end{tikzcd}\egroup}

%%%%% Shortcut macro \zx{...} equivalent to \begin{ZX}...\end{ZX}
\newcommand\zx{%
  \begingroup% To avoid ampersand issues https://tex.stackexchange.com/a/611535/116348
  \NewDocumentCommand{\tmpZX}{O{}+m}{%
    \endgroup%
    \begin{ZX}[##1]%
      ##2%
    \end{ZX}%
  }%
  \catcode`&=13%
  \tmpZX%
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Old code that tried to automatically find if zxShort or zxLong should be used...
%%% Now using a special command for fractions (easier to code, and more customizable)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newsavebox\zx@box % Temporary box to compute height/width/depth

\newlength{\zxMaxDepthPlusHeight}\setlength{\zxMaxDepthPlusHeight}{2em}
\def\zxMaxRatio{1.3} % Ratio width/(height+depth)

\NewExpandableDocumentCommand{\zxChooseStyle}{mmmm}{%
  % #1=text,#2=empty style,#3=short style,#4=long style
  \savebox\zx@box{#1}%
  % Check if width is 0pt:
  \ifdimcomp{\wd\zx@box}{=}{0pt}{% Return empty style if box is empty
    #2%
  }{% Else compute size of thext
    % Check if height+depth < zxMaxDepthPlusHeight to see if short style applies
    \ifdimcomp{\dimexpr\dp\zx@box+\ht\zx@box\relax}{<}{\zxMaxDepthPlusHeight}{%
      % Check if width < ratio*(height+depth) to see if short style applies
      \ifdimcomp{\wd\zx@box}{<}{\dimexpr \zxMaxRatio\ht\zx@box + \zxMaxRatio\dp\zx@box\relax}{%
        #3% Short style is used
      }{ % Else
        #4% Long style is used
      } %
    }{
      #4% Long style is used
    }
  }%
}
