% BEGIN_FOLD Drawing wires % a bit faster than nested \@firstoftwo/\@secondoftwo % note \@thirdofthree is defined in the latex kernel already. \long\def\@firstofthree#1#2#3{#1}% \long\def\@secondofthree#1#2#3{#2}% \long\def\@firstoffour#1#2#3#4{#1}% \long\def\@secondoffour#1#2#3#4{#2}% \long\def\@thirdoffour#1#2#3#4{#3}% \long\def\@fourthoffour#1#2#3#4{#4}% \long\def\@thirdandfourthoffour#1#2#3#4{#3#4}% % 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{% \begingroup% \pgfpointanchor{yquantbox}{center}% \edef\wirexpos{\the\pgf@x}% \yquant@register@get@typeywire{#1}\wiretype\wireypos\wirelast% \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}% \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}{}% {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% }% \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% }% } {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% }% \fi% \endgroup% } % finishes the wire of registers 1 to #1 until x position \yquant@env@end@xpos \protected\def\yquant@circuit@endwires#1{% \yquant@for \yquant@circuit@endwires@i := 1 to #1 { \yquant@draw@wire\yquant@circuit@endwires@i\yquant@env@end@xpos% }% } % 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}{}% \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{% \begingroup% \tikzset{/yquant/every control line}% \expandafter% \endgroup% \eappto\yquant@circuit@extendcontrolline@clip{% \unexpanded\expandafter{\pgfshapeclippathvertresult}% }% \expandafter\@tempdima\the\pgflinewidth% \ifcase#1% % no control (or to a discarded target, which we don't do) \or% % qubit \pgfpointanchor{yquantbox}{center}% \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev% -- (#2,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \or% % cbit \pgfpointanchor{yquantbox}{center}% \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev% -- (\the\dimexpr#2-2\@tempdima\relax,\the\pgf@y)% \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev% -- (\the\dimexpr#2+2\@tempdima\relax,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \or% % quantum-bundle (very unusual, but perhaps for transversal operations?) \pgfpointanchor{yquantbox}{center}% \unless\ifx\yquant@circuit@extendcontrolline@prev\relax% \eappto\yquant@circuit@extendcontrolline@cmd{% \expandafter\@firstofthree\yquant@circuit@extendcontrolline@prev% -- (\the\dimexpr#2-2\@tempdima\relax,\the\pgf@y)% \expandafter\@secondofthree\yquant@circuit@extendcontrolline@prev% -- (\the\dimexpr#2\relax,\the\pgf@y)% \expandafter\@thirdofthree\yquant@circuit@extendcontrolline@prev% -- (\the\dimexpr#2+2\@tempdima\relax,\the\pgf@y)% }% \fi% \yquant@circuit@extendcontrolline@store{#2}% \else% \PackageError{yquant.sty}{Invalid control line type `#1'}% {yquant encountered an internal error.}% \fi% } \protected\def\yquant@circuit@extendcontrolline@store#1{% \edef\yquant@circuit@extendcontrolline@prev{% {(\the\dimexpr#1-2\@tempdima\relax,\the\pgf@y)}% {(\the\dimexpr#1\relax,\the\pgf@y)}% {(\the\dimexpr#1+2\@tempdima\relax,\the\pgf@y)}% }% } % 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{% \begingroup% \tikzset{/yquant/every multi line}% \expandafter% \endgroup% \eappto\yquant@circuit@extendmultiline@clip{% \unexpanded\expandafter{\pgfshapeclippathvertresult}% }% \expandafter\@tempdima\the\pgflinewidth% \pgfpointanchor{yquantbox}{center}% \unless\ifx\yquant@circuit@extendmultiline@prev\relax% \eappto\yquant@circuit@extendmultiline@cmd{% \yquant@circuit@extendmultiline@prev -- (#1,\the\pgf@y)% }% \fi% \edef\yquant@circuit@extendmultiline@prev{% (\the\dimexpr#1\relax,\the\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% % 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% % obtain the required minimal x position \yquant@register@get@maxxrange% \yquant@circuit@operator@x% \yquant@circuit@operator@minctrl% \yquant@circuit@operator@maxctrl% \dimdef\yquant@circuit@operator@x{% \yquant@circuit@operator@x+\yquant@config@operator@sep% }% } % BEGIN_FOLD Subcircuit-related % Does all necessary calculations for inserting a sub-circuit % #1: subcircuit code (should start with \begin{yquant}) %\newbox\yquant@circuit@subcircuit@box %\protected\long\def\yquant@circuit@subcircuit#1{% % % We need to place the inner circuit at the correct position; but for this, we need % % its extent. For this, we first place it within a box. But this box is then % % integrated seamlessly, in particular, named nodes must be re-placed. We use a lot of % % inspiration from pgf's matrix capabilities. % % First, we anticipate the macro that is used by our subcircuit to store the node % % names. % \edef\yquant@circuit@subcircuit@nodelist{yquant@env\the\numexpr\yquant@env+1\relax @circuit@subcircuit@nodelist}% % \global\cslet\yquant@circuit@subcircuit@nodelist\empty% % \pgfinterruptboundingbox% % % we make sure there are no conflicts by prefixing any named nodes in any case. % \ifx\yquant@lang@attr@name\empty% % \pgfkeys{/tikz/name prefix/.expanded={sub\yquant@prefix-}}% % \else% % \pgfkeys{/tikz/name prefix/.expanded={\pgfkeysvalueof{/tikz/name prefix}\yquant@lang@attr@name-}}% % \fi% % \let\pgf@nodecallback=\yquant@circuit@subcircuit@nodecallback% % \pgftransformreset% % \global\setbox\yquant@circuit@subcircuit@box=\hbox{{% % % bypass 'overlay' option % \pgf@relevantforpicturesizetrue% % \pgfsys@beginpicture% % #1% % \pgfsys@endpicture% % \ifdim\pgf@picmaxx=-16000pt % % \global\pgf@picmaxx=0pt % % \global\pgf@picminx=0pt % % \global\pgf@picmaxy=0pt % % \global\pgf@picminy=0pt % % \fi% % }}% % \wd\yquant@circuit@subcircuit@box=0pt % % \global\setbox\yquant@circuit@subcircuit@box=\hbox{{% % \hskip-\pgf@picminx% % \unhbox\yquant@circuit@subcircuit@box% % \hskip\pgf@picmaxx% % }}% % \ht\yquant@circuit@subcircuit@box=\pgf@picmaxy% % \dp\yquant@circuit@subcircuit@box=-\pgf@picminy% % % We need to remember the offset for the coordinate shifts % \dimgdef\yquant@circuit@subcircuit@shiftx{-\pgf@picminx}% % \endpgfinterruptboundingbox% % \ifx\yquant@lang@attr@name\empty% % % However, if the outer node was not named, no access to the inner nodes is desired, % % so we delete all nodes again. % \def\do##1{% % \csgundef{pgf@sh@ns@##1}% % \csgundef{pgf@sh@np@##1}% % \csgundef{pgf@sh@nt@##1}% % \csgundef{pgf@sh@pi@##1}% % \csgundef{pgf@sh@ma@##1}% % }% % \dolistcsloop\yquant@circuit@subcircuit@nodelist% % \global\cslet\yquant@circuit@subcircuit@nodelist\empty% % \else% % % But now access is desired, and probably we are deeply nested. Append the sublist to ours, so that our parent can re-map them again. % \ifx\pgf@nodecallback\yquant@circuit@subcircuit@nodecallback% % \csxappto{\yquant@prefix circuit@subcircuit@nodelist}% % {\csname\yquant@circuit@subcircuit@nodelist\endcsname}% % \fi% % \fi% %} % %\def\yquant@circuit@subcircuit@nodecallback#1{% % \listcsxadd{\yquant@prefix circuit@subcircuit@nodelist}{#1}% %} %\protected\def\yquant@circuit@subcircuit@shiftnodes#1{% % \expandafter\unless\expandafter\ifx\csname\yquant@circuit@subcircuit@nodelist\endcsname\empty{% % \pgftransformreset% % \pgf@process{\pgfpointanchor{#1}{text}}% % \edef\yquant@circuit@subcircuit@offset{% % \noexpand\pgfqpoint{\the\dimexpr\pgf@x+\yquant@circuit@subcircuit@shiftx\relax}% % {\the\dimexpr\pgf@y\relax}% % }% % \def\do##1{% % \pgf@shift@node{##1}\yquant@circuit@subcircuit@offset% % }% % \dolistcsloop\yquant@circuit@subcircuit@nodelist% % }\fi% %} % END_FOLD % BEGIN_FOLD Helpers for operator callbacks % turn a wire into a different type \def\yquant@circuit@settype#1{% \yquant@circuit@flushwire{#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{% \begingroup% \yquant@register@get@maxxlist\x{#1}% \def\do##1{% \yquant@register@set@x{##1}\x% }% \dolistloop{#1}% \endgroup% } % 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{% \begingroup% \yquant@register@get@maxxlist\x{#1}% \dimdef\x{\x+#2}% \def\do##1{% \yquant@register@set@x{##1}\x% }% \dolistloop{#1}% \endgroup% } % applies an action to wires a list of registers and causes them to be redrawn % #1: action % #2: arbitrary register list % #3: parameter(s) \protected\def\yquant@circuit@actonwires#1#2#3{% \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). \appto\tmp{#1{##1}#3}% }% \dolistloop{#2}% \csxappto{\yquant@prefix draw}{\tmp}% \endgroup% } % sets the output of wires % #1: arbitrary register list \protected\def\yquant@circuit@output#1{% \csxappto{\yquant@prefix outputs}% {\noexpand\yquant@circuit@output@do% {\noexpand#1}% there is nothing to expand - except the first token, which might be \yquant@register@multi, and we need to preserve this. {\yquant@attrs@remaining}% {\unexpanded\expandafter{\yquant@lang@attr@value}}% }% } \protected\long\def\yquant@circuit@output@do#1#2#3{% % this must only be called at the end of an environment, where \yquant@env@end@xpos is % set up properly! \def\do##1{% \ifyquant@firsttoken\yquant@register@multi{##1}{% \csxappto{\yquant@prefix draw}% {\noexpand\yquant@circuit@output@do@multi% \yquant@circuit@output@do@multi@@extract##1{\unexpanded{#3}}}% }{% \csgappto{\yquant@prefix draw}% {\yquant@circuit@output@do@single{##1}{#3}}% }% }% \csgappto{\yquant@prefix draw}{% \yquant@circuit@output@group{#2}% } % \dolistloop will carry out one \expandafter on the argument; but this expansion step % is already done. If #1 starts with \yquant@register@multi, this will be expanded once % despite \protected, so insert some expand-to-nothing token first. \dolistloop{\empty#1}% \csgappto{\yquant@prefix draw}{% \yquant@circuit@output@endgroup% }% } \def\yquant@circuit@output@do@multi@@extract#1#2#3#4#5{% {#2}{#3}{#5}% } \protected\long\def\yquant@circuit@output@group#1{% \begingroup% \def\idx{0}% \yquant@set{#1}% } \let\yquant@circuit@output@endgroup=\endgroup% \long\def\yquant@circuit@output@do@single#1#2{% \path (\yquant@env@end@xpos, \yquant@register@get@y{#1}) node[/yquant/every output, /yquant/every \ifcase\yquant@register@get@type{#1} nobit\or qubit\or cbit\or qubits\fi\space output] {#2}; \numdef\idx{\idx+1}% } \long\def\yquant@circuit@output@do@multi#1#2#3#4{% % extremely similar to \yquant@draw@multiinit \@tempdima=-.5\dimexpr\yquant@config@register@sep\relax% \dimdef\yquant@draw@multiinit@@min{\yquant@register@get@y{#1}-\@tempdima}% \dimdef\yquant@draw@multiinit@@max{\yquant@register@get@y{#2}+\@tempdima}% \dimdef\yquant@draw@multiinit@@total{% \yquant@draw@multiinit@@max-\yquant@draw@multiinit@@min% }% \def\pgfdecorationsegmentaspect{0}% \let\yquant@register@multi@contiguous=\yquant@draw@multiinit@contiguous% \let\pgfdecorationsegmentfromto=\empty% #3% \edef\pgfdecorationsegmentfromto{\expandafter\@gobble\pgfdecorationsegmentfromto}% \path[/yquant/every multi output] (\yquant@env@end@xpos, \yquant@draw@multiinit@@min) -- (\yquant@env@end@xpos, \yquant@draw@multiinit@@max) node {#4};% \numdef\idx{\idx+1}% } % END_FOLD