%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Version: 2021/10/22
%%% 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,intersections}
% 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}{2mm}
\newcommand{\zxWRow}{2mm}
%% Same as zxWCol, but when a single empty node is connected to a non-empty node.
\newcommand{\zxwCol}{1mm}
\newcommand{\zxwRow}{1mm}
%% When vdots/dots are used in lines
\newcommand{\zxDotsCol}{3mm}
\newcommand{\zxDotsRow}{3mm}
%% Default separation between rows and columns
\newcommand{\zxDefaultColumnSep}{1.5mm}
\newcommand{\zxDefaultRowSep}{1.5mm}
% To cancel the default tow separation
\newcommand{\zxZeroCol}{-\zxDefaultColumnSep}
\newcommand{\zxZeroRow}{-\zxDefaultRowSep}
%% When adding two lines with only empty nodes, it can create quite a large space. Use this to reduce it
%% Yes, we can add multiple arguments, space will add up (see documentation pgfmatrixnextcell)
\newcommand{\zxNCol}{-\zxDefaultColumnSep,.5mm}
\newcommand{\zxNRow}{-\zxDefaultRowSep,.5mm}


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

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

% Angles by default for s and o related arrows (in/out version)
\def\zxDefaultSoftAngleN{60}
\def\zxDefaultSoftAngleO{40}
\def\zxDefaultSoftAngleChevron{60}

% Styles for O,N,... (new bezier version)
\tikzset{
  /zx/args/-andL/.cd,
  defaultO/.style={-=.2,L=.4},
  defaultN/.style={-=.2,L=.8},
  defaultN-/.style={1-=.4,1L=0},
  defaultNN/.style={},
  defaultNIN/.style={1-=0,1L=.6},
  defaultChevron/.style={}, % < should be stronger than N- also in ui mode.
  defaultChevronDown/.style={}, % The ^ v versions (default NN and default NIN will be loaded before).
  defaultS/.style={-=.8,L=0},
  defaultS'/.style={-=.8,L=.2},
  default-S/.style={1-=.8,1L=0},
  defaultSIS/.style={1-=0,1L=.8},
  % Loads the default styles for the "use intersection" method.
  /zx/args/-andL/ui/.style={
    /zx/args/-andL/defaultO/.style={-=.2,L=.17},
    /zx/args/-andL/defaultN/.style={-=.2,L=.7},
    /zx/args/-andL/defaultN-/.style={1-=.5,1L=.2,2-=.2,2L=.5}, %% Todo: write a different style for <
    /zx/args/-andL/defaultNN/.style={},
    /zx/args/-andL/defaultChevron/.style={1-=.2,1L=0,2-=.2,2L=.8},
    /zx/args/-andL/defaultChevronDown/.style={1L=.2,1-=0,2L=.2,2-=.8},
    /zx/args/-andL/defaultNIN/.style={1-=0,1L=.66,2-=.55,2L=.16},
    /zx/args/-andL/defaultS/.style={-=.8,L=0},
    /zx/args/-andL/defaultS'/.style={-=.8,L=.3},
    /zx/args/-andL/default-S/.style={1-=.8,1L=0},
    /zx/args/-andL/defaultSIS/.style={1-=0,1L=.8,2-=.15,2L=.6},
  },
}


% 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%
}

% Minus sign to use in \zxZ-{\alpha}
%\NewExpandableDocumentCommand{\zxMinusInShort}{}{-}
\NewExpandableDocumentCommand{\zxMinusInShort}{}{-}

% The library tries to find intersection between fake center east/... and the border of the node
% to draw the nodes directly on the border.
% To enable this function (can also be set locally), enable this macro:
% \def\zxEnableIntersectionsNodes{} %% To add the "name shape" on each node
% \def\zxEnableIntersectionsWires{} %% For wires only (can't work without \zxEnableIntersectionsNodes)
\newcommand{\zxEnableIntersections}{%
  \def\zxEnableIntersectionsWires{}%
  \def\zxEnableIntersectionsNodes{}%
}
% to disable intersections, undefined it:
\let\zxEnableIntersectionsNodes\undefined
\let\zxEnableIntersectionsWires\undefined
\newcommand{\zxDisableIntersections}{%
  \let\zxEnableIntersectionsNodes\undefined%
  \let\zxEnableIntersectionsWires\undefined%
}
% Now, if it cannot find a good intersection (either because "name path" is disabled, or
% because no intersection is found, or because intersections are disabled anyway) we need to
% have a fallback mechanism. Either we choose instead the "fake center" (or center if fake
% center does not exists), but then the wire will be hidden behind the node (it is a problem
% mostly if you use H nodes a lot, otherwise we recommend this solution):
\def\zxWireInsideIfNoIntersectionName{}
% If you prefer to start the wire on the surface of the node, do that instead...
% but be aware that the shape of the wire will be changed a lot, since we can't use anymore the
% fake anchors... You could also define a style that does that.
% \let\zxWireInsideIfNoIntersectionName\undefined

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% Adding anchors
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% We add anchors "fake center {north, south, east, west}" to the nodes. The wires will leave from these anchors (except in IO mode) depending on the direction. If the anchor does not exist, center is picked.
% https://tex.stackexchange.com/questions/14769/add-more-anchors-to-standard-tikz-nodes
\def\zx@pgfaddtoshape#1#2{%
  \begingroup
  \def\pgf@sm@shape@name{#1}%
  \let\anchor\pgf@sh@anchor
  #2%
  \endgroup
}
\def\zx@useanchor#1#2{\csname pgf@anchor@#1@#2\endcsname}
\zx@pgfaddtoshape{rounded rectangle}{%
  \anchor{fake center east}{%
    \zx@useanchor{rounded rectangle}{north east}%
    \pgf@yc=.5\pgf@y% final y = 0.5*this y + 0.5*other y.
    \zx@useanchor{rounded rectangle}{south east}%
    \pgf@y=.5\pgf@y%
    \advance\pgf@y by \pgf@yc%
  }%
  \anchor{fake center west}{%
    \zx@useanchor{rounded rectangle}{north west}%
    \pgf@yc=.5\pgf@y% final y = 0.5*this y + 0.5*other y.
    \zx@useanchor{rounded rectangle}{south west}%
    \pgf@y=.5\pgf@y%
    \advance\pgf@y by \pgf@yc%
  }%
  \anchor{fake center north}{%
    \zx@useanchor{rounded rectangle}{center}%
  }%
  \anchor{fake center south}{%
    \zx@useanchor{rounded rectangle}{center}%
  }%
}

\zx@pgfaddtoshape{coordinate}{%
  \anchor{fake center east}{%
    \zx@useanchor{coordinate}{center}%
  }%
  \anchor{fake center west}{%
    \zx@useanchor{coordinate}{center}%
  }%
  \anchor{fake center north}{%
    \zx@useanchor{coordinate}{center}%
  }%
  \anchor{fake center south}{%
    \zx@useanchor{coordinate}{center}%
  }%
}

\zx@pgfaddtoshape{circle}{%
  \anchor{fake center east}{%
    \zx@useanchor{circle}{center}%
  }%
  \anchor{fake center west}{%
    \zx@useanchor{circle}{center}%
  }%
  \anchor{fake center north}{%
    \zx@useanchor{circle}{center}%
  }%
  \anchor{fake center south}{%
    \zx@useanchor{circle}{center}%
  }%
}

\zx@pgfaddtoshape{rectangle}{
  \anchor{fake center east}{%
    \zx@useanchor{rectangle}{center}%
  }%
  \anchor{fake center west}{%
    \zx@useanchor{rectangle}{center}%
  }%
  \anchor{fake center north}{%
    \zx@useanchor{rectangle}{center}%
  }%
  \anchor{fake center south}{%
    \zx@useanchor{rectangle}{center}%
  }%
}


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

%%% For arguments later:
\tikzset{
  /zx/args/-andL/.cd,
  % - is "towards the point", or "x value",
  % L is "perpendicular to the line going towards the point" (L is for the perpendicular shape), or "y value".
  1-/.initial=.5, % random value, defaultO... will change that.
  2-/.initial=.5,
  -/.style={
    1-=#1,
    2-=#1,
  },
  1L/.initial=.5,
  2L/.initial=.5,
  L/.style={
    1L=#1,
    2L=#1,
  },
  symmetry-L/.code={% 1- <-> 1L, 2- <-> 2L
    \edef\zx@tmpone{\pgfkeysvalueof{/zx/args/-andL/1-}}%
    \edef\zx@tmptwo{\pgfkeysvalueof{/zx/args/-andL/2-}}%
    \pgfkeysalso{%
      1-/.evaluated=\pgfkeysvalueof{/zx/args/-andL/1L},
      2-/.evaluated=\pgfkeysvalueof{/zx/args/-andL/2L},
      1L/.evaluated=\zx@tmpone,
      2L/.evaluated=\zx@tmptwo,
    }%
  },
  symmetry/.code={% 1- <-> 2-, 1L <-> 2L
    \edef\zx@tmpone{\pgfkeysvalueof{/zx/args/-andL/1-}}%
    \edef\zx@tmptwo{\pgfkeysvalueof{/zx/args/-andL/1L}}%
    \pgfkeysalso{
      1-/.evaluated=\pgfkeysvalueof{/zx/args/-andL/2-},
      1L/.evaluated=\pgfkeysvalueof{/zx/args/-andL/2L},
      2-/.evaluated=\zx@tmpone,
      2L/.evaluated=\zx@tmptwo,
    }%
  },
  negate1L/.style={
    /zx/args/-andL/1L/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/1L},
  },
  negate2L/.style={
    /zx/args/-andL/2L/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/2L},
  },
  negateL/.style={
    negate1L,
    negate2L,
  },
  negate1-/.style={
    /zx/args/-andL/1-/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/1-},
  },
  negate2-/.style={
    /zx/args/-andL/2-/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/2-},
  },
  negate-/.style={
    negate1-,
    negate2-,
  },
  negateL/.style={
    negate1L,
    negate2L,
  },
  oneMinus1-/.style={
    /zx/args/-andL/2-/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/2-},
  },
  oneMinus2-/.style={
    /zx/args/-andL/2-/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/2-},
  },
  oneMinus1L/.style={
    /zx/args/-andL/1L/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/1L},
  },
  oneMinus2L/.style={
    /zx/args/-andL/2L/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/2L},
  },
  % Angle/length:
  1 angle and length/.code 2 args={%
    \pgfmathparse{#2*cos(#1)}%
    \pgfkeysalso{1-/.expand once=\pgfmathresult}%
    \pgfmathparse{#2*sin(#1)}%
    \pgfkeysalso{1L/.expand once=\pgfmathresult}%
  },
  2 angle and length/.code 2 args={%
    \pgfmathparse{#2*cos(#1)}%
    \pgfkeysalso{2-/.expand once=\pgfmathresult}%
    \pgfmathparse{#2*sin(#1)}%
    \pgfkeysalso{2L/.expand once=\pgfmathresult}%
  },
  1al/.style 2 args={
    1 angle and length={#1}{#2}
  },
  2al/.style 2 args={
    2 angle and length={#1}{#2}
  },
  al/.style 2 args={
    1 angle and length={#1}{#2},
    2 angle and length={#1}{#2},
  },
  1 angle/.style={
    1 angle and length={#1}{.6}
  },
  2 angle/.style={
    2 angle and length={#1}{.6}
  },
  1a/.style={
    1 angle={#1},
  },
  2a/.style={
    2 angle={#1},
  },
  angle/.style={
    1 angle={#1},
    2 angle={#1},
  },
  a/.style={
    1 angle and length={#1}{.6},
    2 angle and length={#1}{.6},
  },
}

%%% Useful debug functions
%% This function will be called when debugging the library.
\def\zx@message#1{}
% The ^^J adds a new line:
\def\zx@verbose@message#1{\message{#1^^J}} % For more important messages. Like to show the code is not looping forever
% To enable debugging:
% WARNING: if you use in code, do not forget the makeatletter!
%\def\zx@message#1{\message{#1^^J}}
% To display stroke of while trying to compute the intersections:
% WARNING: if you use in code, do not forget the makeatletter!
%\def\zx@draw@stroke@inter@debug{}


%% This function checks if the node has a "name path", if so it computes the intersection between
%% if not if \zxWireInsideIfNoIntersectionName is defined it defines the \tikzto* to the
%% new@center (argument #2), otherwise it does nothing.
% #1: Node to consider: \tikztostart or \tikztotarget
% #2: name of the new@center node corresponding to #1
% #3: name of the other new@center node
% #4: result will be stored in this macro... if there is something to change.
% #5: 1 if start, 2 if end
% Result will be moved back into #1
\def\zx@find@intersection@fakecenter#1#2#3#4#5{%
  % First, we check if the user wants to compute the intersection:
  \ifdefined\zxEnableIntersectionsWires%
     %% We compute the intersection
    \edef\tikz@intersect@path@a{zx@name@path@#1}%
    \ifcsname tikz@intersect@path@name@\tikz@intersect@path@a \endcsname%
      \zx@verbose@message{[ZX] I will start computing intersections}%
      \pgfintersectionofpaths{%
        \begin{pgfinterruptboundingbox}%
          %%%% /!\ This lines is the one I'm not sure how to write:
          \expandafter\pgfsetpath\csname tikz@intersect@path@name@\tikz@intersect@path@a\endcsname%
          \pgfgetpath\temppath%
          \ifdefined\zx@draw@stroke@inter@debug%
            \pgfusepath{stroke} % We draw it, useful to debug, and realize the shape is moved.
          \fi%
          \pgfsetpath\temppath%
        \end{pgfinterruptboundingbox}%
      }{% The first path is moved to the center... So we need to shift it also here.
        %%% First intersection: we use the line between the two nodes... but it's really ugly (e.g. in o it does not make a lot of sense)
        \begin{pgfinterruptboundingbox}%
          \ifdefined\zxIntersectionLineBetweenStartEnd%
            %% Not idea why, but x axis is inverted???
            \pgfpointdiff{\tikz@scan@one@point\pgf@process(#2)}{\pgfpointanchor{#1}{center}}%
            \pgfpathmoveto{\pgfpoint{-\pgf@x}{\pgf@y}}%
            % And now both axis are???
            \pgfpointdiff{\tikz@scan@one@point\pgf@process(#3)}{\pgfpointanchor{#1}{center}}%
            \pgfpathlineto{\pgfpoint{-\pgf@x}{-\pgf@y}}%
          \else%
            %% We use now the method used for bezier curve (at least it's what I see "experimentally")
            %% More precisely, we use the direction of the bezier curve to know where to start the wire.
            %% Parse once the control points for efficiency reasons:
            %% First parse the fake centers.
            \tikz@scan@one@point\pgf@process(#2)%
            \edef\zx@tmp@current@fake@x{\the\pgf@x}%
            \edef\zx@tmp@current@fake@y{\the\pgf@y}%
            \zx@message{The input fakes are #2 and #3.}%
            \tikz@scan@one@point\pgf@process(#3)%
            \edef\zx@tmp@other@fake@x{\the\pgf@x}%
            \edef\zx@tmp@other@fake@y{\the\pgf@y}%
            \zx@message{The parsed input fakes are (\zx@tmp@current@fake@x , \zx@tmp@current@fake@y) and (\zx@tmp@other@fake@x , \zx@tmp@other@fake@y).}%
            %% Reorder the controls to compute. #5 = 1 if "start fake center" is "current fake center".
            \ifnum#5=1 % <-- important space!!!
              \edef\zx@tmp@start@fake@x{\zx@tmp@current@fake@x}%
              \edef\zx@tmp@start@fake@y{\zx@tmp@current@fake@y}%
              \edef\zx@tmp@end@fake@x{\zx@tmp@other@fake@x}%
              \edef\zx@tmp@end@fake@y{\zx@tmp@other@fake@y}%
            \else%
              \edef\zx@tmp@end@fake@x{\zx@tmp@current@fake@x}%
              \edef\zx@tmp@end@fake@y{\zx@tmp@current@fake@y}%
              \edef\zx@tmp@start@fake@x{\zx@tmp@other@fake@x}%
              \edef\zx@tmp@start@fake@y{\zx@tmp@other@fake@y}%
            \fi%
            \zx@message{We computed: start fake (\zx@tmp@start@fake@x , \zx@tmp@start@fake@y) end fake (\zx@tmp@end@fake@x , \zx@tmp@end@fake@y )}%
            \pgfkeysalso{/zx/tmp/zx@getControlPoints={\zx@tmp@start@fake@x}{\zx@tmp@start@fake@y}{\zx@tmp@end@fake@x}{\zx@tmp@end@fake@y}}%
            % Now results are in controlOne, and controlTwo
            \ifnum#5=1 \relax%
              \def\zx@control{\controlOne}%
            \else%
              \def\zx@control{\controlTwo}%
            \fi%
            %%% Parse new control
            \tikz@scan@one@point\pgf@process(\zx@control)%
            \edef\zx@tmp@current@ctrl@x{\the\pgf@x}%
            \edef\zx@tmp@current@ctrl@y{\the\pgf@y}%
            \zx@message{[ZX] Current control is number #5, i.e. \zx@control (both are \controlOne and \controlTwo)}%
            % We store the center coordinates since it's used several times
            \pgfpointanchor{#1}{center}%
            \edef\zx@tmp@real@center@x{\the\pgf@x}%
            \edef\zx@tmp@real@center@y{\the\pgf@y}%
            %%% Go to  current fake center, except that real center is the new origin.
            \pgfpointdiff{\pgfpoint{\zx@tmp@real@center@x}{\zx@tmp@real@center@y}}{\pgfpoint{\zx@tmp@current@fake@x}{\zx@tmp@current@fake@y}}%
            \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}%
            %% What, now both axis are inverted??? If someone can explain me this...
            %% We scale the point to force it to cross the boundary.
            \pgfpathlineto{%
              \pgfpointadd{%
                \pgf@process{%
                  \pgfpointscale{10}{%
                    \pgf@process{%
                      \pgfpointdiff{%
                        \pgfpoint{\zx@tmp@current@fake@x}{\zx@tmp@current@fake@y}%
                      }{%
                        \pgfpoint{\zx@tmp@current@ctrl@x}{\zx@tmp@current@ctrl@y}%
                      }%
                    }%
                  }%
                }%
              }{%
                \pgfpointdiff{%
                  \pgfpoint{\zx@tmp@real@center@x}{\zx@tmp@real@center@y}%
                }{%
                  \pgfpoint{\zx@tmp@current@fake@x}{\zx@tmp@current@fake@y}%
                }%
              }%
            }%
          \fi%
          \pgfgetpath\temppath%
          \ifdefined\zx@draw@stroke@inter@debug%
            \pgfusepath{stroke}% We draw it, useful to debug, and realize the shape is moved.
          \fi%
          \pgfsetpath\temppath%
        \end{pgfinterruptboundingbox}%
      }%
      \pgfintersectionsolutions%
      \pgfpointintersectionsolution{1}%
      \ifnum\pgfintersectionsolutions=1%% The good number of solution has been found!
        \zx@message{[ZX] Cool, just found one solution!}
        %% Store the intersection (warning: the center of the shape is moved to the center!)
        \edef\zx@relinter@x{\the\pgf@x}%
        \edef\zx@relinter@y{\the\pgf@y}%
        %% Because the shape was moved to center, we shift it back by adding the coord of the shape:
        \pgfextractx\pgf@xa{\pgfpointanchor{#1}{center}}%
        \pgfextractx\pgf@xb{\pgfpointanchor{#1}{center}}%
        % WARNING! pgfmath removes the dimension (converted in pt). Make sure to put them back after
        \pgfmathsetmacro{\zx@inter@x}{\pgf@x+\zx@relinter@x}%
        \pgfmathsetmacro{\zx@inter@y}{\pgf@y+\zx@relinter@y}%
        \edef#4{\zx@inter@x pt,\zx@inter@y pt}%
      \else% The bad number of solution has been found
        \zx@message{[ZX] WARNING: expecting one solution, found \pgfintersectionsolutions}%
        \ifdefined\zxWireInsideIfNoIntersectionName%
          % No intersection was found, but still want to use fake center (or center).
          % ==> The wire will be inside the shape
          % Basically \tikztostart := tikztostart@new@center
          \edef#4{#2}%
        \fi% Otherwise, do nothing
      \fi%
    \else%
      \zx@message{ZX: no path named \tikz@intersect@path@a was found.}%
      \ifdefined\zxWireInsideIfNoIntersectionName%
        % No intersection was found, but still want to use fake center (or center).
        % ==> The wire will be inside the shape
        % Basically \tikztostart := tikztostart@new@center
        \edef#4{#2}%
      \fi% Otherwise, do nothing
    \fi%
  \else%
      \zx@message{[ZX]: intersection mechanism disabled}%
      \ifdefined\zxWireInsideIfNoIntersectionName%
        % No intersection was found, but still want to use fake center (or center).
        % ==> The wire will be inside the shape
        % Basically \tikztostart := tikztostart@new@center
        \edef#4{#2}%
      \fi% Otherwise, do nothing
  \fi%
}%

% 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...) in IO mode
    between none/.style={
      looseness wires only,
      wire centered
    },
    bn/.style={
      between none
    },
    % To debug the bezier curve.
    edge above/.code={%
      \def\zxEdgesAbove{}%
    },%
    edge not above/.code={%
      \let\zxEdgesAbove\undefined%
    },
    control points visible/.code={%
      \def\zxControlPointsVisible{}%
    },%
    control points not visible/.code={%
      \let\zxControlPointsVisible\undefined%
    },
    % See explaination at the beginning where we define \def\zxEnableIntersectionsWires{}
    % Rouhgly, tries to start the wires on the border of the shape on the line between the
    % fake anchors.
    use intersections/.code={%
      \def\zxEnableIntersectionsWires{}%
    },
    dont use intersections/.code={%
      \let\zxEnableIntersectionsWires\undefined%
    },
    ui/.style={
      use intersections,
      /zx/args/-andL/ui
    },
    intersections mode between start end/.code={%
      \def\zxIntersectionLineBetweenStartEnd{}%
    },
    intersections mode bezier controls/.code={%
      \let\zxIntersectionLineBetweenStartEnd\undefined%
    },
    wires behind nodes/.code={%
      \def\zxWireInsideIfNoIntersectionName{}%
    },
    no wires behind nodes/.code={%
      \let\zxWireInsideIfNoIntersectionName\undefined%
    },
    intersection between start end/.code={
      \def\zxIntersectionLineBetweenStartEnd{}%
    },
    intersection bezier control/.code={
      \let\zxIntersectionLineBetweenStartEnd\undefined%
    },
    % ------------------------------
    % 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
      }
    },
    % At the first version, styles were defined using in=... out=... looseness=... However
    % it gives sometimes bad results (like the curve goes forward at some points) when nodes are
    % too close or too far appart. However, it may still be useful, so now we define the old
    % styles, that you can use them using \ar[r,IO,C].
    % NB: for the newest styles, we add new anchors to the nodes depending on the direction.
    % I also wanted to add more complicated ways to configqure the starting point (i.e. start at the boundary
    % and not behind the node), but seems like it's hard (impossible?) to do with matrices...
    % The reason is that the intersection library seems to fail with matrices.
    % If you know how to solve that, you can help here: https://tex.stackexchange.com/questions/619274
    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,
    %%% bezier{px1}{py1}{px2}{py2} creates a bezier curve where px1/py1 are the
    %%% coordinates of the first control (in "percentage" 0<px1<1, between start and end point) and px2/py2
    %%% are the coordinates in % of the second control point
    %%% bezier@general is used to construct also x/y versions, 5 and 6'th argument are \x or \y.
    bezier@general/.style n args={6}{
      possibly@on@edge@layer/.code={%% see "edges above" style. for debug mode only.
        \ifdefined\zxEdgesAbove\else%
          \pgfkeysalso{%
            on layer=edgelayer%
          }%
        \fi%
      },
      possibly@on@edge@layer,
      to path={%
        %%% First, check that inputs/outputs are points.
        \pgfextra{% <- Type latex code inside path
          %% Setup the startup node. This code can be changed by styles
          %% /zx/tmp/zx@setup@start@node will contain the anchor of the first fake center
          %% /zx/tmp/zx@setup@end@node will contain the anchor of the second fake center
          %% If none of them are defined, nothing happens and the start point will be a node.
          % Retrieve the content of the keys
          % But first check if they are defined
          \pgfkeysifdefined{/zx/tmp/zx@setup@start@node}{}{% Put an empty value
            \pgfkeysalso{/zx/tmp/zx@setup@start@node/.initial=,}%
          }%
          \pgfkeysifdefined{/zx/tmp/zx@setup@end@node}{}{% Put an empty value
            \pgfkeysalso{/zx/tmp/zx@setup@end@node/.initial=,}%
          }%
          \pgfkeysalso{
            /zx/tmp/zx@setup@start@node/.get=\zx@anchor@start@node,
            /zx/tmp/zx@setup@end@node/.get=\zx@anchor@end@node,
            /zx/tmp/zx@getControlPoints/.code n args={4}{%
              \zx@message{I will evaluate my control points:}%
              % Args: start point, x,y then end point x,y
              % Use ########1 ... (yes, LaTeX is a funny exponential language, and I love nested functions)
              % Because to path is considered as a function already.
              \def\x################1{%
                \ifnum################1=1 % <-- super important space...
                  ########1%
                \else%
                  ########3%
                \fi%
              }%
              \zx@message{[ZX] x is defined.}%
              \def\y################1{%
                \ifnum ################1 = 1 % <-- super important space...
                  ########2%
                \else%
                  ########4%
                \fi%
              }%
              \tikz@scan@one@point\pgf@process(\x1-##51*##1+##52*##1,\y1-##61*##2+##62*##2)%
              \edef\controlOne{\the\pgf@x,\the\pgf@y}%
              \tikz@scan@one@point\pgf@process(\x1-##51*##3+##52*##3,\y1-##61*##4+##62*##4)%
              \edef\controlTwo{\the\pgf@x,\the\pgf@y}%
              \zx@message{[ZX] First control point is: \controlOne, second is \controlTwo.}%
            },%
          }%
          %%% This will be the new \tikztostart and \tikztotarget... if someone defines them
          \let\new@tikztostart\undefined%
          \let\new@tikztotarget\undefined%
          % Check if a start anchor was defined...
          \ifthenelse{\equal{\zx@anchor@start@node}{}}{%
            % No start anchor was chosen... :c
            \ifthenelse{\equal{\zx@anchor@end@node}{}}{%
              % Nothing was defined... So I won't do anything! :C
            }{%
              % An end node was defined :D Let's configure its end anchor.
              \pgfkeysalso{%
                /zx/utils/change@tikz@fake@center@intersect={\tikztotarget}{\zx@anchor@end@node}{\tikztostart}{center}{\new@tikztotarget}{2},
              }%
            }%
          }{% A start node was chosen :D
            \ifthenelse{\equal{\zx@anchor@end@node}{}}{%
              % No end node was chosen... I'll take center to configure the start node,
              % and not configure the end node.
              \pgfkeysalso{
                /zx/utils/change@tikz@fake@center@intersect={\tikztostart}{\zx@anchor@start@node}{\tikztotarget}{center}{\new@tikztostart}{1},
              }%
            }{%
              % And an end node was chosen :D
              \zx@message{[ZX] Both anchors are set. Lets configure intersection.}%
              \pgfkeysalso{
                /zx/utils/change@tikz@fake@center@intersect={\tikztostart}{\zx@anchor@start@node}{\tikztotarget}{\zx@anchor@end@node}{\new@tikztostart}{1},
                /zx/utils/change@tikz@fake@center@intersect={\tikztotarget}{\zx@anchor@end@node}{\tikztostart}{\zx@anchor@start@node}{\new@tikztotarget}{2},
              }%
            }%
          }%
          \ifdefined\new@tikztostart%
            \edef\tikztostart{\new@tikztostart}%
          \fi%
          \ifdefined\new@tikztotarget%
            \edef\tikztotarget{\new@tikztotarget}%
          \fi%
          %%% Test if tikztostart is a point or a node, and define StartPoint accordingly.
          % \ifPgfpointOrNode{\tikztostart}{%
          %   \def\StartPoint{\tikztostart}%
          % }{%
          %   \def\StartPoint{\tikztostart.center}%
          % }%
          % % Test if tikztostart is a point or a node, and define StartPoint accordingly.
          % \ifPgfpointOrNode{\tikztotarget}{%
          %   \def\TargetPoint{\tikztotarget}%
          % }{%
          %   \def\TargetPoint{\tikztotarget.center}%
          % }%
          %%% Well, let's just use \tikztostart and \tikztotarget in any case, setting it to
          %%% center will put the wire below the node which is not really desired for H nodes
          %%% (position will be wrong) or when using arrows. And if center is really desired
          %%% it's easy to force it using start anchor and end anchor.
          \def\StartPoint{\tikztostart}%
          \def\TargetPoint{\tikztotarget}%
          %%% TODO: check that it does not change the shape of the wire since I'm not sure what \x1
          %%% is in that case%
        }%
        let
        \p1=(\StartPoint),
        \p2=(\TargetPoint),%% ##5 = \x or \y, so ##51 = \x1 or \y1.
        \p{control1}=(\x1-##51*##1+##52*##1, \y1-##61*##2+##62*##2),
        \p{control2}=(\x1-##51*##3+##52*##3, \y1-##61*##4+##62*##4) in
        (\StartPoint) .. controls (\p{control1}) and (\p{control2}) .. (\TargetPoint)
        \ifdefined\zxControlPointsVisible
          (\StartPoint) node[anchor=center,circle,fill=yellow,inner sep=.5pt,on layer=foreground]{}
          -- (\p{control1}) node[anchor=center,circle,fill=orange,inner sep=.5pt,on layer=foreground]{}
          (\p{control2}) node[anchor=center,circle,fill=purple,inner sep=.5pt,on layer=foreground]{}
          -- (\TargetPoint) node[anchor=center,circle,fill=brown,inner sep=.5pt,on layer=foreground]{}
        \fi
        \tikztonodes
      },
    },
    %% Not sure it will be very useful, compared to bezier, bezier x and bezier y directly.
    bezier 4/.style n args={4}{
      bezier@general={##1}{##2}{##3}{##4}{\x}{\y},
    },
    % Like bezier, all proportions are relative to x distance
    bezier 4 x/.style n args={4}{
      bezier@general={##1}{##2}{##3}{##4}{\x}{\x}
    },
    % Like bezier, all proportions are relative to y distance
    bezier 4 y/.style n args={4}{
      bezier@general={##1}{##2}{##3}{##4}{\y}{\y}
    },
    bezier/.code={%
      \pgfkeys{
        /zx/args/-andL/.cd,
        ##1
      }%
      \pgfkeysalso{
        bezier 4={\pgfkeysvalueof{/zx/args/-andL/1-}}{\pgfkeysvalueof{/zx/args/-andL/1L}}{\pgfkeysvalueof{/zx/args/-andL/2-}}{\pgfkeysvalueof{/zx/args/-andL/2L}}
      }%
    },
    bezier x/.code={%
      \pgfkeys{
        /zx/args/-andL/.cd,
        ##1
      }%
      \pgfkeysalso{
        bezier 4 x={\pgfkeysvalueof{/zx/args/-andL/1-}}{\pgfkeysvalueof{/zx/args/-andL/1L}}{\pgfkeysvalueof{/zx/args/-andL/2-}}{\pgfkeysvalueof{/zx/args/-andL/2L}}
      }%
    },
    bezier y/.code={%
      \pgfkeys{
        /zx/args/-andL/.cd,
        ##1
      }%
      \pgfkeysalso{
        bezier 4 y={\pgfkeysvalueof{/zx/args/-andL/1-}}{\pgfkeysvalueof{/zx/args/-andL/1L}}{\pgfkeysvalueof{/zx/args/-andL/2-}}{\pgfkeysvalueof{/zx/args/-andL/2L}}
      }%
    },
    % Directions: configure start/end points to "fake center *" if it exists.
    % If the input is not a node, it's copied to ##3
    /zx/utils/change@tikz@fake@center/.code n args={3}{%
      % ##1: \tikztostart or \tikztotarget,
      % ##2: fake center north...
      % ##3 name of result. e.g. \tikztostart
      \ifPgfpointOrNode{##1}{%
        %%% Sometimes, ##1 is not 1pt,2pt but "tikz-1-2.north east". Since later we use
        %%% a parsing mechanism which assumes that we have a coordinate... this is a problem.
        \edef##3{##1}%
        % This is a great explaination of how parsing is done in tikz:
        % https://tex.stackexchange.com/a/516897/116348
      }{% This is a node, not a point:
        \ifAnchorExists{##1}{##2}{%
          \pgfpointanchor{##1}{##2}%
        }{%
          \pgfpointanchor{##1}{center}%
        }%
        %%% Whoo, pgfpoint only redefine pgf@x/pgf@y, but in no way it stores it!!!
        %%% So can't do \pgfpoint{\pgf@x}{\pgf@y}...
        %%% I needed to create my own system... see \zx@parse@coordx.
        \edef##3{\the\pgf@x,\the\pgf@y}%
      }%
    },
    % Directions: configure start/end points to the intersection between
    % the "fake center *" if it exists and the "fake center *" of the destination.
    % If the input is not a node, nothing is done.
    /zx/utils/change@tikz@fake@center@intersect/.code n args={6}{%
      % ##1: \tikztostart or \tikztotarget
      % ##2: fake center north... for ##1
      % ##3: \tikztostart or \tikztotarget, the other one (needed to compute the intersection)
      % ##4 fake center north... for ##3
      % ##5: result will be moved to that macro
      % ##6: 1 if start, 2 if end.
      \ifPgfpointOrNode{##1}{}{% This is a node, not a point:
        %% Configure the zx@new@center@* which should point to "fake center" if it exists.
        \pgfkeysalso{%
          /zx/utils/change@tikz@fake@center={##1}{##2}{\zx@new@center},%
        }%
        \pgfkeysalso{%
          /zx/utils/change@tikz@fake@center={##3}{##4}{\zx@new@center@other},%
        }%
        \zx@message{ZX: coordinate of new center is \zx@new@center}%
        \zx@message{ZX: coordinate of new other center is \zx@new@center@other}%
        \zx@find@intersection@fakecenter{##1}{\zx@new@center}{\zx@new@center@other}{##5}{##6}%
      }%
    },
    start fake center east/.style={%
      /zx/tmp/zx@setup@start@node/.initial=fake center east,
    },
    start fake center west/.style={%
      /zx/tmp/zx@setup@start@node/.initial=fake center west,
    },
    start fake center north/.style={%
      /zx/tmp/zx@setup@start@node/.initial=fake center north,
    },
    start fake center south/.style={%
      /zx/tmp/zx@setup@start@node/.initial=fake center south,
    },
    start real center/.style={
      /zx/tmp/zx@setup@start@node/.initial=center,
    },
    start no fake center/.style={
      /zx/tmp/zx@setup@start@node/.initial=,
    },
    end fake center east/.style={%
      /zx/tmp/zx@setup@end@node/.initial=fake center east,
    },
    end fake center west/.style={%
      /zx/tmp/zx@setup@end@node/.initial=fake center west,
    },
    end fake center north/.style={%
      /zx/tmp/zx@setup@end@node/.initial=fake center north,
    },
    end fake center south/.style={%
      /zx/tmp/zx@setup@end@node/.initial=fake center south,
    },
    end real center/.style={
      /zx/tmp/zx@setup@end@node/.initial=center,
    },
    end no fake center/.style={
      /zx/tmp/zx@setup@end@node/.initial=,
    },
    left to right/.style={
      start fake center east,
      end fake center west
    },
    right to left/.style={
      start fake center west,
      end fake center east
    },
    up to down/.style={
      start fake center south,
      end fake center north
    },
    down to up/.style={
      start fake center north,
      end fake center south
    },
    no fake center/.style={
      start no fake center,
      end no fake center,
      start anchor=,
      end anchor=,
    },
    %% Forced versions are versions which do not nicely fallback to center if shape does not
    %% have "fake center XXX". This is used mostly for wires based on in/out (our function b.
    %% Not sure how to have a code which always fallback to center if shape does not.
    %% All shapes used in the default style should work with force left to right.
    force left to right/.style={
      on layer=edgelayer,
      start anchor=fake center east,
      end anchor=fake center west
    },
    force right to left/.style={
      on layer=edgelayer,
      start anchor=fake center west,
      end fake center east
    },
    force up to down/.style={
      on layer=edgelayer,
      start anchor=fake center south,
      end fake center north
    },
    force down to up/.style={
      on layer=edgelayer,
      start anchor=fake center north,
      end fake center south
    },
    % 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.
    %%% Actually, it may not be super useful to define it via bezier since it's used only
    %%% horizontally and vertically... Anyway.
    o'/.style={%
      left to right,
      bezier x={
        defaultO,
        ##1,
        %% 2- --> 1 - (2-)
        oneMinus2-,
      },
    },
    o./.style={%
      left to right,
      bezier x={%
        /zx/args/-andL/.cd,
        defaultO,
        ##1,
        %% 2- --> 1 - (2-)
        oneMinus2-,
        negate1L,
        negate2L,
      },%
    },
    -o/.style={%
      up to down,
      bezier y={%
        /zx/args/-andL/.cd,
        defaultO,
        ##1,
        /zx/args/-andL/2-/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/2-},
        symmetry-L,
      }
    },
    o-/.style={%
      up to down,
      bezier y={%
        /zx/args/-andL/.cd,
        defaultO,
        ##1,
        /zx/args/-andL/2-/.evaluated=1-\pgfkeysvalueof{/zx/args/-andL/2-},
        /zx/args/-andL/1L/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/1L},
        /zx/args/-andL/2L/.evaluated=-\pgfkeysvalueof{/zx/args/-andL/2L},
        symmetry-L,
      },
    },
    % Similar to o, but can be used also for diagonal items. Combine it with
    % The dot versions are mode logic in "left to right", and the others for up to down (possible to change)
    % Can combine with "force left to right"...
    (/.style={
      bend right=##1,
    },
    (/.default=30,
    )/.style={
      bend left=##1,
    },
    )/.default=30,
    ('/.style={
      bend left=##1
    },
    ('/.default=30,
    (./.style={
      bend right=##1
    },
    (./.default=30,
    %%%% 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).
    %% Nbase will be reused later by < > shapes as well. It's useful to make a distinction between N and
    %% Nbase when user will want to overwrite N without overwritting < >.
    Nbase/.style={
      left to right,
      bezier={
        /zx/args/-andL/.cd,
        defaultN,
        ##1,
        oneMinus2-,
        oneMinus2L,
      },
    },
    N/.style={Nbase={##1}},
    % With this model, we don't need differences between N' and N. so we can also call it N.
    % But keep other notations to allow easy style change (to use IO again for instance).
    N'/.style={N={##1}},
    N./.style={N={##1}},
    -N/.style={N={defaultN-,##1}},
    -N'/.style={-N={##1}},
    -N./.style={-N={##1}},
    N-/.style={-N'={symmetry,##1}},
    N'-/.style={N-={##1}},
    N.-/.style={N-={##1}},
    %% Up to down version
    NN/.style={N'={symmetry-L,defaultNN,##1},up to down},
    NN./.style={NN={##1}},
    .NN/.style={NN={##1}},
    NIN/.style={NN={defaultNIN,##1}},
    INN/.style={NIN={symmetry,##1}},
    NNI/.style={INN={##1}},
    %%% <' is basically like -N' (historically < was first), we just put an anchor on the east/....
    <'/.style={Nbase={defaultN,defaultN-,defaultChevron,symmetry,##1},end anchor=west},
    <./.style={<'={##1}},
    % Don't use <>^ alone char as style name, it could be useful later for other shortcuts
    % (replacement directions)
    '>/.style={Nbase={defaultN,defaultN-,defaultChevron,##1},start anchor=east},
    .>/.style={'>={##1}},
    ^./.style={
      Nbase={defaultN,defaultN-,defaultChevron,symmetry-L,defaultNN,defaultNIN,defaultChevronDown,symmetry,##1},
      end anchor=north
    },
    .^/.style={^.={##1}},
    'v/.style={
      Nbase={defaultN,defaultN-,defaultChevron,symmetry-L,defaultNN,defaultNIN,defaultChevronDown,##1},
      start anchor=south
    },
    v'/.style={'v={##1}},
    %%%% Links with a s-like shape.
    s/.style={
      left to right,
      bezier={%
        /zx/args/-andL/.cd,
        defaultS,
        ##1,
        oneMinus2-,
        oneMinus2L,
      }
    },
    % like S, but with anchor east and west
    S/.style={
      s={##1}, start anchor=east, end anchor=west
    },
    % -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={s={defaultS',##1}},
    s./.style={s'={##1}},
    -s/.style={s'={default-S,##1}},
    -s'/.style={-s={##1}},  % To fit with s' notation
    -s./.style={-s={##1}},
    s-/.style={-s'={symmetry,##1}},
    s'-/.style={s-={##1}},
    s.-/.style={s-={##1}},
    % Anchor more marked
    S/.style={s={##1}, start anchor=east, end anchor=west,},
    -S/.style={-s'={##1},start anchor=east},
    -S'/.style={-S={##1}},
    -S./.style={-S={##1}},
    S-/.style={s'-={##1},end anchor=west},
    S'-/.style={S-={##1}},
    S.-/.style={S-={##1}},
    %%%% Doubling = up to down.
    % Links with a s-like shape... but read from top to bottom
    ss/.style={s={symmetry-L,##1},up to down},
    SS/.style={ss={##1}, start anchor=south, end anchor=north},
    % -s'.- shapes are like s, but with a soften (customizable like o) angle.
    % The '. say if you are going up or down, and 'I' forces a sharp angle (I is flat) on the side of the I
    ss./.style={s.={symmetry-L,##1},up to down},
    .ss/.style={ss.={##1}},
    sIs/.style={ss={defaultSIS,##1}},
    sIs./.style={ss.={defaultSIS,##1}},
    .sIs/.style={sIs.={##1}},
    Iss/.style={sIs={symmetry,##1}},
    ssI/.style={Iss={##1}},
    ss.I/.style={sIs.={symmetry,##1}},
    I.ss/.style={ss.I={##1}},
    SIS/.style={sIs={##1},start anchor=south},
    .SIS/.style={.sIs={##1},start anchor=south},
    ISS/.style={ssI={##1},end anchor=north},
    SS.I/.style={ss.I={##1},end anchor=north},
    I.SS/.style={SS.I={##1}},
    SSI/.style={ISS={##1}},
    % At the first version, styles were defined using in=... out=... looseness=... However
    % it gives sometimes bad results (like the curve goes forward at some points) when nodes are
    % too close or too far appart. However, it may still be useful, so now we define the old
    % styles, that you can use them using \ar[r,IO,C].
    IO/.style={
      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}{$\cvdotsCenterMathline$}" 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,##1}},
    H/.default={},
    Z/.style={"" {zxNoPhaseSmallZ,anchor=center,##1}},
    Z/.default={},
    X/.style={"" {zxNoPhaseSmallX,anchor=center,##1}},
    X/.default={},
    % 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,
    },
    % Used to compute the intersection with the node's boundary
    allow boundary intersection/.code={%
      \ifdefined\zxEnableIntersectionsNodes%
        \edef\zx@name@path{zx@name@path@\tikz@fig@name}%
        \zx@message{[ZX] The name of the path will be \zx@name@path.}%
        \pgfkeysalso{
          name path=\zx@name@path, % Used by intersection library
        }%
      \fi%
    },
    % Will be specific to all spiders
    zxSpiders/.style={
      draw=black,
      allow boundary intersection,% Used later to do math on it.
    },
    % 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}$ or $- \alpha$
    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{emptyStyle}{ShortStyle}{LongStyle}{label style}{node content}
    add@Phase@Spider/.style n args={5}{%
      zx@emptyStyle/.style={##1},
      zx@shortStyle/.style={##2},
      zx@notEmptyStyle/.style={##3},
      zx@labelStyle/.style={##4},
      /zx/zx@content/.initial={##5},
      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={5}{
      zx@commandToExecuteVeryEnd/.try={##1}{##2}{##3}{##4}{##5},
    },
    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={5}{%
            execute at begin node={####5},% ####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,%
          }%
        }{% We check if we need to force "short mode" (zxShort instead of zxLong)
          \ifthenelse{\equal{\pgfkeysvalueof{/zx/zx@shortModeForced}}{true}}{%
            \pgfkeysalso{%
              zx@shortStyle,%
            }%
          }{% Otherwise, just use the default style.
            \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={5}{% ####4: label style, ####5: content
            % Checks if the content (stored by add@Phase@Spider in /zx/zx@content) is empty or not
            \ifthenelse{\equal{####5}{}}{% Content is empty
            }{% Content is not empty
              \pgfkeysalso{
                label={[####4,##1] ####5},%
              }%
            }%
          },%
          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 \zxZ4{...} and \zxX4{...} 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 the minus mode: "-" for minus sign, which forces short mode.
    %%% Third argument is "*" for forced short mode.
    %%% 4th argument is content of node.
    zx@spider/.code n args={8}{
      %% ##1: zxnophase style
      %% ##2: zxshort style
      %% ##3: zxlong style
      %% ##4: label style
      %% user provided:
      %% ##5: additional tikz options
      %% ##6: minus "-" or empty, like "-alpha"
      %% ##7: star "*" or empty, to force short mode
      %% ##8: content
      %%% The argument is a minus. Like \zxZ-{\alpha}, goal is to typeset "-\alpha" in short mode.
      \ifthenelse{\equal{##6}{-}}{% It's a minus!
        \pgfkeysalso{% We update the content to "-content"
          /zx/zx@shortModeForced/.initial={true},%
        }%
      }{}%
      \ifthenelse{\equal{##7}{*}}{% We force short mode!
        \pgfkeysalso{%
          /zx/zx@shortModeForced/.initial={true},%
        }%
      }{}%
      %  It's a minus, and LaTeX is... grrrr. How to get a cleaner code? Tried def/let, not working.
      \ifthenelse{\equal{##6}{-}}{%
        \pgfkeysalso{%
          add@Phase@Spider={##1}{##2}{##3}{##4}{\zxMinusInShort##8},%
        }%
      }{%
        \pgfkeysalso{%
          add@Phase@Spider={##1}{##2}{##3}{##4}{##8},%
        }%
      }%
      \pgfkeysalso{%
        /zx/post preparation labels,
        /zx/user post preparation labels,
        % /zx/user overlay nodes,
        ##5,
      }%
      \ifthenelse{\equal{##6}{-}}{% It's a minus, and LaTeX is... grrrr
        \pgfkeysalso{%
          zx@Execute@Very@End={##1}{##2}{##3}{##4}{\zxMinusInShort##8},%
        }%
      }{%
        \pgfkeysalso{%
          zx@Execute@Very@End={##1}{##2}{##3}{##4}{##8},%
        }%
      }%
    },
    %% ##1: additional tikz options
    %% ##2: minus "-" or empty, like "-alpha"
    %% ##3: star "*" or empty, to force short mode
    %% ##4: content
    zxZ4/.style n args={4}{
      zx@spider={zxNoPhaseZ}{zxShortZ}{zxLongZ}{stylePhaseInLabelZ}{##1}{##2}{##3}{##4}
    },
    zxX4/.style n args={4}{
      zx@spider={zxNoPhaseX}{zxShortX}{zxLongX}{stylePhaseInLabelX}{##1}{##2}{##3}{##4}
    },
    %% 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={
    %tiny depends on the size of the font... which we want to keep consistent look
    column sep=\zxDefaultColumnSep,
    row sep=\zxDefaultRowSep,
    zx column sep/.code={%
      \def\zxDefaultColumnSep{##1}%
      \pgfkeysalso{
        column sep=##1,
      }%
    },
    zx row sep/.code={%
      \def\zxDefaultRowSep{##1}%
      \pgfkeysalso{%
        row sep=##1,
      }%
    },
    %column sep=tiny,
    %row sep=tiny,
    % center on the math axis
    baseline={([yshift=-axis_height]current bounding box.center)},
    % Fix 1-row diagram baseline
    % By default, 1-row diagrams have a different baseline... This package does not want a special case for 1-row diagrams.
    1-row diagram/.style={},
    %% usage: math baseline=wantedBaseline, where you have somewhere \zxX[a=wantedBaseline]{\beta}
    math baseline/.style={baseline={([yshift=-axis_height]##1)}},
    %%% Include a diagram in another diagram.
    use diagram/.style 2 args={
      execute at end picture={
        \node[fit=##2,inner sep=0pt,yshift=-axis_height]{\zxUseDiagram{##1}};
      }
    },
    % 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,%
        }%
        %% name path won't work with alias... So let's create two name path ^^
        %% https://tex.stackexchange.com/questions/619622
        \ifdefined\zxEnableIntersectionsNodes%
          \edef\zx@name@path{zx@name@path@####1}%
          \zx@message{[ZX] Name given using an alias: \zx@name@path.}%
          \pgfkeysalso{
            name path=\zx@name@path, % Used by intersection library
          }%
        \fi%
        \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%
  }%
}

% shape anchor name if exists if not. Works, while doing \pgfutil@ifundefined{pgf@anchor@\shapenode{}@#2} fails.
% I guess it has to do with the way macro are expanded...
\def\ifAnchorExistsFromShape#1#2#3#4{
  \pgfutil@ifundefined{pgf@anchor@#1@#2}{%
    #4%
  }{%
    #3%
  }%
}

% node name, anchor name, if exists, if not.
\def\ifAnchorExists#1#2#3#4{%
  %%% First we extract the shape of the node:
  \edef\pgf@node@name{#1}%
  \edef\shapenode{\csname pgf@sh@ns@\pgf@node@name\endcsname}%
  \ifAnchorExistsFromShape{\shapenode}{#2}{#3}{#4}
}

%%% 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 functions to nest diagrams
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\NewDocumentCommand{\zxSaveDiagram}{mO{}m}{
  \newsavebox{#1}%
  \savebox{#1}{\begin{ZX}[ampersand replacement=\&,#2]#3\end{ZX}}%
}

\NewDocumentCommand{\zxUseDiagram}{m}{
  \usebox{#1}%
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% 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}{$\cvdotsCenterMathline$}} \ar[r,-N.,start anchor=north east] \ar[r,-N',start anchor=south east] \pgfmatrixnextcell[\zxwCol]%
}

% 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,N'-,end anchor=north west] \ar[r,N.-,end anchor=south west] \pgfmatrixnextcell[\zxwCol] |[zxNone+,inner xsep=0pt]| \makebox[0pt][r]{\scalebox{#2}{$\cvdotsCenterMathline$}}\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,"\cvdotsCenterMathline" {scale=.6,anchor=north,yshift=-0.25mm},#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{}t*t-m}{
  |[zxZ4={#1}{\IfBooleanTF{#3}{-}{}}{\IfBooleanTF{#2}{*}{}}{#4}]| %
}

%% 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{}t*t-m}{
  |[zxX4={#1}{\IfBooleanTF{#3}{-}{}}{\IfBooleanTF{#2}{*}{}}{#4}]| %
}

\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%
  \fontsize{10}{12}\selectfont% Normalize the font size to have consistent drawings everywhere.
  % 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
    }%
  }%
}
