diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex')
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex | 286 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-config.tex | 168 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-draw.tex | 482 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-env.tex | 319 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-lang.tex | 467 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex | 10 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-registers.tex | 355 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex | 17 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-tools.tex | 326 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant.sty | 9 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty | 681 |
11 files changed, 2505 insertions, 615 deletions
diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex b/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex index 2117e7f4407..2c9e114bdc5 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex @@ -1,19 +1,13 @@ % 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{% +\protected\def\yquant@circuit@extendwire#1#2{% \begingroup% - \pgfpointanchor{yquantbox}{center}% - \edef\wirexpos{\the\pgf@x}% + \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% @@ -29,23 +23,46 @@ {\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 +% finishes the wires of all registers until x position #1 \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% + \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{% - \yquant@draw@wire{#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}{% @@ -156,6 +173,8 @@ \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% @@ -198,92 +217,64 @@ }% } -% 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 +% 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 @@ -358,67 +349,42 @@ } \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! + % 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{% - \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% + \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}% } - -\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
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-config.tex b/Master/texmf-dist/tex/latex/yquant/yquant-config.tex index c1a74fecb46..a6765d14850 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-config.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-config.tex @@ -1,145 +1,151 @@ -\pgfdeclaremetadecoration{tikz@internal}{pre}{ - \state{pre}[width=\pgfkeysvalueof{/pgf/decoration/pre length}+\pgfkeysvalueof{/pgf/decoration/post length}, next state=main]{ - \appto\tikz@dec@shift{\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/post length}}} - \tikz@dec@trans - \decoration{\pgfkeysvalueof{/pgf/decoration/pre}} - } - \state{main}[width=\pgfmetadecoratedremainingdistance, next state=final]{ - \tikz@dec@trans - \decoration{\tikz@decoration@name} - } - \state{final}{ - \tikz@dec@trans - \decoration{\pgfkeysvalueof{/pgf/decoration/post}} - } +\pgfdeclaremetadecoration{tikz@internal}{pre}{% + \state{pre}[width=\pgfkeysvalueof{/pgf/decoration/pre length}+\pgfkeysvalueof{/pgf/decoration/post length}, next state=main]{% + \appto\tikz@dec@shift{\pgftransformxshift{-\pgfkeysvalueof{/pgf/decoration/post length}}}% + \tikz@dec@trans% + \decoration{\pgfkeysvalueof{/pgf/decoration/pre}}% + }% + \state{main}[width=\pgfmetadecoratedremainingdistance, next state=final]{% + \tikz@dec@trans% + \decoration{\tikz@decoration@name}% + }% + \state{final}{% + \tikz@dec@trans% + \decoration{\pgfkeysvalueof{/pgf/decoration/post}}% + }% } -\pgfqkeys{/yquant}{ +\pgfqkeys{/yquant}{% every circuit/.style={% every node/.prefix style={transform shape},% every label/.prefix style={transform shape=false}% TODO: no, we don't really want this, but pgf bug #843 requires this if we still want to have `label position` available - }, + },% % register settings register/default name/.store in=% - \yquant@config@register@default@name, + \yquant@config@register@default@name,% register/minimum height/.code=% - {\dimdef\yquant@config@register@minimum@height{#1}}, + {\dimdef\yquant@config@register@minimum@height{#1}},% register/separation/.code=% - {\dimdef\yquant@config@register@sep{#1}}, + {\dimdef\yquant@config@register@sep{#1}},% % register label style every label/.style=% - {shape=yquant-text, anchor=center, align=right}, + {shape=yquant-text, anchor=center, align=right},% every initial label/.style=% - {anchor=east}, + {anchor=east},% every qubit label/.style=% - {}, + {},% every cbit label/.style=% - {}, + {},% every qubits label/.style=% - {}, + {},% every multi label/.style=% - {shift={(-.075, 0)}, draw, decoration={gapped brace, mirror}, decorate, /yquant/gapped brace/apply shift, - every node/.append style={shape=yquant-text, anchor=east, align=right, shift={(-.05, 0)}, pos=-1}}, + {shift={(-.075, 0)}, draw, decoration={gapped brace, mirror}, decorate, /yquant/gapped brace/apply shift,% + every node/.append style={shape=yquant-text, anchor=east, align=right, shift={(-.05, 0)}, pos=-1}},% + every input label/.style=% + {},% % output label styles every output/.style=% - {shape=yquant-text, anchor=west, align=left}, + {shape=yquant-text, anchor=west, align=left},% every qubit output/.style=% - {}, + {},% every cbit output/.style=% - {}, + {},% every qubits output/.style=% - {}, + {},% every multi output/.style=% - {shift={(.075, 0)}, draw, decoration={gapped brace}, decorate, /yquant/gapped brace/apply shift, - every node/.append style={shape=yquant-text, anchor=west, align=left, shift={(.05, 0)}, pos=-1}}, + {shift={(.075, 0)}, draw, decoration={gapped brace}, decorate, /yquant/gapped brace/apply shift,% + every node/.append style={shape=yquant-text, anchor=west, align=left, shift={(.05, 0)}, pos=-1}},% % wire style every wire/.style=% - {draw}, + {draw},% every qubit wire/.style=% - {}, + {},% every cbit wire/.style=% - {}, + {},% every qubits wire/.style=% - {}, + {},% % operator settings operator/separation/.code=% - {\dimdef\yquant@config@operator@sep{#1}}, + {\dimdef\yquant@config@operator@sep{#1}},% operator/minimum width/.code=% - {\dimdef\yquant@config@operator@minimum@width{#1}}, + {\dimdef\yquant@config@operator@minimum@width{#1}},% operator/multi warning/.is if=% - yquant@config@operator@multi@warn, + yquant@config@operator@multi@warn,% % operator style: control every control line/.style=% - {draw}, + {draw},% every control/.style=% - {shape=yquant-circle, anchor=center, radius=.5mm}, + {shape=yquant-circle, anchor=center, radius=.5mm},% every positive control/.style=% - {fill=black}, + {fill=black},% every negative control/.style=% - {draw}, + {draw},% % operator style: main part every operator/.style=% - {anchor=center}, + {anchor=center},% operator/multi main/.is if=% - yquant@config@operator@multi@main, + yquant@config@operator@multi@main,% operator/multi as single/.style=% - {/yquant/every multi line/.style=/yquant/every control line}, + {/yquant/every multi line/.style=/yquant/every control line},% every multi line/.style=% - {draw, decoration={snake, amplitude=.25mm, segment length=5pt}, decorate}, + {draw, decoration={snake, amplitude=.25mm, segment length=5pt}, decorate},% % overwriting all styles this operator/.style=% - {}, + {},% this control/.style=% - {}, + {},% operator style/.style=% - {/yquant/this operator/.append style={#1}}, + {/yquant/this operator/.append style={#1}},% control style/.style=% - {/yquant/every control line/.append style={#1}, - /yquant/this control/.append style={#1}}, + {/yquant/every control line/.append style={#1},% + /yquant/this control/.append style={#1}},% style/.style=% - {/yquant/this operator/.append style={#1}, - /yquant/every control line/.append style={#1}, - /yquant/this control/.append style={#1}}, + {/yquant/this operator/.append style={#1},% + /yquant/every control line/.append style={#1},% + /yquant/this control/.append style={#1}},% % different operator appearances operators/every box/.style=% - {shape=yquant-rectangle, draw, align=center, inner xsep=1mm, x radius=2mm, y radius=2.47mm}, - operators/every h/.style=% - {/yquant/operators/every box}, + {shape=yquant-rectangle, draw, align=center, inner xsep=1mm, x radius=2mm, y radius=2.47mm},% + operators/every subcircuit/.style=% + {},% + operators/every subcircuit box/.style=% + {/yquant/operators/every box},% + subcircuit box style/.style=% + {/yquant/operators/every subcircuit box/.append style={#1}},% + operators/this subcircuit box/.style=% + {},% + this subcircuit box style/.style=% + {/yquant/operators/this subcircuit box/.append style={#1}},% + operators/every custom gate/.style=% + {/yquant/operators/this subcircuit box/.append style={draw=none, inner sep=0pt},% + /yquant/register/default name=}, + % every h, every x, every y, every z are implicitly defined during gate declaration operators/every pauli/.style=% - {/yquant/operators/every box}, - operators/every x/.style=% - {/yquant/operators/every pauli}, - operators/every y/.style=% - {/yquant/operators/every pauli}, - operators/every z/.style=% - {/yquant/operators/every pauli}, -% operators/every subcircuit/.style=% -% {/yquant/operators/every box, inner ysep=0pt}, + {/yquant/operators/every box},% operators/every phase/.style=% - {shape=yquant-circle, radius=.5mm, fill}, + {shape=yquant-circle, radius=.5mm, fill},% operators/every zz/.style=% - {shape=yquant-circle, radius=.5mm, fill}, + {shape=yquant-circle, radius=.5mm, fill},% operators/every xx/.style=% - {shape=yquant-rectangle, radius=.75mm, draw}, + {shape=yquant-rectangle, radius=.75mm, draw},% operators/every slash/.style=% - {shape=yquant-slash, x radius=.5mm, y radius=.7mm, draw}, + {shape=yquant-slash, x radius=.5mm, y radius=.7mm, draw},% operators/every swap/.style=% - {shape=yquant-swap, radius=.75mm, draw}, + {shape=yquant-swap, radius=.75mm, draw},% operators/every not/.style=% - {shape=yquant-oplus, radius=1.3mm, draw}, + {shape=yquant-oplus, radius=1.3mm, draw},% operators/every measure/.style=% - {shape=yquant-measure, x radius=4mm, y radius=2.5mm, draw}, + {shape=yquant-measure, x radius=4mm, y radius=2.5mm, draw},% operators/every measure meter/.style=% - {draw, -{Latex[length=2.5pt]}}, + {draw, -{Latex[length=2.5pt]}},% operators/every dmeter/.style=% - {shape=yquant-dmeter, x radius=2mm, y radius=2mm, draw}, + {shape=yquant-dmeter, x radius=2mm, y radius=2mm, draw},% operators/every barrier/.style=% - {shape=yquant-line, dashed, draw}, + {shape=yquant-line, dashed, draw},% operators/every wave/.style=% - {shape=yquant-circle, radius=.5mm, fill}, - /pgf/decoration/from to/.store in=\pgfdecorationsegmentfromto, + {shape=yquant-circle, radius=.5mm, fill},% + /pgf/decoration/from to/.store in=\pgfdecorationsegmentfromto,% gapped brace/apply shift/.code={% \let\tikz@timer@line=\yquant@gappedbrace@timer% - }, + },% } \def\yquant@config@register@default@name{\regidx} @@ -162,7 +168,7 @@ \ifdim\tikz@time pt=-1pt % % first set \pgfdecoratedremainingdistance appropriately \pgfpointdiff\tikz@timer@start\tikz@timer@end% - \pgfmathsqrt@{\dimexpr\pgf@x*\pgf@x/65536+\pgf@y*\pgf@y/65536\relax\@gobbletwo} + \pgfmathsqrt@{\dimexpr\pgf@x*\pgf@x/65536+\pgf@y*\pgf@y/65536\relax\@gobbletwo}% \pgfdecoratedremainingdistance=\pgfmathresult pt % % now perform the transformation \pgf@xc=\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex b/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex index c89eb3ef984..ec4dc808371 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex @@ -3,7 +3,11 @@ \protected\def\yquant@draw@group#1#2#3#4#5{% \begingroup% - \def\yquant@draw@@x{#1}% + \ifcsname\yquant@prefix xshift\endcsname% + \dimdef\yquant@draw@@x{#1+\csname\yquant@prefix xshift\endcsname}% + \else% + \def\yquant@draw@@x{#1}% + \fi% \ifx F#2% \yquant@draw@@currentcontroltype=0 % \else% @@ -65,7 +69,7 @@ /yquant/this operator}% }% \cmd% - \yquant@circuit@extendwire{#1}% + \yquant@circuit@extendwire{#1}{center}% \expandafter\yquant@circuit@extendcontrolline\expandafter% {\the\yquant@draw@@currentcontroltype}\yquant@draw@@x% % check for empty name parameter @@ -106,14 +110,14 @@ y radius/.expanded=\the\dimexpr.5\dimexpr\yquant@register@get@ydist{#1}{#2}\relax\relax+% .5*\noexpand\pgfkeysvalueof{/tikz/y radius}\fi,% name prefix=, name suffix=, name=yquantbox]% - {\unexpanded\expandafter{\yquant@draw@@content}}; + {\unexpanded\expandafter{\yquant@draw@@content}};% \pgfshapeclippath{yquantbox}% {/yquant/every operator, \yquant@draw@@style,% /yquant/this operator}% }% \cmd% \yquant@for \i := #1 to #2 {% - \yquant@circuit@extendwire\i% + \yquant@circuit@extendwire\i{center}% }% \yquant@circuit@extendmultiline\yquant@draw@@x% \expandafter\yquant@circuit@extendcontrolline\expandafter% @@ -148,7 +152,7 @@ (\yquant@draw@@x, \yquant@draw@multiinit@@min) --% (\yquant@draw@@x, \yquant@draw@multiinit@@max)% node[name prefix=, name suffix=, name=yquantbox]% - {\unexpanded\expandafter{\yquant@draw@@content}}; + {\unexpanded\expandafter{\yquant@draw@@content}};% }% \cmd% % no wire extension (we are still at the initial position), no control line (init doesn't allow for those, so just save the no-op), no multi line @@ -197,6 +201,162 @@ \fi% } +\newbox\yquant@draw@subcircuit@box + +\protected\def\yquant@draw@subcircuit@nodecallback#1{% + \ifstrequal{#1}{yquantbox}\relax{% + \listcsxadd{\yquant@prefix draw@subcircuit@nodelist}{#1}% + }% +} + +\protected\long\def\yquant@draw@subcircuit@prepare#1#2{% + \let\idx=\yquant@draw@@idx@content% + % In order to wrap the inner circuit in a proper box operator and clip outer paths appropriately (which was not possible yet, as we didn't know the exact vertical positions), we first place it within a box. During the setup time, we assumed that the subcircuit be placed at position #3; however, now, this has changed due to the additional box. + % First, we anticipate the macro that is used by our subcircuit to store the node + % names. + \edef\yquant@draw@subcircuit@nodelist{yquant@env#1@draw@subcircuit@nodelist}% + \global\cslet\yquant@draw@subcircuit@nodelist\empty% + \pgfinterruptboundingbox% + \let\yquant@parent=\yquant@prefix% + \def\yquant@prefix{yquant@env#1@}% + \ifstrempty{#2}{% + % we make sure there are no conflicts by prefixing any named nodes in any case. + \pgfkeys{/tikz/name prefix/.expanded={sub\yquant@prefix-}}% + \let\pgf@nodecallback=\yquant@draw@subcircuit@nodecallback% + }{% + \pgfkeys{/tikz/name prefix/.expanded={\pgfkeysvalueof{/tikz/name prefix}#2-}}% + }% + \letcs\xmin{\yquant@prefix xmin}% + \letcs\xmax{\yquant@prefix xmax}% + \global\setbox\yquant@draw@subcircuit@box=\hbox to 0pt {{% + % bypass 'overlay' option + \pgf@relevantforpicturesizetrue% + \pgfsys@beginpicture% + % reset all styles to the expected defaults (similar, but extended to \pgfpicture, see pgf issue #870) + \pgfsetcolor{.}% + \pgfsetlinewidth{0.4pt}% + \pgfsetbuttcap% + \pgfsetmiterjoin% + \pgfsetmiterlimit{10}% + \pgfsetdash{}{0pt}% + % The left outer position of our box will be \yquant@draw@@x-.5(xmax-xmin). + % To compensate for, we perform a left shift of all commands that take explicit coordinates from the subcircuit. + % The y positions, on the other hand, are exactly the ones as they should be integrated in the picture. + \csdimdef{\yquant@prefix xshift}{\yquant@draw@@x-.5\dimexpr\xmax+\xmin\relax}% + \csname\yquant@prefix draw\endcsname% + \ifdim\pgf@picmaxx=-16000pt % + \global\pgf@picmaxx=0pt % + \global\pgf@picminx=0pt % + \global\pgf@picmaxy=0pt % + \global\pgf@picminy=0pt % + \fi% + \ifyquantdebug% + \pgf@relevantforpicturesizefalse% + \draw[green] (current bounding box.north east) rectangle (current bounding box.south west);% + \fi% + \pgfsys@endpicture% + }}% + \global\setbox\yquant@draw@subcircuit@box=\hbox to \dimexpr\xmax-\xmin\relax {% + \hskip-\dimexpr\yquant@draw@@x-.5\dimexpr\xmax-\xmin\relax\relax% + \lower\pgf@picmaxy% + \box\yquant@draw@subcircuit@box% + }% + \ht\yquant@draw@subcircuit@box=0pt% + \dp\yquant@draw@subcircuit@box=\dimexpr\pgf@picmaxy-\pgf@picminy\relax% + \expandafter% + \endpgfinterruptboundingbox% + \expandafter\edef\expandafter\yquant@draw@subcircuit@y\expandafter{% + \the\dimexpr.5\pgf@picminy+.5\pgf@picmaxy\relax% + }% + \ifstrempty{#2}{% + % 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@draw@subcircuit@nodelist}% + \csgundef\yquant@draw@subcircuit@nodelist% + }{% + \ifcsname\yquant@prefix draw@subcircuit@nodelist\endcsname% + \csxappto{\yquant@prefix draw@subcircuit@nodelist}% + {\csname\yquant@draw@subcircuit@nodelist\endcsname}% + \fi% + }% +} + +\protected\long\def\yquant@draw@subcircuit@single#1#2#3{% + \yquant@draw@subcircuit@prepare{#2}{#3}% + \edef\cmd{% + \noexpand\path (\yquant@draw@@x, \yquant@draw@subcircuit@y)% + node[/yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box,% + name prefix=, name suffix=, name=yquantbox]% + {\box\yquant@draw@subcircuit@box};% + \pgfshapeclippath{yquantbox}% + {/yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box}% + }% + \cmd% + % see comment in draw@subcircuit@multi + \yquant@softpath@extractmaxxat\pgfshapeclippathhorzresult{\yquant@register@get@y{#1}}% + \let\pgfshapeclippathhorzresult=\empty% + \yquant@circuit@extendwire{#1}{*}% + \expandafter\yquant@circuit@extendcontrolline\expandafter% + {\the\yquant@draw@@currentcontroltype}\yquant@draw@@x% + % check for empty name parameter + \ifstrempty{#3}\relax{% + \pgfnodealias{\tikz@pp@name{#3}}{yquantbox}% + }% + \numdef\yquant@draw@@idx@content{\yquant@draw@@idx@content+1}% +} + +\protected\long\def\yquant@draw@subcircuit@multi#1#2#3#4#5#6{% + % there is no contiguous slicing for subcircuits, as they may have all kinds of wire operations that can extend beyond the individual slices, let alone ancillas + \yquant@draw@subcircuit@prepare{#5}{#6}% + % We need to somehow extract the y radius + \edef\cmd{% + \noexpand\path (\yquant@draw@@x, \yquant@draw@subcircuit@y)% + node[/yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box, + /yquant/operator/multi main=true,% + name prefix=, name suffix=, name=yquantbox]% + {\box\yquant@draw@subcircuit@box};% + \pgfshapeclippath{yquantbox}% + {/yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box,% + /yquant/operator/multi main=true}% + }% + \cmd% + % install the clippings - but only on wires that are visually between the first and list while not being part of the circuit. + \let\nonaffectedpgfshapeclippathhorzresult=\pgfshapeclippathhorzresult% + \yquant@for \i := #1 to #2 {% + \xifinlist{\i}{#4}{% + % Usually, we always begin with a wire from the center of the operator shape and clip the inner parts away. This can't be done here, as the wire needs to be drawn _inside_ of the outer box operator here. Instead of clipping against the clip path, we extract its maximum x position at the position of the wire (which is an overkill for simple shapes, but the allows to specify even more complicated ones) and place the wire at this position without clipping. + % Note: this works very well for lines joining at perpendicular angles; but if the shape of the box is more fancy, while the position will be calculated correctly, the wire has a rectangular (or rounded, depending on the line cap) shape that is drawn on top of thw operator. While \yquant@softpath@extractmaxxat could without much effort determine exactly the segment of the path that corresponds to the rightmost line, we would then have to convert this single line into a closed path that fills the linewidth and clip against it to get proper joiners. Since most likely, no-one will ever need this, we don't do it. But file a feature request if desired. + \yquant@softpath@extractmaxxat\nonaffectedpgfshapeclippathhorzresult% + {\yquant@register@get@y\i}% + \let\pgfshapeclippathhorzresult=\empty% + \yquant@circuit@extendwire\i{*}% + }{% + \let\pgfshapeclippathhorzresult=\nonaffectedpgfshapeclippathhorzresult% + \yquant@circuit@extendwire\i{center}% + }% + }% + \expandafter\yquant@circuit@extendcontrolline\expandafter% + {\the\yquant@draw@@currentcontroltype}\yquant@draw@@x% + \ifstrempty{#6}\relax{% + \pgfnodealias{\tikz@pp@name{#6}}{yquantbox}% + }% + \numdef\yquant@draw@@idx@content{\yquant@draw@@idx@content+1}% +} + \protected\def\yquant@draw@control#1#2#3{% \edef\cmd{% \noexpand\path (\yquant@draw@@x, \yquant@register@get@y{#2})% @@ -208,7 +368,7 @@ /yquant/this control}% }% \cmd% - \yquant@circuit@extendwire{#2}% + \yquant@circuit@extendwire{#2}{center}% \yquant@draw@@currentcontroltype=\yquant@register@get@type{#2}\relax% \expandafter\yquant@circuit@extendcontrolline\expandafter% {\yquant@draw@@currentcontroltype}\yquant@draw@@x% @@ -251,7 +411,7 @@ \fi% \edef\cmd{% \noexpand\path[/yquant/every control line]% - \yquant@circuit@extendcontrolline@cmd; + \yquant@circuit@extendcontrolline@cmd;% }% \cmd% \endpgfscope% @@ -285,7 +445,7 @@ \pgfusepathqclip% \endgroup% \fi% - \path[/yquant/every multi line] #2; + \path[/yquant/every multi line] #2;% \endpgfscope% } @@ -300,18 +460,18 @@ \protected\def\yquant@draw@wire#1#2{% \begingroup% \yquant@register@get@typeywire{#1}\wiretype\wireypos\wirelast% - \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}% - \ifx\yquant@env@end@xpos#2\relax% - \let\wirexpos=\yquant@env@end@xpos% - \else% - \edef\wirexpos{\expandafter\@secondoffour\wirelast}% - \fi% \unless\ifnum\wiretype=\yquant@register@type@none% + \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}% + \ifx0#2% + \edef\wirexpos{\expandafter\@secondoffour\wirelast}% + \else% + \let\wirexpos=\yquant@env@end@xpos% + \fi% \ifdim\wirexpos>\wirexprevpos % \edef\wirestyle{\noexpand\tikzset{% /yquant/this wire/.style={% /yquant/every wire,% - /yquant/every \ifcase\wiretype\relax nobit\or qubit \or cbit \or qubits \fi wire,% + /yquant/every \yquant@register@type@tostring\wiretype\space wire,% \yquant@register@get@style{#1}% }, /yquant/this wire% }}% @@ -334,13 +494,13 @@ % We need to access the current bounding box as well as other positions in the local coordinate frame. For this, transform the bounding box to the current frame (though this is expensive). Does this capture rotations correctly? \begingroup% \pgftransforminvert% - \pgfpointtransformednonlinear{\pgfqpoint{\pgf@picminx}{\pgf@picminy}} + \pgfpointtransformednonlinear{\pgfqpoint{\pgf@picminx}{\pgf@picminy}}% \global\@tempdima=\pgf@y% \pgfpointtransformednonlinear{\pgfqpoint{\pgf@picmaxx}{\pgf@picmaxy}}% \global\@tempdimb=\pgf@y% \endgroup% % To avoid rendering artifacts at all zoom levels with all renderers, we need to make the clipping region large. Let's try the current bounding box first. - % This may be insufficient if there no or a tiny wire label and only registers of a small height. In this case, take at ten times the line width or at least 1cm, but don't let it affect the bounding box. + % This may be insufficient if there no or a tiny wire label and only registers of a small height. In this case, take ten times the line width or at least 1cm, but don't let it affect the bounding box. \ifdim\dimexpr\@tempdimb-\@tempdima\relax<10\pgflinewidth % \@tempdima=\dimexpr\wireypos-5\pgflinewidth\relax% \@tempdimb=\dimexpr\wireypos+5\pgflinewidth\relax% @@ -370,7 +530,7 @@ % quantum wire \protected\csdef{yquant@draw@wire@\yquant@register@type@q}#1{% \edef\cmd{% - \noexpand\path [/yquant/this wire] + \noexpand\path [/yquant/this wire]% (\wirexprevpos,\wireypos) -- (\wirexpos,\wireypos);% }% \cmd% @@ -379,7 +539,7 @@ % classical wire \protected\csdef{yquant@draw@wire@\yquant@register@type@c}#1{% \edef\cmd{% - \noexpand\path [/yquant/this wire] + \noexpand\path [/yquant/this wire]% (\wirexprevpos,\wireypos+2\pgflinewidth)--(\wirexpos,\wireypos+2\pgflinewidth)% (\wirexprevpos,\wireypos-2\pgflinewidth)--(\wirexpos,\wireypos-2\pgflinewidth);% }% @@ -389,13 +549,49 @@ % quantum-bundle \protected\csdef{yquant@draw@wire@\yquant@register@type@qs}#1{% \edef\cmd{% - \noexpand\path [/yquant/this wire] + \noexpand\path [/yquant/this wire]% (\wirexprevpos,\wireypos+2\pgflinewidth)--(\wirexpos,\wireypos+2\pgflinewidth)% (\wirexprevpos,\wireypos)--(\wirexpos,\wireypos)% (\wirexprevpos,\wireypos-2\pgflinewidth)--(\wirexpos,\wireypos-2\pgflinewidth);% }% \cmd% } + +\protected\long\def\yquant@draw@output@group#1{% + \begingroup% + \def\idx{0}% + \yquant@set{#1}% +} + +\let\yquant@draw@output@endgroup=\endgroup% + +\protected\long\def\yquant@draw@output@single#1#2{% + \path% + (\yquant@env@end@xpos, \yquant@register@get@y{#1})% + node[/yquant/every output,% + /yquant/every \yquant@register@type@tostring{\yquant@register@get@type{#1}} output] {#2}; + \numdef\idx{\idx+1}% +} + +\protected\long\def\yquant@draw@output@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 % BEGIN_FOLD Preparation of drawing a generic shape @@ -443,6 +639,12 @@ }{% \yquant@draw@@single{#1}{#2}{##1}% }% + \ifx\yquant@draw@@multi\yquant@draw@@multiinit% + % if we draw an initialization (whether multi or single), this possibly affects the minimal x position. All other gates will be shifted so that they cannot extend beyond the minimal position. + \ifdim\pgf@picminx<\csname\yquant@prefix xmin\endcsname% + \csxdef{\yquant@prefix xmin}{\the\pgf@picminx}% + \fi% + \fi% \expandafter% \endpgfinterruptboundingbox% \expandafter\dimen\expandafter0\expandafter=% @@ -451,41 +653,44 @@ \dimen2=\dimen0 % \fi% \numdef\idx{\idx+1}% - % TODO -% \yquant@draw@callback@box\nodename% }% \dolistloop\yquant@circuit@operator@targets% % END_FOLD - % BEGIN_FOLD controls + \yquant@draw@@controls% + \yquant@draw@@finalize{#1}{#2}% +} + +\protected\def\yquant@draw@@controls@loop#1#2{% + \ifx\yquant@lang@attr@name\empty% + \let\nodename=\empty% + \else% + \edef\nodename{\yquant@lang@attr@name-#1\idx}% + \fi% + \yquant@sort@eadd{% + \expandafter\noexpand\csname yquant@draw@#1control\endcsname% + {#2}% register index + {\nodename}% + }% + \unless\ifdefined\yquant@draw@controltype% + \edef\yquant@draw@controltype{#2}% + \fi% + \numdef\idx{\idx+1}% +} + +\protected\def\yquant@draw@@controls{% \ifyquant@circuit@operator@hasControls% - \def\do##1{% - \ifx\yquant@lang@attr@name\empty% - \let\nodename=\empty% - \else% - \edef\nodename{\yquant@lang@attr@name-\yquant@draw@controlprefix\idx}% - \fi% - \yquant@sort@eadd{% - \expandafter\noexpand\csname yquant@draw@\yquant@draw@controlprefix control\endcsname% - {##1}% register index - {\nodename}% - }% - \unless\ifdefined\yquant@draw@controltype% - \edef\yquant@draw@controltype{##1}% - \fi% - \numdef\idx{\idx+1}% - } - \def\yquant@draw@controlprefix{p}% \def\idx{0}% - \dolistloop\yquant@circuit@operator@pctrls% - \def\yquant@draw@controlprefix{n}% + \forlistloop{\yquant@draw@@controls@loop p}\yquant@circuit@operator@pctrls% \def\idx{0}% - \dolistloop\yquant@circuit@operator@nctrls% + \forlistloop{\yquant@draw@@controls@loop n}\yquant@circuit@operator@nctrls% \unless\ifdefined\yquant@draw@controltype% \PackageError{yquant.sty}{Assertion failure}% {Internal inconsistency in yquant: Controlled action detected, but no controls were found.}% \fi% \fi% - % END_FOLD +} + +\protected\long\def\yquant@draw@@finalize#1#2{% % We now know the dimensions of all the registers (though we didn't bother with the height of the control knobs [if present], we just assume they are too small to change this). \protected\def\idx{}% \protected@edef\yquant@draw@append{% @@ -502,16 +707,15 @@ }% \yquant@sort\yquant@draw@sort% \advance \dimen2 by \yquant@circuit@operator@x\relax% - % BEGIN_FOLD shipout \ifyquant@circuit@operator@hasControls% - % If we draw a control line, all intermediate registers are affected in their position so that the line is never crossed. If the vertical line is instead caused by a multi register, \yquant@draw@finalize@ctrl will be responsible for advancing only the affected positions. + % If we draw a control line, all intermediate registers are affected in their position so that the line is never crossed. If the vertical line is instead caused by a multi register, \yquant@draw@@finalize@ctrl will be responsible for advancing only the affected positions. \yquant@for \yquant@i := \yquant@circuit@operator@minctrl to \yquant@circuit@operator@maxctrl {% \yquant@register@set@x\yquant@i{\the\dimen2}% }% \fi% \def\do##1{% \appto\yquant@draw@append{##1}% - \yquant@draw@finalize@ctrl##1% + \yquant@draw@@finalize@ctrl##1% }% \yquant@sort@dolistloop% \csxappto{\yquant@prefix draw}{% @@ -557,7 +761,6 @@ \fi% \fi% }% - % END_FOLD } \protected\def\yquant@draw@@single#1#2#3{% @@ -570,12 +773,11 @@ \pgfinterruptboundingbox% \yquant@env@virtualize@path% \path% - (0pt, 0pt) + (0pt, 0pt)% node[/yquant/every operator, #2, /yquant/this operator,% name prefix=, name suffix=, name=] {#1};% - \yquant@register@update@height{#3}{% - \the\dimexpr\pgf@picmaxy-\pgf@picminy\relax% - }% + \yquant@register@update@height{#3}{\the\pgf@picmaxy}% + \yquant@register@update@depth{#3}{\the\dimexpr-\pgf@picminy\relax}% } \protected\def\yquant@draw@@multi#1#2#3{% @@ -594,9 +796,9 @@ \ifdim\pgf@picmaxy=-16000pt % % if there was no single contiguous part before, determine the width now \path% - (0pt, 0pt) + (0pt, 0pt)% node[/yquant/every operator, #2, /yquant/this operator,% - name prefix=, name suffix=, name=] {#1}; + name prefix=, name suffix=, name=] {#1};% \fi% } @@ -608,14 +810,13 @@ \edef\cmd{% \noexpand\path (0pt, 0pt)% node[/yquant/every operator, \yquant@draw@@style, /yquant/this operator,% - /yquant/operator/multi main=\ifnum#3=1 true\else false\fi, + /yquant/operator/multi main=\ifnum#3=1 true\else false\fi,% name prefix=, name suffix=, name=]% - {\unexpanded\expandafter{\yquant@draw@@content}}; + {\unexpanded\expandafter{\yquant@draw@@content}};% }% \cmd% - \yquant@register@update@height{#1}{% - \the\dimexpr\pgf@picmaxy-\pgf@picminy\relax% - }% + \yquant@register@update@height{#1}{\the\pgf@picmaxy}% + \yquant@register@update@depth{#1}{\the\dimexpr-\pgf@picminy\relax}% \fi% } @@ -629,24 +830,116 @@ \pgfinterruptboundingbox% \yquant@env@virtualize@path% \path% - (0pt, 0pt) + (0pt, 0pt)% node[/yquant/every operator, #2, /yquant/every multi label,% - name prefix=, name suffix=, name=] {#1}; + name prefix=, name suffix=, name=] {#1};% +} + +\protected\long\def\yquant@draw@@subcircuit#1{% + \yquant@sort@clear% + \def\idx{0}% + \dimen2=\yquant@config@operator@minimum@width% + % BEGIN_FOLD register + \def\do##1{% + \ifx\yquant@lang@attr@name\empty% + \let\nodename=\empty% + \else% + \edef\nodename{\yquant@lang@attr@name-\idx}% + \fi% + \ifyquant@firsttoken\yquant@register@multi{##1}{% + \yquant@draw@@subcircuit@multi{#1}{##1}% + }{% + \yquant@draw@@subcircuit@single{#1}{##1}% + }% + \dimen0=\dimexpr% + \csname yquant@env\yquant@circuit@subcircuit@id @xmax\endcsname-% + \csname yquant@env\yquant@circuit@subcircuit@id @xmin\endcsname% + \relax\relax% + \pgfinterruptboundingbox% + % There will still be some extra width taken by separations or other things related to the box itself. + \yquant@env@virtualize@path% + \path% + (0pt, 0pt)% + node[/yquant/every operator, #1,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box,% + name prefix=, name suffix=, name=]% + {\hbox to \dimen0{}};% + % We also don't update the height here, as the height of the subcircuit is undetermined as long as we did not match inner and outer wires. + \expandafter% + \endpgfinterruptboundingbox% + \expandafter\dimen\expandafter0\expandafter=% + \the\dimexpr\pgf@picmaxx-\pgf@picminx\relax\relax% + \ifdim\dimen0>\dimen2 % + \dimen2=\dimen0 % + \fi% + \numdef\idx{\idx+1}% + }% + \dolistloop\yquant@circuit@operator@targets% + % END_FOLD + \yquant@draw@@controls% + \yquant@draw@@finalize{}{#1}% +} + +\protected\def\yquant@draw@@subcircuit@single#1#2{% + \edef\yquant@circuit@subcircuit@param{#2\yquant@list@delim}% + \yquant@circuit@subcircuit{#1}% + \yquant@sort@eadd{% + \yquant@draw@subcircuit@single% + {#2}% register index + {\yquant@circuit@subcircuit@id}% + {\nodename}% + }% +} + +\protected\def\yquant@draw@@subcircuit@multi#1#2{% + \edef\yquant@circuit@subcircuit@param{\@fifthoffive#2}% + \yquant@sort@list\yquant@circuit@subcircuit@param\yquant@sort@ascending% + \yquant@circuit@subcircuit{#1}% + \yquant@sort@eadd{% + \yquant@draw@subcircuit@multi% + #2% + {\yquant@circuit@subcircuit@id}% + {\nodename}% + } +} + +\protected\long\def\yquant@draw@@output@single#1#2{% + \path + (\yquant@env@end@xpos, 0pt)% + node[/yquant/every output,% + /yquant/every \yquant@register@type@tostring{\yquant@register@get@type{#1}} output] {#2};% + \numdef\idx{\idx+1}% +} + +\protected\long\def\yquant@draw@@output@multi#1{% + \path[/yquant/every multi output]% + (\yquant@env@end@xpos, 0pt) -- (\yquant@env@end@xpos, 1cm)% + node {#1};% + \numdef\idx{\idx+1}% } -\def\yquant@draw@finalize@ctrl#1{% +\def\yquant@draw@@finalize@ctrl#1{% + \let\next=\yquant@draw@@finalize@ctrl@single% \ifx\yquant@draw@multi#1% - \expandafter\yquant@draw@finalize@ctrl@multi% + \let\next=\yquant@draw@@finalize@ctrl@multi% \else% \ifx\yquant@draw@multiinit#1% - \expandafter\expandafter\expandafter\yquant@draw@finalize@ctrl@multi% + \let\next=\yquant@draw@@finalize@ctrl@multi% \else% - \expandafter\expandafter\expandafter\yquant@draw@finalize@ctrl@single% + \ifx\yquant@draw@subcircuit@multi#1% + \let\next=\yquant@draw@@finalize@ctrl@subcircuit@multi% + \else% + \ifx\yquant@draw@subcircuit@single#1% + \let\next=\yquant@draw@@finalize@ctrl@subcircuit@single% + \fi% + \fi% \fi% \fi% + \next% } -\protected\def\yquant@draw@finalize@ctrl@single#1#2{% +\protected\def\yquant@draw@@finalize@ctrl@single#1#2{% \unless\ifyquant@circuit@operator@hasControls% \yquant@register@set@x#1{\the\dimen2}% \fi% @@ -655,13 +948,17 @@ }% } -\protected\def\yquant@draw@finalize@ctrl@singleinit#1#2{% +\def\yquant@draw@@finalize@ctrl@subcircuit@single#1#2#3{% + \yquant@draw@@finalize@ctrl@single{#1}{#3}% +} + +\protected\def\yquant@draw@@finalize@ctrl@singleinit#1#2{% \eappto\yquant@draw@append{% \yquant@draw@callback@wire{#1}% }% } -\protected\def\yquant@draw@finalize@ctrl@multi#1#2#3#4#5{% +\protected\def\yquant@draw@@finalize@ctrl@multi#1#2#3#4#5{% \unless\ifyquant@circuit@operator@hasControls{% % \yquant@for uses \loop...\repeat and hence redefines \body, which would destroy an outer loop. % if we did not draw a control line, the x position has not yet been set. A multi-qubit register might visually extend over multiple registers that are not even part, hence we update them all. @@ -669,16 +966,15 @@ \yquant@register@set@x\yquant@i{\the\dimen2}% }% }\fi% - % this is called from a do loop itself, so preserve \do (but do not enter grouping) - \let\yquant@register@multi@contiguous=\yquant@draw@finalize@ctrl@multi@contiguous% + \let\yquant@register@multi@contiguous=\yquant@draw@@finalize@ctrl@multi@contiguous% \ifyquant@circuit@operator@hasControls% \ifyquant@config@operator@multi@warn% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{0}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{0}% \else% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{2}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% \fi% \else% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{2}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% \fi% \cslet{\yquant@prefix finalize@ctrl@draw@appto}\empty% #4% @@ -686,17 +982,37 @@ \csgundef{\yquant@prefix finalize@ctrl@draw@appto}% } -\protected\def\yquant@draw@finalize@ctrl@multiinit#1#2#3#4#5{% +\protected\def\yquant@draw@@finalize@ctrl@subcircuit@multi@loop#1{% + \begingroup% + \edef\tmp{\yquant@draw@callback@wire{#1}}% + \expandafter% + \endgroup% + \expandafter\appto\expandafter\yquant@draw@append\expandafter{\tmp}% +} + +\protected\def\yquant@draw@@finalize@ctrl@subcircuit@multi#1#2#3#4#5#6{% + % there are no contiguous parts here, don't call the normal @multi + \unless\ifyquant@circuit@operator@hasControls{% + % \yquant@for uses \loop...\repeat and hence redefines \body, which would destroy an outer loop. + % if we did not draw a control line, the x position has not yet been set. A multi-qubit register might visually extend over multiple registers that are not even part, hence we update them all. + \yquant@for \yquant@i := #1 to #2 {% + \yquant@register@set@x\yquant@i{\the\dimen2}% + }% + }\fi% + \forlistloop\yquant@draw@@finalize@ctrl@subcircuit@multi@loop{#4}% +} + +\protected\def\yquant@draw@@finalize@ctrl@multiinit#1#2#3#4#5{% % this is called from a do loop itself, so preserve \do (but do not enter grouping) - \let\yquant@register@multi@contiguous=\yquant@draw@finalize@ctrl@multi@contiguous% + \let\yquant@register@multi@contiguous=\yquant@draw@@finalize@ctrl@multi@contiguous% \ifyquant@circuit@operator@hasControls% \ifyquant@config@operator@multi@warn% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{0}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{0}% \else% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{2}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% \fi% \else% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{2}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% \fi% \cslet{\yquant@prefix finalize@ctrl@draw@appto}\empty% #4% @@ -704,15 +1020,15 @@ \csgundef{\yquant@prefix finalize@ctrl@draw@appto}% } -\protected\def\yquant@draw@finalize@ctrl@multi@contiguous#1#2#3{% - \ifnum\yquant@draw@finalize@ctrl@multi@contiguous@warn=1 % +\protected\def\yquant@draw@@finalize@ctrl@multi@contiguous#1#2#3{% + \ifnum\yquant@draw@@finalize@ctrl@multi@contiguous@warn=1 % \PackageWarning{yquant.sty}{Ambiguous operation: multiple discontiguous multi-register operations in combination with controls make it hard to visually determine on which registers the gates act on.}% % switch the warning off for this group (which is a single operation) \yquant@config@operator@multi@warnfalse% - \def\yquant@draw@finalize@ctrl@multi@contiguous@warn{2}% + \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% \else% - \numdef\yquant@draw@finalize@ctrl@multi@contiguous@warn{% - \yquant@draw@finalize@ctrl@multi@contiguous@warn+1% + \numdef\yquant@draw@@finalize@ctrl@multi@contiguous@warn{% + \yquant@draw@@finalize@ctrl@multi@contiguous@warn+1% }% \fi% {% save \body diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex index 16c3598af38..bb901d1d2cf 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex @@ -42,71 +42,235 @@ \yquant@env@begin@arg[]% } -\long\protected\def\yquant@env@begin@arg[#1]{% +\def\yquant@env@begin@arg{% + \let\yquant@env@check=\yquant@env@check@% + \yquant@env@begin@generic\yquant% +} + +\long\protected\def\yquant@env@begin@generic#1[#2]{ \begingroup% - \advance\yquant@env by 1 % + \let\yquant@parent=\yquant@prefix% + \global\advance\yquant@env by 1 % \edef\yquant@prefix{yquant@env\the\yquant@env @}% - \let\yquant=\yquant@env@scan% - \yquant@lang@reset@attrs% + \ifnum\yquant@env=1 % + \yquant@env@substikz#1% + \def\yquant@env@create@x{0pt}% + \global\cslet{\yquant@prefix parameters}\empty% + \else% + \let\yquant@lang@reset@attrs@inputoutput=\yquant@lang@reset@attrs@inputoutput@subcircuit% + \let\yquant@env@create@x=\yquant@circuit@operator@x% + \global\cslet{\yquant@prefix parameters}\yquant@circuit@subcircuit@param% + \yquant@env@lazyfalse% forbid lazy register creation in subcircuits. We need a proper and in-order declaration of the subcircuit's interface. + \fi% + \let#1=\yquant@env@scan% + \yquant@env@reset@commands% \csgdef{\yquant@prefix registers}{0}% \global\cslet{\yquant@prefix draw}\relax% \global\cslet{\yquant@prefix outputs}\relax% + \csdimgdef{\yquant@prefix xmin}{\yquant@env@create@x+\yquant@config@operator@sep}% + \global\cslet{\yquant@prefix subcircuits}\empty% + \global\cslet{\yquant@prefix inonly}\empty% \csxdef{\yquant@prefix cleanup}{% \expandafter\noexpand\csname\yquant@prefix registers\endcsname% \expandafter\noexpand\csname\yquant@prefix draw\endcsname% \expandafter\noexpand\csname\yquant@prefix outputs\endcsname% + \expandafter\noexpand\csname\yquant@prefix parameters\endcsname% + \expandafter\noexpand\csname\yquant@prefix xmin\endcsname% + \expandafter\noexpand\csname\yquant@prefix subcircuits\endcsname% + \expandafter\noexpand\csname\yquant@prefix inonly\endcsname% \expandafter\noexpand\csname\yquant@prefix cleanup\endcsname% }% - \ifnum\yquant@env=1 % - \yquant@env@substikz% - \fi% - \scope[{/yquant/.cd, #1, /tikz/.cd, /yquant/every circuit}]% + \scope[{/yquant/.cd, #2, /tikz/.cd, /yquant/every circuit}]% } -\newif\ifyquantdebug + \protected\def\yquant@env@end{% \letcs\yquant@env@end@registers{\yquant@prefix registers}% \ifnum\yquant@env@end@registers>0 % % draw all wires \yquant@register@get@maxxrange\yquant@env@end@xpos{1}{\yquant@env@end@registers}% - % to have a symmetric situation, we extend again one separation at the end + \ifdim\csname\yquant@prefix xmin\endcsname<% + \dimexpr\yquant@env@create@x+\yquant@config@operator@sep\relax% + % to have a symmetric situation, we extend again one separation at the end + \dimdef\yquant@env@end@xpos{\yquant@env@end@xpos+\yquant@config@operator@sep}% + \global\cslet{\yquant@prefix xmax}\yquant@env@end@xpos% + \else% + % while the outputs need this, the subcircuit doesn't if there are no outputs. + \global\cslet{\yquant@prefix xmax}\yquant@env@end@xpos% + \dimdef\yquant@env@end@xpos{\yquant@env@end@xpos+\yquant@config@operator@sep}% + \fi% + \yquant@cleanup@csadd{xmax}% \csxappto{\yquant@prefix draw}{% - \def\noexpand\yquant@env@end@xpos{% - \the\dimexpr\yquant@env@end@xpos+\yquant@config@operator@sep\relax% - }% - \yquant@circuit@endwires{\yquant@env@end@registers}% - } - % also calculate the true y positions - \dimen0=0pt % - \dimen2=0pt % - \dimen4=\yquant@config@register@sep % - \yquant@for \i := 1 to \yquant@env@end@registers {% - % we do not care if the wire is present for the y position - \dimen2=.5\dimexpr\yquant@register@get@height\i\relax% - \advance\dimen0 by \dimen2\relax% - % top-to-bottom means negative coordinates in pgf - \yquant@register@set@y\i{-\the\dimen0}% - \advance\dimen0 by \dimen2\relax% - \advance\dimen0 by \dimen4\relax% + \yquant@circuit@endwires{\yquant@env@end@xpos}% }% \csname\yquant@prefix outputs\endcsname% + % also calculate the true y positions + \unless\ifdefined\yquant@parent% + \yquant@env@end@calcypositions% + \fi% + \else% + \ifdefined\yquant@parent% + \PackageError{yquant.sty}{Empty subcircuit}% + {Subcircuits must contain registers.}% + \else% + \PackageWarning{yquant.sty}{Empty quantum circuit}% + \fi% + \fi% + \global\let\yquant@env@scan=\relax% don't rescan after the scope + \endscope% this will exit five to seven groups (depending on the transparency group state, and it might even be driver-dependent, though it is not at the moment), so better make the relax global + \global\let\yquant@env@scan=\yquant@env@scan@% + \ifdefined\yquant@parent% + % We are in a subcircuit. The drawing and cleanup is delayed until the end. + \csxappto{\yquant@parent cleanup}% + {\unexpanded\expandafter\expandafter\expandafter{% + \csname\yquant@prefix cleanup\endcsname% + }}% + \ifyquantdebug% + \csshow{\yquant@prefix draw}% + \fi% + \else% + % Now we actually carry out the tikz commands which were previously stored in the draw command. But before this, we get rid of all \yquant@env@scan calls and also restore the scope command, since this would add itself once again. And get@y needs to expand. + \let\path=\tikz@command@path% + \let\tikz@lib@scope@check=\yquant@env@substikz@scopecheck% + \let\tikz@scope@opt=\yquant@env@substikz@scope% + \let\endtikz@scope@env=\yquant@env@substikz@endscope% + \let\endscope=\endtikz@scope@env% + \let\stopscope=\endscope% + \yquant@register@get@y@@expandable% + \ifyquantdebug% + \csshow{\yquant@prefix draw}% \fi% - \endscope% - % Now we actually carry out the tikz commands which were previously stored in the draw command. But before this, we get rid of all \yquant@env@scan calls and also restore the scope command, since this would add itself once again. And get@y needs to expand. - \let\path=\tikz@command@path% - \let\tikz@lib@scope@check=\yquant@env@substikz@scopecheck% - \let\tikz@scope@opt=\yquant@env@substikz@scope% - \let\endtikz@scope@env=\yquant@env@substikz@endscope% - \let\endscope=\endtikz@scope@env% - \let\stopscope=\endscope% - \yquant@register@get@y@@expandable% - \ifyquantdebug% - \csshow{\yquant@prefix draw}% + \csname\yquant@prefix draw\endcsname% + \expandafter\expandafter\expandafter\yquant@cleanup\csname\yquant@prefix cleanup\endcsname|% + \global\yquant@env=0 % \fi% - \csname\yquant@prefix draw\endcsname% - \expandafter\expandafter\expandafter\yquant@cleanup\csname\yquant@prefix cleanup\endcsname|% \endgroup% } +\protected\def\yquant@env@end@calcypositions{% + \begingroup% + \dimen4=\yquant@config@register@sep % + % We know the heights of most gates, but subcircuits are tricky. Since the position of their inner wires depends on the heights of the outer wires, we could not make any assumption about their heights yet. So we now need multiple iterations: First, we fix the positions of our own wires preliminarily. Then, we iterate through all subcircuits at the first level, place their wires appropriately and try to align input and output. In doing so, we recognize when there's not enough space at an outer wire. If this is the case, we enlarge the outer wire's height appropriately and restart alignment from the outmost level. If everything is proper, we start aligning at the next level. + \yquant@env@end@calcypositions@toplevel1% + % Turn the preliminary positions into true ones at every level. + \yquant@env@end@setypositions1% + \endgroup% +} + +\protected\def\yquant@env@end@calcypositions@loop#1{% + % \yquant@parent has to be set already + \def\yquant@prefix{yquant@env#1@}% + % #1 now holds the id of the subcircuit. Find the first input. + \edef\firstinput{% + \expandafter\expandafter\expandafter% + \@firstoftwo\csname\yquant@prefix firstinput\endcsname% + }% + \edef\lastinput{% + \expandafter\expandafter\expandafter% + \@firstoftwo\csname\yquant@prefix lastinput\endcsname% + }% + % we already made sure during in \yquant@circuit@subcircuit that there is enough space above and below the subcircuit. Still, the wires need to be positioned. However, we will first deal with all intermediate wires, which need to be placed by means of shifts - there is no direct correspondence to heights or depths of parent wires any more. + \ifnum\firstinput<\numexpr\lastinput-1\relax% + \dimen0=\dimexpr% + \csname y@\csname\yquant@prefix registermap@\firstinput\endcsname\endcsname+% + \yquant@register@get@depth\firstinput+\dimen4% + \relax% + \yquant@for \i := \numexpr\firstinput+1\relax to \lastinput {% + \advance\dimen0 by \yquant@register@get@height\i\relax% + \ifcsname\yquant@prefix registermap@\i\endcsname% + % this is an input: do we have enough space by using the outer position? + \letcs\outername{\yquant@prefix registermap@\i}% + \letcs\outery{y@\outername}% + \ifdim\dimen0>\outery\relax% + % re-aligning the outer positions is required + \ifcsname y+@\outername\endcsname% + \csdimdef{y+@\outername}% + {\csname y+@\outername\endcsname+\dimen0-\outery}% + \else% + \csdimdef{y+@\outername}{\dimen0-\outery}% + \fi% + \let\yquant@env@end@calcypositions@redo=\relax% + \fi% + \else% + \csedef{y@\yquant@prefix register@\i}{\the\dimen0}% + \fi% + \ifdefined\yquant@env@end@calcypositions@redo% + \expandafter\yquant@for@break% + \else% + \advance\dimen0 by \dimexpr\yquant@register@get@depth\i+\dimen4\relax% + \fi% + }% + \fi% + \unless\ifdefined\yquant@env@end@calcypositions@redo% + % sounds good, no readjustments necessary. Now transfer the wires above and below in the appropriate macros. + \ifnum\firstinput>1 % + \dimen0=\dimexpr% + \csname y@\csname\yquant@prefix registermap@\firstinput\endcsname\endcsname-% + \yquant@register@get@height\firstinput-\dimen4% + \relax% + \yquant@fordown \i := \numexpr\firstinput-1\relax downto 1 {% + \advance\dimen0 by -\yquant@register@get@depth\i\relax% + \csedef{y@\yquant@prefix register@\i}{\the\dimen0}% + \advance\dimen0 by -\dimexpr\yquant@register@get@height\i+\dimen4\relax% + }% + \fi% + \ifnum\lastinput<\csname\yquant@prefix registers\endcsname% + \dimen0=\dimexpr% + \csname y@\csname\yquant@prefix registermap@\lastinput\endcsname\endcsname+% + \yquant@register@get@depth\lastinput+\dimen4% + \relax% + \yquant@for \i := \numexpr\lastinput+1\relax to \csname\yquant@prefix registers\endcsname {% + \advance\dimen0 by \yquant@register@get@height\i\relax% + \csedef{y@\yquant@prefix register@\i}{\the\dimen0}% + \advance\dimen0 by \dimexpr\yquant@register@get@depth\i+\dimen4\relax% + }% + \fi% + \fi% + \ifdefined\yquant@env@end@calcypositions@redo% + % forget every plan about going deeper, restart. + \expandafter\listbreak% + \else% + \expandafter\yquant@env@end@calcypositions@subcircuits% + \fi% +} + +\protected\def\yquant@env@end@calcypositions@subcircuits{% + \let\yquant@parent=\yquant@prefix% + \forlistcsloop\yquant@env@end@calcypositions@loop{\yquant@prefix subcircuits}% + \ifdefined\yquant@env@end@calcypositions@redo% + \expandafter\listbreak% + \fi% +} + +\protected\def\yquant@env@end@calcypositions@toplevel{% + \def\yquant@prefix{yquant@env1@}% + \dimen0=0pt % + \yquant@for \i := 1 to \yquant@env@end@registers {% + % we do not care if the wire is present for the y position + \advance\dimen0 by \yquant@register@get@height\i\relax% + \ifcsname y+@\yquant@prefix register@\i\endcsname% + \advance\dimen0 by \csname y+@\yquant@prefix register@\i\endcsname\relax% + \fi% + \csedef{y@\yquant@prefix register@\i}{\the\dimen0}% + \advance\dimen0 by \dimexpr\yquant@register@get@depth\i+\dimen4\relax% + }% + \undef\yquant@env@end@calcypositions@redo% + \let\yquant@parent=\yquant@prefix% + \forlistcsloop\yquant@env@end@calcypositions@loop{\yquant@prefix subcircuits}% + \ifdefined\yquant@env@end@calcypositions@redo% + \expandafter\yquant@env@end@calcypositions@toplevel% + \fi% +} + +\protected\def\yquant@env@end@setypositions#1{% + \def\yquant@prefix{yquant@env#1@}% + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + \unless\ifcsname\yquant@prefix registermap@\i\endcsname% + \yquant@register@set@y\i{-\csname y@\yquant@prefix register@\i\endcsname}% + \fi% + }% + \forlistcsloop\yquant@env@end@setypositions{\yquant@prefix subcircuits}% +} + \tikzaddtikzonlycommandshortcutlet\yquant\yquant@envunstar \expandafter\tikzaddtikzonlycommandshortcutlet\csname yquant*\endcsname\yquant@envstar \tikzaddtikzonlycommandshortcutlet\endyquant\yquant@env@end @@ -117,11 +281,16 @@ } \let\yquant@set=\yquantset% -% private yquant-language related helpers % In order to allow nested environments and also grouping (without the need to smuggle definitions out of the groups whenever necessary), we count the number of nested environments. \newcount\yquant@env -\def\yquant@env@substikz@finish{% +% Some commands may be overwritten while a subcircuit is processed, in particular attributes, but also some others. However, within the subcircuit, they need to have their original (un)definition. +\protected\def\yquant@env@reset@commands{% + \yquant@lang@reset@attrs% + \yquant@register@reset@multi% +} + +\protected\def\yquant@env@substikz@finish{% % Rendering pipeline \endgroup% \global\pgflinewidth=\tikzscope@linewidth\relax% @@ -137,24 +306,24 @@ } % substitute the tikz commands (defined in \tikz@installcommands) so that they can be arbitrarily interleaved with yquant code. We patch \path, \scope, \endscope, \stopscope, their internal complements, and also patch \yquantset. -\protected\def\yquant@env@substikz{% +\protected\def\yquant@env@substikz#1{% % \tikz@path@do@at@end is called after a path. Hence, it is an ideal candidate to re-invoke \yquant@env@scan. However, it is by default defined to be \tikz@lib@scope@check, and we need this definition for the scopes library to work correctly. But since \tikz@lib@scope@check is also called after a scope and the end of a scope, this is even better. Yet, we need to check whether the scopes library is present or not. \let\yquant@env@substikz@scopecheck=\tikz@lib@scope@check% \ifx\tikz@lib@scope@check\pgfutil@empty% % no, it is not. This is simple. - \let\tikz@lib@scope@check=\yquant@env@scan% + \def\tikz@lib@scope@check{\yquant@env@scan}% \else% % yes, it is. Call it after the special behavior is done. \patchcmd\tikz@lib@scope@check{{}}{\yquant@env@scan}\relax{% \PackageWarning{yquant.sty}{Patching \string\tikz@lib@scope@check\space failed; you must invoke \string\yquant\space manually after every tikz command to switch back to yquant code.}% - } + }% \fi% % We not only need to re-invoke yquant after the tikz command, but we must also make sure that the tikz command is not actually drawn now, but at the end. However, what happens if some macros are used within the command? Here, we choose to expand the macros to the values they have _now_, but protected (which should prevent bad things for formatting commands). If you find this to be an issue, please report. \def\path##1;{% \protected@csxappto{\yquant@prefix draw}{% \noexpand\path##1;% }% - \yquant% + #1% }% % no need for \scoped, because it internally calls \scope. % We need to hack into \scope, but this is a bit tricky due to its argument handling. In order to get all optional arguments, including the possible animations library, correct, we change \tikz@scope@opt. @@ -189,6 +358,7 @@ \begingroup% \yquant@env@contscan% } +\let\yquant@env@scan@=\yquant@env@scan \protected\def\yquant@env@contscan{% \yquant@futurenonspacelet\yquant@env@nextchar\yquant@env@check% @@ -199,7 +369,7 @@ \yquant@env@scan% } -\protected\def\yquant@env@check{% +\protected\def\yquant@env@check@{% \let\next=\relax% % Here we assume standard catcodes for A and [, but our language specification also requires this implicitly. \ifx\yquant@env@nextchar[% @@ -254,4 +424,59 @@ \def\yquant@env@gobblepar{% \afterassignment\yquant@env@contscan% \let\@eattoken= % +} + +\def\yquantimport@now#1{% + \expandafter\yquant\@@input #1\relax% +} + +\def\yquantimportcommand{\yquantimport@now}% + +\AtBeginDocument{% + % do we have the import package? + \ifdefined\@doimport% + \providecommand\yquantimportpath{./}% + \def\yquantimportcommand{\@doimport\yquantimport@now{\yquantimportpath}}% + \fi% +} + +\def\yquantimport{% + \@ifstar{\yquantimport@i{*}}{\yquantimport@i{}}% +} + +\def\yquantimport@i#1{% + \@ifnextchar[{\yquantimport@ii{#1}}{\yquantimport@ii{#1}[]}% +}% + +\def\yquantimport@ii#1[#2]#3{% + \ifpgfpicture% + \ifnum\yquant@env>0 % + \begingroup% + \ifstrequal{#1}{*}{% + \yquant@env@lazytrue% + }{% + \yquant@env@lazyfalse% + }% + \ifstrempty{#2}{% + \yquantimportcommand{#3}% + }{% + \scope% + \yquantset{#2}% + \yquantimportcommand{#3}% + \endscope% + }% + \endgroup% + \expandafter\expandafter\expandafter\yquant% + \else% + \begin{yquant#1}[{#2}] + \yquantimportcommand{#3}% + \end{yquant#1}% + \fi% + \else% + \begin{tikzpicture}% + \begin{yquant#1}[{#2}] + \yquantimportcommand{#3}% + \end{yquant#1}% + \end{tikzpicture} + \fi% }
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex b/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex index b250f788276..2ea08e8b16c 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex @@ -1,70 +1,100 @@ % BEGIN_FOLD Attributes -\yquant@langhelper@declare@attr{ - value/.store in=\yquant@lang@attr@value, +\yquant@langhelper@declare@attr{% + value/.store in=\yquant@lang@attr@value,% after/.code={% \yquant@register@get@ids{#1}% \let\yquant@lang@attr@after=\yquant@register@get@ids@list% - }, - type/.store in=\yquant@lang@attr@type + },% + type/.store in=\yquant@lang@attr@type,% + ancilla/.code={% + \undef\yquant@lang@attr@input% + \undef\yquant@lang@attr@output% + },% + in/.code={% + \let\yquant@lang@attr@input=\relax% + \undef\yquant@lang@attr@output% + },% + in/.default=\regidx,% + out/.code={% + \undef\yquant@lang@attr@input% + \let\yquant@lang@attr@output=\relax% + },% + out/.default=\regidx,% + inout/.code={% + \let\yquant@lang@attr@input=\relax% + \let\yquant@lang@attr@output=\relax% + }% + inout/.default=\regidx,% } -\yquant@langhelper@declare@attr@global{ - name/.store in=\yquant@lang@attr@name +\yquant@langhelper@declare@attr@global{% + name/.store in=\yquant@lang@attr@name% } \protected\def\yquant@lang@reset@attrs{% \undef\yquant@lang@attr@value% \undef\yquant@lang@attr@after% \undef\yquant@lang@attr@type% + \yquant@lang@reset@attrs@inputoutput% \let\yquant@lang@attr@name=\empty% } + +\protected\def\yquant@lang@reset@attrs@inputoutput{% + \undef\yquant@lang@attr@input% + \undef\yquant@lang@attr@output% +} + +\protected\def\yquant@lang@reset@attrs@inputoutput@subcircuit{% + \let\yquant@lang@attr@input=\relax% + \let\yquant@lang@attr@output=\relax% +} % END_FOLD % BEGIN_FOLD Declaration of registers \yquant@langhelper@declare@command@uncontrolled{nobit}\yquant@lang@@nobit -\yquant@langhelper@setup@attrs{nobit}{}{} +\yquant@langhelper@setup@attrs{nobit}{}{ancilla,out} \def\yquant@lang@@nobit#1{% \let\yquant@lang@create@type=\yquant@register@type@none% \def\yquant@lang@create@style{initial}% there is no separate style, just duplicate \ifdefined\yquant@lang@attr@value% \PackageError{yquant.sty}{Placeholder initialization must not have value}% {You must not provide a description for an invisible register.} - \else + \else% \let\yquant@lang@attr@value=\empty% \fi% - \yquant@lang@create@parse@name#1[; + \yquant@lang@create@parse@name#1[;% } \yquant@langhelper@declare@command@uncontrolled{qubit}\yquant@lang@@qubit -\yquant@langhelper@setup@attrs{qubit}{}{after,value} +\yquant@langhelper@setup@attrs{qubit}{}{after,value,ancilla,in,out,inout} \def\yquant@lang@@qubit#1{% \let\yquant@lang@create@type=\yquant@register@type@q% \def\yquant@lang@create@style{qubit}% \unless\ifdefined\yquant@lang@attr@value% \let\yquant@lang@attr@value=\yquant@config@register@default@name% \fi% - \yquant@lang@create@parse@name#1[; + \yquant@lang@create@parse@name#1[;% } \yquant@langhelper@declare@command@uncontrolled{cbit}\yquant@lang@@cbit -\yquant@langhelper@setup@attrs{qubit}{}{after,value} +\yquant@langhelper@setup@attrs{cbit}{}{after,value,ancilla,in,out,inout} \def\yquant@lang@@cbit#1{% \let\yquant@lang@create@type=\yquant@register@type@c% \def\yquant@lang@create@style{qubit}% \unless\ifdefined\yquant@lang@attr@value% \let\yquant@lang@attr@value=\yquant@config@register@default@name% \fi% - \yquant@lang@create@parse@name#1[; + \yquant@lang@create@parse@name#1[;% } \yquant@langhelper@declare@command@uncontrolled{qubits}\yquant@lang@@qubits -\yquant@langhelper@setup@attrs{qubit}{}{after,value} +\yquant@langhelper@setup@attrs{qubits}{}{after,value,ancilla,in,out,inout} \def\yquant@lang@@qubits#1{% \let\yquant@lang@create@type=\yquant@register@type@qs% \def\yquant@lang@create@style{qubits}% \unless\ifdefined\yquant@lang@attr@value% \let\yquant@lang@attr@value=\yquant@config@register@default@name% \fi% - \yquant@lang@create@parse@name#1[; + \yquant@lang@create@parse@name#1[;% } \def\yquant@lang@create@parse@name#1[#2;{% @@ -82,7 +112,7 @@ \ifnum\len<1 % \PackageError{yquant.sty}{Invalid register length}% {Valid register lengths are integers greater or equal to one.}% - \fi + \fi% }{% \PackageError{yquant.sty}{Invalid register name}% {Register names must not contain `[' apart from register length indication.}% @@ -109,8 +139,11 @@ % determine x position \ifdefined\yquant@lang@attr@after% \yquant@register@get@maxxlist\yquant@lang@create@x\yquant@lang@attr@after% + \ifdefined\yquant@lang@attr@input% + \PackageError{yquant.sty}{An input register cannot be created with `after` attribute}{}% + \fi% \else% - \def\yquant@lang@create@x{0pt}% + \let\yquant@lang@create@x=\yquant@env@create@x% \fi% \begingroup% \ifx\yquant@lang@attr@name\empty% @@ -120,29 +153,87 @@ \fi% % pre-set y position \yquant@for \idx := \idx to \numexpr \len -1\relax {% - \yquant@register@define% - \yquant@lang@create@type% - \yquant@lang@create@x% - \reg\idx% + \ifdefined\yquant@lang@attr@input% + \expandafter\yquant@list@gdequeue\csname \yquant@prefix parameters\endcsname\outermap% + \ifx\outermap\empty% + \PackageError{yquant.sty}{Invalid subcircuit parameter count}% + {No outer register available for input register `\reg[\idx]`.}% + \fi% + \csxappto{\yquant@prefix draw}{% + \yquant@lang@create@check@input{\outermap}{\yquant@lang@create@type}% + {\reg[\idx]}% + }% + \unless\ifdefined\yquant@lang@attr@output% + \listcsxadd{\yquant@prefix inonly}% + {\the\numexpr\csname\yquant@prefix registers\endcsname+1\relax}% + \fi% + \yquant@register@alias% + \yquant@lang@create@type% + \yquant@lang@create@x% + \reg\idx\outermap% + \else% + \ifdefined\yquant@lang@attr@output% + \expandafter\yquant@list@gdequeue\csname\yquant@prefix parameters\endcsname\outermap% + \ifx\outermap\empty% + \PackageError{yquant.sty}{Invalid subcircuit parameter count}% + {No outer register available for output register `\reg`.}% + \fi% + \csxappto{\yquant@prefix draw}{% + \yquant@lang@create@check@output{\outermap}{\reg[\idx]}% + }% + \yquant@register@alias% + \yquant@lang@create@type% + \yquant@lang@create@x% + \reg\idx\outermap% + \else% + \yquant@register@define% + \yquant@lang@create@type% + \yquant@lang@create@x% + \reg\idx% + \fi% + \fi% % First determine the actual height by a virtual draw command - \pgfinterruptboundingbox% - \yquant@env@virtualize@path% - \path% - (\yquant@lang@create@x, 0pt) - node[/yquant/every label, /yquant/every initial label,% - /yquant/every \yquant@lang@create@style\space label] - {\trim@spaces{\yquant@lang@attr@value}};% - \expandafter\yquant@register@update@height% - \csname\yquant@prefix registers\endcsname% - {\the\dimexpr\pgf@picmaxy-\pgf@picminy\relax}% - \endpgfinterruptboundingbox% + \protected@edef\trimmedvalue{\trim@spaces{\yquant@lang@attr@value}}% + \unless\ifx\empty\trimmedvalue% + \pgfinterruptboundingbox% + \yquant@env@virtualize@path% + \edef\cmd{% + \noexpand\path% + (\yquant@lang@create@x, 0pt)% + node[/yquant/every label, /yquant/every initial label,% + /yquant/every \yquant@lang@create@style\space label% + \ifdefined\yquant@lang@attr@input, /yquant/every input label\fi]% + {\unexpanded\expandafter{\trimmedvalue}};% + }% + \cmd% + \ifdim\pgf@picminx<\csname\yquant@prefix xmin\endcsname% + \csxdef{\yquant@prefix xmin}{\the\pgf@picminx}% + \fi% + \expandafter\yquant@register@update@height% + \csname\yquant@prefix registers\endcsname% + {\the\pgf@picmaxy}% + \expandafter\yquant@register@update@depth% + \csname\yquant@prefix registers\endcsname% + {\the\dimexpr-\pgf@picminy\relax}% + \endpgfinterruptboundingbox% + \fi% % Prepare to shipout - \protected@csxappto{\yquant@prefix draw}{% + \csxappto{\yquant@prefix draw}{% \yquant@lang@create@draw{\csname\yquant@prefix registers\endcsname}% {\yquant@lang@create@x}% {\yquant@lang@create@style}% - {\yquant@lang@attr@value}% + \ifdefined\yquant@lang@attr@input1\else0\fi% + {\unexpanded\expandafter{\trimmedvalue}}% {\yquant@lang@create@name}% + \unless\ifdefined\yquant@lang@attr@input% + \ifdefined\yquant@lang@attr@output% + \yquant@circuit@flushwire% + {\csname\yquant@prefix registers\endcsname}% + \yquant@register@set@type% + {\csname\yquant@prefix registers\endcsname}% + \yquant@lang@create@type% + \fi% + \fi% }% }% \unless\ifx\yquant@lang@attr@name\empty% @@ -154,32 +245,166 @@ \endgroup% } -\protected\def\yquant@lang@create@draw#1#2#3#4#5{% +\protected\def\yquant@lang@create@check@input#1#2#3{% + \begingroup% + \let\yquant@prefix=\yquant@parent% + \unless\if#2\yquant@register@get@type{#1}% + \PackageError{yquant.sty}{Subcircuit expects wire of type `\yquant@register@type@tostring{#2}', but got `\yquant@register@type@tostring{\yquant@register@get@type{#1}}'}% + {Outer and inner wire types must match for input wire `\detokenize{#3}`.}% + \fi% + \endgroup% +} + +\protected\def\yquant@lang@create@check@output#1#2{% + \begingroup% + \let\yquant@prefix=\yquant@parent% + \unless\if\yquant@register@type@none\yquant@register@get@type{#1}% + \PackageError{yquant.sty}% + {Subcircuit expects discarded wire, got `\yquant@register@type@tostring{\yquant@register@get@type{#1}}'}% + {Outer wire must be discarded before being acceptable for output-only register `\detokenize{#2}`.}% + \fi% + \endgroup% +} + +\protected\def\yquant@lang@create@draw#1#2#3#4#5#6{% \begingroup% \dimdef\wireypos{\yquant@register@get@y{#1}}% - \ifstrempty{#4}{% + \ifcsname\yquant@prefix xshift\endcsname% + \dimdef\createxpos{#2+\csname\yquant@prefix xshift\endcsname}% + \else% + \dimdef\createxpos{#2}% + \fi% + \ifstrempty{#5}{% % For empty labels, we still put the node at the appropriate position as it may needs to be referenced, but we will not let it effect the bounding box (so that the left end is not shifted), and we don't need an inner separation, so that the label is truely just a coordinate. - \path[overlay] - (#2, \wireypos)% - coordinate[name prefix=, name suffix=, name=yquantbox]; + \path[overlay]% + (\createxpos, \wireypos)% + coordinate[name prefix=, name suffix=, name=yquantbox];% + \let\pgfshapeclippathhorzresult=\empty% }{% - \path - (#2, \wireypos)% - node[/yquant/every label, /yquant/every initial label,% - /yquant/every #3 label, name prefix=, name suffix=, name=yquantbox]% - {#4};% + \edef\cmd{% + \noexpand\path% + (\createxpos, \wireypos)% + node[/yquant/every label, /yquant/every initial label,% + /yquant/every #3 label\ifx1#4, /yquant/every input label\fi,% + name prefix=, name suffix=, name=yquantbox]% + {\unexpanded{#5}};% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \pgfshapeclippath{yquantbox}% + {/yquant/every label, /yquant/every initial label,% + /yquant/every #3 label\ifx1#4, /yquant/every input label\fi}% + \fi% + }% + \cmd% }% - % set the wire style to have the correct \pgflinewidth available (we don't allow individual line widths for different types of wires) - \tikzset{/yquant/every wire}% - \pgfpointanchor{yquantbox}{east}% - \yquant@register@set@lastwire{#1}{{\the\pgf@x}{\the\pgf@x}{}{}}% - \ifstrempty{#5}\relax{% - \pgfnodealias{\tikz@pp@name{#5}}{yquantbox}% + \ifcsname\yquant@prefix registermap@#1\endcsname% + % if this is an alias, the creation is just an extension + \if\yquant@register@type@none\yquant@register@get@type{#1}% + \ifstrequal{#3}{initial}{% + \yquant@circuit@extendwire{#1}{east}% + }{% + % however, our inner wire is present, while the outer wire was discarded. + \tikzset{/yquant/every wire}% + \pgfpointanchor{yquantbox}{east}% + \yquant@register@set@lastwire{#1}{% + {\the\pgf@x}{\the\pgf@x}{}% + {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% + }% + }% + \else% + \yquant@circuit@extendwire{#1}{east}% + \fi% + \else% + % set the wire style to have the correct \pgflinewidth available (we don't allow individual line widths for different types of wires) + \tikzset{/yquant/every wire}% + \pgfpointanchor{yquantbox}{east}% + \yquant@register@set@lastwire{#1}{{\the\pgf@x}{\the\pgf@x}{}{}}% + \fi% + \ifstrempty{#6}\relax{% + \pgfnodealias{\tikz@pp@name{#6}}{yquantbox}% }% \endgroup% } % END_FOLD +% BEGIN_FOLD Define own gates +\def\yquantdefinegate#1{% + \ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Gate redefined}% + {The gate `#1' already exists. Use \string\yquantredefinegate\space if you really want to redefine it.}% + \fi% + \@ifnextchar[{\yquantdefinegate@i{#1}}% + {\yquantdefinegate@i{#1}[/yquant/operators/every custom gate]}% +} + +% while this command is provided to redefine gates, we do not clear the attributes that were once assigned to the previous one, so gate redefinition is discouraged! +\def\yquantredefinegate#1{% + \unless\ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Unknown gate redefined}% + {The gate `#1' is unknown and cannot be redefined. Use \string\yquantdefinegate\space to define it.}% + \fi% + \@ifnextchar[{\yquantdefinegate@i{#1}}% + {\yquantdefinegate@i{#1}[/yquant/operators/every custom gate]}% +} + +\protected\long\def\yquantdefinegate@i#1[#2]#3{% + \pgfkeys{/yquant/operators/every #1/.style={#2}}% + \protected@edef\yquantdefinegate@do{% + \yquant@langhelper@declare@command% + {#1}% + \expandafter\noexpand\csname yquant@lang@@#1\endcsname% + % This does not clear the attributes for redefines, but makes at least sure nothing is marked as required that should not be. + \yquant@langhelper@setup@attrs{#1}{}{}% + % Now define the gate's content as a macro + \def\expandafter\noexpand\csname yquant@lang@@@#1\endcsname{% + #3% + }% + % And provide the implementation + \protected\def\expandafter\noexpand\csname yquant@lang@@#1\endcsname####1####2####3{% + \yquant@register@get@multiaslist% + \yquant@circuit@operator{####1}{####2}{####3}% + \let\noexpand\yquant@lang@attr@value=\expandafter\noexpand\csname yquant@lang@@@#1\endcsname% + \yquant@draw@@subcircuit{/yquant/operators/every #1}% + }% + }% + \yquantdefinegate@do% +} + +\def\yquantdefinebox#1{% + \ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Gate redefined}% + {The gate `#1' already exists. Use \string\yquantredefinebox\space if you really want to redefine it.}% + \fi% + \@ifnextchar[{\yquantdefinebox@i{#1}}% + {\yquantdefinebox@i{#1}[/yquant/operators/every box]}% +} + +\def\yquantredefinebox#1{% + \unless\ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Unknown gate redefined}% + {The gate `#1' is unknown and cannot be redefined. Use \string\yquantdefinebox\space to define it.}% + \fi% + \yquantdefinebox@i{#1}% + \@ifnextchar[{\yquantdefinebox@i{#1}}% + {\yquantdefinebox@i{#1}[/yquant/operators/every box]}% +} + +\protected\long\def\yquantdefinebox@i#1[#2]#3{% + \pgfkeys{/yquant/operators/every #1/.style={#2}}% + \protected@edef\yquantdefinebox@do{% + \yquant@langhelper@declare@command% + {#1}% + \expandafter\noexpand\csname yquant@lang@@#1\endcsname% + \yquant@langhelper@setup@attrs{#1}{}{}% + \def\expandafter\noexpand\csname yquant@lang@@#1\endcsname{% + \yquant@draw% + {#3}% + {/yquant/operators/every #1}% + }% + }% + \yquantdefinebox@do% +} +% END_FOLD + % BEGIN_FOLD Box registers % all-purpose box with arbitrary text \yquant@langhelper@declare@command{box}\yquant@lang@@box @@ -187,68 +412,30 @@ \def\yquant@lang@@box{% \yquant@register@get@allowmultitrue% \expandafter\yquant@draw% - \expandafter{\yquant@lang@attr@value} + \expandafter{\yquant@lang@attr@value}% {/yquant/operators/every box}% } % Hadamard -\yquant@langhelper@declare@command{h}\yquant@lang@@h -\yquant@langhelper@setup@attrs{h}{}{} -\def\yquant@lang@@h{% - \yquant@draw% - {$H$}% - {/yquant/operators/every h}% -} +\yquantdefinebox{h}{$H$} % Pauli X (or NOT) -\yquant@langhelper@declare@command{x}\yquant@lang@@x -\yquant@langhelper@setup@attrs{x}{}{} -\def\yquant@lang@@x{% - \yquant@draw% - {$X$}% - {/yquant/operators/every x}% -} +\yquantdefinebox{x}[/yquant/operators/every pauli]{$X$} % Pauli Y -\yquant@langhelper@declare@command{y}\yquant@lang@@y -\yquant@langhelper@setup@attrs{y}{}{} -\def\yquant@lang@@y{% - \yquant@draw% - {$Y$}% - {/yquant/operators/every y}% -} +\yquantdefinebox{y}[/yquant/operators/every pauli]{$Y$} % Pauli Z -\yquant@langhelper@declare@command{z}\yquant@lang@@z -\yquant@langhelper@setup@attrs{z}{}{} -\def\yquant@lang@@z{% - \yquant@draw% - {$Z$}% - {/yquant/operators/every z}% -} +\yquantdefinebox{z}[/yquant/operators/every pauli]{$Z$} % sub-circuit: This is a nested circuit. -%\yquant@langhelper@declare@command{subcircuit}\yquant@lang@@subcircuit -%\yquant@langhelper@setup@attrs{subcircuit}{}{shift} -%\protected\def\yquant@lang@@subcircuit#1#2#3{% -% % First we restore access to the yquant environment (which was a shorthand to -% % re-starting the parser within the environment, conveniently forbidding nesting). -% \let\yquant=\yquant@envunstar% -% \cslet{yquant*}\yquant@envstar% -% % Then determine the actual subcircuit content. -% \yquant@circuit@subcircuit\yquant@lang@attr@value% -% % Now the subcircuit is stored in \yquant@circuit@subcircuit@box. However, note that -% % it may contain named nodes (whose names are stored in -% % \csname\yquant@prefix circuit@subcircuit@nodelist\endcsname) that need to be shifted -% % whenever we actually position the subcircuit. -%% \let\yquant@draw@callback@box=\yquant@circuit@subcircuit@shiftnodes% -% \yquant@register@get@allowmultitrue% -% \yquant@draw% -% {\copy\yquant@circuit@subcircuit@box}% -% {/yquant/operators/every subcircuit} -% {#1}{#2}{#3}% -% \global\setbox\yquant@circuit@subcircuit@box=\box\voidb@x% memory management -%} +\yquant@langhelper@declare@command{subcircuit}\yquant@lang@@subcircuit +\yquant@langhelper@setup@attrs{subcircuit}{value}{} +\protected\def\yquant@lang@@subcircuit#1#2#3{% + \yquant@register@get@multiaslist% + \yquant@circuit@operator{#1}{#2}{#3}% + \yquant@draw@@subcircuit{/yquant/operators/every subcircuit}% +} % END_FOLD % BEGIN_FOLD other geometric shapes @@ -291,8 +478,8 @@ \protected\def\yquant@lang@@slash#1{% % temporarily squeeze most into the separation \pgfkeys{% - /yquant/operator/minimum width=0pt, - /yquant/operator/separation=.5\dimexpr\yquant@config@operator@sep-\pgflinewidth\relax + /yquant/operator/minimum width=0pt,% + /yquant/operator/separation=.5\dimexpr\yquant@config@operator@sep-\pgflinewidth\relax% }% \def\yquant@draw@callback@wire##1{% \yquant@register@set@x% @@ -332,20 +519,7 @@ \yquant@langhelper@setup@attrs{measure}{}{value,type} \def\yquant@lang@@measure{% \ifdefined\yquant@lang@attr@type% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@q}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{cbit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@c}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubits}% - {\let\yquant@circuit@settype@to=\yquant@register@type@qs}% - {% - \PackageError{yquant.sty}{Invalid bit type: `\yquant@lang@attr@type}% - {Use one of `qubit', `cbit', or `qubits'.}% - }% - }% - }% + \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% \else% \let\yquant@circuit@settype@to=\yquant@register@type@c% \fi% @@ -365,20 +539,7 @@ \yquant@langhelper@setup@attrs{dmeter}{}{value,type} \def\yquant@lang@@dmeter{% \ifdefined\yquant@lang@attr@type% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@q}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{cbit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@c}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubits}% - {\let\yquant@circuit@settype@to=\yquant@register@type@qs}% - {% - \PackageError{yquant.sty}{Invalid bit type: `\yquant@lang@attr@type}% - {Use one of `qubit', `cbit', or `qubits'.}% - }% - }% - }% + \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% \else% \let\yquant@circuit@settype@to=\yquant@register@type@c% \fi% @@ -402,7 +563,7 @@ \yquant@draw% {}% {/yquant/operators/every barrier}% - {}{} + {}{}% } \yquant@langhelper@declare@command@uncontrolled{correlate}\yquant@lang@@correlate @@ -453,25 +614,12 @@ \fi% }% } -\long\def\@fifthoffive#1#2#3#4#5{#5} + \protected\def\yquant@lang@@init#1{% \yquant@register@get@allowmultitrue% \yquant@register@get@ids{#1}% \ifdefined\yquant@lang@attr@type% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@q}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{cbit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@c}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@type}{qubits}% - {\let\yquant@circuit@settype@to=\yquant@register@type@qs}% - {% - \PackageError{yquant.sty}{Invalid bit type: `\yquant@lang@attr@type}% - {Use one of `qubit', `cbit', or `qubits'.}% - }% - }% - }% + \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% \else% % We don't know which type is desired. Scan all target registers and use the first wire that is available as a type. \let\yquant@circuit@settype@to=\yquant@register@type@none% @@ -492,15 +640,9 @@ % now we don't have a clue; assume it's a qubit \let\yquant@circuit@settype@to=\yquant@register@type@q% \fi% - \ifx\yquant@circuit@settype@to\yquant@register@type@q% - \def\yquant@lang@attr@type{qubit}% - \else% - \ifx\yquant@circuit@settype@to\yquant@register@type@c% - \def\yquant@lang@attr@type{cbit}% - \else% - \def\yquant@lang@attr@type{qubits}% - \fi% - \fi% + \edef\yquant@lang@attr@type{% + \yquant@register@type@tostring\yquant@circuit@settype@to% + }% \fi% \let\yquant@draw@callback@wire=\yquant@circuit@settype% \let\yquant@draw@@multi=\yquant@draw@@multiinit% @@ -532,20 +674,7 @@ \yquant@langhelper@setup@attrs{settype}{value}{} \protected\def\yquant@lang@@settype#1{% \yquant@register@get@ids{#1}% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@value}{qubit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@q}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@value}{cbit}% - {\let\yquant@circuit@settype@to=\yquant@register@type@c}% - {% - \expandafter\ifstrequal\expandafter{\yquant@lang@attr@value}{qubits}% - {\let\yquant@circuit@settype@to=\yquant@register@type@qs}% - {% - \PackageError{yquant.sty}{Invalid bit type: `\yquant@lang@attr@value}% - {Use one of `qubit', `cbit', or `qubits'.}% - }% - }% - }% + \yquant@register@type@fromstring\yquant@lang@attr@value\yquant@circuit@settype@to% \yquant@circuit@actonwires% \yquant@circuit@settype% \yquant@register@get@ids@list% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex index 102a8959d90..86114241940 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex @@ -45,7 +45,7 @@ }% \fi% \endpgfkeysinterruptkeyfilter% - }, + },% /pgf/key filters/attr filter/.code={% % we need to capture every non-attribute (which means filtering them out). \expandafter\ifyquant@beginswith\expandafter{\pgfkeyscurrentkey}{/yquant/attrs/}{% @@ -84,9 +84,9 @@ \pgfkeysfiltercontinuefalse% }% }% - }, - /yquant/attr filter/.style={ - /pgf/key filters/attr filter/.install key filter, + },% + /yquant/attr filter/.style={% + /pgf/key filters/attr filter/.install key filter,% /yquant/attr filter handler/.install key filter handler=\yquant@attrs@remaining% }% } @@ -112,7 +112,7 @@ \pgfkeysinterruptkeyfilter% \pgfkeys{/yquant/all attrs/##1={####1}}% \endpgfkeysinterruptkeyfilter% - } + }% }% }% \eappto\keysset{% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex index 18a23662d3b..c90a44614ca 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex @@ -3,6 +3,38 @@ \def\yquant@register@type@c{2} \def\yquant@register@type@qs{3} +\def\yquant@register@type@tostring#1{% + \ifcase#1 % + nobit% + \or% + qubit% + \or% + cbit% + \or% + qubits% + \else% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Unknown wire type: `#1'.}% + \fi% +} + +\protected\def\yquant@register@type@fromstring#1#2{% + \expandafter\ifstrequal\expandafter{#1}{qubit}% + {\let#2=\yquant@register@type@q}% + {% + \expandafter\ifstrequal\expandafter{#1}{cbit}% + {\let#2=\yquant@register@type@c}% + {% + \expandafter\ifstrequal\expandafter{#1}{qubits}% + {\let#2=\yquant@register@type@qs}% + {% + \PackageError{yquant.sty}{Invalid bit type: `#1'}% + {Use one of `qubit', `cbit', or `qubits'.}% + }% + }% + }% +} + % Internally, we store the register information in a single macro. Indeed, this is almost always faster than using multiple macros (at least in the way implemented here), apart from changing a single type of information, which is almost as fast. % BEGIN_FOLD Constructor: create single register and cleanup environment @@ -16,17 +48,55 @@ \csxdef{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}{% {#1}% type {#2}% x pos - {\yquant@config@register@minimum@height}% height; at the end, the y position - {{0pt}{0pt}{}{}}% wire start positions and clipping + {{\the\dimexpr.5\dimexpr\yquant@config@register@minimum@height\relax\relax}% + {\the\dimexpr.5\dimexpr\yquant@config@register@minimum@height\relax\relax}}% height and depth; at the end, the y position + {{\yquant@env@create@x}{\yquant@env@create@x}{}{}}% wire start positions and clipping {}% wire style }% \global\csletcs{\yquant@prefix registername@#3[#4]}{\yquant@prefix registers}% - \csxdef{\yquant@prefix registerhigh@\reg}{#4}% + \csxdef{\yquant@prefix registerhigh@#3}{#4}% \yquant@cleanup@csadd{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}% \yquant@cleanup@csadd{\yquant@prefix registername@#3[#4]}% \ifnum0=#4\relax% - \yquant@cleanup@csadd{\yquant@prefix registerhigh@\reg}% + \yquant@cleanup@csadd{\yquant@prefix registerhigh@#3}% + \fi% +} + +% in a subcircuit, create a new register that is only an alias for an existing register in the outer circuit. +% #5: id in the outer circuit +\protected\def\yquant@register@alias#1#2#3#4#5{% + \csnumgdef{\yquant@prefix registers}% + {\csname\yquant@prefix registers\endcsname+1}% + \ifcsname\yquant@parent registermap@#5\endcsname% + % the parent is already an alias itself, pass this on transparently + \global\csletcs% + {\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname}% + {\yquant@parent registermap@#5}% + \else% + \csxdef{\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname}% + {\yquant@parent register@#5}% + \fi% + % even though this is an alias, we still need to keep track of its internal dimensions + \csgdef{\yquant@prefix registerdim@\csname\yquant@prefix registers\endcsname}% + {{0pt}{0pt}}% + \yquant@cleanup@csadd{\yquant@prefix registerdim@\csname\yquant@prefix registers\endcsname}% + \global\csletcs{\yquant@prefix registername@#3[#4]}{\yquant@prefix registers}% + \csxdef{\yquant@prefix registerhigh@#3}{#4}% + \yquant@cleanup@csadd{\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname}% + \yquant@cleanup@csadd{\yquant@prefix registername@#3[#4]}% + \ifnum0=#4\relax% + \yquant@cleanup@csadd{\yquant@prefix registerhigh@#3}% + \fi% + \csxdef{\yquant@prefix lastinput}{{\csname\yquant@prefix registers\endcsname}{#5}}% + \unless\ifcsname\yquant@prefix firstinput\endcsname% + \csxdef{\yquant@prefix firstinput}{{\csname\yquant@prefix registers\endcsname}{#5}}% + \yquant@cleanup@csadd{\yquant@prefix firstinput}% + \yquant@cleanup@csadd{\yquant@prefix lastinput}% \fi% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname\endcsname\endcsname% + \yquant@register@set@x@aux% + {#2}% } % END_FOLD @@ -43,19 +113,17 @@ % same as before, but resolves to the _index_ of the last register \protected\def\yquant@register@get@id@high#1#2{% - \ifcsname\yquant@prefix registerhigh@#2\endcsname% - \letcs#1{\yquant@prefix registerhigh@#2}% - \else% + \unless\ifcsname\yquant@prefix registerhigh@#2\endcsname% \yquant@register@get@id@lazycreate{#2}% - \letcs#1{\yquant@prefix registers}% \fi% + \letcs#1{\yquant@prefix registerhigh@#2}% } % In the lazy mode, we create all unknown registers on-the-fly. \def\yquant@register@get@id@lazycreate#1{% \ifyquant@env@lazy% % In principle, we could just call \yquant@lang@@qubit. However, if access to a vector register is desired and a _part_ of this does already exist (though not the requested index), we only create the missing registers. - \yquant@register@get@id@lazycreate@parse#1[; + \yquant@register@get@id@lazycreate@parse#1[;% \else% \PackageError{yquant.sty}{Register `#1' unknown}% {You referred to an unknown register. @@ -96,13 +164,14 @@ \yquant@for \idx := \idx to \numexpr \len -1\relax {% \yquant@register@define% \yquant@register@type@q% - {0pt}% - \reg\idx + {\yquant@env@create@x}% + \reg\idx% % Prepare to shipout \csxappto{\yquant@prefix draw}{% \yquant@lang@create@draw{\csname\yquant@prefix registers\endcsname}% {0pt}% {qubit}% + 0% {}% {}% }% @@ -137,7 +206,10 @@ \catcode`(=\active% \def[##1]{\yquant@register@get@ids@@index{##1}}% \def(##1){\yquant@register@get@ids@@multi{##1}}% - \edef\yquant@register@get@ids@retokenized{\scantokens{#1\noexpand}}% + % this is also invoked by other languages which might have completely redefined all catcodes (qasm redefines the backslash), so don't just add \noexpand at the end of the \scantokens... + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\yquant@register@get@ids@retokenized{\scantokens{#1}}% \expandafter% \endgroup% \expandafter\docsvlist\expandafter{\yquant@register@get@ids@retokenized}% @@ -239,7 +311,7 @@ }% \count0=2147483647 % \csletcs{ifallowmain}{iffalse}% - }{ + }{% \let\yquant@register@get@ids@norange@checkindex@setmain=\relax% }% \else% @@ -346,7 +418,7 @@ \expandafter\yquant@register@get@id\expandafter\idx\expandafter{\idx}% \count6=\idx% \csletcs{ifallowmain}{iffalse}% - }{ + }{% \yquant@register@get@id\idx{\current[#1]}% }% \else% @@ -575,50 +647,99 @@ }% } +\protected\def\yquant@register@multi@splitparts@sort{% + \yquant@sort@list\yquant@register@get@ids@list\yquant@sort@ascending% +} + \protected\def\yquant@register@get@multiassingle{% \yquant@register@get@allowmultitrue% \let\yquant@register@multi@splitparts=\yquant@register@multi@splitparts@sepall% \preto\yquant@attrs@remaining{/yquant/operator/multi as single,}% } + +\protected\def\yquant@register@get@multiaslist{% + \yquant@register@get@allowmultitrue% + \let\yquant@register@multi@splitparts=\yquant@register@multi@splitparts@sort% +} + +\let\yquant@register@multi@reset@original@splitparts=\yquant@register@multi@splitparts% +\protected\def\yquant@register@reset@multi{% +% \yquant@register@get@allowmultifalse% not needed, as \yquant@circuit@operator automatically resets it + \let\yquant@register@multi@splitparts=\yquant@register@multi@reset@original@splitparts% +} % END_FOLD % BEGIN_FOLD Getters: extract the requested information from the register with given id \def\yquant@register@get@type#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@type@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \yquant@register@get@type@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@type@aux\csname\yquant@prefix register@#1\endcsname% + \fi% } \def\yquant@register@get@type@aux#1#2#3#4#5{#1} \def\yquant@register@get@x#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@x@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \yquant@register@get@x@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@x@aux\csname\yquant@prefix register@#1\endcsname% + \fi% } \def\yquant@register@get@x@aux#1#2#3#4#5{#2} \def\yquant@register@get@height#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \@firstoftwo\csname\yquant@prefix registerdim@#1\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% + \fi% } -\def\yquant@register@get@height@aux#1#2#3#4#5{#3} +\def\yquant@register@get@height@aux#1#2#3#4#5{\@firstoftwo#3} + +\def\yquant@register@get@depth#1{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \@secondoftwo\csname\yquant@prefix registerdim@#1\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@depth@aux\csname\yquant@prefix register@#1\endcsname% + \fi% +} + +\def\yquant@register@get@depth@aux#1#2#3#4#5{\@secondoftwo#3} % The y parameter get macros exist in two forms: The protected one is used during the storage to the draw macro; it should never be executed. The env environment then maps them to their proper expandable forms. -\protected\def\yquant@register@get@@protected{% +\protected\def\yquant@register@get@y{% \PackageError% {yquant.sty}% {Execution of a get-y macro in an illegal context}% {get-y macros may not be called unless the yquant environment ends.}% } -\let\yquant@register@get@y=\yquant@register@get@@protected -\let\yquant@register@y=\yquant@register@get@@protected % This plays a similar role: It must never be expanded before the tikz command is invoked (because it does not exist). -\let\nodepart=\yquant@register@get@@protected +\protected\def\nodepart{} -% getting the y position is the same as getting the height parameter, since we will reuse it at the end. -\let\yquant@register@get@y@unprotected=\yquant@register@get@height +\def\yquant@register@get@y@unprotected#1{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \yquant@register@get@y@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@y@aux\csname\yquant@prefix register@#1\endcsname% + \fi% +} + +\def\yquant@register@get@y@aux#1#2#3#4#5{#3} % y distance between two registers. \def\yquant@register@get@ydist#1#2{% @@ -626,17 +747,23 @@ {\the\dimexpr\yquant@register@get@y{#2}-\yquant@register@get@y{#1}\relax}% } -% y position of the current register -\def\yquant@register@y@unprotected{0pt}% - \protected\def\yquant@register@get@y@@expandable{% \let\yquant@register@get@y=\yquant@register@get@y@unprotected% - \let\yquant@register@y=\yquant@register@y@unprotected% } \def\yquant@register@get@lastwire#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@lastwire@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\expandafter\expandafter% + \yquant@register@get@lastwire@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\expandafter\expandafter% + \yquant@register@get@lastwire@aux\csname\yquant@prefix register@#1\endcsname% + }% } \protected\def\yquant@register@get@lastwire@aux#1#2#3#4#5#6{% @@ -644,15 +771,30 @@ } \def\yquant@register@get@style#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@style@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \yquant@register@get@style@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + \else% + \expandafter\expandafter\expandafter% + \yquant@register@get@style@aux\csname\yquant@prefix register@#1\endcsname% + \fi% } \def\yquant@register@get@style@aux#1#2#3#4#5{#5} \def\yquant@register@get@typeywire#1{% - \expandafter\expandafter\expandafter% - \yquant@register@get@typeywire@aux\csname\yquant@prefix register@#1\endcsname% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\expandafter\expandafter% + \yquant@register@get@typeywire@aux\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\expandafter\expandafter% + \yquant@register@get@typeywire@aux\csname\yquant@prefix register@#1\endcsname% + }% } \protected\def\yquant@register@get@typeywire@aux#1#2#3#4#5#6#7#8{% @@ -695,12 +837,23 @@ % BEGIN_FOLD Setters: change register information \protected\long\def\yquant@register@set@@aux#1#2#3{% - \long\xdef#1{\expandafter#2#1{#3}}% + \xdef#1{\expandafter#2#1{#3}}% } \protected\def\yquant@register@set@type#1{% - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@type@aux% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + }% + \yquant@register@set@type@aux% } \long\def\yquant@register@set@type@aux#1#2#3#4#5#6{% @@ -708,8 +861,19 @@ } \protected\def\yquant@register@set@x#1{% - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@x@aux% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + }% + \yquant@register@set@x@aux% } \long\def\yquant@register@set@x@aux#1#2#3#4#5#6{% @@ -717,25 +881,99 @@ } \protected\def\yquant@register@update@height#1#2{% - \ifdim#2>\yquant@register@get@height{#1} % - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@height@aux{#2}% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \ifdim#2>% + \expandafter\expandafter\expandafter% + \@firstoftwo\csname\yquant@prefix registerdim@#1\endcsname% + \relax% + \csxdef{\yquant@prefix registerdim@#1}{% + {#2}% + {\expandafter\expandafter\expandafter% + \@secondoftwo\csname\yquant@prefix registerdim@#1\endcsname}% + }% + \fi% + \else% + \ifdim#2>% + \expandafter\expandafter\expandafter% + \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% + \relax% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + \yquant@register@set@height@aux{#2}% + \fi% + \fi% +} + +\long\def\yquant@register@set@height@aux#1#2#3#4#5#6{% + \unexpanded{{#1}{#2}}% + {{#6}{\unexpanded\expandafter{\@secondoftwo#3}}}% + \unexpanded{{#4}{#5}}% +} + +\protected\def\yquant@register@update@depth#1#2{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \ifdim#2>% + \expandafter\expandafter\expandafter% + \@secondoftwo\csname\yquant@prefix registerdim@#1\endcsname% + \relax% + \csxdef{\yquant@prefix registerdim@#1}{% + {\expandafter\expandafter\expandafter% + \@firstoftwo\csname\yquant@prefix registerdim@#1\endcsname}% + {#2}% + }% + \fi% + \else% + \ifdim#2>% + \expandafter\expandafter\expandafter% + \yquant@register@get@depth@aux\csname\yquant@prefix register@#1\endcsname% + \relax% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + \yquant@register@set@depth@aux{#2}% + \fi% \fi% } +\long\def\yquant@register@set@depth@aux#1#2#3#4#5#6{% + \unexpanded{{#1}{#2}}% + {{\unexpanded\expandafter{\@firstoftwo#3}}{#6}}% + \unexpanded{{#4}{#5}}% +} + \protected\def\yquant@register@set@y#1{% - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@height@aux% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + }% + \yquant@register@set@y@aux% } -% Set the currently used register -\long\def\yquant@register@set@height@aux#1#2#3#4#5#6{% +\long\def\yquant@register@set@y@aux#1#2#3#4#5#6{% \unexpanded{{#1}{#2}}{#6}\unexpanded{{#4}{#5}}% } \protected\def\yquant@register@set@lastwire#1{% - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@lastwire@aux% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + }% + \yquant@register@set@lastwire@aux% } \long\def\yquant@register@set@lastwire@aux#1#2#3#4#5#6{% @@ -743,8 +981,19 @@ } \protected\def\yquant@register@set@style#1{% - \expandafter\yquant@register@set@@aux% - \csname\yquant@prefix register@#1\endcsname\yquant@register@set@style@aux% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \expandafter\yquant@register@set@@aux% + \csname\csname\yquant@prefix registermap@#1\endcsname\endcsname% + }{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + }% + \yquant@register@set@style@aux% } \long\def\yquant@register@set@style@aux#1#2#3#4#5#6{% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex b/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex index 3a03985ca5a..7ce146171b3 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex @@ -21,7 +21,7 @@ {\PackageError{yquant.sty}% {Failed to patch \string\pgfdeclareshape}% {yquant could not provide a necessary extension to pgf.}}% -% Every shape additionally provides information about how it should clip the wires. The clipping softpath instructions of shape #1 are stored into \pgfshapeclippathresult. The path is drawn with the tikz options #2 in place. +% Every shape additionally provides information about how it should clip the wires. The clipping softpath instructions of shape #1 are stored into \pgfshapeclippath[horz|vert]result. The path is drawn with the tikz options #2 in place. \protected\def\pgfshapeclippath#1#2{% % Ok, check whether #1 is known! \ifcsname pgf@sh@ns@#1\endcsname% @@ -56,7 +56,8 @@ \end{pgfinterruptpath}% \else% \pgferror{No shape named #1 is known}% - \pgfpointorigin% + \global\let\pgfshapeclippathhorzresult=\empty% + \global\let\pgfshapeclippathvertresult=\empty% \fi% } @@ -81,7 +82,7 @@ {\southwest% \advance\pgf@x by \@tempdima% \advance\pgf@y by \@tempdimb% - } + }% {\northeast% \advance\pgf@x by -\@tempdima% \advance\pgf@y by -\@tempdimb% @@ -441,7 +442,7 @@ % we only draw the meter symbol if this is the main part of a multi-register (or there is no text) \ifyquant@config@operator@multi@main% % Make sure the meter does not extend beyond the box (we are in a scope here) - \path [clip] + \path [clip]% (-\xradius, \yradius) rectangle (\xradius, -\yradius);% % The position of the meter symbol depends on the presence of the text. If there is no text, we just vertically center. If there is some text, we shift the symbol upwards from the text until there is no overlap any more. \csname pgf@anchor@yquant-measure@text\endcsname% @@ -451,10 +452,10 @@ \else% \@tempdima=\dimexpr\pgf@y+2pt\relax% \fi% - \path [/yquant/operators/every measure meter] + \path [/yquant/operators/every measure meter]% (-2.25mm, \@tempdima) arc[start angle=160, end angle=20,% - x radius=2.25mm, y radius=1.4mm] - (0, \@tempdima) -- ++(1.6mm, 2.3mm); + x radius=2.25mm, y radius=1.4mm]% + (0, \@tempdima) -- ++(1.6mm, 2.3mm);% \fi% }% } @@ -553,7 +554,7 @@ \shorten% \@tempdima=\dimexpr\yradius+\pgf@x\relax% \@tempdimb=\dimexpr\yradius+\pgf@y\relax% - \pgfpathrectanglecorners + \pgfpathrectanglecorners% {\pgfqpoint{-.5\pgflinewidth}{\@tempdima}}% {\pgfqpoint{.5\pgflinewidth}{-\@tempdimb}}% }% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex index fe1efecbf47..5f7efe5e037 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex @@ -21,11 +21,27 @@ \let\@eattoken= % } +% 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}% +\long\def\@fifthoffive#1#2#3#4#5{#5} + % Loop #1 from min(#2, #3) to max(#2, #3), executing #4 \protected\def\yquant@for #1:=#2to#3#{% \yquant@for@aux#1{#2}{#3}% } +% Loop #1 from max(#2, #3) down to min(#2, #3), executing #4 +\protected\def\yquant@fordown #1:=#2downto#3#{% + \yquant@fordown@aux#1{#2}{#3}% +} + \long\def\yquant@for@aux#1#2#3#4{% \ifnum#2<#3\relax% \numdef#1{#2}% @@ -37,6 +53,17 @@ \fi% } +\long\def\yquant@fordown@aux#1#2#3#4{% + \ifnum#2>#3\relax% + \numdef#1{#2}% + % to allow for things like \yquant@for \i := \i to ..., expand the boundaries + \expandafter\yquant@fordown@loop\expandafter#1\expandafter{\the\numexpr#3-1\relax}{#4}% + \else% + \numdef#1{#3}% + \expandafter\yquant@fordown@loop\expandafter#1\expandafter{\the\numexpr#2-1\relax}{#4}% + \fi% +} + \long\def\yquant@for@loop#1#2#3{% \loop% \ifnum#1<#2\relax% @@ -45,6 +72,14 @@ \repeat% } +\long\def\yquant@fordown@loop#1#2#3{% + \loop% + \ifnum#1>#2\relax% + #3% + \numdef#1{#1-1}% + \repeat% +} + \def\yquant@for@break{% \fi% \iffalse% @@ -219,7 +254,7 @@ \expandafter\iffalse@hidden% \fi% \repeat% - \expandafter + \expandafter% }% \expandafter\count\expandafter2\expandafter=\the\count2\relax% \ifnum\count0<\count2 % @@ -235,15 +270,21 @@ \cslet{yquant@sort@item#2}\tmp% } +% Add an internal etoolbox list to the sorted items +\def\yquant@sort@addlist#1{% + \forlistloop\yquant@sort@addlist@aux#1% +} + +\protected\def\yquant@sort@addlist@aux#1{% + \csdef{yquant@sort@item\the\yquant@sort@count}{#1}% + \advance\yquant@sort@count by 1 % +} + % Sorts an internal etoolbox list #1 using macro #2 \protected\def\yquant@sort@list#1#2{% \begingroup% \yquant@sort@count=0 % - \def\do##1{% - \csdef{yquant@sort@item\the\yquant@sort@count}{##1}% - \advance\yquant@sort@count by 1 % - }% - \dolistloop#1% + \yquant@sort@addlist#1% \yquant@sort#2% \let#1=\empty% \count0=0 % @@ -268,7 +309,278 @@ \expandafter\expandafter\expandafter\do% \expandafter\expandafter\expandafter{% \csname yquant@sort@item\the\count0\endcsname% - } + }% \advance\count0 by 1 % \repeat% +} + +\begingroup +\catcode`\|=3 +\gdef\yquant@list@delim{|} + +\protected\gdef\yquant@list@dequeue#1#2{% + \expandafter\ifblank\expandafter{#1}{% + \let#2=\empty% + }{% + \expandafter\yquant@list@dequeue@i#1\etb@lst@q@end{#1}{#2}\def% + }% +}% + +\protected\gdef\yquant@list@dequeue@i#1|#2\etb@lst@q@end#3#4#5{% + \def#4{#1}% + #5#3{#2}% +} + +\protected\gdef\yquant@list@gdequeue#1#2{% + \expandafter\ifblank\expandafter{#1}{% + \let#2=\empty% + }{% + \expandafter\yquant@list@dequeue@i#1\etb@lst@q@end{#1}{#2}\gdef% + }% +} +\endgroup + +\def\ifyquant@OR#1#2{% + #1% + \expandafter\@firstoftwo% + \else% + #2% + \expandafter\expandafter\expandafter\@firstoftwo% + \else% + \expandafter\expandafter\expandafter\@secondoftwo% + \fi% + \fi% +} + +% #1 is a pgf soft path. We extract the maximum x position at the y position specified in #2 and assign it to \dimen0. +\protected\def\yquant@softpath@extractmaxxat#1#2{% + \begingroup% + \dimen0=-16000pt % + \dimen2=#2 % + \let\pgfsyssoftpath@movetotoken=\yquant@softpath@extractmaxxat@moveto% + \let\pgfsyssoftpath@linetotoken=\yquant@softpath@extractmaxxat@lineto% + \let\pgfsyssoftpath@curvetosupportatoken=\yquant@softpath@extractmaxxat@curveto% + \let\pgfsyssoftpath@rectcornertoken=\yquant@softpath@extractmaxxat@rectto% + \let\pgfsyssoftpath@closepath=\@gobbletwo% + % the specialroundtoken (undocumented) is \@gobbletwo by default. + #1% + \expandafter% + \endgroup% + \expandafter\dimen\expandafter0\expandafter=\the\dimen0 % +} + +\protected\def\yquant@softpath@extractmaxxat@update#1{% + \ifdim\dimen0<#1 % + \dimen0=#1 % + \fi% +} + +\protected\def\yquant@softpath@extractmaxxat@moveto#1#2{% + \dimen4=#1 % + \dimen6=#2 % +} + +\protected\def\yquant@softpath@extractmaxxat@lineto#1#2{% + \ifyquant@OR{\ifdim\dimen4>\dimen0 }{\ifdim#1>\dimen0 }{% + \ifdim\dimen6=\dimen2 % + \yquant@softpath@extractmaxxat@update{\dimen4}% + \else% + \ifdim\dimen6<\dimen2 % + \unless\ifdim#2<\dimen2 % + \expandafter\yquant@softpath@extractmaxxat@update\expandafter{\the\dimexpr% + \dimen4+% x0 + \dimexpr#1-\dimen4\relax*% (x1-x0) + \dimexpr\dimen2-\dimen6\relax/\dimexpr#2-\dimen6\relax% (y-y0)/(y1-y0) + \relax}% + \fi% + \else% + \unless\ifdim#2>\dimen2 % + \expandafter\yquant@softpath@extractmaxxat@update\expandafter{\the\dimexpr% + \dimen4+% x0 + \dimexpr#1-\dimen4\relax*% (x1-x0) + \dimexpr\dimen2-\dimen6\relax/\dimexpr#2-\dimen6\relax% (y-y0)/(y1-y0) + \relax}% + \fi% + \fi% + \fi% + }\relax% + \dimen4=#1 % + \dimen6=#2 % +} + +\protected\def\yquant@softpath@extractmaxxat@curveto@checkx#1#2#3{% + % \dimen11 holds our only candidate for t. Is it within the curve? + \unless\ifdim\dimen11<0pt % + \unless\ifdim\dimen11>1pt % + % it is. \dimen4: x0, #1: xa, #2: xb, #3: x1 + \begingroup% + \dimen12=\dimexpr1pt-\dimen11\relax% 1 - t + \dimen13=\dimexpr\dimen11*\dimen11/65535\relax% t^2 + \dimen14=\dimexpr\dimen12*\dimen12/65535\relax% (1 - t)^2 + \dimen255=\dimexpr\dimen13*\dimen11/65535*\dimexpr#3\relax/65535+% t^3 x1 + 3\dimen13*\dimen12/65535*\dimexpr#2\relax/65535+% t^2(1 - t) xb + \dimen14*\dimen12/65535*\dimen4/65535+% (1 - t)^3 x0 + 3\dimen11*\dimen14/65535*\dimexpr#1\relax/65535% 3t(1 - t)^2 xa + \relax% + \expandafter% + \endgroup% + \expandafter\yquant@softpath@extractmaxxat@update\expandafter{\the\dimen255}% + \fi% + \fi% +} + +\protected\def\yquant@softpath@extractmaxxat@curveto#1#2\pgfsyssoftpath@curvetosupportbtoken#3#4\pgfsyssoftpath@curvetotoken#5#6{% + % There's really no good way to do this apart from solving the Bézier curve (a third-order polynomial). Let's do it. (Yes, this is inefficient, but if someone substitutes the rectangular box of a subcircuit by a more fancy design, this is not our fault). + % Parametrized by t, the x coordinates of the curve are + % x0 + 3 (xa - x0) t + 3 (x0 - 2xa + xb) t^2 + (3xa - 3xb + x1 - x0) t^3 + % where x0 = \dimen4 (the moveto point), xa = #1, xb = #3, x1 = #5. + % Likewise for y: + % y0 = \dimen6 (the moveto point), ya = #2, yb = #4, y1 = #6. + % We first solve the third-order polynomial for t using the y value, then plug it back into the x value. + % TODO: this is accurate to approx. 3 digits. Can this be improved by reformulating Cardanos formula to involve less divisions? + \begingroup% + % We need so may dimensions that we break with TeX's convention for their use. + % for the multiplications with and divisions by dimensions, we exploit that eTeX fuses muldiv to 64 bits. Further note that each dimension has a scaling factor of 65535 for sp<->pt conversion. This is why don't factor out divisions (which would be more efficient, but not give the benefit of 64bit accuracy). + % a = 3(ya - yb) + (y1 - y0) + \dimen1=\dimexpr3\dimexpr#2-#4\relax+#6-\dimen6\relax% + \ifdim\dimen1=0pt % + % this is only a quadratic curve! + % b = 3(y0 - 2ya + yb) + \dimen3=\dimexpr3\dimexpr\dimen6-2\dimexpr#2\relax+#4\relax*65535\relax% + % c: 3(ya - y0) + \dimen5=\dimexpr3\dimexpr#2-\dimen6\relax*65535\relax% + % d: y0 - <desired y> + \dimen7=\dimexpr\dimexpr\dimen6-\dimen2\relax*65535\relax% + % check the discriminant of the equation + \dimen8=\dimexpr\dimen3*\dimen3/65535-4\dimen3*\dimen7/65535\relax% + \unless\ifdim\dimen8<0pt% + % there are two potential candidates, (-c +- sqrt(c^2 - 4b d))/2b + \pgfmathsqrt@{\the\dimen8\@gobbletwo}% + \dimen11=\dimexpr\dimexpr-\dimen5+\pgfmathresult pt\relax*65535/% + \dimexpr2\dimen3\relax\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \dimen11=\dimexpr\dimexpr-\dimen5-\pgfmathresult pt\relax*65535/% + \dimexpr2\dimen3\relax\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \fi% + \else% + % We will simplify by directly dividing all coefficients by a + % b = 3(y0 - 2ya + yb) + \dimen3=\dimexpr3\dimexpr\dimen6-2\dimexpr#2\relax+#4\relax*65535/\dimen1\relax% + % c: 3(ya - y0) + \dimen5=\dimexpr3\dimexpr#2-\dimen6\relax*65535/\dimen1\relax% + % d: y0 - <desired y> + \dimen7=\dimexpr\dimexpr\dimen6-\dimen2\relax*65535/\dimen1\relax% + % Note that now our a value (\dimen1) is no longer needed, it is one. + % check the discriminant of the equation + % Q = (3c - b^2)/9 + \dimen8=\dimexpr\dimexpr3\dimen5-\dimen3*\dimen3/65535\relax/9\relax% + % R = (9bc - 27d - 2b^3)/54 = bc/6 - d/2 - b^3/27 + \dimen9=\dimexpr\dimen3*\dimen5/393210-% 6*65535 + .5\dimen7-% + \dimen3*\dimen3/65535*\dimen3/1769445% 27*65535 + \relax% + % D = Q^3 + R^2 + \dimen10=\dimexpr\dimen8*\dimen8/65535*\dimen8/65535+\dimen9*\dimen9/65535\relax% + \ifdim\dimen10>0pt % + % only one real root: y_1 = S + T - b/3a + % S = cbrt(R + sqrt(Q^3 + R^2)) + % T = cbrt(R - sqrt(Q^3 + R^2)) + \pgfmathsqrt@{\the\dimen10\@gobbletwo}% + \dimen12=\dimexpr\dimen9+\pgfmathresult pt\relax% + \dimen13=\dimexpr\dimen9-\pgfmathresult pt\relax% + \ifdim\dimen12>0pt % + \pgfmathpow@{\the\dimen12\@gobbletwo}{.3333333333}% + \dimen11=\pgfmathresult pt % + \else% + \pgfmathpow@{\the\dimexpr-\dimen12\relax\@gobbletwo}{.3333333333}% + \dimen11=-\pgfmathresult pt % + \fi% + \ifdim\dimen13>0pt % + \pgfmathpow@{\the\dimen13\@gobbletwo}{.3333333333}% + \dimen11=\dimexpr\dimen11+\pgfmathresult pt-.33333333333\dimen3\relax% + \else% + \pgfmathpow@{\the\dimexpr-\dimen13\relax\@gobbletwo}{.3333333333}% + \dimen11=\dimexpr\dimen11-\pgfmathresult pt-.33333333333\dimen3\relax% + \fi% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \else% + \ifdim\dimen10=0pt % + % easiest case, three real roots, two of which are equal: + % y_1 = 2cbrt(R) - b/3a + % y_2, x_3 = -cbrt(R) - b/3a + \ifdim\dimen9>0pt % + \pgfmathpow@{\the\dimen9\@gobbletwo}{.3333333333}% + \dimen15=\pgfmathresult pt % + \else% + \pgfmathpow@{\the\dimexpr-\dimen9\relax\@gobbletwo}{.3333333333}% + \dimen15=-\pgfmathresult pt % + \fi% + \dimen11=\dimexpr2\dimen15-.33333333333\dimen3\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + % check the next candidate + \dimen11=\dimexpr-\dimen15-.33333333333\dimen3\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \else% + % nastiest case, three distinct real roots which we can find only by taking a complex-valued cube root. + % p + i q = cbrt(R + i sqrt(|D|)) + \pgfmathsqrt@{\the\dimexpr-\dimen10\relax\@gobbletwo}% + \dimen10=\pgfmathresult pt % + % Let us first find the absolute value + \dimen12=\dimexpr\dimen9*\dimen9/65535+\dimen10*\dimen10/65535\relax% + \pgfmathpow@{\the\dimen12\@gobbletwo}{.1666666667}% + \dimen12=\pgfmathresult pt% + % then we need 1/3 the argument of R + i sqrt(|D|). + \pgfmathatantwo@{\the\dimen10\@gobbletwo}{\the\dimen9\@gobbletwo}% + \dimen13=.3333333333\dimexpr\pgfmathresult pt\relax% + % and then the real and imaginary parts as cosine and sine. + \pgfmathcos@{\the\dimen13\@gobbletwo}% + \dimen14=\dimexpr\pgfmathresult\dimen12\relax% + \pgfmathsin@{\the\dimen13\@gobbletwo}% + \dimen15=\dimexpr\pgfmathresult\dimen12\relax% + % Now the candidates are + % y_1 = 2p - b/3a + % y_2 = -p - sqrt(3)q - b/3a + % y_3 = -p + sqrt(3)q - b/3a + \dimen11=\dimexpr2\dimen14-.33333333333\dimen3\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \dimen11=\dimexpr-\dimen14-1.732050808\dimen15-.33333333333\dimen3\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \dimen11=\dimexpr-\dimen14+1.732050808\dimen15-.33333333333\dimen3\relax% + \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \fi% + \fi% + \fi% + % Now after all these calculations, \dimen0 was updated within the group. Make available outside. + \expandafter% + \endgroup% + \expandafter\dimen\expandafter0\expandafter=\the\dimen0 % + \dimen4=#5 % + \dimen6=#6 % +} + +\protected\def\yquant@softpath@extractmaxxat@rectto#1#2\pgfsyssoftpath@rectsizetoken#3#4{% + % #1: lower left x, #2: lower left y, #3: width, #4: height + % note that neither width nor height need be positive! + \ifdim#4>0pt % + \unless\ifdim#2>\dimen2 % + \unless\ifdim\dimexpr#2+#4\relax<\dimen2 % + \ifdim#3>0pt % + \yquant@softpath@extractmaxxat@update{\dimexpr#1+#3\relax}% + \else% + \yquant@softpath@extractmaxxat@update{#1}% + \fi% + \fi% + \fi% + \else% + \unless\ifdim#2<\dimen2 % + \unless\ifdim\dimexpr#2+#4\relax>\dimen2 % + \ifdim#3>0pt % + \yquant@softpath@extractmaxxat@update{\dimexpr#1+#3\relax}% + \else% + \yquant@softpath@extractmaxxat@update{#1}% + \fi% + \fi% + \fi% + \fi% }
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant.sty b/Master/texmf-dist/tex/latex/yquant/yquant.sty index c402c6342c4..2395f674624 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant.sty +++ b/Master/texmf-dist/tex/latex/yquant/yquant.sty @@ -11,17 +11,18 @@ % and version 1.3c or later is part of all distributions of LaTeX version 2005/12/01 or % later. % -% This work has the LPPL maintenance status `maintained'. +% This work has the LPPL maintenance status `author-maintained'. % % The Current Maintainer of this work is Benjamin Desef. \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{yquant}[2020/04/11 v0.1.2 Yet another quantum circuit library for LaTeX] +\ProvidesPackage{yquant}[2020/06/13 v0.3 Yet another quantum circuit library for LaTeX] \RequirePackage{etoolbox}[2018/02/11] \RequirePackage{tikz}[2015/08/29] \RequirePackage{trimspaces}[2009/09/17] \usetikzlibrary{arrows.meta,decorations.pathreplacing,decorations.pathmorphing} +\newif\ifyquantdebug \input yquant-config.tex \input yquant-tools.tex \input yquant-registers.tex @@ -35,6 +36,10 @@ % usually, \\ is robust; but when using \centering, it is \let to \@centercr, which is not robust (probably because this happens only when not protecting). Fix this, so that \\ does not require \protect if a centered circuit is drawn. \robustify\@centercr +\outer\def\useyquantlanguage#1{% + \RequirePackage{yquantlanguage-#1} +} + \endinput %% %% End of file `yquant.sty'.
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty new file mode 100644 index 00000000000..eaa848e03f2 --- /dev/null +++ b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty @@ -0,0 +1,681 @@ +% yquantlanguage-qasm.sty +% Extend yquant to understand qasm syntax. +% +% Copyright 2020 Benjamin Desef +% +% This work may be distributed and/or modified under the conditions of the LaTeX Project +% Public License, either version 1.3c of this license or (at your option) any later +% version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX version 2005/12/01 or +% later. +% +% This work has the LPPL maintenance status `author-maintained'. +% +% The Current Maintainer of this work is Benjamin Desef. +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{yquantlanguage-qasm}[2020/06/13 v0.3 yquant-qasm] + +\RequirePackage{yquant}[2020/06/13] + +% BEGIN_FOLD Environment definitions +\begingroup + \catcode`\{=12 \global\let\qasm@env@charbgroup={ + \catcode`\#=12 \global\let\qasm@env@charhashtag=# +\endgroup +{\catcode`\^^M=12 \protected\gdef\qasm@defwithnewline#1#{\def#1^^M}} +{\catcode`\|=0 \catcode`\\=12 |global|let|qasm@env@charbackslash=\ |gdef|qasm@env@charend{\endqasm}} +\protected\def\qasm@env@begin{% + \begingroup% + \qasm@env@setcatcodes% + \@ifnextchar[\qasm@env@begin@arg{\qasm@env@begin@arg[]}% +} + +\protected\def\qasm@env@setcatcodes{% + % make most TeX specials ordinary - not \dospecials, we want to keep spaces + \catcode`\\=12 % + \catcode`\{=12 % + \catcode`\}=12 % + \catcode`\$=12 % + \catcode`\&=12 % + \catcode`\#=12 % + \catcode`\^=12 \catcode`\^^K=12 % + \catcode`\_=12 \catcode`\^^A=12 % + \catcode`\%=12 % + \catcode`\~=12 % + \catcode`\^^M=12 % +} + +\def\qasm@env@begin@arg{% + \yquant@env@lazyfalse% + \let\yquant@env@check=\qasm@env@check% + \let\yquant@register@get@ids=\qasm@register@get@ids% + \let\yquant@attrs@remaining=\empty% we don't have attributes, but the backend requires this to be set up + \let\tikz@ensure@dollar@catcode=\relax% this check will fail, but it does not make sense in our case. Every tikz command will be read with the appropriate dollar catcode. + % provide some commands that might be used during gate construction + \let\m=\qasm@cmd@m% + \let\txt=\qasm@cmd@txt% + \let\meter=\qasm@cmd@meter% + \let\dmeter=\qasm@cmd@dmeter% + \let\dmeterwide=\qasm@cmd@dmeterwide% + \yquant@env@begin@generic\qasm% +} + +\def\qasm@env@end{% + \yquant@env@end% + \endgroup% +} + +% since the backslash is just an `other' character, we cannot leave our environment. Hence, we manually check for \endqasm and \end{qasm}. +\def\qasm@env@checkend#1#2#3#4#5{% + \ifstrequal{#1#2#3#4 }{\end}{% for us, \end is a macro so that TeX will insert another space + \ifx q#5% + \expandafter\qasm@env@checkend@plain% + \else% + \ifx\qasm@env@charbgroup#5% + \expandafter\expandafter\expandafter\qasm@env@checkend@latex% + \else% + \PackageError{yquant.sty}% + {Invalid qasm syntax: `\meaning#1'}% + {Adhere to the specs!}% + \fi% + \fi% + }{% + \PackageError{yquant.sty}% + {Invalid qasm syntax: `\meaning#1'}% + {Adhere to the specs!}% + }% +} + +\def\qasm@env@checkend@plain#1#2#3{% + \ifstrequal{#1#2#3}{asm}{% + \endgroup% we initially thought this was a normal command, so exit the group + \endqasm% + \futurelet\qasm@env@checkend@plain@delimiter\qasm@env@checkend@plain@validate% + }{% + \PackageError{yquant.sty}% + {Invalid qasm syntax: `\meaning\qasm@env@charbackslash'}% + {Adhere to the specs!}% + }% +} + +\def\qasm@env@checkend@plain@validate{% + % we already ended the qasm environment, based on the assumption that what followed was not a letter + \ifcat\qasm@env@checkend@plain@delimiter A% + % we were wrong and should never have left the environment. Now it's too late + \PackageError{yquant.sty}% + {Invalid qasm syntax: `\meaning\qasm@env@charbackslash'}% + {Adhere to the specs!}% + \fi% +} + +\begingroup + \catcode`\[=1 \catcode`\]=2 \catcode`\}=12 % we set [ just for editors that scan for matching parenthesis, though we don't need it + \gdef\qasm@env@checkend@latex#1#2#3#4#5[% + \ifstrequal[#1#2#3#4#5][qasm}][% + \endgroup% we initially thought this was a normal command, so exit the group + \end[qasm]% + ][% + \PackageError[yquant.sty]% + [Invalid qasm syntax: `\meaning\qasm@env@charbackslash']% + [Adhere to the specs!]% + ]% + ]% +\endgroup + +\protected\def\qasm@env@restorecatcodes{% + % restore standard catcodes (hopefully they were standard before entering the environment) + \catcode`\\=0 % backslash is TeX escape character + \catcode`\{=1 % left brace is begin-group character + \catcode`\}=2 % right brace is end-group character + \catcode`\$=3 % dollar sign is math shift + \catcode`\&=4 % ampersand is alignment tab + \catcode`\#=6 % hash mark is macro parameter character + \catcode`\^=7 \catcode`\^^K=7 % circumflex and uparrow are for superscripts + \catcode`\_=8 \catcode`\^^A=8 % underline and downarrow are for subscripts + \catcode`\%=14 % percent sign is comment character + \catcode`\~=\active % tilde is active +% \catcode`\^^M=5 % ascii return is end-line - not needed, is done manually +} + +\tikzaddtikzonlycommandshortcutlet\qasm\qasm@env@begin +\tikzaddtikzonlycommandshortcutlet\endqasm\qasm@env@end + +\protected\def\qasm@env@check{% + \let\next=\relax% + \ifx\yquant@env@nextchar\qasm@env@charhashtag% comment + \let\next=\qasm@env@gobblecomment% + \else% + % Here we assume standard catcodes for A + \ifcat\noexpand\yquant@env@nextchar A% letter + \let\next=\qasm@langhelper@check@name% + \else% + \ifx\yquant@env@nextchar\yquant@env@linebreak% linebreaks are no longer end-of-line characters, but have catcode 12 (other). + \let\next=\yquant@env@gobblepar% + \else% + \ifx\yquant@env@nextchar\par% + \let\next=\yquant@env@gobblepar% + \else% + \ifx\yquant@env@nextchar\qasm@env@charbackslash% backslash might end the environment + \let\next=\qasm@env@checkend% + \else% + \PackageError{yquant.sty}% + {Invalid qasm syntax: `\meaning\yquant@env@nextchar'}% + {Adhere to the specs!}% + \fi% + \fi% + \fi% + \fi% + \fi% + \next% +} + +\qasm@defwithnewline\qasm@env@gobblecomment#1{% + \yquant@env@contscan% +} + +\def\qasmimport#1{% + \ifpgfpicture% + \ifnum\yquant@env>0 % + \PackageError{yquant.sty}{You cannot use qasm circuits as subcircuits}{}% + \else% + \begingroup% + \let\yquantimport@now=\qasmimport@now% + \everyeof{\noexpand}% + \qasm@env@setcatcodes% + \yquantimportcommand{#1}% + \expandafter\expandafter\expandafter\qasm% + \expandafter\qasmimport@file% + \qasm@env@charend% + \endgroup% + \fi% + \else% + \begin{tikzpicture}% + \begingroup% + \let\yquantimport@now=\qasmimport@now% + \everyeof{\noexpand}% + \qasm@env@setcatcodes% + \yquantimportcommand{#1}% + \expandafter\expandafter\expandafter\qasm% + \expandafter\qasmimport@file% + \qasm@env@charend% + \endgroup% + \end{tikzpicture} + \fi% +} + +\def\qasmimport@now#1{% + \edef\qasmimport@file{\@@input #1 }% +} +% END_FOLD + +% BEGIN_FOLD Langhelper definitions +% Parsing command itself +\protected\qasm@defwithnewline\qasm@langhelper@check@name#1 #2{% + \lowercase{\edef\cmd{#1}}% + \unless\ifcsname qasm@lang@\cmd\endcsname% + \PackageError{yquant.sty}{Unsupported qasm command: `#1'}% + {You used a command that is unknown to qasm.}% + \fi% + \catcode`\^^M=5 % this catcode is required for scantokens, which we almost always need (because we use yquant's extensive register name facilities) + \csname qasm@lang@\cmd\endcsname#2 \qasm@end% +} + +% Defining commands that accept registers and take an optional value +% #1: name of the argument +% #2: command that is to be called +% #3: number of controls +% #4: number of targets +\protected\def\qasm@langhelper@declare@command#1#2#3#4{% + \begingroup% + \lowercase{\edef\cmd{#1}}% + % everything after the next space is just gobbled + \protected\long\csgdef{qasm@lang@\cmd}##1 ##2\qasm@end{% + \qasm@langhelper@declare@command@@fetchargs{#3}{#4}{##1}{#2}% + \yquant@env@rescan% + }% + \endgroup% +} + +\protected\def\qasm@langhelper@declare@command@@fetchargs#1#2#3#4{% + \let\targets=\empty% + \let\controls=\empty% + \count0=0 % + \count2=#1 % + \forcsvlist% + \qasm@langhelper@declare@command@@fetchargs@% + {#3}% + \unless\ifnum\count0=\numexpr\count2+#2\relax % + \PackageError{yquant.sty}{Invalid command use}% + {This gate requires #2 target\unless\ifnum#2=1 s\fi\space and #1 control\unless\ifnum#1=1 s\fi.}% + \fi% + \edef\cmd{% + \unexpanded{#4}% + {\expandafter\@gobble\controls\empty}{}% + {\expandafter\@gobble\targets\empty}% + }% + \cmd% +} + +\protected\def\qasm@langhelper@declare@command@@fetchargs@#1{% + \advance\count0 by 1 % + \unless\ifnum\count0>\count2 % + % we are at the beginning + \appto\controls{,#1}% + \else% + \appto\targets{,#1}% + \fi% +} + +% converts names to indices +\protected\def\qasm@register@get@ids#1{% + \begingroup% + \let\yquant@register@get@ids@list=\empty% + \count0=2147483647 % minimal id + \count2=0 % maximal id + \count4=0 % number of total registers + \forcsvlist\qasm@register@get@ids@outerlist{#1}% + \global\let\yquant@register@get@ids@list=\yquant@register@get@ids@list% + \xdef\yquant@register@get@ids@min{\the\count0}% + \xdef\yquant@register@get@ids@max{\the\count2}% + \xdef\yquant@register@get@ids@count{\the\count4}% + % this is very simple: if multi-registers are allowed and we have more than one, then we are in a multi-register; else not. + \ifyquant@register@get@allowmulti% + \ifnum\count4> 1% + \count6=\count0 % no way to chain the main register + \yquant@register@multi@splitparts% + \xdef\yquant@register@get@ids@list{% + \noexpand\yquant@register@multi% + {\the\count0}{\the\count2}{\the\count4}{\yquant@register@get@ids@list}% + \yquant@list@delim% + }% + \count4=1 % + \fi% + \fi% + \endgroup% +} + +\protected\def\qasm@register@get@ids@outerlist#1{% + \yquant@register@get@id\idx{#1[0]}% + \listeadd\yquant@register@get@ids@list{\idx}% + \ifnum\count0>\idx % + \count0=\idx % + \fi% + \ifnum\count2<\idx % + \count2=\idx % + \fi% + \advance\count4 by 1 % +} +% END_FOLD + +% BEGIN_FOLD Configuration +\pgfkeys{% + /yquant/operators/every s/.style={% + /yquant/operators/every box% + },% + /yquant/operators/every t/.style={% + /yquant/operators/every box% + },% + /yquant/operators/every utwo/.style={% + /yquant/operators/every box% + }, + /qasm/zero/.store in=% + \qasm@config@zero,% + /qasm/register/default qubit name/.store in=% + \qasm@config@qubit@nameonly,% + /qasm/register/default qubit name value/.store in=% + \qasm@config@qubit@namevalue% +} +\def\qasm@ket#1{\mathopen|\mathinner{#1}\rangle} +\def\qasm@config@zero{$\qasm@ket0$} +\let\qasm@config@qubit@nameonly=\qasm@ket +\def\qasm@config@qubit@namevalue#1#2{\qasm@ket{#1} = \qasm@ket{#2}} +% END_FOLD + +% BEGIN_FOLD Automagically convert names +% if ([A-z]+)(\d+) matches, replace by $1_{$2}, else let unchanged, fully expandable +\def\qasmname#1{% + \expandafter\qasmname@entry\expandafter{#1}% +} + +\def\qasmname@entry#1{% + \ifstrempty{#1}{}{% + \qasmname@checkletter#1\relax\qasmname@end{}% + }% +} + +\def\qasmname@checkletter#1#2\qasmname@end#3{% + \ifstrempty{#2}{% + % done, and we didn't get a number, so regex doesn't match (#1 is \relax) + #3% + }{% + \ifnum`#1>64 % + \ifnum`#1<123 % + \expandafter\expandafter\expandafter\@firstoftwo% + \else% + \expandafter\expandafter\expandafter\@secondoftwo% + \fi% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \qasmname@checkletter#2\qasmname@end{#3#1}% + }{% + % not in A-z, move to the number part - but only if there was something matching before! + \ifstrempty{#3}{% + \qasmname@droprelax#1#2\qasmname@end% + }{% + \qasmname@checknumber#1#2\qasmname@end{#3}{}% + }% + }% + }% +} + +\def\qasmname@checknumber#1#2\qasmname@end#3#4{% + \ifstrempty{#2}{% + % done - was there a number? + \ifstrempty{#4}{% + #3% + }{% + #3_{#4}% + }% + }{% + \ifnum`#1>47 % + \ifnum`#1<58 % + \expandafter\expandafter\expandafter\@firstoftwo% + \else% + \expandafter\expandafter\expandafter\@secondoftwo% + \fi% + \else% + \expandafter\@secondoftwo% + \fi% + {% + \qasmname@checknumber#2\qasmname@end{#3}{#4#1}% + }{% + \qasmname@droprelax#3#4#1#2\qasmname@end% + }% + }% +} + +\def\qasmname@droprelax#1\relax#2\qasmname@end{% + \ifstrempty{#2}{% + #1% + }{% + \qasmname@droprelax{#1\relax}#2\qasmname@end% + }% +} +% END_FOLD + +% BEGIN_FOLD Language definitions +\protected\def\qasm@lang@qubit#1 #2\qasm@end{% + \let\yquant@lang@create@type=\yquant@register@type@q% + \def\yquant@lang@create@style{qubit}% + \qasm@lang@create#1,,,,\qasm@end% +} + +\protected\def\qasm@lang@cbit#1 #2\qasm@end{% + \let\yquant@lang@create@type=\yquant@register@type@c% + \def\yquant@lang@create@style{cbit}% + \qasm@lang@create#1,,,,\qasm@end% +} + +\protected\def\qasm@lang@create#1,#2,#3,#4,#5\qasm@end{% + \ifstrempty{#4}\relax{% + \PackageError{yquant.sty}{Invalid number of arguments}% + {Register creation in qasm expects at most three arguments.}% + }% + \ifstrequal{#5}{,,}{% + % we have a third parameter which defines the TeX name - retokenize it + \begingroup% + \qasm@env@restorecatcodes% + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\process{% + \def\noexpand\yquant@lang@attr@value{% + \scantokens{\unexpanded{#3}}% + }% + } + \expandafter% + \endgroup% + \process% + }{% + % make num subscript if name = alpha+numbers + \edef\yquant@lang@attr@value{\qasmname{#1}}% + }% + \ifx\yquant@lang@create@type\yquant@register@type@c% + \ifstrempty{#2}{% cbit has initial value? + \edef\yquant@lang@attr@value{% + $\unexpanded\expandafter{\yquant@lang@attr@value}$% + }% + }{% + \begingroup% + \qasm@env@restorecatcodes% + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\process{% + \def\noexpand\yquant@lang@attr@value{% + $\unexpanded\expandafter{\yquant@lang@attr@value} = % + \scantokens{\unexpanded{#2}}$% + }% + } + \expandafter% + \endgroup% + \process% + }% + \else% + \ifstrempty{#2}{% qubit has initial value? + \edef\yquant@lang@attr@value{% + \unexpanded\expandafter{\expandafter$% + \expandafter\qasm@config@qubit@nameonly% + \expandafter{\yquant@lang@attr@value}% + $}% + }% + }{% + \begingroup% + \qasm@env@restorecatcodes% + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\process{% + \def\noexpand\yquant@lang@attr@value{% + $\noexpand\qasm@config@qubit@namevalue% + {\unexpanded\expandafter{\yquant@lang@attr@value}}% + {\scantokens{\unexpanded{#2}}}$% + }% + } + \expandafter% + \endgroup% + \process% + }% + \fi% + \yquant@lang@create@do{#1}[1][;% + \yquant@env@rescan% +} + +\protected\def\qasm@lang@def#1,#2,'#3' #4\qasm@end{% + \lowercase{\def\cmd{#1}}% + % we need to do a couple of case distictions (it might seem crazy to look for the existence of a particular macro in #3, but this is what qasm does) + \ifstrequal{#3}{bullet}{% + \edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% + \let\noexpand\yquant@lang@attr@value=\noexpand\empty% + \noexpand\yquant@lang@@phase% + }% + }% + }{% + % re-tokenize the code + \begingroup% + \qasm@env@restorecatcodes% + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\process{% + \def\noexpand\texcode{% + \scantokens{\unexpanded{#3}}% + }% + }% + \expandafter% + \endgroup% + \process% + % now check whether the text begins with \meter, \dmeter or \dmeterwide. This is not 100% equivalent to qasm, which only checks whether these macros are present, not whether they are at the beginning. But due to our node approach, anything different from the whole content being this macro does not make sense. + \expandafter\ifyquant@firsttoken\expandafter\meter\expandafter{\texcode}{% + \edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname####1####2{% + \noexpand\yquant@lang@@measure% + }% + }% + }{% + \expandafter\ifyquant@firsttoken\expandafter\dmeter\expandafter{\texcode}{% + \protected@edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname####1####2{% + \def\noexpand\yquant@lang@attr@value{\texcode}% + \noexpand\yquant@lang@@dmeter% + }% + }% + }{% + \expandafter\ifyquant@firsttoken\expandafter\dmeterwide\expandafter{\texcode}{% + \protected@edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname####1####2{% + \def\noexpand\yquant@lang@attr@value{\texcode}% + \noexpand\yquant@lang@@dmeter% + }% + }% + }{% + \edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% + \yquant@draw% + {$\unexpanded\expandafter{\texcode}$}% + {/yquant/operators/every box}% + }% + }% + }% + }% + }% + }% + \eappto\process{% + % we don't use \qasm@langhelper@declare@command here, since it works globally + \protected\long\def\expandafter\noexpand\csname qasm@lang@\cmd\endcsname####1 ####2\noexpand\qasm@end{% + \qasm@langhelper@declare@command@@fetchargs{#2}1{####1}\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname% + \noexpand\yquant@env@rescan% + }% + }% + \expandafter% + \endgroup% + \process% + \yquant@env@scan% +} + +\protected\def\qasm@lang@defbox#1,#2,#3,'#4' #5\qasm@end{% + \ifnum#2<#3 % + \PackageError{yquant.sty}{Invalid box definition}% + {You need at least as many total qubits as controls.}% + \fi% + \lowercase{\def\cmd{#1}}% + % no special cases here + \begingroup% + \qasm@env@restorecatcodes% + \everyeof{\noexpand}% + \endlinechar=-1 % + \edef\process{% + \def\noexpand\texcode{% + \scantokens{\unexpanded{#4}}% + }% + }% + \expandafter% + \endgroup% + \process% + \edef\process{% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% + \noexpand\yquant@register@get@allowmultitrue% + \yquant@draw% + {$\unexpanded\expandafter{\texcode}$}% + {/yquant/operators/every box}% + }% + % we don't use \qasm@langhelper@declare@command here, since it works globally + \protected\long\def\expandafter\noexpand\csname qasm@lang@\cmd\endcsname####1 ####2\noexpand\qasm@end{% + \qasm@langhelper@declare@command@@fetchargs{#3}{\the\numexpr#2-#3\relax}{####1}\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname% + \noexpand\yquant@env@rescan% + }% + }% + \expandafter% + \endgroup% + \process% + \yquant@env@scan% +} + +\qasm@langhelper@declare@command{measure}{\expandafter\yquant@lang@@measure\@gobbletwo}01 + +\qasm@langhelper@declare@command{H}\yquant@lang@@h01 + +\qasm@langhelper@declare@command{X}\yquant@lang@@x01 + +\qasm@langhelper@declare@command{Y}\yquant@lang@@y01 + +\qasm@langhelper@declare@command{Z}\yquant@lang@@z01 + +\qasm@langhelper@declare@command{S}\qasm@lang@@s01 +\def\qasm@lang@@s{% + \yquant@draw% + {$S$}% + {/yquant/operators/every s}% +} + +\qasm@langhelper@declare@command{T}\qasm@lang@@t01 +\def\qasm@lang@@t{% + \yquant@draw% + {$T$}% + {/yquant/operators/every t}% +} + +\qasm@langhelper@declare@command{nop}\qasm@lang@@nop01 +\def\qasm@lang@@nop#1#2#3{% + \dimdef\yquant@lang@attr@value{\yquant@config@operator@minimum@width+\yquant@config@operator@sep}% + \yquant@lang@@hspace{#3}% + % we don't use a grid-based layout, so a nop really does nothing +} + +\qasm@langhelper@declare@command{zero}\qasm@lang@@zero01 +\def\qasm@lang@@zero#1#2#3{% + \let\yquant@lang@attr@value=\qasm@config@zero% + \yquant@lang@@init{#3}% +} + +\qasm@langhelper@declare@command{discard}{\expandafter\yquant@lang@@discard\@gobbletwo}01 + +\qasm@langhelper@declare@command{slash}{\expandafter\yquant@lang@@slash\@gobbletwo}01 + +\qasm@langhelper@declare@command{dmeter}{\expandafter\yquant@lang@@dmeter\@gobbletwo}01 + +\qasm@langhelper@declare@command{cnot}\yquant@lang@@not11 + +\qasm@langhelper@declare@command{c-z}\yquant@lang@@z11 + +\qasm@langhelper@declare@command{c-x}\yquant@lang@@x11 + +\qasm@langhelper@declare@command{toffoli}\yquant@lang@@not21 + +\qasm@langhelper@declare@command{ZZ}{\expandafter\yquant@lang@@zz\@gobbletwo}02 + +\qasm@langhelper@declare@command{XX}\yquant@lang@@xx02 + +\qasm@langhelper@declare@command{swap}\yquant@lang@@swap02 + +\qasm@langhelper@declare@command{Utwo}\qasm@lang@@Utwo02 +\def\qasm@lang@@Utwo{% + \yquant@register@get@allowmultitrue% + \yquant@draw% + {$U$}% + {/yquant/operators/every utwo}% +} + +% space is a hspace _without_ wire - in priciple, we would have to discard and then re-initialize +\qasm@langhelper@declare@command{space}\qasm@lang@@nop01 +% END_FOLD + +% some commands that might be used in boxes +\def\qasm@cmd@m#1{\begin{pmatrix}#1\end{pmatrix}} +\def\qasm@cmd@txt#1{$#1$}% do not use \text{...}, but exit math mode - in this way, TikZ can still handle linebreak +\def\qasm@cmd@meter{}% +\def\qasm@cmd@dmeterwide#1#2{$#1$}% +\def\qasm@cmd@dmeter#1{$#1$}% + +\endinput
\ No newline at end of file |