% 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\pgf@x}% \fi% \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 wires of all registers until x position #1 \protected\def\yquant@circuit@endwires#1{% \ifcsname\yquant@prefix xshift\endcsname% \dimdef\yquant@env@end@xpos{#1+\csname\yquant@prefix xshift\endcsname}% \else% \def\yquant@env@end@xpos{#1}% \fi% \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 \edef\storedleft{\the\pgf@picminx}% \yquant@draw@wire\yquant@circuit@endwires@i1% \global\pgf@picminx=\storedleft% \yquant@register@set@type\yquant@circuit@endwires@i\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{% \ifcsname\yquant@prefix registermap@#1\endcsname% % make sure drawing the wire does not affect our left bounding box position \edef\storedleft{\the\pgf@picminx}% \yquant@draw@wire{#1}0% \global\pgf@picminx=\storedleft% \else% \yquant@draw@wire{#1}0% \fi% \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% % 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% % 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% }% } % creates a subcircuit. Parameter registers must be filled in \yquant@circuit@subcircuit@params. \protected\def\yquant@circuit@subcircuit#1{% \numdef\yquant@circuit@subcircuit@id{\yquant@env+1}% \listcsxadd{\yquant@prefix subcircuits}{\yquant@circuit@subcircuit@id}% \begingroup% \tikzset{/yquant/every operator, #1,% /yquant/this operator, /yquant/operators/this subcircuit box/.style={}}% % execute the subcircuit \expandafter% \yquant@env@begin@noarg% \yquant@lang@attr@value% this contains the subcircuit's content \expandafter\unless\expandafter\ifx\csname\yquant@prefix parameters\endcsname\empty% \PackageError{yquant.sty}{Invalid subcircuit parameters count}% {Too many parameters given.}% \fi% \global\cslet{\yquant@prefix parameters}\yquant@circuit@subcircuit@param% \dimen0=\yquant@config@register@sep% % the first input must count all its height plus everything that is above it in the subcircuit as the height of the outer wire it is attached to \edef\firstinput{% \expandafter\expandafter\expandafter% \@firstoftwo\csname\yquant@prefix firstinput\endcsname% }% \edef\outerfirst{% \expandafter\expandafter\expandafter% \@secondoftwo\csname\yquant@prefix firstinput\endcsname% }% \dimen2=\yquant@register@get@height\firstinput\relax% \ifnum\firstinput>1 % \yquant@fordown \i := \the\numexpr\firstinput-1\relax downto 1 {% \advance\dimen2 by \dimexpr\yquant@register@get@height\i+% \yquant@register@get@depth\i+\dimen0\relax% }% \fi% % the last input must count all its depth plus everything that is below it in the subcircuit as the depth of the outer wire it is attached to \edef\lastinput{% \expandafter\expandafter\expandafter% \@firstoftwo\csname\yquant@prefix lastinput\endcsname% }% \edef\outerlast{% \expandafter\expandafter\expandafter% \@secondoftwo\csname\yquant@prefix lastinput\endcsname% }% \dimen4=\yquant@register@get@depth\lastinput\relax% \ifnum\lastinput<\csname\yquant@prefix registers\endcsname% \yquant@for \i := \the\numexpr\lastinput+1\relax to \csname\yquant@prefix registers\endcsname {% \advance\dimen4 by \dimexpr\yquant@register@get@height\i+% \yquant@register@get@depth\i+\dimen0\relax% }% \fi% \begingroup% \let\yquant@prefix=\yquant@parent% \yquant@register@update@height\outerfirst{\the\dimen2}% \yquant@register@update@depth\outerlast{\the\dimen4}% \endgroup% % we cannot make more precise statements about the inputs in between - for example, if input 1 is mapped to outer wire 1 and input 2 to outer wire 5, how to split the heights/depth appropriately between the outer wires 1-5? \yquant@env@end% \endgroup% } % 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! It not only has to provide the appropriate drawing commands for later, but also has to measure the actual width of the outputs, which is required for proper subcircuit positioning. \def\do##1{% \pgfinterruptboundingbox% \yquant@env@virtualize@path% \ifyquant@firsttoken\yquant@register@multi{##1}{% \csxappto{\yquant@prefix draw}% {\yquant@draw@output@multi% \yquant@circuit@output@do@multi@@extract##1{\unexpanded{#3}}}% \yquant@draw@@output@multi{#3}% }{% \csgappto{\yquant@prefix draw}% {\yquant@draw@output@single{##1}{#3}}% \yquant@draw@@output@single{##1}{#3}% \yquant@register@update@height{##1}{\the\pgf@picmaxy}% \yquant@register@update@depth{##1}{\the\dimexpr-\pgf@picminy\relax}% }% \ifdim\pgf@picmaxx>\csname\yquant@prefix xmax\endcsname% \csxdef{\yquant@prefix xmax}{\the\pgf@picmaxx}% \fi% \endpgfinterruptboundingbox% }% \yquant@draw@output@group{#2}% \csgappto{\yquant@prefix draw}{% \yquant@draw@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@draw@output@endgroup% }% \yquant@draw@output@endgroup% } \def\yquant@circuit@output@do@multi@@extract#1#2#3#4#5{% {#2}{#3}{#5}% } % END_FOLD