% BEGIN_FOLD Drawing wires
% extends the wire of register #1. Assumes a node called yquantbox is set up, and the \pgfshapeclippathhorzresult was set up appropriately for this node.
\protected\def\yquant@circuit@extendwire#1#2{%
   \begingroup%
      \ifx*#2%
         \edef\wirexpos{\the\dimen0}%
      \else%
         \pgfpointanchor{yquantbox}{#2}%
         \edef\wirexpos{\the\yquant@pgf@x}%
      \fi%
      \ifdim\yquant@orientation@plus\wirexpos>0pt % may be negative for init gates
         \yquant@register@get@typeywire{#1}\wiretype\wireypos\wirelast%
         \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}%
         \ifdefined\yquant@config@corner@at%
            \ifinlist{#1}\yquant@config@corner@at{%
               \ifnum\yquant@register@type@c>\yquant@draw@@currentcontroltype%
                  \dimdef\wirexpos{\wirexpos\yquant@config@corner@xamount}%
               \else%
                  \dimdef\wirexpos{\wirexpos+5\dimexpr\yquant@config@corner@xamount\relax}%
               \fi%
            }\relax%
         \fi%
         \ifnum\wiretype=\yquant@register@type@none%
            % the clippings of the previous operator will for sure not be needed, but the type might be turned into an active one, so we need the last clipping.
            \yquant@register@set@lastwire{#1}{%
               {\wirexprevpos}{\wirexpos}{}%
               {\ifyquant@config@draw@quality%
                   \unexpanded\expandafter{\pgfshapeclippathhorzresult}%
                \fi}%
            }%
         \else%
            % append the previous `last' clipping to the old list and insert the new one
            \yquant@register@set@lastwire{#1}{%
               {\wirexprevpos}{\wirexpos}%
               {\unexpanded\expandafter\expandafter\expandafter{%
                   \expandafter\@thirdandfourthoffour\wirelast%
                }%
               }%
               {\ifyquant@config@draw@quality%
                  \unexpanded\expandafter{\pgfshapeclippathhorzresult}%
                \fi}%
            }%
         \fi%
      \fi%
   \endgroup%
}

% finishes the wires of all registers
\protected\def\yquant@circuit@endwires{%
   \expandafter\expandafter\expandafter\yquant@register@get@maxxrange%
      \expandafter\expandafter\expandafter\yquant@circuit@endwires@x%
      \expandafter\expandafter\expandafter1%
      \expandafter\expandafter\expandafter{\csname\yquant@prefix registers\endcsname}%
   % to have a symmetric situation, we extend again one separation at the end, unless this is supposed to be seamless and we don't have outputs (for seamless circuits with outputs, extend - since this extension will be between last register and output)
   \ifyquant@env@seamless{%
      \expandafter\unless\expandafter\ifx\csname\yquant@prefix outputs\endcsname\relax%
         \dimdef\yquant@circuit@endwires@x{%
            \yquant@circuit@endwires@x\yquant@orientation@plus\yquant@config@operator@sep%
         }%
      \fi%
   }{%
      \dimdef\yquant@circuit@endwires@x{%
         \yquant@circuit@endwires@x\yquant@orientation@plus\yquant@config@operator@sep%
      }%
   }%
   \let\yquant@circuit@endwires@finalize=\relax%
   \yquant@for \yquant@circuit@endwires@i := 1 to \csname\yquant@prefix registers\endcsname {%
      % we only extend the wire if it does not come from the outer circuit - this one would be responsible for the extension.
      \ifcsname\yquant@prefix registermap@\yquant@circuit@endwires@i\endcsname%
         \xifinlistcs\yquant@circuit@endwires@i{\yquant@prefix inonly}{%
            % however, the wire is to be discarded after this circuit
            \ifyquanthorz{%
               \edef\storedleft{\the\pgf@picminx}%
               \yquant@draw@wire\yquant@circuit@endwires@i1%
               \global\pgf@picminx=\storedleft%
            }{%
               \edef\storedtop{\the\pgf@picmaxy}%
               \yquant@draw@wire\yquant@circuit@endwires@i1%
               \global\pgf@picmaxy=\storedtop%
            }%
            \eappto\yquant@circuit@endwires@finalize{%
               \yquant@register@set@type%
                  {\yquant@circuit@endwires@i}\noexpand\yquant@register@type@none%
            }%
         }\relax%
      \else%
         \yquant@draw@wire\yquant@circuit@endwires@i1%
      \fi%
   }%
}

% outputs the wire according to its previous instructions and prepares for a change in the wire style
\protected\def\yquant@circuit@flushwire#1{%
   \yquant@draw@wire{#1}0%
   \begingroup%
      \yquant@register@get@lastwire{#1}\wirelast%
      \yquant@register@set@lastwire{#1}{%
         {\expandafter\@secondoffour\wirelast}{\expandafter\@secondoffour\wirelast}{}%
         {\unexpanded\expandafter\expandafter\expandafter{%
             \expandafter\@fourthoffour\wirelast%
          }}%
      }%
   \endgroup%
}
% END_FOLD

% BEGIN_FOLD Drawing control lines
% populates a drawing macro with the current control line with style #1 at position #2. Assumes a node called yquantbox is set up, and the \pgfshapeclippathvertresult was set up appropriately for this node. At the first call, \yquant@circuit@extendcontrolline@cmd must be \let to \empty and \yquant@circuit@extendcontrolline@prev to \relax.
\protected\def\yquant@circuit@extendcontrolline#1#2#3{%
   \ifyquant@config@draw@quality%
      \eappto\yquant@circuit@extendcontrolline@clip{%
         \unexpanded\expandafter{\pgfshapeclippathvertresult}%
      }%
   \fi%
   \ifdefined\yquant@config@corner@at%
      \let\yquant@circuit@extendcontrolline@cmd@old=\yquant@circuit@extendcontrolline@cmd%
      \let\yquant@circuit@extendcontrolline@prev@old=\yquant@circuit@extendcontrolline@prev%
   \fi%
   \unless\ifnum#1=0 %
      \yquant@begingroup%
         \tikzset{/yquant/every control line}%
         \expandafter%
      \yquant@endgroup%
      \expandafter\@tempdima\the\pgflinewidth%
      \pgfpointanchor{yquantbox}{center}%
      \advance \yquant@pgf@y by #3\relax%
      \ifcase#1 %
         % no control (or to a discarded target, which we don't do)
      \or%
         % qubit
         \unless\ifx\yquant@circuit@extendcontrolline@prev\relax%
            \eappto\yquant@circuit@extendcontrolline@cmd{%
               \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(#2,\the\yquant@pgf@y)%
            }%
         \fi%
      \or%
         % cbit
         \unless\ifx\yquant@circuit@extendcontrolline@prev\relax%
            \eappto\yquant@circuit@extendcontrolline@cmd{%
               \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(\the\dimexpr#2-2\@tempdima\relax,\the\yquant@pgf@y)%
               \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(\the\dimexpr#2+2\@tempdima\relax,\the\yquant@pgf@y)%
            }%
         \fi%
      \or%
         % quantum-bundle (very unusual, but perhaps for transversal operations?)
         \unless\ifx\yquant@circuit@extendcontrolline@prev\relax%
            \eappto\yquant@circuit@extendcontrolline@cmd{%
               \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(\the\dimexpr#2-2\@tempdima\relax,\the\yquant@pgf@y)%
               \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(\the\dimexpr#2\relax,\the\yquant@pgf@y)%
               \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev%
               -- \yquant@coords(\the\dimexpr#2+2\@tempdima\relax,\the\yquant@pgf@y)%
            }%
         \fi%
      \else%
         \PackageError{yquant.sty}{Invalid control line type `#1'}%
                      {yquant encountered an internal error.}%
      \fi%
      \yquant@circuit@extendcontrolline@store{#2}%
   \fi%
}

\protected\def\yquant@circuit@extendcontrolline@store#1{%
   \edef\yquant@circuit@extendcontrolline@prev{%
      {\yquant@coords(\the\dimexpr#1-2\@tempdima\relax,\the\yquant@pgf@y)}%
      {\yquant@coords(\the\dimexpr#1\relax,\the\yquant@pgf@y)}%
      {\yquant@coords(\the\dimexpr#1+2\@tempdima\relax,\the\yquant@pgf@y)}%
   }%
}

\def\yquant@circuit@extendcontrolline@corner@hackprev#1#2#3{%
   {\yquant@circuit@extendcontrolline@corner@hackprev@coord#1}%
   {\yquant@circuit@extendcontrolline@corner@hackprev@coord#2}%
   {\yquant@circuit@extendcontrolline@corner@hackprev@coord#3}%
}

\def\yquant@circuit@extendcontrolline@corner@hackprev@coord(#1,#2){%
   \ifyquanthorz{%
      (#1,\the\dimexpr#2+1.5\pgflinewidth\relax)%
   }{%
      (\the\dimexpr#1-1.5\pgflinewidth\relax,#2)%
   }%
}

\protected\def\yquant@circuit@extendcontrolline@corner#1{%
   \ifyquant@OR
      \ifnum\yquant@config@corner@min=#1 \fi%
      \ifnum\yquant@config@corner@max=#1 \fi{%
      \ifnum\yquant@register@type@q<\yquant@register@get@type{#1} %
         % the topmost/bottom-most register is a non-qubit target
         \begingroup%
            \edef\wiretype{\yquant@register@get@type{#1}}%
            \edef\wirestyle{\noexpand\tikzset{%
               /yquant/this wire/.style={%
                  /yquant/every wire,%
                  /yquant/every \yquant@register@type@tostring\wiretype\space wire,%
                     \yquant@register@get@style{#1}%
               }, /yquant/this wire%
            }}%
            \wirestyle%
            \ifnum\yquant@config@corner@min=#1 %
               % no line draw command was stored yet, only the previous position; modify it
               \edef\extend{%
                  \endgroup%
                  \edef\noexpand\yquant@circuit@extendcontrolline@prev{%
                     \expandafter\yquant@circuit@extendcontrolline@corner@hackprev%
                        \yquant@circuit@extendcontrolline@prev%
                  }%
               }%
            \else%
               % the line draw command was already stored; revert to the previous state and re-compute the value
               \edef\extend{%
                  \endgroup%
                  \unexpanded{%
                     \let\pgfshapeclippathvertresult=\noexpand\empty%
                     \let\yquant@circuit@extendcontrolline@prev=\yquant@circuit@extendcontrolline@prev@old%
                     \let\yquant@circuit@extendcontrolline@cmd=\yquant@circuit@extendcontrolline@cmd@old%
                  }%
                  \yquant@circuit@extendcontrolline{\the\yquant@draw@@currentcontroltype}{\yquant@draw@@x}{\the\dimexpr\yquant@orientation@minus1.5\pgflinewidth\relax}%
               }%
            \fi%
         \extend%
      \fi%
   }\relax%
}

% populates a drawing macro with the multi operation connector at position #2. Assumes a node called yquantbox is set up, and the \pgfshapeclippathvertresult was set up appropriately for this node. At the first call, \yquant@circuit@extendmultiline@cmd must be \let to \empty and \yquant@circuit@extendmultiline@prev to \relax.
\protected\def\yquant@circuit@extendmultiline#1{%
   \yquant@begingroup%
      \tikzset{/yquant/every multi line}%
      \expandafter%
   \yquant@endgroup%
   \ifyquant@config@draw@quality%
      \eappto\yquant@circuit@extendmultiline@clip{%
         \unexpanded\expandafter{\pgfshapeclippathvertresult}%
      }%
   \fi%
   \expandafter\@tempdima\the\pgflinewidth%
   \pgfpointanchor{yquantbox}{center}%
   \unless\ifx\yquant@circuit@extendmultiline@prev\relax%
      \eappto\yquant@circuit@extendmultiline@cmd{%
         \yquant@circuit@extendmultiline@prev -- \yquant@coords(#1,\the\yquant@pgf@y)%
      }%
   \fi%
   \edef\yquant@circuit@extendmultiline@prev{%
      \yquant@coords(\the\dimexpr#1\relax,\the\yquant@pgf@y)%
   }%
}
% END_FOLD

\newif\ifyquant@circuit@operator@hasControls%
% sets up the relevant variables associated with an operator
% #1: positive controls
% #2: negative controls
% #3: targets
\protected\def\yquant@circuit@operator#1#2#3{%
   % convert all names to indices
   % targets
   \yquant@register@get@ids{#3}%
   \let\yquant@circuit@operator@targets=\yquant@register@get@ids@list%
   \let\yquant@circuit@operator@mintarget=\yquant@register@get@ids@min%
   \let\yquant@circuit@operator@maxtarget=\yquant@register@get@ids@max%
   \let\yquant@circuit@operator@numtarget=\yquant@register@get@ids@count%
   % make sure to reset this for subcircuits
   \yquant@circuit@operator@hasControlsfalse%
   % For the targets, multi-qubit registers might have been allowed, but certainly not for
   % the controls!
   \yquant@register@get@allowmultifalse%
   % positive controls
   \yquant@register@get@ids{#1}%
   \let\yquant@circuit@operator@pctrls=\yquant@register@get@ids@list%
   \let\yquant@circuit@operator@minpctrl=\yquant@register@get@ids@min%
   \let\yquant@circuit@operator@maxpctrl=\yquant@register@get@ids@max%
   \let\yquant@circuit@operator@numpctrl=\yquant@register@get@ids@count%
   \ifnum\yquant@register@get@ids@count>0 %
      \yquant@circuit@operator@hasControlstrue%
   \fi%
   % negative controls
   \yquant@register@get@ids{#2}%
   \let\yquant@circuit@operator@nctrls=\yquant@register@get@ids@list%
   \let\yquant@circuit@operator@minnctrl=\yquant@register@get@ids@min%
   \let\yquant@circuit@operator@maxnctrl=\yquant@register@get@ids@max%
   \let\yquant@circuit@operator@numnctrl=\yquant@register@get@ids@count%
   \ifnum\yquant@register@get@ids@count>0 %
      \yquant@circuit@operator@hasControlstrue%
   \fi%
   % determine the qubits spanned
   \yquant@min\yquant@circuit@operator@minctrl%
      \yquant@circuit@operator@mintarget%
      \yquant@circuit@operator@minpctrl%
      \yquant@circuit@operator@minnctrl%
      \relax%
   \yquant@max\yquant@circuit@operator@maxctrl%
      \yquant@circuit@operator@maxtarget%
      \yquant@circuit@operator@maxpctrl%
      \yquant@circuit@operator@maxnctrl%
      \relax%
}

% restores the data captured for an uncontrolled operator and starts preparation
% #1: \yquant@attrs@remaining
% #2: \yquant@lang@attr@name
% #3: \yquant@circuit@operator@targets
% #4: \yquant@circuit@operator@mintarget
% #5: \yquant@circuit@operator@maxtarget
% #6: \yquant@circuit@operator@numtarget
\protected\def\yquant@circuit@restore#1#2#3#4#5#6{%
   \def\yquant@attrs@remaining{#1}%
   \def\yquant@lang@attr@name{#2}%
   \def\yquant@circuit@operator@targets{#3}%
   \def\yquant@circuit@operator@mintarget{#4}%
   \def\yquant@circuit@operator@maxtarget{#5}%
   \def\yquant@circuit@operator@numtarget{#6}%
   \yquant@circuit@operator@hasControlsfalse%
   \let\yquant@circuit@operator@pctrls=\empty%
   \def\yquant@circuit@operator@minpctrl{2147483647}%
   \def\yquant@circuit@operator@maxpctrl{0}%
   \let\yquant@circuit@operator@numpctrl=\yquant@circuit@operator@maxpctrl%
   \let\yquant@circuit@operator@nctrls=\empty%
   \let\yquant@circuit@operator@minnctrl=\yquant@circuit@operator@minpctrl%
   \let\yquant@circuit@operator@maxnctrl=\yquant@circuit@operator@maxpctrl%
   \let\yquant@circuit@operator@numnctrl=\yquant@circuit@operator@numpctrl%
   \let\yquant@circuit@operator@minctrl=\yquant@circuit@operator@mintarget%
   \let\yquant@circuit@operator@maxctrl=\yquant@circuit@operator@maxtarget%
}

% creates a subcircuit. Parameter registers must be filled in \yquant@circuit@subcircuit@params.
% #1: style
\protected\def\yquant@circuit@subcircuit#1{%
   \numdef\yquant@circuit@subcircuit@id{\yquant@env+1}%
   \listcsxadd{\yquant@prefix subcircuits}{\yquant@circuit@subcircuit@id}%
   \yquant@begingroup%
      \tikzset{/yquant/every operator, #1,%
               /yquant/this operator, /yquant/operators/this subcircuit box/.style={}}%
      % execute the subcircuit
      \expandafter\undef\expandafter\yquant@circuit@subcircuit@content%
      \expandafter%
      \yquant@env@begin@noarg%
         \yquant@circuit@subcircuit@content%
         \expandafter\unless\expandafter\ifx\csname\yquant@prefix parameters\endcsname\empty%
            \PackageError{yquant.sty}{Invalid subcircuit parameters count}%
                         {Too many parameters given.}%
         \fi%
      \yquant@env@end%
   \yquant@endgroup%
}

% BEGIN_FOLD Helpers for operator callbacks
% turn a wire into a different type
\def\yquant@circuit@settype#1{%
   \unless\if\yquant@circuit@settype@to\yquant@register@get@type{#1} %
      \yquant@circuit@flushwire{#1}%
      \yquant@register@set@type{#1}{\yquant@circuit@settype@to}%
   \fi%
}

\def\yquant@circuit@settype@beforenobit#1{%
   \unless\if\yquant@circuit@settype@to\yquant@register@get@type{#1} %
      \ifyquant@OR%
         \ifnum\yquant@circuit@operator@minctrl=#1 \fi%
         \ifnum\yquant@circuit@operator@maxctrl=#1 \fi{%
         \yquant@circuit@extendcontrolline@corner{#1}%
      }\empty%
      \yquant@circuit@flushwire{#1}%
      \yquant@register@set@type{#1}{\yquant@circuit@settype@to}%
   \fi%
}

\def\yquant@circuit@settype@afternobit#1{%
   % same, but possibly extend control line according to the style before the change
   \unless\if\yquant@circuit@settype@to\yquant@register@get@type{#1} %
      \yquant@circuit@flushwire{#1}%
      \yquant@register@set@type{#1}{\yquant@circuit@settype@to}%
      \ifyquant@OR%
         \ifnum\yquant@circuit@operator@minctrl=#1 \fi%
         \ifnum\yquant@circuit@operator@maxctrl=#1 \fi{%
         \yquant@circuit@extendcontrolline@corner{#1}%
      }\empty%
   \fi%
}

\protected\def\yquant@circuit@settype@prepare#1{%
   \yquant@register@set@type{#1}{\yquant@circuit@settype@to}%
}

\protected\long\def\yquant@circuit@setstyle#1#2{%
   \yquant@circuit@flushwire{#1}%
   \yquant@register@set@style{#1}{#2}%
}

\protected\long\def\yquant@circuit@addstyle#1#2{%
   \yquant@circuit@flushwire{#1}%
   \yquant@register@set@style{#1}{\yquant@register@get@style{#1},#2}%
}

% performs an alignment of all registers specified in the argument; that is, the next operation on any of the listed registers will be after the maximum position of all of them
% #1: arbitrary register list
\protected\def\yquant@circuit@align#1{%
   \csxappto{\yquant@prefix draw}{%
      \yquant@draw@hspace{#1}{0pt}%
   }%
}

% introduces a horizontal skip (= invisible operator of given width) among the registers; that is, those registers are first aligned, then skipped by the given amount.
% #1: arbitrary register list
% #2: skip width
\protected\def\yquant@circuit@hspace#1#2{%
   \csxappto{\yquant@prefix draw}{%
      \yquant@draw@hspace{#1}{#2}%
   }%
}

% applies an action to wires a list of registers and causes them to be redrawn
% #1: action for prepare
% #2: action for draw
% #3: arbitrary register list
% #4: parameter(s)
\protected\def\yquant@circuit@actonwires#1#2#3#4{%
   \begingroup%
      \let\tmp=\empty%
      \def\do##1{%
         % We do not extend the wire: a register that is discarded somewhere does not make
         % sense, only right after some application (which is supposed to already have
         % extended the wire appropriately).
         \eappto\tmp{#2{##1}#4}%
         #1{##1}#4%
      }%
      \dolistloop{#3}%
      \csxappto{\yquant@prefix draw}{\tmp}%
   \endgroup%
}

% sets the output of wires
% #1: arbitrary register list
\protected\def\yquant@circuit@output{%
   \let\idx=\yquant@protectedempty%
   \ifnum\yquant@compat>1 %
      \let\Ifnum=\yquant@protectedempty%
      \let\Ifcase=\yquant@protectedempty%
      \let\Or=\yquant@protectedempty%
      \let\Else=\yquant@protectedempty%
      \let\Fi=\yquant@protectedempty%
      \let\Unless=\yquant@protectedempty%
      \let\The=\yquant@protectedempty%
   \fi%
   \protected@csxappto{\yquant@prefix outputs}%
            {\yquant@circuit@restore%
               {\yquant@attrs@remaining}%
               {\yquant@lang@attr@name}%
               {\unexpanded\expandafter{\yquant@circuit@operator@targets}}%
               {\yquant@circuit@operator@mintarget}{\yquant@circuit@operator@maxtarget}%
               {\yquant@circuit@operator@numtarget}%
             \yquant@prepare{\yquant@lang@attr@value}{}%
            }%
}
% END_FOLD