diff options
author | Norbert Preining <preining@logic.at> | 2021-04-03 23:54:49 +0000 |
---|---|---|
committer | Norbert Preining <preining@logic.at> | 2021-04-03 23:54:49 +0000 |
commit | 32f9a397a899dfac82a4f4d80670f48b675da246 (patch) | |
tree | 4d4429493606d826f06de7ae1401bf3a3b667bcc /Master/texmf-dist/tex/latex | |
parent | 8687c318c8de471be301f160ad143242f1a88e68 (diff) |
yquant (4apr21)
git-svn-id: svn://tug.org/texlive/trunk@58712 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex')
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex | 248 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-config.tex | 395 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-draw.tex | 1016 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-env.tex | 449 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-lang.tex | 859 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex | 89 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex | 883 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-registers.tex | 356 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex | 356 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-tools.tex | 100 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant.sty | 19 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty | 151 |
12 files changed, 3189 insertions, 1732 deletions
diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex b/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex index 2c9e114bdc5..52cb435b2f0 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-circuit.tex @@ -8,35 +8,45 @@ \pgfpointanchor{yquantbox}{#2}% \edef\wirexpos{\the\pgf@x}% \fi% - \yquant@register@get@typeywire{#1}\wiretype\wireypos\wirelast% - \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}% - \ifnum\wiretype=\yquant@register@type@none% - % the clippings of the previous operator will for sure not be needed, but the type might be turned into an active one, so we need the last clipping. - \yquant@register@set@lastwire{#1}{% - {\wirexprevpos}{\wirexpos}{}% - {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% - }% - \else% - % append the previous `last' clipping to the old list and insert the new one - \yquant@register@set@lastwire{#1}{% - {\wirexprevpos}{\wirexpos}% - {\unexpanded\expandafter\expandafter\expandafter{% - \expandafter\@thirdandfourthoffour\wirelast% - }% + \ifdim\wirexpos>0pt % may be negative for init gates + \yquant@register@get@typeywire{#1}\wiretype\wireypos\wirelast% + \edef\wirexprevpos{\expandafter\@firstoffour\wirelast}% + \ifnum\wiretype=\yquant@register@type@none% + % the clippings of the previous operator will for sure not be needed, but the type might be turned into an active one, so we need the last clipping. + \yquant@register@set@lastwire{#1}{% + {\wirexprevpos}{\wirexpos}{}% + {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% }% - {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% - }% + \else% + % append the previous `last' clipping to the old list and insert the new one + \yquant@register@set@lastwire{#1}{% + {\wirexprevpos}{\wirexpos}% + {\unexpanded\expandafter\expandafter\expandafter{% + \expandafter\@thirdandfourthoffour\wirelast% + }% + }% + {\unexpanded\expandafter{\pgfshapeclippathhorzresult}}% + }% + \fi% \fi% \endgroup% } -% finishes the wires of all registers until x position #1 -\protected\def\yquant@circuit@endwires#1{% - \ifcsname\yquant@prefix xshift\endcsname% - \dimdef\yquant@env@end@xpos{#1+\csname\yquant@prefix xshift\endcsname}% - \else% - \def\yquant@env@end@xpos{#1}% - \fi% +% finishes the wires of all registers +\protected\def\yquant@circuit@endwires{% + \expandafter\expandafter\expandafter\yquant@register@get@maxxrange% + \expandafter\expandafter\expandafter\yquant@circuit@endwires@x% + \expandafter\expandafter\expandafter1% + \expandafter\expandafter\expandafter{\csname\yquant@prefix registers\endcsname}% + % to have a symmetric situation, we extend again one separation at the end, unless this is supposed to be seamless and we don't have outputs (for seamless circuits with outputs, extend - since this extension will be between last register and output) + \ifyquant@env@seamless{% + \expandafter\unless\expandafter\ifx\csname\yquant@prefix outputs\endcsname\relax% + \dimdef\yquant@circuit@endwires@x{\yquant@circuit@endwires@x+\yquant@config@operator@sep}% + \fi% + }{% + \dimdef\yquant@circuit@endwires@x{\yquant@circuit@endwires@x+\yquant@config@operator@sep}% + }% + \let\yquant@circuit@endwires@finalize=\relax% \yquant@for \yquant@circuit@endwires@i := 1 to \csname\yquant@prefix registers\endcsname {% % we only extend the wire if it does not come from the outer circuit - this one would be responsible for the extension. \ifcsname\yquant@prefix registermap@\yquant@circuit@endwires@i\endcsname% @@ -45,7 +55,10 @@ \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% + \eappto\yquant@circuit@endwires@finalize{% + \yquant@register@set@type% + \yquant@circuit@endwires@i\noexpand\yquant@register@type@none% + }% }\relax% \else% \yquant@draw@wire\yquant@circuit@endwires@i1% @@ -55,14 +68,7 @@ % outputs the wire according to its previous instructions and prepares for a change in the wire style \protected\def\yquant@circuit@flushwire#1{% - \ifcsname\yquant@prefix registermap@#1\endcsname% - % make sure drawing the wire does not affect our left bounding box position - \edef\storedleft{\the\pgf@picminx}% - \yquant@draw@wire{#1}0% - \global\pgf@picminx=\storedleft% - \else% - \yquant@draw@wire{#1}0% - \fi% + \yquant@draw@wire{#1}0% \begingroup% \yquant@register@get@lastwire{#1}\wirelast% \yquant@register@set@lastwire{#1}{% @@ -78,13 +84,13 @@ % BEGIN_FOLD Drawing control lines % populates a drawing macro with the current control line with style #1 at position #2. Assumes a node called yquantbox is set up, and the \pgfshapeclippathvertresult was set up appropriately for this node. At the first call, \yquant@circuit@extendcontrolline@cmd must be \let to \empty and \yquant@circuit@extendcontrolline@prev to \relax. \protected\def\yquant@circuit@extendcontrolline#1#2{% + \eappto\yquant@circuit@extendcontrolline@clip{% + \unexpanded\expandafter{\pgfshapeclippathvertresult}% + }% \begingroup% \tikzset{/yquant/every control line}% \expandafter% \endgroup% - \eappto\yquant@circuit@extendcontrolline@clip{% - \unexpanded\expandafter{\pgfshapeclippathvertresult}% - }% \expandafter\@tempdima\the\pgflinewidth% \ifcase#1% % no control (or to a discarded target, which we don't do) @@ -207,17 +213,35 @@ \yquant@circuit@operator@maxpctrl% \yquant@circuit@operator@maxnctrl% \relax% - % obtain the required minimal x position - \yquant@register@get@maxxrange% - \yquant@circuit@operator@x% - \yquant@circuit@operator@minctrl% - \yquant@circuit@operator@maxctrl% - \dimdef\yquant@circuit@operator@x{% - \yquant@circuit@operator@x+\yquant@config@operator@sep% - }% +} + +% restores the data captured for an uncontrolled operator and starts preparation +% #1: \yquant@attrs@remaining +% #2: \yquant@circuit@operator@targets +% #3: \yquant@circuit@operator@mintarget +% #4: \yquant@circuit@operator@maxtarget +% #5: \yquant@circuit@operator@numtarget +\protected\def\yquant@circuit@restore#1#2#3#4#5{% + \def\yquant@attrs@remaining{#1}% + \def\yquant@circuit@operator@targets{#2}% + \def\yquant@circuit@operator@mintarget{#3}% + \def\yquant@circuit@operator@maxtarget{#4}% + \def\yquant@circuit@operator@numtarget{#5}% + \yquant@circuit@operator@hasControlsfalse% + \let\yquant@circuit@operator@pctrls=\empty% + \def\yquant@circuit@operator@minpctrl{2147483647}% + \def\yquant@circuit@operator@maxpctrl{0}% + \let\yquant@circuit@operator@numpctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@nctrls=\empty% + \let\yquant@circuit@operator@minnctrl=\yquant@circuit@operator@minpctrl% + \let\yquant@circuit@operator@maxnctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@numnctrl=\yquant@circuit@operator@numpctrl% + \let\yquant@circuit@operator@minctrl=\yquant@circuit@operator@mintarget% + \let\yquant@circuit@operator@maxctrl=\yquant@circuit@operator@maxtarget% } % creates a subcircuit. Parameter registers must be filled in \yquant@circuit@subcircuit@params. +% #1: style \protected\def\yquant@circuit@subcircuit#1{% \numdef\yquant@circuit@subcircuit@id{\yquant@env+1}% \listcsxadd{\yquant@prefix subcircuits}{\yquant@circuit@subcircuit@id}% @@ -232,46 +256,6 @@ \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% } @@ -279,7 +263,13 @@ % BEGIN_FOLD Helpers for operator callbacks % turn a wire into a different type \def\yquant@circuit@settype#1{% - \yquant@circuit@flushwire{#1}% + \unless\if\yquant@register@get@type{#1}\yquant@circuit@settype@to % + \yquant@circuit@flushwire{#1}% + \yquant@register@set@type{#1}{\yquant@circuit@settype@to}% + \fi% +} + +\protected\def\yquant@circuit@settype@prepare#1{% \yquant@register@set@type{#1}{\yquant@circuit@settype@to}% } @@ -296,95 +286,51 @@ % performs an alignment of all registers specified in the argument; that is, the next operation on any of the listed registers will be after the maximum position of all of them % #1: arbitrary register list \protected\def\yquant@circuit@align#1{% - \begingroup% - \yquant@register@get@maxxlist\x{#1}% - \def\do##1{% - \yquant@register@set@x{##1}\x% - }% - \dolistloop{#1}% - \endgroup% + \csxappto{\yquant@prefix draw}{% + \yquant@draw@hspace{#1}{0pt}% + }% } % introduces a horizontal skip (= invisible operator of given width) among the registers; that is, those registers are first aligned, then skipped by the given amount. % #1: arbitrary register list % #2: skip width \protected\def\yquant@circuit@hspace#1#2{% - \begingroup% - \yquant@register@get@maxxlist\x{#1}% - \dimdef\x{\x+#2}% - \def\do##1{% - \yquant@register@set@x{##1}\x% - }% - \dolistloop{#1}% - \endgroup% + \csxappto{\yquant@prefix draw}{% + \yquant@draw@hspace{#1}{#2}% + }% } % applies an action to wires a list of registers and causes them to be redrawn -% #1: action -% #2: arbitrary register list -% #3: parameter(s) -\protected\def\yquant@circuit@actonwires#1#2#3{% +% #1: action for prepare +% #2: action for draw +% #3: arbitrary register list +% #4: parameter(s) +\protected\def\yquant@circuit@actonwires#1#2#3#4{% \begingroup% \let\tmp=\empty% \def\do##1{% % We do not extend the wire: a register that is discarded somewhere does not make % sense, only right after some application (which is supposed to already have % extended the wire appropriately). - \appto\tmp{#1{##1}#3}% + \eappto\tmp{#2{##1}#4}% + #1{##1}#4% }% - \dolistloop{#2}% + \dolistloop{#3}% \csxappto{\yquant@prefix draw}{\tmp}% \endgroup% } % sets the output of wires % #1: arbitrary register list -\protected\def\yquant@circuit@output#1{% - \csxappto{\yquant@prefix outputs}% - {\noexpand\yquant@circuit@output@do% - {\noexpand#1}% there is nothing to expand - except the first token, which might be \yquant@register@multi, and we need to preserve this. +\protected\def\yquant@circuit@output{% + \protected\def\idx{}% + \protected@csxappto{\yquant@prefix outputs}% + {\yquant@circuit@restore% {\yquant@attrs@remaining}% - {\unexpanded\expandafter{\yquant@lang@attr@value}}% + {\unexpanded\expandafter{\yquant@circuit@operator@targets}}% + {\yquant@circuit@operator@mintarget}{\yquant@circuit@operator@maxtarget}% + {\yquant@circuit@operator@numtarget}% + \yquant@prepare{\yquant@lang@attr@value}{}% }% } - -\protected\long\def\yquant@circuit@output@do#1#2#3{% - % this must only be called at the end of an environment, where \yquant@env@end@xpos is set up properly! It not only has to provide the appropriate drawing commands for later, but also has to measure the actual width of the outputs, which is required for proper subcircuit positioning. - \def\do##1{% - \pgfinterruptboundingbox% - \yquant@env@virtualize@path% - \ifyquant@firsttoken\yquant@register@multi{##1}{% - \csxappto{\yquant@prefix draw}% - {\yquant@draw@output@multi% - \yquant@circuit@output@do@multi@@extract##1{\unexpanded{#3}}}% - \yquant@draw@@output@multi{#3}% - }{% - \csgappto{\yquant@prefix draw}% - {\yquant@draw@output@single{##1}{#3}}% - \yquant@draw@@output@single{##1}{#3}% - \yquant@register@update@height{##1}{\the\pgf@picmaxy}% - \yquant@register@update@depth{##1}{\the\dimexpr-\pgf@picminy\relax}% - }% - \ifdim\pgf@picmaxx>\csname\yquant@prefix xmax\endcsname% - \csxdef{\yquant@prefix xmax}{\the\pgf@picmaxx}% - \fi% - \endpgfinterruptboundingbox% - }% - \yquant@draw@output@group{#2}% - \csgappto{\yquant@prefix draw}{% - \yquant@draw@output@group{#2}% - }% - % \dolistloop will carry out one \expandafter on the argument; but this expansion step - % is already done. If #1 starts with \yquant@register@multi, this will be expanded once - % despite \protected, so insert some expand-to-nothing token first. - \dolistloop{\empty#1}% - \csgappto{\yquant@prefix draw}{% - \yquant@draw@output@endgroup% - }% - \yquant@draw@output@endgroup% -} - -\def\yquant@circuit@output@do@multi@@extract#1#2#3#4#5{% - {#2}{#3}{#5}% -} % END_FOLD
\ 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 a6765d14850..d5844480ee0 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-config.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-config.tex @@ -13,21 +13,53 @@ \decoration{\pgfkeysvalueof{/pgf/decoration/post}}% }% } + +% BEGIN_FOLD Circuit layout +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + register/minimum height/.code=% + {\dimdef\yquant@config@register@minimum@height{.5\dimexpr#1\relax}% + \let\yquant@config@register@minimum@depth=\yquant@config@register@minimum@height}% + } +\else% + \pgfqkeys{/yquant}{% + register/minimum height/.code=% + {\dimdef\yquant@config@register@minimum@height{#1}},% + register/minimum depth/.code=% + {\dimdef\yquant@config@register@minimum@depth{#1}}% + } +\fi \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,% - register/minimum height/.code=% - {\dimdef\yquant@config@register@minimum@height{#1}},% register/separation/.code=% {\dimdef\yquant@config@register@sep{#1}},% - % register label style - every label/.style=% - {shape=yquant-text, anchor=center, align=right},% + operator/minimum width/.code=% + {\dimdef\yquant@config@operator@minimum@width{#1}},% + operator/separation/.code=% + {\dimdef\yquant@config@operator@sep{#1}},% + operator/multi warning/.is if=% + yquant@config@operator@multi@warn% +}% +% END_FOLD +% BEGIN_FOLD Register creation +\pgfqkeys{/yquant}{% + register/default name/.store in=% + \yquant@config@register@default@name% +} +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + every label/.style=% + {shape=yquant-init, anchor=center, align=right, outer xsep=2pt},% + every multi label/.style=% + {draw, decoration={gapped brace, mirror, raise=2pt}, decorate}% + } +\else + \pgfqkeys{/yquant}{% + every label/.style=% + {shape=yquant-init, anchor=center, align=right, outer xsep=2pt,% + /yquant/operator/if multi={draw, decoration={gapped brace, mirror, raise=2pt}, decorate}}% + } +\fi +\pgfqkeys{/yquant}{ every initial label/.style=% {anchor=east},% every qubit label/.style=% @@ -35,25 +67,51 @@ 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}},% - every input label/.style=% - {},% - % output label styles - every output/.style=% - {shape=yquant-text, anchor=west, align=left},% + {}% +} +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + every input label/.style=% + {}% + }% +\fi% +% END_FOLD +% BEGIN_FOLD Register outputs +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + every output/.style=% + {shape=yquant-output, anchor=west, align=left, outer xsep=2pt},% + every multi output/.style=% + {draw, decoration={gapped brace, raise=2pt}, decorate}% + } +\else + \pgfqkeys{/yquant}{% + every output/.style=% + {shape=yquant-output, anchor=west, align=left, outer xsep=2pt,% + /yquant/operator/if multi={draw, decoration={gapped brace, raise=2pt}, decorate}}% + } +\fi +\pgfqkeys{/yquant}{% 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}},% - % wire style + {}% +} +% END_FOLD +% BEGIN_FOLD General styling +\pgfqkeys{/yquant}{% + every circuit/.style={% + every node/.prefix style={transform shape} + }% +} +\@ifpackagelater{pgf}{2020/09/31}\relax{ + \pgfkeys{/yquant/every circuit/.append style={% + every label/.prefix style={transform shape=false}% + }} +} +\pgfqkeys{/yquant}{% every wire/.style=% {draw},% every qubit wire/.style=% @@ -62,14 +120,6 @@ {},% every qubits wire/.style=% {},% - % operator settings - operator/separation/.code=% - {\dimdef\yquant@config@operator@sep{#1}},% - operator/minimum width/.code=% - {\dimdef\yquant@config@operator@minimum@width{#1}},% - operator/multi warning/.is if=% - yquant@config@operator@multi@warn,% - % operator style: control every control line/.style=% {draw},% every control/.style=% @@ -78,16 +128,10 @@ {fill=black},% every negative control/.style=% {draw},% - % operator style: main part every operator/.style=% {anchor=center},% - operator/multi main/.is if=% - yquant@config@operator@multi@main,% - operator/multi as single/.style=% - {/yquant/every multi line/.style=/yquant/every control line},% every multi line/.style=% {draw, decoration={snake, amplitude=.25mm, segment length=5pt}, decorate},% - % overwriting all styles this operator/.style=% {},% this control/.style=% @@ -101,9 +145,66 @@ {/yquant/this operator/.append style={#1},% /yquant/every control line/.append style={#1},% /yquant/this control/.append style={#1}},% - % different operator appearances + operator/multi as single/.style=% + {/yquant/every multi line/.style=/yquant/every control line},% + operator/if multi/.code=% + {\ifyquant@config@operator@multi\pgfkeysalso{#1}\fi},% + circuit/seamless/.is if=yquant@config@circuit@seamless,% + every post measurement control/.is choice, + every post measurement control/indirect/.code={% + \undef\yquant@lang@attr@directcontrol% + },% + every post measurement control/direct/.code={% + \let\yquant@lang@attr@directcontrol=\relax% + }% +} +% END_FOLD +% BEGIN_FOLD Styles for operators +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + operators/every barrier/.style=% + {shape=yquant-line, dashed, draw}% + } +\else + \pgfqkeys{/yquant}{% + operators/every barrier/.style=% + {shape=yquant-line, dashed, draw, shorten <= -1mm, shorten >= -1mm} + } +\fi +\pgfqkeys{/yquant}{% operators/every box/.style=% {shape=yquant-rectangle, draw, align=center, inner xsep=1mm, x radius=2mm, y radius=2.47mm},% +} +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + operators/every custom gate/.style=% + {/yquant/operators/subcircuit/frameless, /yquant/register/default name=}% + } +\else + \pgfqkeys{/yquant}{% + operators/every custom gate/.style=% + {/yquant/operators/subcircuit/seamless}% + } +\fi +\pgfqkeys{/yquant}{% + operators/every dmeter/.style=% + {shape=yquant-dmeter, x radius=2mm, y radius=2mm, draw}, + % every h is implicitly defined during gate declaration + operators/every inspect/.style=% + {shape=yquant-output, align=left, outer xsep=.3333em, y radius=2.47mm,% + /yquant/operator/if multi={draw, decoration={gapped brace, raise=2pt}, decorate}},% + operators/every measure/.style=% + {shape=yquant-measure, x radius=4mm, y radius=2.5mm, draw},% + operators/every measure meter/.style=% + {draw, -{Latex[length=2.5pt]}},% + operators/every not/.style=% + {shape=yquant-oplus, radius=1.3mm, draw},% + operators/every pauli/.style=% + {/yquant/operators/every box},% + operators/every phase/.style=% + {shape=yquant-circle, radius=.5mm, fill},% + operators/every slash/.style=% + {shape=yquant-slash, x radius=.5mm, y radius=.7mm, draw},% operators/every subcircuit/.style=% {},% operators/every subcircuit box/.style=% @@ -114,181 +215,61 @@ {},% 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 phase/.style=% - {shape=yquant-circle, radius=.5mm, fill},% - operators/every zz/.style=% - {shape=yquant-circle, radius=.5mm, fill},% - operators/every xx/.style=% - {shape=yquant-rectangle, radius=.75mm, draw},% - operators/every slash/.style=% - {shape=yquant-slash, x radius=.5mm, y radius=.7mm, draw},% + operators/subcircuit/frameless/.style= + {/yquant/operators/this subcircuit box/.append style={draw=none, inner sep=0pt}},% + operators/subcircuit/seamless/.code=% + {\pgfkeysalso{/yquant/operators/subcircuit/frameless, /yquant/register/default name=}% + \letcs\yquant@prevseamless{\yquant@prefix seamless}% + \yquant@config@circuit@seamlesstrue}, operators/every swap/.style=% {shape=yquant-swap, radius=.75mm, draw},% - operators/every not/.style=% - {shape=yquant-oplus, radius=1.3mm, draw},% - operators/every measure/.style=% - {shape=yquant-measure, x radius=4mm, y radius=2.5mm, draw},% - operators/every measure meter/.style=% - {draw, -{Latex[length=2.5pt]}},% - operators/every dmeter/.style=% - {shape=yquant-dmeter, x radius=2mm, y radius=2mm, draw},% - operators/every barrier/.style=% - {shape=yquant-line, dashed, draw},% operators/every wave/.style=% + {shape=yquant-circle, radius=.5mm, fill}% + % every x is implicitly defined during gate declaration + operators/every xx/.style=% + {shape=yquant-rectangle, radius=.75mm, draw},% + % every y is implicitly defined during gate declaration + % every z is implicitly defined during gate declaration + operators/every zz/.style=% {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% - },% } +% END_FOLD +% BEGIN_FOLD Internal styles (undocument, do not use!) +\pgfqkeys{/yquant}{% + internal/move label/.code=% + {\yquant@config@operator@position@rightaligntrue}, + internal/no advance/.code=% + {\unless\ifyquantmeasuring% We don't draw subcircuits during measuring time, but we need their advancement + \yquant@config@operator@position@advancefalse% + \fi}, + internal/multi main/.is if=% + yquant@config@internal@multi@main,% +} +\ifnum\yquant@compat<2 % + \pgfqkeys{/yquant}{% + internal/squeeze slash/.code=% + {\dimdef\yquant@config@operator@sep{.5\dimexpr\yquant@config@operator@sep-\pgflinewidth\relax}% + \yquant@config@operator@position@advancefalse},% + } +\else% + \pgfqkeys{/yquant}{% + internal/squeeze slash/.code={}% + } +\fi +% END_FOLD \def\yquant@config@register@default@name{\regidx} -\def\yquant@config@register@minimum@height{3mm} +\def\yquant@config@register@minimum@height{1.5mm} +\def\yquant@config@register@minimum@depth{1.5mm} \def\yquant@config@register@sep{1mm} \def\yquant@config@operator@sep{1mm} \def\yquant@config@operator@minimum@width{5mm} -\newif\ifyquant@config@operator@multi@main% -\yquant@config@operator@multi@maintrue +\newif\ifyquant@config@internal@multi@main% +\yquant@config@internal@multi@maintrue \newif\ifyquant@config@operator@multi@warn \yquant@config@operator@multi@warntrue -\def\pgfdecorationsegmentfromto{0-1}% - -\protected\def\yquant@gappedbrace@extract#1-#2\yquant@sep{% - \dimdef\from{#1\pgfdecoratedremainingdistance}% - \dimdef\to{#2\pgfdecoratedremainingdistance}% -} -% This function is set to replace the transformation that changes the fraction value specified in the node property pos by a computation of the correct value for the gappedbrace decoration. It thus requires \pgfdecorationsegmentfromto to be already set up properly. Only if the special position -1 is given, these transformations are applied; else, the default behavior is reproduced (\tikz@timer@line). -\protected\def\yquant@gappedbrace@timer{% - \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}% - \pgfdecoratedremainingdistance=\pgfmathresult pt % - % now perform the transformation - \pgf@xc=\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% - \expandafter\forcsvlist\expandafter\yquant@gappedbrace@shiftloop% - \expandafter{\pgfdecorationsegmentfromto}% - % and finally let us return the desired position, just ignoring \tikz@time... - \pgftransformlineattime{\pgfdecorationsegmentaspect}{\tikz@timer@start}{\tikz@timer@end}% - \else% - \pgftransformlineattime{\tikz@time}{\tikz@timer@start}{\tikz@timer@end}% - \fi% -} -\def\yquant@gappedbrace@shiftloop#1{% - \yquant@gappedbrace@extract#1\yquant@sep% - \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance<\from % - \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance>\to % - % be careful about arch positions at the border - \ifdim\dimexpr\to-\from\relax<2\pgfdecorationsegmentamplitude % - % The arch is larger than the segment. We do not draw a line to it or an end line and place it in the mid of the segment, even if it is too short (this issues one extra \pgfpathmoveto command, but catching this rare case is not worth the effort). - \edef\pgfdecorationsegmentaspect{\pgfmath@tonumber{\dimexpr% - .5\dimexpr\from+\to\relax*65536/\pgfdecoratedremainingdistance% - \relax}}% - \else% - % The segment is large enough to cover the whole arch. But maybe we are too close at the border? - \ifdim\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax<\from % - \pgf@xc=\dimexpr\from+\pgfdecorationsegmentamplitude\relax% - \fi% - \ifdim\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax>\to % - \pgf@xc=\dimexpr\to-\pgfdecorationsegmentamplitude\relax% - \fi% - \edef\pgfdecorationsegmentaspect{\pgfmath@tonumber{\dimexpr% - \dimexpr\pgf@xc*65536/\pgfdecoratedremainingdistance% - \relax}}% - \fi% - \expandafter\expandafter\expandafter\listbreak% - \fi% - \fi% -} -\def\yquant@gappedbrace@loop#1{% - \yquant@gappedbrace@extract#1\yquant@sep% - \unless\ifdim\from=0pt % - \pgfpathmoveto{% - \pgfqpoint{\from}{.5\pgfdecorationsegmentamplitude}% - }% - \fi% - \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance<\from % - \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance>\to % - % be careful about arch positions at the border - \ifdim\dimexpr\to-\from\relax<2\pgfdecorationsegmentamplitude % - % The arch is larger than the segment. We do not draw a line to it or an end line and place it in the mid of the segment, even if it is too short (this issues one extra \pgfpathmoveto command, but catching this rare case is not worth the effort). - \pgfpathmoveto{% - \pgfqpoint{\dimexpr.5\dimexpr\from+\to\relax-\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }% - \edef\to{\the\pgfdecoratedremainingdistance}% to prevent the final line, we do not need "to" any more - \else% - % The segment is large enough to cover the whole arch. But maybe we are too close at the border? - \ifdim\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax<\from % - \pgf@xc=\dimexpr\from+\pgfdecorationsegmentamplitude\relax% - \fi% - \ifdim\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax>\to % - \pgf@xc=\dimexpr\to-\pgfdecorationsegmentamplitude\relax% - \fi% - % Both cases can't occur at the same time in this \else clause. - \pgfpathlineto{% - \pgfqpoint{\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }% - \fi% - \pgfpathcurveto{% - \pgfqpoint{\dimexpr\pgf@xc-.5\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\dimexpr\pgf@xc-.15\pgfdecorationsegmentamplitude\relax}% - {.7\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\pgf@xc}{\pgfdecorationsegmentamplitude}% - }% - \pgfpathcurveto{% - \pgfqpoint{\dimexpr\pgf@xc+.15\pgfdecorationsegmentamplitude\relax}% - {.7\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\dimexpr\pgf@xc+.5\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }% - \fi% - \fi% - \unless\ifdim\to=\pgfdecoratedremainingdistance % - \pgfpathlineto{% - \pgfqpoint{\to}{.5\pgfdecorationsegmentamplitude}% - }% - \fi% -} -% This is a variant of the brace in pathreplacing that allows for holes -\pgfdeclaredecoration{gapped brace}{final}{% - \state{final}{% - \pgf@xc=\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% - \pgfpathcurveto{% - \pgfqpoint{.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}% - }% - \expandafter\forcsvlist\expandafter\yquant@gappedbrace@loop% - \expandafter{\pgfdecorationsegmentfromto}% - \pgfpathlineto{% - \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }% - \pgfpathcurveto{% - \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-.5\pgfdecorationsegmentamplitude\relax}% - {.5\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-.15\pgfdecorationsegmentamplitude\relax}% - {.3\pgfdecorationsegmentamplitude}% - }{% - \pgfqpoint{\pgfdecoratedremainingdistance}{0pt}% - }% - }% -}%
\ No newline at end of file +\newif\ifyquant@config@operator@position@rightalign +\newif\ifyquant@config@operator@position@advance +\yquant@config@operator@position@advancetrue +\newif\ifyquant@config@circuit@seamless +\newif\ifyquant@config@operator@multi
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex b/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex index a74197192c7..1bf8d3fb19a 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex @@ -1,31 +1,96 @@ -% BEGIN_FOLD Actual drawing at shipout \newcount\yquant@draw@@currentcontroltype% -\protected\def\yquant@draw@group#1#2#3#4#5{% - \begingroup% - \ifcsname\yquant@prefix xshift\endcsname% - \dimdef\yquant@draw@@x{#1+\csname\yquant@prefix xshift\endcsname}% - \else% - \def\yquant@draw@@x{#1}% +\protected\def\yquant@draw@init#1#2{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + % for connected subcircuit wires, check if this actually changes the type [happens for formerly discarded output wires] and flush the wire if necessary + \edef\yquant@draw@init@type{\yquant@register@get@type{#1}}% + \unless\if\yquant@draw@init@type#2\relax% + \yquant@circuit@flushwire{#1}% + \ifx\yquant@draw@init@type\yquant@register@type@none% + % in case the wire was discarded before, forget about the lastx position, it should always start with the others + \yquant@register@get@lastwire{#1}\wirelast% + \expandafter\expandafter\expandafter\ifstrempty\expandafter\expandafter\expandafter{% + \expandafter\@thirdoffour\wirelast% + }{% + \yquant@register@set@lastwire{#1}{% + {\yquant@draw@subcircuit@wirestart}{\yquant@draw@subcircuit@wirestart}{}% + {\unexpanded\expandafter\expandafter\expandafter{% + \expandafter\@fourthoffour\wirelast% + }}% + }% + }\relax + \fi% + \yquant@register@set@type{#1}{#2}% \fi% + \else% + % for new wires, reset the type, and if this a subcircuit, put the appropriate x position in place. It might have changed from its initial value during preparation stage + \yquant@register@set@type{#1}{#2}% + \ifdefined\yquant@draw@subcircuit@wirestart% + \yquant@register@set@x{#1}{\yquant@draw@subcircuit@wirestart}% + \yquant@register@set@lastwire{#1}{% + {\yquant@draw@subcircuit@wirestart}{\yquant@draw@subcircuit@wirestart}{}{}% + }% + \fi% + \fi% +} + +\def\yquant@draw@subcircuit@leftpos{0pt}% outermost circuit: 0pt +\protected\long\def\yquant@draw@group#1#2#3#4#5#6{% + \begingroup% + \yquant@register@get@maxxlist\yquant@draw@@x{#6}% \ifx F#2% \yquant@draw@@currentcontroltype=0 % \else% - \yquant@draw@@currentcontroltype=\yquant@register@get@type{#2}\relax% + \yquant@draw@@currentcontroltype=#2 % \fi% \let\yquant@circuit@extendcontrolline@cmd=\empty% \let\yquant@circuit@extendcontrolline@prev=\relax% \let\yquant@circuit@extendcontrolline@clip=\empty% \let\yquant@circuit@extendmultiline@total=\empty% - \yquant@langhelper@list@attrs% - % If the quotes library is loaded, activate it. (else, this is by default \relax) - \tikz@enable@node@quotes% - \yquant@set{#3}% + \def\yquant@draw@@width{#1}% \def\yquant@draw@@style{#4}% \def\yquant@draw@@content{#5}% \def\yquant@draw@@idx@content{0}% \def\yquant@draw@@idx@pcontrol{0}% \def\yquant@draw@@idx@ncontrol{0}% + % If the quotes library is loaded, activate it. (else, this is by default \relax) + \tikz@enable@node@quotes% + \yquant@config@operator@position@rightalignfalse% + \yquant@config@operator@position@advancetrue% + \yquant@set{#3}% + % if the operator is right-aligned, we will not advance, as we must assume that the x position is already chosen appropriately + \ifyquant@config@operator@position@rightalign% + % for rightalign, we instead overwrite the lastx configurations, so that the outgoing wire starts after the operator. + \forlistloop\yquant@draw@group@rightadvance{#6}% + \else% + \ifyquant@env@seamless{% + \unless\ifdim\yquant@draw@@x=\yquant@draw@subcircuit@leftpos% + \dimdef\yquant@draw@@x{% + \yquant@draw@@x+\yquant@config@operator@sep% + }% + \fi% + }{% + \dimdef\yquant@draw@@x{% + \yquant@draw@@x+\yquant@config@operator@sep% + }% + }% + \ifyquant@config@operator@position@advance% + \dimdef\newx{\yquant@draw@@x+#1}% + \forlistloop\yquant@draw@group@advance{#6}% + \fi% + \dimdef\yquant@draw@@x{\yquant@draw@@x+.5\dimexpr#1\relax}% + \fi% +} + +\protected\def\yquant@draw@group@advance#1{% + \yquant@register@set@x{#1}\newx% +} + +\protected\def\yquant@draw@group@rightadvance#1{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + % for connected subcircuit wires, make sure to flush the wire until the beginning. + \yquant@circuit@flushwire{#1}% + \fi% } \protected\def\yquant@draw@endgroup#1#2#3{% @@ -57,8 +122,83 @@ \endgroup% } -\protected\long\def\yquant@draw@single#1#2{% +\protected\def\yquant@draw@injectiongroup#1#2\yquant@draw@endinjectiongroup#3#4#5{% + \csdef{yquant@draw@@injection@#1}{% + \yquant@draw@begininjection#2\yquant@draw@stopinjection{#3}{#4}{#5}% + }% +} + +\protected\long\def\yquant@draw@begininjection#1#2#3#4#5#6{% + % this is called within another draw group, so lots of things are already set up + \begingroup% + \def\yquant@draw@@style{#4}% + \def\yquant@draw@@content{#5}% + \let\yquant@draw@@idx@content=\yquant@draw@@idx@pcontrol% + \yquant@set{#3}% this will accumulate with outer styles from the enclosing draw group, but there is nothing we can do about it +} + +\protected\def\yquant@draw@stopinjection#1#2#3{% + \ifcase#3\relax% + \or% + \yquant@draw@alias@ctrl{#2}n% + \or% + \yquant@draw@alias@ctrl{#2}p% + \or% + \yquant@draw@alias@ctrl{#2}p% + \yquant@draw@alias@ctrl{#2}n% + \or% + \yquant@draw@alias{#2}% + \or% + \yquant@draw@alias{#2}% + \yquant@draw@alias@ctrl{#2}n% + \or% + \yquant@draw@alias{#2}% + \yquant@draw@alias@ctrl{#2}p% + \or% + \yquant@draw@alias{#2}% + \yquant@draw@alias@ctrl{#2}p% + \yquant@draw@alias@ctrl{#2}n% + \fi% + \edef\process{% + \endgroup% + \def\noexpand\yquant@circuit@extendcontrolline@clip{% + \unexpanded\expandafter{\yquant@circuit@extendcontrolline@clip}% + }% + \def\noexpand\yquant@circuit@extendcontrolline@prev{% + \unexpanded\expandafter{\yquant@circuit@extendcontrolline@prev}% + }% + \def\noexpand\yquant@circuit@extendcontrolline@cmd{% + \unexpanded\expandafter{\yquant@circuit@extendcontrolline@cmd}% + }% + \def\noexpand\yquant@circuit@extendmultiline@total{% + \unexpanded\expandafter{\yquant@circuit@extendmultiline@total}% + }% + \def\noexpand\yquant@draw@@idx@pcontrol{\yquant@draw@@idx@content}% + }% + \process% +} + +\protected\def\yquant@draw@inject#1{% + \csname yquant@draw@@injection@#1\endcsname% + \csgundef{yquant@draw@@injection@#1}% +} + +\protected\def\yquant@draw@inject@outer#1{% + % we thought we wanted to inject #1, however, this was not valid; so now insert it directly. + \expandafter\expandafter\expandafter\yquant@draw@inject@outer@helper% + \csname yquant@draw@@injection@#1\endcsname% + \csgundef{yquant@draw@@injection@#1}% +} + +\def\yquant@draw@inject@outer@helper\yquant@draw@begininjection#1\yquant@draw@stopinjection{% + \yquant@draw@group% + #1% + \yquant@draw@endgroup% +} + +\protected\def\yquant@draw@single#1#2{% \let\idx=\yquant@draw@@idx@content% + \yquant@config@operator@multifalse% \edef\cmd{% \noexpand\path (\yquant@draw@@x, \yquant@register@get@y{#1})% node[/yquant/every operator, \yquant@draw@@style, /yquant/this operator,% @@ -80,6 +220,7 @@ } \protected\def\yquant@draw@multi#1#2#3#4#5{% + \yquant@config@operator@multitrue% \let\idx=\yquant@draw@@idx@content% \edef\yquant@draw@multi@@name{#5}% \def\yquant@draw@@idx@multipart{0}% @@ -106,7 +247,7 @@ \yquant@register@get@y{#1}+\yquant@register@get@y{#2}\relax% \relax)% node[/yquant/every operator, \yquant@draw@@style, /yquant/this operator,% - /yquant/operator/multi main=\ifnum#3=1 true\else false\fi\unless\ifnum#1=#2 ,% + /yquant/internal/multi main=\ifnum#3=1 true\else false\fi\unless\ifnum#1=#2 ,% 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]% @@ -145,17 +286,28 @@ \let\pgfdecorationsegmentfromto=\empty% #4% \edef\pgfdecorationsegmentfromto{\expandafter\@gobble\pgfdecorationsegmentfromto}% + \yquant@config@operator@multitrue% % We need to somehow extract the y radius \edef\cmd{% - \noexpand\path[/yquant/every operator, \yquant@draw@@style,% - /yquant/every multi label, /yquant/this operator]% - (\yquant@draw@@x, \yquant@draw@multiinit@@min) --% - (\yquant@draw@@x, \yquant@draw@multiinit@@max)% - node[name prefix=, name suffix=, name=yquantbox]% + \noexpand\path (\yquant@draw@@x, \the\dimexpr.5\dimexpr% + \yquant@draw@multiinit@@min+\yquant@draw@multiinit@@max\relax% + \relax)% + node[/yquant/every operator, \yquant@draw@@style, + \ifnum\yquant@compat<2 /yquant/every multi label,\fi% + /yquant/this operator,% + y radius=\yquant@abs{\the\dimexpr.5\dimexpr\yquant@draw@multiinit@@total\relax\relax},% + name prefix=, name suffix=, name=yquantbox]% {\unexpanded\expandafter{\yquant@draw@@content}};% + \pgfshapeclippath{yquantbox}% + {/yquant/every operator, \yquant@draw@@style,% + \ifnum\yquant@compat<2 /yquant/every multi label,\fi% + /yquant/this operator}% }% \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 + \yquant@for \i := #1 to #2 {% + \yquant@circuit@extendwire\i{center}% + }% + % no control line (init doesn't allow for those, so just save the no-op), no multi line % check for empty name parameter \ifstrempty{#5}\relax{% \pgfnodealias{\tikz@pp@name{#5}}{yquantbox}% @@ -201,7 +353,85 @@ \fi% } -\newbox\yquant@draw@subcircuit@box +\protected\long\def\yquant@draw@output@single#1#2{% + \let\idx=\yquant@draw@@idx@content% + \yquant@config@operator@multifalse% + \edef\cmd{% + \noexpand\path (\yquant@circuit@endwires@x, \yquant@register@get@y{#1})% + node[\ifnum\yquant@compat>1 /yquant/every operator,\fi% + /yquant/every output,% + /yquant/every \yquant@register@type@tostring{\yquant@register@get@type{#1}} output,% + \yquant@draw@@style, /yquant/this operator,% + name prefix=, name suffix=, name=yquantbox]% + {\unexpanded\expandafter{\yquant@draw@@content}};% + \ifdefined\yquant@parent% + \pgfshapeclippath{yquantbox}% + {\ifnum\yquant@compat>1 /yquant/every operator,\fi% + /yquant/every output,% + /yquant/every \yquant@register@type@tostring{\yquant@register@get@type{#1}} output,% + \yquant@draw@@style,% + /yquant/this operator}% + \fi% + }% + \cmd% + % only extend for subcircuits + \ifdefined\yquant@parent% + \yquant@circuit@extendwire{#1}{center}% + \fi% + % check for empty name parameter + \ifstrempty{#2}\relax{% + \pgfnodealias{\tikz@pp@name{#2}}{yquantbox}% + }% + \numdef\yquant@draw@@idx@content{\yquant@draw@@idx@content+1}% +} + +\protected\long\def\yquant@draw@output@multi#1#2#3#4#5{% + \let\idx=\yquant@draw@@idx@content% + \@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% + #4% + \edef\pgfdecorationsegmentfromto{\expandafter\@gobble\pgfdecorationsegmentfromto}% + \yquant@config@operator@multitrue% + % We need to somehow extract the y radius + \edef\cmd{% + \noexpand\path (\yquant@circuit@endwires@x, \the\dimexpr.5\dimexpr% + \yquant@draw@multiinit@@min+\yquant@draw@multiinit@@max\relax% + \relax)% + node[\ifnum\yquant@compat>1 /yquant/every operator, /yquant/every output,\fi% + \yquant@draw@@style,% + \ifnum\yquant@compat<2 /yquant/every multi output,\fi% + /yquant/this operator,% + y radius=\yquant@abs{\the\dimexpr.5\dimexpr\yquant@draw@multiinit@@total\relax\relax},% + name prefix=, name suffix=, name=yquantbox]% + {\unexpanded\expandafter{\yquant@draw@@content}};% + \ifdefined\yquant@parent% + \pgfshapeclippath{yquantbox}% + {\ifnum\yquant@compat>1 /yquant/every operator, /yquant/every output,\fi% + \yquant@draw@@style, + \ifnum\yquant@compat<2 /yquant/every multi output,\fi% + /yquant/this operator}% + \fi% + }% + \cmd% + % only extend for subcircuits + \ifdefined\yquant@parent% + \yquant@for \i := #1 to #2 {% + \yquant@circuit@extendwire\i{center}% + }% + \fi% + % check for empty name parameter + \ifstrempty{#5}\relax{% + \pgfnodealias{\tikz@pp@name{#5}}{yquantbox}% + }% + \numdef\yquant@draw@@idx@content{\yquant@draw@@idx@content+1}% +} \protected\def\yquant@draw@subcircuit@nodecallback#1{% \ifstrequal{#1}{yquantbox}\relax{% @@ -209,65 +439,87 @@ }% } -\protected\long\def\yquant@draw@subcircuit@prepare#1#2{% +% #1: id of subcircuit +% #2: name +% #3: {width of subcircuit (excluding outer box)}{including outer box}{left margin} +% #4: affected wires +\protected\long\def\yquant@draw@subcircuit@prepare#1#2#3#4{% \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. + % 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. % 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-}}% + % \pgfinterruptboundingbox, but just for y + \begingroup% + \edef\pgf@interrupt@savemaxy{\the\pgf@picmaxy}% + \edef\pgf@interrupt@saveminy{\the\pgf@picminy}% + \pgf@picmaxy=-16000pt % + \pgf@picminy=16000pt % + \pgf@size@hookedfalse% + \let\pgf@path@size@hook=\pgfutil@empty% + % now we must take care of extending all the wires appropriately until the beginning of the box. #3 contains width of this box, #4 contains registers affected by this box. Note that for subcircuits, x extension by the group is disabled. + \dimdef\newx{% + \yquant@draw@@x-.5\dimexpr\@secondofthree#3\relax% }% - \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% + \dimen0=\newx% + \let\yquant@draw@subcircuit@leftpos=\newx% seamless subcircuits: do not add another separation if we are there + \let\pgfshapeclippathhorzresult=\empty% + \forlistloop\yquant@draw@move@loop{#4}% + % but the new positions are not at the beginning of the box, but inside (with possible margin) + \dimdef\newx{% + \yquant@draw@@x-.5\dimexpr\@firstofthree#3\relax-\@thirdofthree#3% + }% + \forlistloop\yquant@draw@group@advance{#4}% + \setbox\yquant@prepare@subcircuit@box=\hbox{{% + \let\yquant@draw@subcircuit@wirestart=\newx% + \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-}}% + }% + \pgfkeys{/yquant/operators/this subcircuit box/.style={}}% + \edef\yquant@draw@subcircuit@style{% + /yquant/every operator, \yquant@draw@@style,% + /yquant/this operator, /yquant/internal/multi main=true,% + } + \expandafter\tikzset\expandafter{\yquant@draw@subcircuit@style}% + \csname\yquant@prefix draw\endcsname% + \dimen0=\yquant@register@get@y1\relax% + \ifdim\dimen0>\pgf@picmaxy % + \global\pgf@picmaxy=\dimen0 % + \fi% + \dimen0=\dimexpr\yquant@register@get@y{\csname\yquant@prefix registers\endcsname}\relax% + \ifdim\dimen0<\pgf@picminy % + \global\pgf@picminy=\dimen0 % + \fi% }}% - \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% + \edef\cmd{% + \noexpand\path (\yquant@draw@@x, \the\dimexpr.5\pgf@picminy+.5\pgf@picmaxy\relax)% + node[/yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box,% + /yquant/internal/multi main=true,% + name prefix=, name suffix=, name=yquantbox]% + {\vbox to \the\dimexpr\pgf@picmaxy-\pgf@picminy\relax {\hbox to \@firstofthree#3 {}}};% }% - \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% - }% + \cmd% + \unhbox\yquant@prepare@subcircuit@box + % \endpgfinterruptboundingbox + increase + \ifdim\pgf@interrupt@savemaxy>\pgf@picmaxy% + \global\pgf@picmaxy=\pgf@interrupt@savemaxy% + \fi% + \ifdim\pgf@interrupt@saveminy<\pgf@picminy% + \global\pgf@picminy=\pgf@interrupt@saveminy% + \fi% + \endgroup% + % Now that the subcircuit is finished, we need advance all the wires + \dimdef\newx{\yquant@draw@@x+.5\dimexpr\yquant@draw@@width\relax}% + \forlistloop\yquant@draw@group@advance{#4}% \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{% @@ -287,25 +539,21 @@ }% } -\protected\long\def\yquant@draw@subcircuit@single#1#2#3{% - \yquant@draw@subcircuit@prepare{#2}{#3}% +\protected\long\def\yquant@draw@subcircuit@single#1#2#3#4{% + \yquant@config@operator@multifalse% + \yquant@draw@subcircuit@prepare{#2}{#3}{#4}{#1}% \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}% + \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}{*}% + \yquant@circuit@extendwire{#1}*% \expandafter\yquant@circuit@extendcontrolline\expandafter% {\the\yquant@draw@@currentcontroltype}\yquant@draw@@x% % check for empty name parameter @@ -315,31 +563,25 @@ \numdef\yquant@draw@@idx@content{\yquant@draw@@idx@content+1}% } -\protected\long\def\yquant@draw@subcircuit@multi#1#2#3#4#5#6{% +\protected\long\def\yquant@draw@subcircuit@multi#1#2#3#4#5#6#7{% + \yquant@config@operator@multitrue% % 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 + \yquant@draw@subcircuit@prepare{#5}{#6}{#7}{#4}% \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}% + \pgfshapeclippath{yquantbox}{% + /yquant/every operator, \yquant@draw@@style,% + /yquant/operators/every subcircuit box, /yquant/this operator,% + /yquant/operators/this subcircuit box,% + /yquant/internal/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. + % 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 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 the 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% @@ -465,7 +707,7 @@ \ifx0#2% \edef\wirexpos{\expandafter\@secondoffour\wirelast}% \else% - \let\wirexpos=\yquant@env@end@xpos% + \let\wirexpos=\yquant@circuit@endwires@x% \fi% \ifdim\wirexpos>\wirexprevpos % \edef\wirestyle{\noexpand\tikzset{% @@ -483,41 +725,52 @@ }% }% \pgfscope% - % install the clipping - \pgfsyssoftpath@setcurrentpath\wireclipping% - % invert the clipping - \ifyquantdebug% - \pgfsetfillcolor{orange}% - \pgfsetfillopacity{.3}% - \pgfusepathqfill% - \else% - % 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}}% - \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 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% - \fi% - \ifdim\dimexpr\@tempdimb-\@tempdima\relax<1cm % - \@tempdima=\dimexpr\wireypos-5mm\relax% - \@tempdimb=\dimexpr\wireypos+5mm\relax% + \unless\ifx\wireclipping\empty% may happen if the style is altered to be invisible, though the type is not none + % install the clipping + \pgfsyssoftpath@setcurrentpath\wireclipping% + % invert the clipping + \ifyquantdebug% + \pgfsetfillcolor{orange}% + \pgfsetfillopacity{.3}% + \pgfusepathqfill% + \else% + % 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% + \ifdim\pgf@picminx>\pgf@picmaxx% + % nothing drawn yet (or bounding box reset) + \pgf@picminx=0pt % + \pgf@picmaxx=0pt % + \fi% + \ifdim\pgf@picminy>\pgf@picmaxy% + \pgf@picminy=0pt % + \pgf@picmaxy=0pt % + \fi% + \pgftransforminvert% + \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 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% + \fi% + \ifdim\dimexpr\@tempdimb-\@tempdima\relax<1cm % + \@tempdima=\dimexpr\wireypos-5mm\relax% + \@tempdimb=\dimexpr\wireypos+5mm\relax% + \fi% + \pgf@relevantforpicturesizefalse% + \pgfpathrectanglecorners% + {\pgfqpoint{\dimexpr\wirexprevpos-2\pgflinewidth\relax}% + {\@tempdima}}% + {\pgfqpoint{\dimexpr\wirexpos+2\pgflinewidth\relax}% + {\@tempdimb}}% + \pgf@relevantforpicturesizetrue% + \pgfseteorule% even-odd to properly invert the clipping + \pgfusepathqclip% \fi% - \pgfinterruptboundingbox% - \pgfpathrectanglecorners% - {\pgfqpoint{\dimexpr\wirexprevpos-2\pgflinewidth\relax}% - {\@tempdima}}% - {\pgfqpoint{\dimexpr\wirexpos+2\pgflinewidth\relax}% - {\@tempdimb}}% - \endpgfinterruptboundingbox% - \pgfseteorule% even-odd to properly invert the clipping - \pgfusepathqclip% \fi% % the clip inversion is left to the drawing commands (clip two \pgflinewidth more to avoid renderer artifacts) \csname yquant@draw@wire@\wiretype\endcsname{#1}% @@ -557,486 +810,17 @@ \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 -% Most drawing operations will be realized through nodes -\let\yquant@draw@callback@box=\@gobble -\let\yquant@draw@callback@wire=\@gobble - -\def\yquant@draw@sort#1#2{% - \yquant@draw@sort@aux#1\relax#2\relax% - \expandafter\@firstoftwo% - \else% - \expandafter\@secondoftwo% - \fi% -} - -\def\yquant@draw@sort@aux#1#2#3\relax#4#5#6\relax{% - \unless\ifnum#2>#5\relax% -} - -% generic shape of an operator -% #1: value -% #2: tikz options that select the correct shape -% #3: positive controls -% #4: negative controls -% #5: targets -\protected\long\def\yquant@draw#1#2#3#4#5{% - % setup the required macros - \yquant@circuit@operator{#3}{#4}{#5}% - \yquant@draw@{#1}{#2}% -} - -\protected\long\def\yquant@draw@#1#2{% - \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@@multi{#1}{#2}{##1}% - }{% - \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=% - \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}{#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\idx{0}% - \forlistloop{\yquant@draw@@controls@loop p}\yquant@circuit@operator@pctrls% - \def\idx{0}% - \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% -} - -\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{% - \noexpand\yquant@draw@group% - {\the\dimexpr\yquant@circuit@operator@x+.5\dimen2\relax}% mid x position - \ifyquant@circuit@operator@hasControls% - \yquant@draw@controltype% - \else% - F% - \fi% if-switch whether controls are present - {\yquant@attrs@remaining}% custom style - {#2}% operator style - {#1}% - }% - \yquant@sort\yquant@draw@sort% - \advance \dimen2 by \yquant@circuit@operator@x\relax% - \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. - \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@sort@dolistloop% - \csxappto{\yquant@prefix draw}{% - \unexpanded\expandafter{\yquant@draw@append}% - \noexpand\yquant@draw@endgroup% - \ifyquant@circuit@operator@hasControls% - T% - \else% - F% - \fi% - \ifx\yquant@lang@attr@name\empty% - {}0% - \else% - {\yquant@lang@attr@name}% - \ifnum\yquant@circuit@operator@numtarget=1 % - \ifnum\yquant@circuit@operator@numpctrl=1 % - \ifnum\yquant@circuit@operator@numnctrl=1 % - 7% - \else% - 6% - \fi% - \else% - \ifnum\yquant@circuit@operator@numnctrl=1 % - 5% - \else% - 4% - \fi% - \fi% - \else% - \ifnum\yquant@circuit@operator@numpctrl=1 % - \ifnum\yquant@circuit@operator@numnctrl=1 % - 3% - \else% - 2% - \fi% - \else% - \ifnum\yquant@circuit@operator@numnctrl=1 % - 1% - \else% - 0% - \fi% - \fi% - \fi% - \fi% - }% -} - -\protected\def\yquant@draw@@single#1#2#3{% - \yquant@sort@eadd{% - \yquant@draw@single% - {#3}% register index - {\nodename}% - }% - % determine the actual dimensions by a virtual draw command - \pgfinterruptboundingbox% - \yquant@env@virtualize@path% - \path% - (0pt, 0pt)% - node[/yquant/every operator, #2, /yquant/this operator,% - name prefix=, name suffix=, name=] {#1};% - \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{% - \yquant@sort@eadd{% - \yquant@draw@multi% - #3% - {\nodename}% - }% - % Determining the actual height is a problem - where to store its value? If there are single-register parts, we update the height accordingly; else we just assume that there is always enough space for such a control, since it anyways already spans multiple registers. (TODO?) - \pgfinterruptboundingbox% - \yquant@env@virtualize@path% - \def\yquant@draw@@content{#1}% - \def\yquant@draw@@style{#2}% - \let\yquant@register@multi@contiguous=\yquant@draw@@multi@contiguous% - \@fifthoffive#3% - \ifdim\pgf@picmaxy=-16000pt % - % if there was no single contiguous part before, determine the width now - \path% - (0pt, 0pt)% - node[/yquant/every operator, #2, /yquant/this operator,% - name prefix=, name suffix=, name=] {#1};% - \fi% -} - -\protected\def\yquant@draw@@multi@contiguous#1#2#3{% - \ifnum#1=#2 % - % we only care about single-register parts - \global\pgf@picmaxy=-16000pt % - \global\pgf@picminy=16000pt % - \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,% - name prefix=, name suffix=, name=]% - {\unexpanded\expandafter{\yquant@draw@@content}};% - }% - \cmd% - \yquant@register@update@height{#1}{\the\pgf@picmaxy}% - \yquant@register@update@depth{#1}{\the\dimexpr-\pgf@picminy\relax}% - \fi% -} - -\protected\def\yquant@draw@@multiinit#1#2#3{% - \yquant@sort@eadd{% - \yquant@draw@multiinit% - #3% - {\nodename}% - }% - % Determining the actual height is a problem - where to store its value? We just assume that there is always enough space for such a control, since it anyway already spans multiple registers. (TODO?) - \pgfinterruptboundingbox% - \yquant@env@virtualize@path% - \path% - (0pt, 0pt)% - node[/yquant/every operator, #2, /yquant/every multi label,% - 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{% - \let\next=\yquant@draw@@finalize@ctrl@single% - \ifx\yquant@draw@multi#1% - \let\next=\yquant@draw@@finalize@ctrl@multi% - \else% - \ifx\yquant@draw@multiinit#1% - \let\next=\yquant@draw@@finalize@ctrl@multi% - \else% - \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{% - \unless\ifyquant@circuit@operator@hasControls% - \yquant@register@set@x{#1}{\the\dimen2}% - \fi% - \eappto\yquant@draw@append{% - \yquant@draw@callback@wire{#1}% - }% -} - -\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{% - \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% - \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}% - \else% - \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% - \fi% - \else% - \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% - \fi% - \cslet{\yquant@prefix finalize@ctrl@draw@appto}\empty% - #4% - \eappto\yquant@draw@append{\csname\yquant@prefix finalize@ctrl@draw@appto\endcsname}% - \csgundef{\yquant@prefix finalize@ctrl@draw@appto}% -} - -\protected\def\yquant@draw@@finalize@ctrl@subcircuit@multi@loop#1{% +\protected\def\yquant@draw@hspace#1#2{% \begingroup% - \edef\tmp{\yquant@draw@callback@wire{#1}}% - \expandafter% + \yquant@register@get@maxxlist\newx{#1}% + \dimdef\newx{\newx+#2}% + \dimen0=\newx% + \let\pgfshapeclippathhorzresult=\empty% + \forlistloop\yquant@draw@move@loop{#1}% \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% - \ifyquant@circuit@operator@hasControls% - \ifyquant@config@operator@multi@warn% - \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{0}% - \else% - \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% - \fi% - \else% - \def\yquant@draw@@finalize@ctrl@multi@contiguous@warn{2}% - \fi% - \cslet{\yquant@prefix finalize@ctrl@draw@appto}\empty% - #4% - \eappto\yquant@draw@append{\csname\yquant@prefix finalize@ctrl@draw@appto\endcsname}% - \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 % - \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}% - \else% - \numdef\yquant@draw@@finalize@ctrl@multi@contiguous@warn{% - \yquant@draw@@finalize@ctrl@multi@contiguous@warn+1% - }% - \fi% - {% save \body - \yquant@for \yquant@i := #1 to #2 {{% let inner loop mess up with macros - \csxappto{\yquant@prefix finalize@ctrl@draw@appto}{% - \expandafter\yquant@draw@callback@wire\expandafter{\yquant@i}% - }% - }}% - }% -} -% END_FOLD
\ No newline at end of file +\protected\def\yquant@draw@move@loop#1{% + \yquant@register@set@x{#1}\newx% + \yquant@circuit@extendwire{#1}*% +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex index a9262b957da..96ea7bbac37 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex @@ -1,4 +1,5 @@ \newif\ifyquant@env@lazy +\newif\ifyquantmeasuring \protected\def\yquant@envunstar{% \yquant@env@lazyfalse% @@ -47,18 +48,17 @@ \yquant@env@begin@generic\yquant% } -\long\protected\def\yquant@env@begin@generic#1[#2]{ +\long\protected\def\yquant@env@begin@generic#1[#2]{% \begingroup% \let\yquant@parent=\yquant@prefix% \global\advance\yquant@env by 1 % \edef\yquant@prefix{yquant@env\the\yquant@env @}% \ifnum\yquant@env=1 % + \yquantmeasuringtrue% \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% @@ -67,42 +67,45 @@ \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% + \global\csletcs{\yquant@prefix seamless}{ifyquant@config@circuit@seamless}% + \ifdefined\yquant@prevseamless% + \cslet{ifyquant@config@circuit@seamless}\yquant@prevseamless% + \undef\yquant@prevseamless% + \fi% \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 seamless\endcsname% \expandafter\noexpand\csname\yquant@prefix cleanup\endcsname% }% \scope[{/yquant/.cd, #2, /tikz/.cd, /yquant/every circuit}]% } \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}% - \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}% + \ifnum\csname\yquant@prefix registers\endcsname>0 % + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + \yquant@register@execclear@lastgate{\i}{@end}% + }% + \csgappto{\yquant@prefix draw}{% + \yquant@circuit@endwires% + }% + \expandafter\unless\expandafter\ifx\csname\yquant@prefix outputs\endcsname\relax% + \begingroup% + \def\yquant@config@operator@minimum@width{0pt}% + \let\yquant@prepare@single=\yquant@prepare@output@single% + \let\yquant@prepare@multi=\yquant@prepare@output@multi% + \csname\yquant@prefix outputs\endcsname% + \endgroup% \fi% - \yquant@cleanup@csadd{xmax}% - \csxappto{\yquant@prefix draw}{% - \yquant@circuit@endwires{\yquant@env@end@xpos}% + \csgappto{\yquant@prefix draw}{% + \yquant@circuit@endwires@finalize% }% - \csname\yquant@prefix outputs\endcsname% % also calculate the true y positions \unless\ifdefined\yquant@parent% \yquant@env@end@calcypositions% @@ -139,6 +142,7 @@ \ifyquantdebug% \csshow{\yquant@prefix draw}% \fi% + \yquantmeasuringfalse% \csname\yquant@prefix draw\endcsname% \expandafter\expandafter\expandafter\yquant@cleanup\csname\yquant@prefix cleanup\endcsname|% \global\yquant@env=0 % @@ -146,128 +150,342 @@ \endgroup% } +\protected\def\ifyquant@env@seamless{% + \csname\yquant@prefix seamless\endcsname% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +\newif\ifyquant@env@end@calcypositions@godeep \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% + \yquant@sort@clear% + % Setup... + \yquant@env@end@calcypositions@setup1% + % and go! + \let\redolist=\empty% + \yquant@env@end@calcypositions@godeeptrue% + \yquant@env@end@calcypositions@run1% + \yquant@env@end@calcypositions@godeepfalse% + \yquant@env@end@calcypositions@redo% +% % The macros now set up performed all the proper and unambiguous justification. After that, we will also need to take care of the multi gates. We expect that for most of all multi gates, we already have enough space. But sometimes, this may not be the case, so we need to increase overall spacing and re-evaluate all spacing. In order to get a proper balanced layout, we start with the largest enlargement that is required. Every enlargement step will equally distribute the registers in between. Starting with the largest one, this is likely to also solve issues with smaller ones. + \yquant@env@end@calcypositions@multi% % 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 +\protected\def\yquant@env@end@calcypositions@setup#1{% \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% + % Our problem is a linear program. To solve it, we proceed iteratively: We define macros for each subcircuit that, based on the current positions, calculate the allowed positions. + \letcs\max{\yquant@prefix registers}% + % BEGIN_FOLD find out about the first and last register with maps + \let\firstinout=\relax% + \let\lastinout=\relax% + \yquant@for \i := 1 to \max {% + \ifcsname\yquant@prefix registermap@\i\endcsname% + \ifx\firstinout\relax% + \let\firstinout=\i% + \fi% + \let\lastinout=\i% + \fi% }% - \edef\lastinput{% - \expandafter\expandafter\expandafter% - \@firstoftwo\csname\yquant@prefix lastinput\endcsname% + % END_FOLD + % BEGIN_FOLD Take care with internal registers before the first inout + % We could in principle merge the loop to define \firstinout/\lastinout, but nested for loops are problematic. + \ifx\firstinout\relax% + \dimen0=\yquant@register@get@height1 % + \def\i{1}% + \else% + \edef\outerlevel{\yquant@register@get@parent{\firstinout}}% + \dimen0=\csname yquant@env\expandafter\@firstoftwo\outerlevel @env@endy@\expandafter\@secondoftwo\outerlevel\endcsname\relax% + \ifnum\firstinout>1 % + % We need to take special care with internal registers if the first one is not a connected one. In this case, the internal registers will grow upwards instead... Since the y position may change in both upward and downward direction, we need to have an additional bookkeeping value that stores the last y position of the first item in this subcircuit. + \csedef{\yquant@prefix env@endyprev}{\the\dimen0}% + \yquant@fordown \i := \numexpr\firstinout-1\relax downto 1 {% + \advance \dimen0 by -\dimexpr% + \expandafter\yquant@register@get@height\expandafter{\the\numexpr\i+1\relax}+% + \dimen4+% + \yquant@register@get@depth\i% + \relax% + % We know for sure there's none with a parent in this loop + \csedef{\yquant@prefix env@endy@\i}{\the\dimen0}% + \csedef{yquant@env@end@calcypositions@#1@\i}{% + \advance\dimen0 by -\dimexpr% + \noexpand\yquant@register@get@height{\the\numexpr\i+1\relax}+% + \dimen4+% + \noexpand\yquant@register@get@depth{\i}% + \relax% + % The first connected wire might have been re-aligned, which destroys all our knowledge. \dimen2 will contain the relative shift that we must take into account. + % Make sure the current y position is at most the previous y position + previous depth + separation + current height. + \noexpand\ifdim\dimexpr\dimen0-\dimen2\relax<\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\space% + \edef\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname{\noexpand\the\dimen0}% + \ifinlist{#1}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{#1}% + }% + \noexpand\else% + \noexpand\ifdim\dimen2=0pt % + % No change at all + \dimen0=\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\space% + \noexpand\else% + % We must still overwrite the position macro due to the shift + \dimen0=\dimexpr\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname+\dimen2\relax% + \edef\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname{\noexpand\the\dimen0}% + \ifinlist{#1}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{#1}% + }% + \noexpand\fi + \noexpand\fi% + \unless\ifx\i1% + \expandafter\noexpand\csname yquant@env@end@calcypositions@#1@\the\numexpr\i-1\relax\endcsname% + \fi% + }% + }% + \fi% + \let\i=\firstinout% + \fi% + % END_FOLD + % BEGIN_FOLD Define initial macro + \csedef{yquant@env@end@calcypositions@#1}{% + \def\noexpand\yquant@prefix{\yquant@prefix}% + \dimen0=\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\relax% + \listremove\noexpand\redolist{#1}% + \expandafter\noexpand\csname yquant@env@end@calcypositions@#1@\i\endcsname% + \expandafter\unless\expandafter\ifx\csname\yquant@prefix subcircuits\endcsname\empty% + \ifinlist{#1}\noexpand\redolist{% + \noexpand\forlistloop% + \yquant@env@end@calcypositions@run% + \expandafter\noexpand\csname\yquant@prefix subcircuits\endcsname% + }{% + \noexpand\ifyquant@env@end@calcypositions@godeep% + \noexpand\forlistloop% + \yquant@env@end@calcypositions@run% + \expandafter\noexpand\csname\yquant@prefix subcircuits\endcsname% + \noexpand\fi% + }% + \fi% }% - % 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% + % END_FOLD + % BEGIN_FOLD Set up chain of other macros + % We set up a chain of position evaluation macros. We start with the first [external] register in the outermost circuit; it is supposed to call the evaluation macro of its successor. Next, we iterate through all subcircuits (recursively). Whenever we find a register that is mapped to an outer one, we take appropriate measures. + \yquant@for \i := \i to \max {% + \ifcsname\yquant@prefix registermap@\i\endcsname% + % \outery = env@endy macro of parent wire + \edef\outerlevel{\yquant@register@get@parent{\i}}% + \edef\outery{% + \expandafter\noexpand\csname yquant@env\expandafter\@firstoftwo\outerlevel @env@endy@\expandafter\@secondoftwo\outerlevel\endcsname% + }% + % in this initialization step, we only check in one direction + \ifdim\dimen0<\outery\space% + \dimen0=\outery\space% + \fi% + \fi% + \csedef{\yquant@prefix env@endy@\i}{\the\dimen0}% + \unless\ifx\i\max% + \advance \dimen0 by \dimexpr% + \yquant@register@get@depth\i+% + \dimen4+% + \expandafter\yquant@register@get@height\expandafter{\the\numexpr\i+1\relax}% + \relax% + \fi% + \csedef{yquant@env@end@calcypositions@#1@\i}{% + % make sure the current y position is at least the previous y position + previous depth + separation + current height + \noexpand\ifdim\dimen0>\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\space% + \edef\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname{\noexpand\the\dimen0}% + \ifinlist{#1}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{#1}% + }% + \noexpand\else% + \dimen0=\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\space% + \noexpand\fi% + % now \dimen0 holds the current y position of register \i + % BEGIN_FOLD map \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}% + % if this is an in/out register, put it at the same position as the outer one + \noexpand\ifdim\dimen0<\expandafter\noexpand\outery\space% + \dimen0=\expandafter\noexpand\outery\space% + \let\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname\expandafter\noexpand\outery% + \ifinlist{#1}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{#1}% + }% + \noexpand\fi% + \noexpand\ifdim\dimen0>\expandafter\noexpand\outery\space% + \let\expandafter\noexpand\outery\expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname% + \ifinlist{\expandafter\@firstoftwo\outerlevel}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{\expandafter\@firstoftwo\outerlevel}% + }% + \noexpand\fi% + \ifx\i\firstinout% + % This is the first in/out register. Find all previous internal registers and make sure the parent has enough height. + \ifnum\i>1 % + % Here, we must now call the (backwards-running) alignment macros of the previous registers. First fill \dimen2 with the relative shift of this wire's position with respect to the last iteration. + \dimen2=\dimexpr\dimen0-\expandafter\noexpand\csname\yquant@prefix env@endyprev\endcsname\relax% + % Store \dimen0... + \dimen6=\dimen0 % + % ...call previous calculations... + \expandafter\noexpand\csname yquant@env@end@calcypositions@#1@\the\numexpr\i-1\relax\endcsname% + % ...restore... + \dimen0=\dimen6 % + % ...and backup its value for the next iteration. + \edef\expandafter\noexpand\csname\yquant@prefix env@endyprev\endcsname{\noexpand\the\dimen0}% + \expandafter\noexpand\csname ifdim\endcsname\noexpand\yquant@register@peek@height\outerlevel<\dimexpr% + \noexpand\yquant@register@get@height1+% + \expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname-% + \expandafter\noexpand\csname\yquant@prefix env@endy@1\endcsname% + \relax% + \yquant@register@set@height@remote\outerlevel{\noexpand\the\dimexpr% + \noexpand\yquant@register@get@height1+% + \expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname-% + \expandafter\noexpand\csname\yquant@prefix env@endy@1\endcsname% + }% \else% - \csdimdef{y+@\outername}{\dimen0-\outery}% + \expandafter\noexpand\csname ifdim\endcsname\noexpand\yquant@register@peek@height\outerlevel<% + \noexpand\yquant@register@get@height1 % + \yquant@register@set@height@remote\outerlevel{% + \noexpand\yquant@register@get@height1% + }% \fi% - \let\yquant@env@end@calcypositions@redo=\relax% + \ifinlist{\expandafter\@firstoftwo\outerlevel}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{\expandafter\@firstoftwo\outerlevel}% + }% + \expandafter\noexpand\csname fi\endcsname% + \fi% + \ifx\i\lastinout% + % this is the last in/out register. Find all following internal registers and make sure the parent has enough depth. + \ifnum\i<\max\space% + \expandafter\noexpand\csname ifdim\endcsname\noexpand\yquant@register@peek@depth\outerlevel<\dimexpr% + \noexpand\yquant@register@get@depth{\max}+% + \expandafter\noexpand\csname\yquant@prefix env@endy@\max\endcsname-% + \expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname% + \relax% + \yquant@register@set@depth@remote\outerlevel{\noexpand\the\dimexpr% + \noexpand\yquant@register@get@depth{\max}+% + \expandafter\noexpand\csname\yquant@prefix env@endy@\max\endcsname-% + \expandafter\noexpand\csname\yquant@prefix env@endy@\i\endcsname% + }% + \else% + \expandafter\noexpand\csname ifdim\endcsname\noexpand\yquant@register@peek@depth\outerlevel<% + \noexpand\yquant@register@get@depth{\max} % + \yquant@register@set@depth@remote\outerlevel{% + \noexpand\yquant@register@get@depth{\max}% + }% + \fi% + \ifinlist{\expandafter\@firstoftwo\outerlevel}\noexpand\redolist\relax{% + \listadd\noexpand\redolist{\expandafter\@firstoftwo\outerlevel}% + }% + \expandafter\noexpand\csname fi\endcsname% \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% + % END_FOLD + \unless\ifx\i\max% + \advance\dimen0 by \dimexpr% + \noexpand\yquant@register@get@depth{\i}+% + \dimen4+% + \noexpand\yquant@register@get@height{\the\numexpr\i+1\relax}% + \relax% + \expandafter\noexpand\csname yquant@env@end@calcypositions@#1@\the\numexpr\i+1\relax\endcsname% \fi% }% + % for every multi-register space requirement, install the requirement in the sortlist + \edef\multidata{\yquant@register@get@multispace\i}% + \forlistloop{\yquant@env@end@calcypositions@setupmulti{#1}}\multidata% + }% + % END_FOLD + \forlistcsloop\yquant@env@end@calcypositions@setup{\yquant@prefix subcircuits}% +} + +\protected\def\yquant@env@end@calcypositions@setupmulti#1#2{% + \yquant@sort@eadd{% + {#1}% + {\i}% + {\expandafter\@firstoftwo\yquant@env@end@calcypositions@setupmulti@group#2\yquant@end}% + {\expandafter\@secondoftwo\yquant@env@end@calcypositions@setupmulti@group#2\yquant@end}% + }% +} + +\def\yquant@env@end@calcypositions@setupmulti@group#1:#2\yquant@end{{#1}{#2}} + +\protected\def\yquant@env@end@calcypositions@run#1{% + \csname yquant@env@end@calcypositions@#1\endcsname% +} + +\protected\def\yquant@env@end@calcypositions@redo{% + \forlistloop\yquant@env@end@calcypositions@run\redolist% + \unless\ifx\redolist\empty% + \expandafter\yquant@env@end@calcypositions@redo% \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% +\def\yquant@env@end@calcypositions@multiheight#1#2#3#4{% + \dimexpr% + \csname yquant@env#1@env@endy@#3\endcsname- + \csname yquant@env#1@env@endy@#2\endcsname+% + \yquant@register@peek@height{#1}{#2}+% + \yquant@register@peek@depth{#1}{#3}% + \relax% +} + +\def\yquant@env@end@calcypositions@sortmulti#1#2{% + % sort, in descending order, by the amount of missing space + \ifdim\dimexpr\@fourthoffour#2-\yquant@env@end@calcypositions@multiheight#2\relax>% + \dimexpr\@fourthoffour#1-\yquant@env@end@calcypositions@multiheight#1\relax% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% \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% +\protected\def\yquant@env@end@calcypositions@multi{% + % We will always only operate on the first item in the sortlist, which is determined anew in each iteration - as changes due to this first item will potentially affect all others, including which one is the next... + \yquant@sort@findfirst\yquant@env@end@calcypositions@sortmulti\first% + \unless\ifx\first\empty% + \dimdef\missing{% + \expandafter\@fourthoffour\first-% + \expandafter\yquant@env@end@calcypositions@multiheight\first% + }% + % maybe this was already resolved? + \ifdim\missing>0pt % + \edef\yquant@prefix{yquant@env\expandafter\@firstoffour\first @}% + \numdef\divisor{\expandafter\@thirdoffour\first-\expandafter\@secondoffour\first}% not +1, since we will not move the first element + \dimdef\add{1sp+\dimexpr\missing-1sp\relax/\divisor}% + \let\inc=\add% + \edef\max{\expandafter\@thirdoffour\first}% + \ifnum\expandafter\@secondoffour\first<\max\relax% + \yquant@for \i := \numexpr\expandafter\@secondoffour\first+1\relax to \max {% + \csdimdef{\yquant@prefix env@endy@\i}{\csname\yquant@prefix env@endy@\i\endcsname+\add}% + \dimdef\add{\add+\inc}% + }% + \fi% + \yquant@env@end@calcypositions@godeeptrue% + \csname yquant@env@end@calcypositions@\expandafter\@firstoffour\first\endcsname% + \yquant@env@end@calcypositions@godeepfalse% + \yquant@env@end@calcypositions@redo% + \expandafter\expandafter\expandafter\yquant@env@end@calcypositions@multi% \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% - }% + \ifyquantdebug% + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + \ifcsname\yquant@prefix registermap@\i\endcsname% + \message{^^J y(#1, \i): external}% + \else% + \message{^^J y(#1, \i): \csname\yquant@prefix env@endy@\i\endcsname}% + \yquant@register@set@y\i{-\csname\yquant@prefix env@endy@\i\endcsname}% + \fi% + }% + \else% + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + \unless\ifcsname\yquant@prefix registermap@\i\endcsname% + \yquant@register@set@y\i{-\csname\yquant@prefix env@endy@\i\endcsname}% + \fi% + }% + \fi% \forlistcsloop\yquant@env@end@setypositions{\yquant@prefix subcircuits}% } @@ -303,6 +521,9 @@ \let\path=\tikz@command@path% \let\tikz@finish=\yquant@env@substikz@finish% \let\tikz@lib@scope@check=\yquant@env@substikz@scopecheck% + % we rely on the origin being the origin + \pgf@pt@x=0pt % + \pgf@pt@y=0pt % } % 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. diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex b/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex index 2ea08e8b16c..f19ebfcc386 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex @@ -14,21 +14,66 @@ \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% + },% + frameless/.code={% + \pgfkeysalso{/yquant/operators/subcircuit/frameless}% + \appto\yquant@attrs@remaining{,/yquant/operators/subcircuit/frameless}% + },% + seamless/.code={% + \pgfkeysalso{/yquant/operators/subcircuit/seamless}% + \appto\yquant@attrs@remaining{,/yquant/operators/subcircuit/seamless}% + },% + direct control/.code={% + \let\yquant@lang@attr@directcontrol=\relax% + },% + indirect control/.code={% + \undef\yquant@lang@attr@directcontrol% }% - inout/.default=\regidx,% } \yquant@langhelper@declare@attr@global{% - name/.store in=\yquant@lang@attr@name% -} + name/.store in=\yquant@lang@attr@name,% + overlay/.code={% + \ifstrequal{#1}{true}{% + \yquant@lang@attr@overlay@multitrue% + \yquant@lang@attr@overlay@heighttrue% + \yquant@lang@attr@overlay@depthtrue% + }{% + \ifstrequal{#1}{false}{% + % Why??? This is the default and should always be reset automatically! + \yquant@lang@attr@overlay@multifalse% + \yquant@lang@attr@overlay@heightfalse% + \yquant@lang@attr@overlay@depthfalse% + }{% + \pgfqkeys{/yquant/global attrs/overlay}{#1}% + }% + }% + },% + overlay/.default=true,% + overlay/multi/.is if=yquant@lang@attr@overlay@multi,% + overlay/m/.forward to=/yquant/global attrs/overlay/multi,% + overlay/height/.is if=yquant@lang@attr@overlay@height,% + overlay/ht/.forward to=/yquant/global attrs/overlay/height,% + overlay/h/.forward to=/yquant/global attrs/overlay/height,% + overlay/depth/.is if=yquant@lang@attr@overlay@depth,% + overlay/dp/.forward to=/yquant/global attrs/overlay/depth,% + overlay/d/.forward to=/yquant/global attrs/overlay/depth,% + overlay/single/.code={\pgfkeysalso{% + /yquant/global attrs/overlay/height={#1},% + /yquant/global attrs/overlay/depth={#1}% + }},% + overlay/single/.default=true,% + overlay/s/.forward to=/yquant/global attrs/overlay/single,% +} +\newif\ifyquant@lang@attr@overlay@multi% +\newif\ifyquant@lang@attr@overlay@height% +\newif\ifyquant@lang@attr@overlay@depth% \protected\def\yquant@lang@reset@attrs{% \undef\yquant@lang@attr@value% @@ -36,6 +81,9 @@ \undef\yquant@lang@attr@type% \yquant@lang@reset@attrs@inputoutput% \let\yquant@lang@attr@name=\empty% + \yquant@lang@attr@overlay@multifalse% + \yquant@lang@attr@overlay@heightfalse% + \yquant@lang@attr@overlay@depthfalse% } \protected\def\yquant@lang@reset@attrs@inputoutput{% @@ -50,7 +98,7 @@ % END_FOLD % BEGIN_FOLD Declaration of registers -\yquant@langhelper@declare@command@uncontrolled{nobit}\yquant@lang@@nobit +\yquant@langhelper@declare@command@create{nobit}\yquant@lang@@nobit \yquant@langhelper@setup@attrs{nobit}{}{ancilla,out} \def\yquant@lang@@nobit#1{% \let\yquant@lang@create@type=\yquant@register@type@none% @@ -64,7 +112,7 @@ \yquant@lang@create@parse@name#1[;% } -\yquant@langhelper@declare@command@uncontrolled{qubit}\yquant@lang@@qubit +\yquant@langhelper@declare@command@create{qubit}\yquant@lang@@qubit \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% @@ -75,18 +123,18 @@ \yquant@lang@create@parse@name#1[;% } -\yquant@langhelper@declare@command@uncontrolled{cbit}\yquant@lang@@cbit +\yquant@langhelper@declare@command@create{cbit}\yquant@lang@@cbit \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}% + \def\yquant@lang@create@style{cbit}% \unless\ifdefined\yquant@lang@attr@value% \let\yquant@lang@attr@value=\yquant@config@register@default@name% \fi% \yquant@lang@create@parse@name#1[;% } -\yquant@langhelper@declare@command@uncontrolled{qubits}\yquant@lang@@qubits +\yquant@langhelper@declare@command@create{qubits}\yquant@lang@@qubits \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% @@ -136,193 +184,87 @@ \else% \def\regidx{\reg[\idx]}% \fi% - % 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}{}% + \numdef\yquant@circuit@operator@mintarget{\csname\yquant@prefix registers\endcsname+1}% + % create the registers + \begingroup% + % if we have the after attribute, we start with a discarded wire + \ifdefined\yquant@lang@attr@after% + \ifdefined\yquant@lang@attr@input% + \PackageError{yquant.sty}{An input register cannot be created with `after` attribute}{}% + \fi% + \let\yquant@lang@create@type=\yquant@register@type@none% \fi% + \yquant@for \idx := \idx to \numexpr \len -1\relax {% + \yquant@prepare@create\reg\idx\yquant@lang@create@type% + }% + \endgroup% + % gather details about the created registers + \letcs\yquant@circuit@operator@maxtarget{\yquant@prefix registers}% + \numdef\yquant@circuit@operator@numtarget{\yquant@circuit@operator@maxtarget-\yquant@circuit@operator@mintarget+1}% + \edef\yquant@circuit@operator@targets{% + \yquant@list@range% + \yquant@circuit@operator@mintarget% + \yquant@circuit@operator@maxtarget% + }% + \let\yquant@circuit@operator@pctrls=\empty% + \def\yquant@circuit@operator@minpctrl{2147483647}% + \def\yquant@circuit@operator@maxpctrl{0}% + \let\yquant@circuit@operator@numpctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@nctrls=\empty% + \let\yquant@circuit@operator@minnctrl=\yquant@circuit@operator@minpctrl% + \let\yquant@circuit@operator@maxnctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@numnctrl=\yquant@circuit@operator@numpctrl% + \let\yquant@circuit@operator@minctrl=\yquant@circuit@operator@mintarget% + \let\yquant@circuit@operator@maxctrl=\yquant@circuit@operator@maxtarget% + % if we have the after attribute, we fake an align gate + \ifdefined\yquant@lang@attr@after% + \edef\jointindices{\yquant@circuit@operator@targets\yquant@lang@attr@after}% + \yquant@circuit@align\jointindices% + % and we also need to change the wire after the alignment + \let\yquant@circuit@settype@to=\yquant@lang@create@type% + \let\yquant@prepare@callback@prepare=\yquant@circuit@settype@prepare% + \let\yquant@prepare@callback@draw=\yquant@circuit@settype% + \expandafter\@thirdofthree% \else% - \let\yquant@lang@create@x=\yquant@env@create@x% + \expandafter\@firstofone% \fi% - \begingroup% + % unless there is no name, no text and no after attribute, we now need an init gate + {% + \ifx\yquant@lang@attr@value\empty% + \expandafter\@firstofone% + \else% + \expandafter\@secondoftwo% + \fi% + }% + {% \ifx\yquant@lang@attr@name\empty% - \let\yquant@lang@create@name=\empty% + \expandafter\@gobble% \else% - \def\yquant@lang@create@name{\yquant@lang@attr@name-\idx}% + \expandafter\@firstofone% \fi% - % pre-set y position - \yquant@for \idx := \idx to \numexpr \len -1\relax {% - \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 - \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 - \csxappto{\yquant@prefix draw}{% - \yquant@lang@create@draw{\csname\yquant@prefix registers\endcsname}% - {\yquant@lang@create@x}% - {\yquant@lang@create@style}% - \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% + }% + {% + % there are no multi inits in this context + \preto\yquant@attrs@remaining{internal/move label,}% + \def\yquant@config@operator@minimum@width{0pt}% + \unless\ifx\yquant@lang@attr@value\empty% + % make sure to immediately remove the "clear" marker again if we have a text + \yquant@for \i := \yquant@circuit@operator@mintarget to \yquant@circuit@operator@maxtarget {% + \yquant@register@execclear@lastgate{\i}{init}% }% - }% + \fi% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/every label, /yquant/every initial label,% + /yquant/every \yquant@lang@create@style\space label,% + \ifnum\yquant@compat<2 \ifdefined\yquant@lang@attr@input /yquant/every input label\fi\fi}% \unless\ifx\yquant@lang@attr@name\empty% \ifnum\len=1 % \csxappto{\yquant@prefix draw}% {\yquant@draw@alias{\yquant@lang@attr@name}}% \fi% \fi% - \endgroup% -} - -\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}}% - \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]% - (\createxpos, \wireypos)% - coordinate[name prefix=, name suffix=, name=yquantbox];% - \let\pgfshapeclippathhorzresult=\empty% - }{% - \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% - }% - \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 @@ -348,23 +290,21 @@ \protected\long\def\yquantdefinegate@i#1[#2]#3{% \pgfkeys{/yquant/operators/every #1/.style={#2}}% + \yquant@prepare@ifs@set% \protected@edef\yquantdefinegate@do{% \yquant@langhelper@declare@command% {#1}% - \expandafter\noexpand\csname yquant@lang@@#1\endcsname% + \yquant@register@get@multiaslist% + {% + \let\noexpand\yquant@lang@attr@value=\expandafter\noexpand\csname yquant@lang@@#1\endcsname% + \yquant@prepare@subcircuit{/yquant/operators/every #1}% + }% % 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{% + \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% } @@ -374,8 +314,15 @@ \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]}% + \yquantdefinebox@{#1}{}% +} + +\def\yquantdefinemultibox#1{% + \ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Gate redefined}% + {The gate `#1' already exists. Use \string\yquantredefinemultibox\space if you really want to redefine it.}% + \fi% + \yquantdefinebox@{#1}\yquant@register@get@allowmultitrue% } \def\yquantredefinebox#1{% @@ -383,38 +330,47 @@ \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]}% + \yquantdefinebox@{#1}{}% } -\protected\long\def\yquantdefinebox@i#1[#2]#3{% - \pgfkeys{/yquant/operators/every #1/.style={#2}}% +\def\yquantredefinemultibox#1{% + \unless\ifcsname yquant@lang@#1\endcsname% + \PackageError{yquant.sty}{Unknown gate redefined}% + {The gate `#1' is unknown and cannot be redefined. Use \string\yquantdefinemultibox\space to define it.}% + \fi% + \yquantdefinebox@{#1}\yquant@register@get@allowmultitrue% +} + +\def\yquantdefinebox@#1#2{% + \@ifnextchar[{\yquantdefinebox@i{#1}{#2}}% + {\yquantdefinebox@i{#1}{#2}[/yquant/operators/every box]}% +} + +\protected\long\def\yquantdefinebox@i#1#2[#3]#4{% + \pgfkeys{/yquant/operators/every #1/.style={#3}}% + \yquant@prepare@ifs@set% \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}% - }% + {\unexpanded{#2}}% + {\yquant@prepare{#4}{/yquant/operators/every #1}}% }% \yquantdefinebox@do% + \yquant@langhelper@setup@attrs{#1}{}{}% } % END_FOLD % BEGIN_FOLD Box registers % all-purpose box with arbitrary text -\yquant@langhelper@declare@command{box}\yquant@lang@@box -\yquant@langhelper@setup@attrs{box}{value}{} -\def\yquant@lang@@box{% +\yquant@langhelper@declare@command% + {box}% \yquant@register@get@allowmultitrue% - \expandafter\yquant@draw% - \expandafter{\yquant@lang@attr@value}% - {/yquant/operators/every box}% -} + {% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every box}% + } +\yquant@langhelper@setup@attrs{box}{value}{} % Hadamard \yquantdefinebox{h}{$H$} @@ -429,183 +385,255 @@ \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}{value}{} -\protected\def\yquant@lang@@subcircuit#1#2#3{% +\yquant@langhelper@declare@command% + {subcircuit}% \yquant@register@get@multiaslist% - \yquant@circuit@operator{#1}{#2}{#3}% - \yquant@draw@@subcircuit{/yquant/operators/every subcircuit}% -} + {% + \yquant@prepare@subcircuit{/yquant/operators/every subcircuit}% + } +\yquant@langhelper@setup@attrs{subcircuit}{value}{frameless,seamless} % END_FOLD % BEGIN_FOLD other geometric shapes % phase -\yquant@langhelper@declare@command{phase}\yquant@lang@@phase +\yquant@langhelper@declare@command% + {phase}% + {}% + {% + \edef\cmd{% + \yquant@prepare% + {}% + {/yquant/operators/every phase, label={\unexpanded\expandafter{\yquant@lang@attr@value}}}% + }% + \cmd% + } \yquant@langhelper@setup@attrs{phase}{value}{}% -\def\yquant@lang@@phase{% - \edef\cmd{% - \noexpand\yquant@draw% - {}% - {/yquant/operators/every phase, label={\unexpanded\expandafter{\yquant@lang@attr@value}}}% - }% - \cmd% -} % two-qubit controlled x (symmetric notation) -\yquant@langhelper@declare@command{xx}\yquant@lang@@xx -\yquant@langhelper@setup@attrs{xx}{}{} -\def\yquant@lang@@xx{% +\yquant@langhelper@declare@command% + {xx}% \yquant@register@get@multiassingle% - \yquant@draw% - {}% - {/yquant/operators/every xx}% -} + {% + \yquant@prepare% + {}% + {/yquant/operators/every xx}% + } +\yquant@langhelper@setup@attrs{xx}{}{} % two-qubit controlled phase (symmetric notation) -\yquant@langhelper@declare@command@uncontrolled{zz}\yquant@lang@@zz -\yquant@langhelper@setup@attrs{zz}{}{} -\def\yquant@lang@@zz{% +\yquant@langhelper@declare@command@uncontrolled% + {zz}% \yquant@register@get@multiassingle% - \yquant@draw% - {}% - {/yquant/operators/every zz}% - {}{}% -} + {% + \yquant@prepare% + {}% + {/yquant/operators/every zz}% + } +\yquant@langhelper@setup@attrs{zz}{}{} % slash (pseudo-operator, alternative indication for a bundle) -\yquant@langhelper@declare@command@uncontrolled{slash}\yquant@lang@@slash -\yquant@langhelper@setup@attrs{slash}{}{} -\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% - }% - \def\yquant@draw@callback@wire##1{% - \yquant@register@set@x% - {##1}% - {\the\dimexpr\yquant@register@get@x{##1}-\yquant@config@operator@sep-\pgflinewidth\relax}% +\yquant@langhelper@declare@command@uncontrolled% + {slash}% + {}% + {% + % temporarily squeeze most into the separation + \pgfkeys{% + /yquant/operator/minimum width=0pt,% + }% + \preto\yquant@attrs@remaining{internal/squeeze slash,}% + \yquant@prepare% + {}% + {/yquant/operators/every slash}% } - \yquant@draw% - {}% - {/yquant/operators/every slash}% - {}{}{#1}% -} +\yquant@langhelper@setup@attrs{slash}{}{} % swap -\yquant@langhelper@declare@command{swap}\yquant@lang@@swap +\yquant@langhelper@declare@command% + {swap}% + \yquant@register@get@multiassingle + {% + \yquant@prepare% + {}% + {/yquant/operators/every swap}% + } \yquant@langhelper@setup@attrs{swap}{}{} -\def\yquant@lang@@swap{% - \yquant@register@get@multiassingle% - \yquant@draw% - {}% - {/yquant/operators/every swap}% -} % not -\yquant@langhelper@declare@command{not}\yquant@lang@@not +\yquant@langhelper@declare@command% + {not}% + {}% + {% + \yquant@prepare% + {}% + {/yquant/operators/every not}% + } \yquant@langhelper@setup@attrs{not}{}{} -\def\yquant@lang@@not{% - \yquant@draw% - {}% - {/yquant/operators/every not}% -} % alias to cnot -\let\yquant@lang@cnot=\yquant@lang@not +\yquant@langhelper@declare@command@alias{cnot}{not} \yquant@langhelper@setup@attrs{cnot}{}{} % measure -\yquant@langhelper@declare@command@uncontrolled{measure}\yquant@lang@@measure -\yquant@langhelper@setup@attrs{measure}{}{value,type} -\def\yquant@lang@@measure{% - \ifdefined\yquant@lang@attr@type% - \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% - \else% - \let\yquant@circuit@settype@to=\yquant@register@type@c% - \fi% - \let\yquant@draw@callback@wire=\yquant@circuit@settype% +\yquant@langhelper@declare@command@uncontrolled% + {measure}% \yquant@register@get@allowmultitrue% - \unless\ifcsname yquant@lang@attr@value\endcsname% - \let\yquant@lang@attr@value=\empty% - \fi% - \expandafter\yquant@draw% - \expandafter{\yquant@lang@attr@value}% - {/yquant/operators/every measure}% - {}{}% -} + {% + \ifdefined\yquant@lang@attr@type% + \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% + \else% + \let\yquant@circuit@settype@to=\yquant@register@type@c% + \fi% + \let\yquant@prepare@callback@prepare=\yquant@circuit@settype@prepare% + \let\yquant@prepare@callback@draw=\yquant@circuit@settype% + \unless\ifcsname yquant@lang@attr@value\endcsname% + \let\yquant@lang@attr@value=\empty% + \fi% + \ifdefined\yquant@lang@attr@directcontrol% + % direct control means that we must defer this operator until the next that has this/these targets as positive controls. + \expandafter\yquant@prepare@injection% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every measure}% + \else% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every measure}% + \fi% + } +\yquant@langhelper@setup@attrs{measure}{}{value,type,direct control,indirect control} % measure (dmeter) -\yquant@langhelper@declare@command@uncontrolled{dmeter}\yquant@lang@@dmeter -\yquant@langhelper@setup@attrs{dmeter}{}{value,type} -\def\yquant@lang@@dmeter{% - \ifdefined\yquant@lang@attr@type% - \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% - \else% - \let\yquant@circuit@settype@to=\yquant@register@type@c% - \fi% - \let\yquant@draw@callback@wire=\yquant@circuit@settype% +\yquant@langhelper@declare@command@uncontrolled% + {dmeter}% \yquant@register@get@allowmultitrue% - \unless\ifcsname yquant@lang@attr@value\endcsname% - \let\yquant@lang@attr@value=\empty% - \fi% - \expandafter\yquant@draw% - \expandafter{\yquant@lang@attr@value}% - {/yquant/operators/every dmeter}% - {}{}% -} + {% + \ifdefined\yquant@lang@attr@type% + \yquant@register@type@fromstring\yquant@lang@attr@type\yquant@circuit@settype@to% + \else% + \let\yquant@circuit@settype@to=\yquant@register@type@c% + \fi% + \let\yquant@prepare@callback@prepare=\yquant@circuit@settype@prepare% + \let\yquant@prepare@callback@draw=\yquant@circuit@settype% + \unless\ifcsname yquant@lang@attr@value\endcsname% + \let\yquant@lang@attr@value=\empty% + \fi% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every dmeter}% + } +\yquant@langhelper@setup@attrs{dmeter}{}{value,type} % END_FOLD % BEGIN_FOLD miscellaneous -\yquant@langhelper@declare@command@uncontrolled{barrier}\yquant@lang@@barrier -\yquant@langhelper@setup@attrs{barrier}{}{} -\def\yquant@lang@@barrier{% +\yquant@langhelper@declare@command@uncontrolled% + {barrier}% \yquant@register@get@allowmultitrue% - \yquant@draw% - {}% - {/yquant/operators/every barrier}% - {}{}% -} + {% + \yquant@prepare% + {}% + {/yquant/operators/every barrier}% + }% +\yquant@langhelper@setup@attrs{barrier}{}{} -\yquant@langhelper@declare@command@uncontrolled{correlate}\yquant@lang@@correlate +\yquant@langhelper@declare@command@uncontrolled% + {correlate}% + {% + % do not call \yquant@register@get@multiassingle, we do not want to install a different multi line style! + \yquant@register@get@allowmultitrue% + \let\yquant@register@multi@splitparts=\yquant@register@multi@splitparts@sepall% + }{% + \yquant@prepare% + {}% + {/yquant/operators/every wave}% + } \yquant@langhelper@setup@attrs{correlate}{}{} -\def\yquant@lang@@correlate{% - % do not call \yquant@register@get@multiassingle, we do not want to install a different multi line style! - \yquant@register@get@allowmultitrue% - \let\yquant@register@multi@splitparts=\yquant@register@multi@splitparts@sepall% - \yquant@draw% - {}% - {/yquant/operators/every wave}% - {}{}% -} -\yquant@langhelper@declare@command@uncontrolled{align}\yquant@lang@@align +\yquant@langhelper@declare@command@uncontrolled% + {align}% + {}% + {% + \yquant@circuit@align\yquant@circuit@operator@targets% + } \yquant@langhelper@setup@attrs{align}{}{} -\def\yquant@lang@@align#1{% - \yquant@register@get@ids{#1}% - \yquant@circuit@align\yquant@register@get@ids@list% -} -\yquant@langhelper@declare@command@uncontrolled{hspace}\yquant@lang@@hspace +\yquant@langhelper@declare@command@uncontrolled% + {hspace}% + {% + \yquant@langhelper@validate\amount\dimen\yquant@lang@attr@value% + }{% + \yquant@circuit@hspace\yquant@circuit@operator@targets\amount% + } \yquant@langhelper@setup@attrs{hspace}{value}{} -\def\yquant@lang@@hspace#1{% - \yquant@langhelper@validate\amount\dimen\yquant@lang@attr@value% - \yquant@register@get@ids{#1}% - \yquant@circuit@hspace\yquant@register@get@ids@list\amount% -} -\yquant@langhelper@declare@command@uncontrolled{discard}\yquant@lang@@discard +\yquant@langhelper@declare@command@uncontrolled% + {discard}% + {\yquant@langhelper@execclear@lastgatefalse}% + {% + \let\yquant@circuit@settype@to=\yquant@register@type@none% + \yquant@circuit@actonwires% + \yquant@circuit@settype@prepare% + \yquant@circuit@settype% + \yquant@circuit@operator@targets% + {}% + } \yquant@langhelper@setup@attrs{discard}{}{} -\def\yquant@lang@@discard#1{% - \yquant@register@get@ids{#1}% - \let\yquant@circuit@settype@to=\yquant@register@type@none% - \yquant@circuit@actonwires% - \yquant@circuit@settype% - \yquant@register@get@ids@list% - \yquant@register@type@none% -} -\yquant@langhelper@declare@command@uncontrolled{init}\yquant@lang@@init +\yquant@langhelper@declare@command@uncontrolled% + {init}% + {% + \yquant@register@get@allowmultitrue% + % we will count how many registers contain the "clean" flag, and only if this is equal to the number of targets, we apply the shift. + \count8=0 % + }% + {% + \ifdefined\yquant@lang@attr@type% + \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% + \forlistloop\yquant@lang@@init@loop\yquant@circuit@operator@targets% + \ifx\yquant@circuit@settype@to\yquant@register@type@none% + % now we don't have a clue; assume it's a qubit + \let\yquant@circuit@settype@to=\yquant@register@type@q% + \fi% + \edef\yquant@lang@attr@type{% + \yquant@register@type@tostring\yquant@circuit@settype@to% + }% + \fi% + \let\yquant@prepare@callback@prepare=\yquant@circuit@settype@prepare% + \let\yquant@prepare@callback@draw=\yquant@circuit@settype% + \let\yquant@prepare@multi=\yquant@prepare@multiinit% + \ifnum\count8=\numexpr\yquant@circuit@operator@maxctrl-\yquant@circuit@operator@minctrl+1\relax% + \def\yquant@config@operator@minimum@width{0pt}% + \preto\yquant@attrs@remaining{internal/move label,}% + \edef\cmd{% + \yquant@prepare% + {\unexpanded\expandafter{\yquant@lang@attr@value}}% + {/yquant/every label, /yquant/every initial label,% + /yquant/every \yquant@lang@attr@type\space label}% + }% + \else% + \edef\cmd{% + \yquant@prepare% + {\unexpanded\expandafter{\yquant@lang@attr@value}}% + {/yquant/every label, /yquant/every \yquant@lang@attr@type\space label}% + }% + \fi% + \cmd% + } \yquant@langhelper@setup@attrs{init}{value}{type} + +\protected\def\yquant@lang@@init@loop#1{% + \ifyquant@firsttoken\yquant@register@multi{#1}{% + \let\yquant@register@multi@contiguous=\yquant@lang@@init@multi@@extract% + \@fifthoffive#1% + % we should reset multi@contiguous to the original command; but this is really just a placeholder. As long as it is \protected, everything is fine. + }{% + \edef\yquant@circuit@settype@to{\yquant@register@get@type{#1}}% + }% + \unless\ifx\yquant@circuit@settype@to\yquant@register@type@none% + \expandafter\listbreak% + \fi% +} + \protected\def\yquant@lang@@init@multi@@extract#1#2#3{% \yquant@for \yquant@i := #1 to #2 {% \edef\yquant@circuit@settype@to{\yquant@register@get@type\yquant@i}% @@ -615,95 +643,64 @@ }% } -\protected\def\yquant@lang@@init#1{% +\yquant@langhelper@declare@command@uncontrolled% + {output}% \yquant@register@get@allowmultitrue% - \yquant@register@get@ids{#1}% - \ifdefined\yquant@lang@attr@type% - \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% - \def\do##1{% - \ifyquant@firsttoken\yquant@register@multi{##1}{% - \let\yquant@register@multi@contiguous=\yquant@lang@@init@multi@@extract% - \@fifthoffive##1% - % we should reset multi@contiguous to the original command; but this is really just a placeholder. As long as it is \protected, everything is fine. - }{% - \edef\yquant@circuit@settype@to{\yquant@register@get@type{##1}}% - }% - \unless\ifx\yquant@circuit@settype@to\yquant@register@type@none% - \expandafter\listbreak% - \fi% - }% - \dolistloop\yquant@register@get@ids@list% - \ifx\yquant@circuit@settype@to\yquant@register@type@none% - % now we don't have a clue; assume it's a qubit - \let\yquant@circuit@settype@to=\yquant@register@type@q% - \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% - \yquant@circuit@operator{}{}{#1}% - % special case: if there were no operations at any affected wire before, we will replace the wire description - \ifdim\yquant@circuit@operator@x=\yquant@config@operator@sep\relax% - \def\yquant@circuit@operator@x{-.5\dimen2}% - \let\yquant@draw@finalize@ctrl@single=\yquant@draw@finalize@ctrl@singleinit% - \let\yquant@draw@finalize@ctrl@multi=\yquant@draw@finalize@ctrl@multiinit% - \expandafter\yquant@draw@% - \expandafter{\yquant@lang@attr@value}% - {/yquant/every label, /yquant/every initial label, /yquant/every \yquant@lang@attr@type\space label}% - \else% - \expandafter\yquant@draw@% - \expandafter{\yquant@lang@attr@value}% - {/yquant/every label, /yquant/every \yquant@lang@attr@type\space label}% - \fi% -} - -\yquant@langhelper@declare@command@uncontrolled{output}\yquant@lang@@output + \yquant@circuit@output% \yquant@langhelper@setup@attrs{output}{value}{} -\def\yquant@lang@@output#1{% - \yquant@register@get@allowmultitrue% - \yquant@register@get@ids{#1}% - \expandafter\yquant@circuit@output\expandafter{\yquant@register@get@ids@list}% -} -\yquant@langhelper@declare@command@uncontrolled{settype}\yquant@lang@@settype +\yquant@langhelper@declare@command@uncontrolled% + {inspect}% + \yquant@register@get@allowmultitrue% + {% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every inspect}% + } +\yquant@langhelper@setup@attrs{inspect}{value}{} + +\yquant@langhelper@declare@command@uncontrolled% + {settype}% + {\yquant@langhelper@execclear@lastgatefalse}% + {% + \yquant@register@type@fromstring\yquant@lang@attr@value\yquant@circuit@settype@to% + \yquant@circuit@actonwires% + \yquant@circuit@settype@prepare% + \yquant@circuit@settype% + \yquant@circuit@operator@targets% + {}% + } \yquant@langhelper@setup@attrs{settype}{value}{} -\protected\def\yquant@lang@@settype#1{% - \yquant@register@get@ids{#1}% - \yquant@register@type@fromstring\yquant@lang@attr@value\yquant@circuit@settype@to% - \yquant@circuit@actonwires% - \yquant@circuit@settype% - \yquant@register@get@ids@list% - {}% -} - -\def\yquant@lang@setwire{% - \PackageWarning{yquant.sty}{`setwire' gate is deprecated as of yquant 0.1.2. Use `settype' instead.}% - \yquant@lang@settype% -} -\yquant@langhelper@setup@attrs{setwire}{value}{} -\yquant@langhelper@declare@command@uncontrolled{setstyle}\yquant@lang@@setstyle +\ifnum\yquant@compat<2 % + \def\yquant@lang@setwire{% + \PackageWarning{yquant.sty}{`setwire' gate is deprecated as of yquant 0.1.2. Use `settype' instead.}% + \yquant@lang@settype% + } + \yquant@langhelper@setup@attrs{setwire}{value}{} +\fi + +\yquant@langhelper@declare@command@uncontrolled% + {setstyle}% + {\yquant@langhelper@execclear@lastgatefalse}% + {% + \yquant@circuit@actonwires% + \@gobbletwo% + \yquant@circuit@setstyle% + \yquant@circuit@operator@targets% + {{\yquant@lang@attr@value}}% + } \yquant@langhelper@setup@attrs{setstyle}{value}{} -\protected\def\yquant@lang@@setstyle#1{% - \yquant@register@get@ids{#1}% - \yquant@circuit@actonwires% - \yquant@circuit@setstyle% - \yquant@register@get@ids@list% - {{\yquant@lang@attr@value}}% -} -\yquant@langhelper@declare@command@uncontrolled{addstyle}\yquant@lang@@addstyle +\yquant@langhelper@declare@command@uncontrolled% + {addstyle}% + {\yquant@langhelper@execclear@lastgatefalse}% + {% + \yquant@circuit@actonwires% + \@gobbletwo% + \yquant@circuit@addstyle% + \yquant@circuit@operator@targets% + {{\yquant@lang@attr@value}}% + } \yquant@langhelper@setup@attrs{addstyle}{value}{} -\protected\def\yquant@lang@@addstyle#1{% - \yquant@register@get@ids{#1}% - \yquant@circuit@actonwires% - \yquant@circuit@addstyle% - \yquant@register@get@ids@list% - {{\yquant@lang@attr@value}}% -} % END_FOLD
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex index 86114241940..72a5969cb60 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex @@ -1,4 +1,4 @@ -% Parsing attributes +% BEGIN_FOLD Parsing attributes \let\yquant@langhelper@list@attrs=\empty \protected\long\def\yquant@langhelper@check@attrs[#1]{% @@ -166,8 +166,9 @@ \PackageError{yquant.sty}{Required attribute `#1' missing}% {You used a command that requires specifying the attribute `#1'.}% }% +% END_FOLD -% Parsing command itself +% BEGIN_FOLD Parsing command itself \protected\def\yquant@langhelper@check@name#1 {% \lowercase{\edef\cmd{#1}}% \unless\ifcsname yquant@lang@\cmd\endcsname% @@ -209,35 +210,84 @@ % Check all necessary attributes were given. \csname yquant@langhelper@setup@attrs@check@\cmd\endcsname% % Finally execute the command - \csname yquant@lang@\cmd\endcsname% + \letcs\cmd{yquant@lang@\cmd}% + \yquant@langhelper@declare@command@@parse% } +% END_FOLD +% BEGIN_FOLD Declarations +\newif\ifyquant@langhelper@execclear@lastgate % Defining commands that accept registers and take an optional value % #1: name of the argument -% #2: command that is to be called with three parameters: the indices of the positive and negative controls and registers, all as named lists -\protected\def\yquant@langhelper@declare@command#1#2{% +% #2: command (sequence) that is to be called before the target macros are filled +% #3: command (sequence) that is to be called after the target macros are filled +\protected\def\yquant@langhelper@declare@command#1#2#3{% \begingroup% \lowercase{\edef\cmd{#1}}% - \long\protected\csgdef{yquant@lang@\cmd}{% - \let\cmd=#2% - \yquant@langhelper@declare@command@@parse% + \long\protected\csxdef{yquant@lang@\cmd}##1##2##3{% + \noexpand\yquant@langhelper@execclear@lastgatetrue% + \unexpanded{#2}% + \yquant@circuit@operator{##1}{##2}{##3}% + \noexpand\ifyquant@langhelper@execclear@lastgate% + \yquant@for \noexpand\i := \noexpand\yquant@circuit@operator@minctrl to \noexpand\yquant@circuit@operator@maxctrl {% + \yquant@register@execclear@lastgate{\noexpand\i}{\cmd}% + }% + \noexpand\fi% + \unexpanded{#3}% }% \endgroup% } -% Defining commands that accept registers and take an additional value +% Defining commands that accept registers and take an optional value, but don't allow for controls % #1: name of the argument -% #2: command that is to be called with three parameters: the indices of the positive and negative controls and registers, all as named lists -\protected\def\yquant@langhelper@declare@command@uncontrolled#1#2{% +% #2: command (sequence) that is to be called before the target macros are filled +% #3: command (sequence) that is to be called after the target macros are filled +\protected\def\yquant@langhelper@declare@command@uncontrolled#1#2#3{% \begingroup% \lowercase{\edef\cmd{#1}}% - \long\protected\csgdef{yquant@lang@\cmd}{% - \def\cmd{\yquant@langhelper@declare@command@@uncontrolled{#2}}% - \yquant@langhelper@declare@command@@parse% + \long\protected\csxdef{yquant@lang@\cmd}##1##2##3{% + \noexpand\ifstrempty{##1}\relax{% + \noexpand\PackageError{yquant.sty}{Positive controls are not allowed for the command `\cmd`}{}% + }% + \noexpand\ifstrempty{##2}\relax{% + \noexpand\PackageError{yquant.sty}{Negative controls are not allowed for the command `\cmd`}{}% + }% + \noexpand\yquant@langhelper@execclear@lastgatetrue% + \unexpanded{#2}% + \yquant@circuit@operator{}{}{##3}% + \noexpand\ifyquant@langhelper@execclear@lastgate% + \yquant@for \noexpand\i := \noexpand\yquant@circuit@operator@minctrl to \noexpand\yquant@circuit@operator@maxctrl {% + \yquant@register@execclear@lastgate{\noexpand\i}{\cmd}% + }% + \noexpand\fi% + \unexpanded{#3}% }% \endgroup% } +% Defining commands that accept an undefined register and take an optional value, but don't allow for controls +% #1: name of the argument +% #2: macro that is to be called with parameter #1 being the name of the register +\protected\def\yquant@langhelper@declare@command@create#1#2{% + \begingroup% + \lowercase{\edef\cmd{#1}}% + \long\protected\csxdef{yquant@lang@\cmd}##1##2{% + \noexpand\ifstrempty{##1}\relax{% + \noexpand\PackageError{yquant.sty}{Positive controls are not allowed for the command `\cmd`}{}% + }% + \noexpand\ifstrempty{##2}\relax{% + \noexpand\PackageError{yquant.sty}{Negative controls are not allowed for the command `\cmd`}{}% + }% + \noexpand#2% + }% + \endgroup% +} + +% make #1 an identical command to #2 (does not copy attributes) +\protected\def\yquant@langhelper@declare@command@alias#1#2{% + \global\csletcs{yquant@lang@#1}{yquant@lang@#2}% +} + \long\def\yquant@langhelper@declare@command@@parse#1;{% \yquant@langhelper@declare@command@@extract@nctrl#1~;% \yquant@env@rescan% @@ -267,16 +317,7 @@ }% \expandafter\cmd\params% } - -\protected\def\yquant@langhelper@declare@command@@uncontrolled#1#2#3{% - \ifstrempty{#2}\relax{% - \PackageError{yquant.sty}{Positive controls are not allowed for this command}{}% - }% - \ifstrempty{#3}\relax{% - \PackageError{yquant.sty}{Negative controls are not allowed for this command}{}% - }% - #1% -} +% END_FOLD % shorthands for validation of property values % #1: a macro that will contain the sanitized value diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex b/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex new file mode 100644 index 00000000000..c9db0883b67 --- /dev/null +++ b/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex @@ -0,0 +1,883 @@ +% Most drawing operations will be realized through nodes +\let\yquant@prepare@callback@prepare=\@gobble +\let\yquant@prepare@callback@draw=\@gobble% + +% #1: register name +% #2: register index +% #3: register type +\protected\def\yquant@prepare@create#1#2#3{% + \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 `#1[#2]`.}% + \fi% + \begingroup% + \let\yquant@prefix=\yquant@parent % + \unless\if#3\yquant@register@get@type\outermap% + \PackageError{yquant.sty}% + {Subcircuit expects wire of type `\yquant@register@type@tostring#3', but got `\yquant@register@type@tostring{\yquant@register@get@type\outermap}'}% + {Outer and inner wire types must match for input wire `#1[#2]`.}% + \fi% + \endgroup% + \unless\ifdefined\yquant@lang@attr@output% + \listcsxadd{\yquant@prefix inonly}% + {\the\numexpr\csname\yquant@prefix registers\endcsname+1\relax}% + \fi% + \yquant@register@alias{#3}{#1}{#2}\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 `#1[#2]`.}% + \fi% + \begingroup% + \let\yquant@prefix=\yquant@parent% + \unless\if\yquant@register@type@none\yquant@register@get@type\outermap% + \PackageError{yquant.sty}% + {Subcircuit expects discarded wire, got `\yquant@register@type@tostring{\yquant@register@get@type\outermap}'}% + {Outer wire must be discarded before being acceptable for output-only register `#1[#2]`.}% + \fi% + \endgroup% + \yquant@register@alias{#3}{#1}{#2}\outermap% + \else% + \yquant@register@define{#3}{#1}{#2}% + \fi% + \fi% + % we must be allowed to change the wire types during preparation for various reasons, so we need to reset it here (TODO: can we eliminate all those reasons?) + \csxappto{\yquant@prefix draw}{% + \yquant@draw@init{\csname\yquant@prefix registers\endcsname}{#3}% + }% +} + +% generic shape of an operator +% #1: value +% #2: tikz options that select the correct shape +\protected\long\def\yquant@prepare#1#2{% + \yquant@sort@clear% + \def\yquant@prepare@injectcontrols@count{0}% + \def\idx{0}% + \yquant@prepare@ifs@direct% + \dimen2=\yquant@config@operator@minimum@width% + \ifyquant@circuit@operator@hasControls% + \edef\yquant@prepare@list{% + \yquant@list@range% + \yquant@circuit@operator@minctrl% + \yquant@circuit@operator@maxctrl% + }% + \else% + \let\yquant@prepare@list=\empty% + \fi% + % 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@prepare@multi{#1}{#2}{##1}% + }{% + \yquant@prepare@single{#1}{#2}{##1}% + }% + \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@prepare@controls% + \yquant@prepare@finalize{#1}{#2}% +} + +\newcount\yquant@prepare@injections +% generic shape of an operator - but delayed to some later point +% #1: value +% #2: tikz options that select the correct shape +\protected\long\def\yquant@prepare@injection#1#2{% + \global\advance\yquant@prepare@injections by 1 % we just keep increasing, doesn't really matter + \edef\yquant@draw@group{\yquant@draw@injectiongroup{\the\yquant@prepare@injections}}% + \def\yquant@draw@endgroup{\noexpand\yquant@draw@endinjectiongroup}% + \yquant@prepare{#1}{#2}% + \csxdef{yquant@prepare@@injection@\the\yquant@prepare@injections}{% + {\the\dimen2}{\unexpanded\expandafter{\yquant@circuit@operator@targets}}% + }% + \forlistloop\yquant@prepare@injection@loop\yquant@circuit@operator@targets% +} + +\protected\def\yquant@prepare@injection@loop#1{% + \ifyquant@firsttoken\yquant@register@multi{#1}{% + \edef\first{\@secondoffive#1}% + \edef\last{\@thirdoffive#1}% + \yquant@for \i := \first to \last {% + \yquant@register@set@lastgate\i{% + % we only need this once, but it may be called multiple times if acting on multiple registers + \noexpand\ifcsname yquant@prepare@@injection@\the\yquant@prepare@injections\noexpand\endcsname% + % first check whether this is valid - i.e., the list of targets for this measurement is in fact a subset of the list of positive controls for the next operation + \ifyquant@registersubset% + {\unexpanded\expandafter{\yquant@circuit@operator@targets}}% + {\noexpand\yquant@circuit@operator@pctrls}{% + \yquant@prepare@inject{\the\yquant@prepare@injections}% + }{% + \yquant@prepare@inject@discard{\the\yquant@prepare@injections}% + }% + \yquant@prepare@injection@clean{\first}{\last}% + \noexpand\fi + \noexpand\@gobble% + }% + }% + }{% + \yquant@register@set@lastgate{#1}{% + \noexpand\ifcsname yquant@prepare@@injection@\the\yquant@prepare@injections\noexpand\endcsname% + % first check whether this is valid - i.e., the list of targets for this measurement is in fact a subset of the list of positive controls for the next operation + \ifyquant@registersubset% + {\unexpanded\expandafter{\yquant@circuit@operator@targets}}% + {\noexpand\yquant@circuit@operator@pctrls}{% + \yquant@prepare@inject{\the\yquant@prepare@injections}% + }{% + \yquant@prepare@inject@discard{\the\yquant@prepare@injections} + }% + \noexpand\fi% + \noexpand\@gobble% + }% + }% +} + +\protected\def\yquant@prepare@injection@clean#1#2{% + \yquant@for \i := #1 to #2 {% + \yquant@register@set@lastgate\i{}% + }% +} + +\protected\def\yquant@prepare@inject#1{% + \letcs\yquant@prepare@inject@@data{yquant@prepare@@injection@#1}% + \csgundef{yquant@prepare@@injection@#1}% + \dimen0=\expandafter\@firstoftwo\yquant@prepare@inject@@data\relax% + \let\@tmpconti=\yquant@register@multi@contiguous% + \protected\def\yquant@register@multi@contiguous##1##2{% + \yquant@for \i := ##1 to ##2 {% + \cslet{yquant@prepare@replacecontrol@\i}\empty% + }% + }% + \expandafter\expandafter\expandafter\etb@forlistloop% + \expandafter\expandafter\expandafter{% + \expandafter\@secondoftwo% + \yquant@prepare@inject@@data% + }{\yquant@prepare@inject@loop{#1}}% + \let\yquant@register@multi@contiguous=\@tmpconti% +} + +\protected\def\yquant@prepare@inject@loop#1#2{% + \ifyquant@firsttoken\yquant@register@multi{#2}{% + \@fifthoffive#2% this clears all the actions for the individual contiguous slices + % but we need to do something for the first register + \csedef{yquant@prepare@replacecontrol@\@secondoffive#2}{% + \noexpand\ifdim\the\dimen0>\dimen2 % + \dimen2=\the\dimen0 \relax% + \noexpand\fi% + \yquant@sort@eadd{% + \yquant@draw@inject{#1}% + } + }% + }{% + \csedef{yquant@prepare@replacecontrol@#2}{% + \noexpand\ifdim\the\dimen0>\dimen2 % + \dimen2=\the\dimen0 \relax% + \noexpand\fi% + \yquant@sort@eadd{% + \yquant@draw@inject{#1}% + }% + }% + }% +} + +\protected\def\yquant@prepare@inject@discard#1{% + \csappto{\yquant@prefix draw}{% + \yquant@draw@inject@outer{#1}% + }% + \csgundef{yquant@prepare@@injection@#1}% +} + +\def\yquant@prepare@sort#1#2{% + \yquant@prepare@sort@aux#1\relax#2\relax% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +\def\yquant@prepare@sort@aux#1#2#3\relax#4#5#6\relax{% + \unless\ifnum#2>#5\relax% +} + +\protected\def\yquant@prepare@controls@loop#1#2{% + \ifx\yquant@lang@attr@name\empty% + \let\nodename=\empty% + \else% + \edef\nodename{\yquant@lang@attr@name-#1\idx}% + \fi% + \ifcsname yquant@prepare@replacecontrol@#2\endcsname% + \ifcsempty{yquant@prepare@replacecontrol@#2}\relax{% + % do something unorthodox + \csname yquant@prepare@replacecontrol@#2\endcsname% + \numdef\idx{\idx+1}% + \unless\ifdefined\yquant@prepare@controltype% + \edef\yquant@prepare@controltype{#2}% + \fi% + }% + \else% + \yquant@sort@eadd{% + \expandafter\noexpand\csname yquant@draw@#1control\endcsname% + {#2}% register index + {\nodename}% + }% + \numdef\idx{\idx+1}% + \unless\ifdefined\yquant@prepare@controltype% + \edef\yquant@prepare@controltype{#2}% + \fi% + \fi% +} + +\protected\def\yquant@prepare@controls{% + \ifyquant@circuit@operator@hasControls% + \def\idx{0}% + \forlistloop{\yquant@prepare@controls@loop p}\yquant@circuit@operator@pctrls% + \def\idx{0}% + \forlistloop{\yquant@prepare@controls@loop n}\yquant@circuit@operator@nctrls% + \unless\ifdefined\yquant@prepare@controltype% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Controlled action without controls found.}% + \fi% + \fi% +} + +\ifnum\yquant@compat>1 % + \expandafter\@firstoftwo +\else + \expandafter\@secondoftwo +\fi{ + \def\yquant@prepare@ifs@Ifnum{\noexpand\ifnum} + \def\yquant@prepare@ifs@Ifcase{\noexpand\ifcase} + \def\yquant@prepare@ifs@Or{\noexpand\or} + \def\yquant@prepare@ifs@Else{\noexpand\else} + \def\yquant@prepare@ifs@Fi{\noexpand\fi} + \def\yquant@prepare@ifs@Unless{\noexpand\unless} + \def\yquant@prepare@ifs@The{\noexpand\the} + \protected\def\yquant@prepare@ifs@set{% + \let\Ifnum=\yquant@prepare@ifs@Ifnum% + \let\Ifcase=\yquant@prepare@ifs@Ifcase% + \let\Or=\yquant@prepare@ifs@Or% + \let\Else=\yquant@prepare@ifs@Else% + \let\Fi=\yquant@prepare@ifs@Fi% + \let\Unless=\yquant@prepare@ifs@Unless% + \let\The=\yquant@prepare@ifs@The% + } + \protected\def\yquant@prepare@ifs@direct{% + \let\Ifnum=\ifnum% + \let\Ifcase=\ifcase% + \let\Or=\or% + \let\Else=\else% + \let\Fi=\fi% + \let\Unless=\unless% + \let\The=\the% + } +}{ + \let\yquant@prepare@ifs@set=\relax% + \let\yquant@prepare@ifs@direct=\relax% +} +\protected\long\def\yquant@prepare@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{}%# + \yquant@prepare@ifs@set% + \let\yquant@prepare@append=\empty% + \yquant@sort\yquant@prepare@sort% + \def\do##1{% + \appto\yquant@prepare@append{##1}% + \yquant@prepare@finalize@ctrl##1% + }% + \yquant@sort@dolistloop% + \protected@csxappto{\yquant@prefix draw}{% + \yquant@draw@group% + {\the\dimen2}% + \ifyquant@circuit@operator@hasControls% + \yquant@register@get@type\yquant@prepare@controltype% + \else% + F% + \fi% if-switch whether controls are present + {\yquant@attrs@remaining}% custom style + {#2}% operator style + {#1}% + {\yquant@prepare@list}% + \unexpanded\expandafter{\yquant@prepare@append}% + \yquant@draw@endgroup% + \ifyquant@circuit@operator@hasControls% + T% + \else% + F% + \fi% + \ifx\yquant@lang@attr@name\empty% + {}0% + \else% + {\yquant@lang@attr@name}% + \ifnum\yquant@circuit@operator@numtarget=1 % + \ifnum\yquant@circuit@operator@numpctrl=1 % + \ifnum\yquant@circuit@operator@numnctrl=1 % + 7% + \else% + 6% + \fi% + \else% + \ifnum\yquant@circuit@operator@numnctrl=1 % + 5% + \else% + 4% + \fi% + \fi% + \else% + \ifnum\yquant@circuit@operator@numpctrl=1 % + \ifnum\yquant@circuit@operator@numnctrl=1 % + 3% + \else% + 2% + \fi% + \else% + \ifnum\yquant@circuit@operator@numnctrl=1 % + 1% + \else% + 0% + \fi% + \fi% + \fi% + \fi% + }% +} + +\protected\def\yquant@prepare@single#1#2#3{% + \yquant@sort@eadd{% + \yquant@draw@single% + {#3}% register index + {\nodename}% + }% + \unless\ifyquant@circuit@operator@hasControls% + \listadd\yquant@prepare@list{#3}% + \fi% + % determine the actual dimensions by a virtual draw command + \pgfinterruptboundingbox% + \yquant@config@operator@multifalse% + \yquant@env@virtualize@path% + \path% + (0pt, 0pt)% + node[/yquant/every operator, #2, /yquant/this operator,% + name prefix=, name suffix=, name=] {#1};% + \yquant@register@update@height{#3}{\the\pgf@picmaxy}% + \yquant@register@update@depth{#3}{\the\dimexpr-\pgf@picminy\relax}% +} + +\protected\def\yquant@prepare@multi#1#2#3{% + \yquant@sort@eadd{% + \yquant@draw@multi% + #3% + {\nodename}% + }% + \unless\ifyquant@circuit@operator@hasControls% + \eappto\yquant@prepare@list{% + \expandafter\yquant@list@range\@secondandthirdoffive#3% + }% + \fi% + \pgfinterruptboundingbox% + \yquant@config@operator@multitrue% + \yquant@env@virtualize@path% + \def\yquant@prepare@content{#1}% + \def\yquant@prepare@style{#2}% + \let\yquant@register@multi@contiguous=\yquant@prepare@multi@contiguous% + \@fifthoffive#3% + \ifdim\pgf@picmaxy=-16000pt % + % if there was no single contiguous part before, determine the width now + \path% + (0pt, 0pt)% + node[/yquant/every operator, #2, /yquant/this operator,% + name prefix=, name suffix=, name=] {#1};% + \fi% +} + +\protected\def\yquant@prepare@multi@contiguous#1#2#3{% + \global\pgf@picmaxy=-16000pt % + \global\pgf@picminy=16000pt % + \edef\cmd{% + \noexpand\path (0pt, 0pt)% + node[/yquant/every operator, \yquant@prepare@style, /yquant/this operator,% + /yquant/internal/multi main=\ifnum#3=1 true\else false\fi,% + name prefix=, name suffix=, name=]% + {\unexpanded\expandafter{\yquant@prepare@content}};% + }% + \cmd% + \ifnum#1=#2 % + % this is a single register in disguise + \yquant@register@update@height{#1}{\the\pgf@picmaxy}% + \yquant@register@update@depth{#1}{\the\dimexpr-\pgf@picminy\relax}% + \else% + \yquant@register@update@multispace{#1}{#2}{\the\dimexpr\pgf@picmaxy-\pgf@picminy\relax}% + \fi% +} + +\protected\def\yquant@prepare@multiinit#1#2#3{% + \yquant@sort@eadd{% + \yquant@draw@multiinit% + #3% + {\nodename}% + }% + \unless\ifyquant@circuit@operator@hasControls% + \eappto\yquant@prepare@list{% + \expandafter\yquant@list@range\@secondandthirdoffive#3% + }% + \fi% + \pgfinterruptboundingbox% + \yquant@config@operator@multitrue% + \yquant@env@virtualize@path% + \edef\first{\@secondoffive#3}% + \def\pgfdecorationsegmentaspect{0.5}% + \def\pgfdecorationsegmentfromto{0-1}% + \ifnum\yquant@compat<2 % + \path (0pt, 0pt)% + node[/yquant/every operator, #2, /yquant/every multi label,% + /yquant/this operator, name prefix=, name suffix=, name=] {#1};% + \else% + \path (0pt, 0pt)% + node[/yquant/every operator, #2,% + /yquant/this operator, name prefix=, name suffix=, name=] {#1};% + \fi% + \ifnum\@secondoffive#3=\@thirdoffive#3 % + % this is a single register in disguise + \yquant@register@update@height{\first}{\the\pgf@picmaxy}% + \yquant@register@update@depth{\first}{\the\dimexpr-\pgf@picminy\relax}% + \else% + % this may not be sufficient. Since the text position need not necessarily be at the center (if the register corresponding to the visual center is excluded), we may require some space here which we will later only use in parts, but then extend where we should not. However, resolving this would require a special handling when calculating the y positions at the end, meaning we could not use the multispace facility. Let's assume discontiguous init registers are so scarce that this does not matter (disable the acquiration by using the operator/overlay key). + \edef\upd{% + \yquant@register@update@multispace% + {\first}{\@thirdoffive#3}% + {\the\dimexpr\pgf@picmaxy-\pgf@picminy\relax}% + }% + \upd% + \fi% +} + +\protected\long\def\yquant@prepare@output@single#1#2#3{% + \yquant@sort@eadd{% + \yquant@draw@output@single% + {#3}% register index + {\nodename}% + }% + \listadd\yquant@prepare@list{#3}% + % determine the actual dimensions by a virtual draw command + \pgfinterruptboundingbox% + \yquant@config@operator@multifalse% + \yquant@env@virtualize@path% + % #2 is empty anyway + \edef\cmd{% + \noexpand\path (0pt, 0pt)% + node[\ifnum\yquant@compat>1 /yquant/every operator, \fi /yquant/every output,% + /yquant/every \yquant@register@type@tostring{\yquant@register@get@type{#3}} output,% + \ifnum\yquant@compat>1 /yquant/this operator, \fi% + name prefix=, name suffix=, name=] {\unexpanded{#1}};% + }% + \cmd% + \yquant@register@update@height{#3}{\the\pgf@picmaxy}% + \yquant@register@update@depth{#3}{\the\dimexpr-\pgf@picminy\relax}% +} + +\protected\long\def\yquant@prepare@output@multi#1#2#3{% + \yquant@sort@eadd{% + \yquant@draw@output@multi% + #3% + {\nodename}% + }% + \eappto\yquant@prepare@list{% + \expandafter\yquant@list@range\@secondandthirdoffive#3% + }% + \pgfinterruptboundingbox% + \yquant@config@operator@multitrue% + \yquant@env@virtualize@path% + % We need to draw a line with some vertical extent, so just take the current height, whether it makes sense or not. We only need an estimate + \edef\first{\@secondoffive#3}% + \def\pgfdecorationsgmentaspect{0.5}% + \def\pgfdecorationsegmentfromto{0-1}% + % #2 is empty anyway + \edef\cmd{% + \noexpand\path (0pt, 0pt) + node[\ifnum\yquant@compat>1 /yquant/every operator, /yquant/every output, \fi% + \ifnum\yquant@compat<2 /yquant/every multi output,\fi% + \ifnum\yquant@compat>1 /yquant/this operator,\fi% + name prefix=, name suffix=, name=] {\unexpanded{#1}};% + }% + \cmd% + \ifnum\@secondoffive#3=\@thirdoffive#3 % + % this is a single register in disguise + \yquant@register@update@height{\first}{\the\pgf@picmaxy}% + \yquant@register@update@depth{\first}{\the\dimexpr-\pgf@picminy\relax}% + \else% + % this may not be sufficient. Since the text position need not necessarily be at the center (if the register corresponding to the visual center is excluded), we may require some space here which we will later only use in parts, but then extend where we should not. However, resolving this would require a special handling when calculating the y positions at the end, meaning we could not use the multispace facility. Let's assume discontiguous output registers are so scarce that this does not matter (disable the acquiration by using the operator/overlay key). + \edef\upd{% + \yquant@register@update@multispace% + {\first}{\@thirdoffive#3}% + {\the\dimexpr\pgf@picmaxy-\pgf@picminy\relax}% + }% + \upd% + \fi% +} + +% BEGIN_FOLD replacement commands for draw actions that just keep track of the width +\protected\long\def\yquant@prepare@subcircuit@init#1#2{% + \csdef{\yquant@prefix xpos@#1}{0pt}% + \yquant@register@set@type{#1}{#2}% +} + +\protected\def\yquant@prepare@subcircuit@getmaxx#1{% + \begingroup% + \dimen0=-16383.99999pt % + \def\do##1{% + \ifcsname\yquant@prefix xpos@##1\endcsname% + \dimen2=\csname\yquant@prefix xpos@##1\endcsname\relax% + \ifdim\dimen0<\dimen2 % + \dimen0=\dimen2 % + \fi% + \else% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Undefined internal wire x position.}% + \fi% + }% + \dolistloop{#1}% + \expandafter% + \endgroup% + \expandafter\def\expandafter\newx\expandafter{\the\dimen0}% +} + +\protected\def\yquant@prepare@subcircuit@move@loop#1{% + \cslet{\yquant@prefix xpos@#1}\newx% +} + +\protected\long\def\yquant@prepare@subcircuit@group#1#2#3#4#5#6#7\yquant@draw@endgroup{% + \begingroup% + \yquant@prepare@subcircuit@getmaxx{#6}% + % If the quotes library is loaded, activate it. (else, this is by default \relax) + \tikz@enable@node@quotes% + \yquant@config@operator@position@rightalignfalse% + \yquant@config@operator@position@advancetrue% + \yquant@set{#3}% + \let\next=\endgroup% + \ifyquant@config@operator@position@rightalign% + \ifdim#1>-\pgf@picminx% + \global\pgf@picminx=-\dimexpr#1\relax% + \fi% + \else% + \ifyquant@env@seamless{% + \ifdim\newx=0pt % + \dimdef\newx{% + \newx+#1% + }% + \else% + \dimdef\newx{% + \newx+\yquant@config@operator@sep+#1% + }% + \fi% + }{% + \dimdef\newx{% + \newx+\yquant@config@operator@sep+#1% + }% + }% + \ifdim\newx>\pgf@picmaxx% + \global\pgf@picmaxx=\newx% + \fi% + \ifyquant@config@operator@position@advance% + \edef\next{% + \endgroup% + \def\noexpand\newx{\newx}% + \noexpand\forlistloop\yquant@prepare@subcircuit@move@loop{#6}% + }% + \fi% + \fi% + \next% + \@gobblethree% three arguments for the endgroup +} + +\protected\def\yquant@prepare@subcircuit@hspace#1#2{% + \yquant@prepare@subcircuit@getmaxx{#1}% + \dimdef\newx{\newx+#2}% + \forlistloop\yquant@prepare@subcircuit@move@loop{#1}% + \ifdim\newx>\pgf@picmaxx % + \global\pgf@picmaxx=\newx % + \fi% +} + +\protected\def\yquant@prepare@subcircuit@endwires{% + \expandafter\ifx\csname\yquant@prefix outputs\endcsname\relax% + % to have a symmetric situation, we extend again one separation at the end, unless this is supposed to be seamless and we don't have outputs (for seamless circuits with outputs, extend - since this extension will be between last register and output) + \ifyquant@env@seamless\relax{% + \global\advance\pgf@picmaxx by \yquant@config@operator@sep\relax% + }% + \else% + % if we have outputs, those will be realized as additional drawing groups following this macro, so increasing the picture at this point is rather pointless. Instead, we adjust the wire positions appropriately. The additional separation will be inserted by the outputs. + \begingroup% + \dimen0=-16383.99999pt % + \yquant@fordown \i := \csname\yquant@prefix registers\endcsname downto 1 {% + \ifcsname\yquant@prefix xpos@\i\endcsname% + \dimen2=\csname\yquant@prefix xpos@\i\endcsname\relax% + \ifdim\dimen0<\dimen2 % + \dimen0=\dimen2 % + \fi% + \else% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Undefined internal wire x position.}% + \fi% + }% + \expandafter% + \endgroup% + \expandafter\def\expandafter\newx\expandafter{\the\dimen0}% + \yquant@fordown \i := \csname\yquant@prefix registers\endcsname downto 1 {% + \cslet{\yquant@prefix xpos@\i}\newx% + }% + \fi% + \let\yquant@circuit@endwires@finalize=\relax% + \forlistcsloop\yquant@prepare@subcircuit@endwires@loop{\yquant@prefix inonly}% +} + +\protected\def\yquant@prepare@subcircuit@endwires@loop#1{% + \eappto\yquant@circuit@endwires@finalize{% + \yquant@register@set@type{#1}\noexpand\yquant@register@type@none% + }% +} +% END_FOLD + +\newbox\yquant@prepare@subcircuit@box + +\protected\long\def\yquant@prepare@subcircuit#1{% + \yquant@sort@clear% + \def\idx{0}% + \dimen2=\yquant@config@operator@minimum@width% + \ifyquant@circuit@operator@hasControls% + \edef\yquant@prepare@list{% + \yquant@list@range% + \yquant@circuit@operator@minctrl% + \yquant@circuit@operator@maxctrl% + }% + \else% + \let\yquant@prepare@list=\empty% + \fi% + % 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@prepare@subcircuit@multi{#1}{##1}% + }{% + \yquant@prepare@subcircuit@single{#1}{##1}% + }% + \pgfinterruptboundingbox% + % In order to determine the width of the subcircuit, we must execute the draw command at preparation time, where we will remap all relevant commands to virtual ones so that this has no effect and is not very costly. Although nothing should be drawn, as a precaution, we "draw" everything in a box that is dropped afterwards. + % There will still be some extra width and height taken by separations or other things related to the box itself. + \yquant@env@virtualize@path% + \begingroup% + \let\yquant@parent=\yquant@prefix% + \edef\yquant@prefix{yquant@env\yquant@circuit@subcircuit@id @}% + \let\yquant@draw@init=\yquant@prepare@subcircuit@init% + \let\yquant@draw@group=\yquant@prepare@subcircuit@group% + \let\yquant@draw@alias=\@gobble% + \let\yquant@draw@hspace=\yquant@prepare@subcircuit@hspace% + \let\yquant@circuit@endwires=\yquant@prepare@subcircuit@endwires% + \let\yquant@circuit@flushwire=\@gobble% + \let\yquant@circuit@setstyle=\@gobbletwo% + \let\yquant@circuit@addstyle=\@gobbletwo% + % do not overwrite \yquant@register@set@type, which may also occur - we want to change the register type! + % restore tikz commands... as in env@end + \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% + \global\pgf@picmaxx=0pt % + \global\pgf@picminx=0pt % + \global\setbox\yquant@prepare@subcircuit@box=\vbox to 1sp{% + \csname\yquant@prefix draw\endcsname% + }% + \ifdim\pgf@picmaxy=-16000pt % + \global\pgf@picmaxy=0pt % + \global\pgf@picminy=0pt % + \fi% + \ifyquant@env@seamless{% + % for seamless circuits, we do not have an initial separation. However, if there is an label to registers (which you should not do for seamless subcircuits), the "initial" separation is in fact an inner one, so we need it. + \ifdim\pgf@picminx<0pt % + \global\advance\pgf@picmaxx by \yquant@config@operator@sep\relax% + \fi% + }\relax% + \global\wd\yquant@prepare@subcircuit@box=\dimexpr\pgf@picmaxx-\pgf@picminx\relax% + \endgroup% + \edef\yquant@prepare@subcircuit@width{% + {\the\wd\yquant@prepare@subcircuit@box}% inner width + {\noexpand\the\dimexpr\pgf@picmaxx-\pgf@picminx\relax}% outer width + {\the\pgf@picminx}% left margin + }% + \pgfresetboundingbox% + \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=, y radius=0pt]% + {\box\yquant@prepare@subcircuit@box};% + % the extra height is taken care for by manually inserting it to the height of the first and last register in the subcircuit + \yquant@register@inject@extents{\pgf@picmaxy}{-\pgf@picminy}% + \edef\cmd{% + \dimen0=\the\dimexpr\pgf@picmaxx-\pgf@picminx\relax\relax% + \yquant@prepare@subcircuit@add% + }% + \expandafter% + \endpgfinterruptboundingbox% + \cmd% + \ifdim\dimen0>\dimen2 % + \dimen2=\dimen0 % + \fi% + \numdef\idx{\idx+1}% + }% + \dolistloop\yquant@circuit@operator@targets% + % END_FOLD + \yquant@prepare@controls% + \preto\yquant@attrs@remaining{internal/no advance,}% + \yquant@prepare@finalize{}{#1}% +} + +\protected\def\yquant@prepare@subcircuit@single#1#2{% + \yquant@config@operator@multifalse% + \edef\yquant@circuit@subcircuit@param{#2\yquant@list@delim}% + \yquant@circuit@subcircuit{#1}% + \unless\ifyquant@circuit@operator@hasControls% + \listadd\yquant@prepare@list{#2}% + \fi% + \edef\yquant@prepare@subcircuit@add{% + \yquant@sort@eadd{% + \yquant@draw@subcircuit@single% + {#2}% register index + {\yquant@circuit@subcircuit@id}% + {\nodename}% + {\noexpand\yquant@prepare@subcircuit@width}% + }% + }% +} + +\protected\def\yquant@prepare@subcircuit@multi#1#2{% + \yquant@config@operator@multitrue% + \edef\yquant@circuit@subcircuit@param{\@fifthoffive#2}% + \yquant@sort@list\yquant@circuit@subcircuit@param\yquant@sort@ascending% + \yquant@circuit@subcircuit{#1}% + \unless\ifyquant@circuit@operator@hasControls% + \eappto\yquant@prepare@list{% + \expandafter\yquant@list@range\@secondandthirdoffive#2% + }% + \fi% + \edef\yquant@prepare@subcircuit@add{% + \yquant@sort@eadd{% + \yquant@draw@subcircuit@multi% + #2% + {\yquant@circuit@subcircuit@id}% + {\nodename}% + {\noexpand\yquant@prepare@subcircuit@width}% + }% + }% +} + +\protected\def\yquant@prepare@finalize@ctrl#1{% + \let\next=\yquant@prepare@finalize@ctrl@single% + \ifx\yquant@draw@multi#1% + \let\next=\yquant@prepare@finalize@ctrl@multi% + \else% + \ifx\yquant@draw@multiinit#1% + \let\next=\yquant@prepare@finalize@ctrl@multi% + \else% + \ifx\yquant@draw@output@multi#1% + \let\next=\yquant@prepare@finalize@ctrl@multi% + \else% + \ifx\yquant@draw@subcircuit@multi#1% + \let\next=\yquant@prepare@finalize@ctrl@subcircuit@multi% + \else% + \ifx\yquant@draw@subcircuit@single#1% + \let\next=\yquant@prepare@finalize@ctrl@subcircuit@single% + \else% + \ifx\yquant@draw@inject#1% + \let\next=\@gobble% + \fi% + \fi% + \fi% + \fi% + \fi% + \fi% + \next% +} + +\protected\def\yquant@prepare@finalize@ctrl@single#1#2{% + \eappto\yquant@prepare@append{% + \yquant@prepare@callback@draw{#1}% + }% + \yquant@prepare@callback@prepare{#1}% +} + +\protected\def\yquant@prepare@finalize@ctrl@multi#1#2#3#4#5{% + \let\yquant@register@multi@contiguous=\yquant@prepare@finalize@ctrl@multi@contiguous% + \ifyquant@circuit@operator@hasControls% + \ifyquant@config@operator@multi@warn% + \def\yquant@prepare@finalize@ctrl@multi@contiguous@warn{0}% + \else% + \def\yquant@prepare@finalize@ctrl@multi@contiguous@warn{2}% + \fi% + \else% + \def\yquant@prepare@finalize@ctrl@multi@contiguous@warn{2}% + \fi% + \cslet{\yquant@prefix finalize@ctrl@prepare@appto}\empty% + #4% + \eappto\yquant@prepare@append{\csname\yquant@prefix finalize@ctrl@prepare@appto\endcsname}% + \csgundef{\yquant@prefix finalize@ctrl@prepare@appto}% +} + +\protected\def\yquant@prepare@finalize@ctrl@multi@contiguous#1#2#3{% + \ifnum\yquant@prepare@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@prepare@finalize@ctrl@multi@contiguous@warn{2}% + \else% + \numdef\yquant@prepare@finalize@ctrl@multi@contiguous@warn{% + \yquant@prepare@finalize@ctrl@multi@contiguous@warn+1% + }% + \fi% + {% save \body + \yquant@for \yquant@i := #1 to #2 {{% let inner loop mess up with macros + \csxappto{\yquant@prefix finalize@ctrl@prepare@appto}{% + \expandafter\yquant@prepare@callback@draw\expandafter{\yquant@i}% + }% + \expandafter\yquant@prepare@callback@prepare\expandafter{\yquant@i}% + }}% + }% +} + +\def\yquant@prepare@finalize@ctrl@subcircuit@single#1#2#3#4{% + \yquant@prepare@finalize@ctrl@single{#1}{#3}% +} + +\protected\def\yquant@prepare@finalize@ctrl@subcircuit@multi@loop#1{% + \eappto\yquant@prepare@append{% + \yquant@prepare@callback@draw{#1}% + }% + \yquant@prepare@callback@prepare{#1}% +} + +\protected\def\yquant@prepare@finalize@ctrl@subcircuit@multi#1#2#3#4#5#6#7{% + % there are no contiguous parts here, don't call the normal @multi + \forlistloop\yquant@prepare@finalize@ctrl@subcircuit@multi@loop{#4}% +}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex index c90a44614ca..2c44fd039bb 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex @@ -39,65 +39,70 @@ % BEGIN_FOLD Constructor: create single register and cleanup environment % #1: type -% #2: x position -% #3: name -% #4: index -\protected\def\yquant@register@define#1#2#3#4{% +% #2: name +% #3: index +\protected\def\yquant@register@define#1#2#3{% \csnumgdef{\yquant@prefix registers}% {\csname\yquant@prefix registers\endcsname+1}% \csxdef{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}{% {#1}% type - {#2}% x pos - {{\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 + {0pt}% x pos + {{\yquant@config@register@minimum@height}% + {\yquant@config@register@minimum@depth}% + {}}% height, depth, and multi-space parts; at the end, the y position + {{0pt}{0pt}{}{}}% wire start positions and clipping {}% wire style + {\yquant@register@flag@clean}% information about the last gate }% - \global\csletcs{\yquant@prefix registername@#3[#4]}{\yquant@prefix registers}% - \csxdef{\yquant@prefix registerhigh@#3}{#4}% + \global\csletcs{\yquant@prefix registername@#2[#3]}{\yquant@prefix registers}% + \csxdef{\yquant@prefix registerhigh@#2}{#3}% \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@#3}% + \yquant@cleanup@csadd{\yquant@prefix registername@#2[#3]}% + \ifnum0=#3\relax% + \yquant@cleanup@csadd{\yquant@prefix registerhigh@#2}% \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{% +% #4: id in the outer circuit +\protected\def\yquant@register@alias#1#2#3#4{% \csnumgdef{\yquant@prefix registers}% {\csname\yquant@prefix registers\endcsname+1}% - \ifcsname\yquant@parent registermap@#5\endcsname% + \ifcsname\yquant@parent registermap@#4\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}% + {\yquant@parent registermap@#4}% \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}% + {\yquant@parent register@#4}% \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}% + % we still store height, depth, and multi-space parts. To keep the same macros, we create a full register structure, but "abuse" the type component to contain the direct parent + \csxdef{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}{% + {{\expandafter\yquant@register@alias@extract\yquant@parent}{#4}}% direct parent (circuit id, register id) + {}% unused + {{\yquant@config@register@minimum@height}% + {\yquant@config@register@minimum@depth}% + {}}% height, depth, and multi-space parts + {}% unused + {}% unused + {}% unused + }% + \global\csletcs{\yquant@prefix registername@#2[#3]}{\yquant@prefix registers}% + \csxdef{\yquant@prefix registerhigh@#2}{#3}% + \yquant@cleanup@csadd{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}% + \yquant@cleanup@csadd{\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname}% + \yquant@cleanup@csadd{\yquant@prefix registername@#2[#3]}% + \ifnum0=#3\relax% + \yquant@cleanup@csadd{\yquant@prefix registerhigh@#2}% \fi% \expandafter\yquant@register@set@@aux% \csname\csname\yquant@prefix registermap@\csname\yquant@prefix registers\endcsname\endcsname\endcsname% - \yquant@register@set@x@aux% - {#2}% + \yquant@register@set@typelastgate@aux% + {{#1}{\yquant@register@flag@clean}}% } + +\def\yquant@register@alias@extract yquant@env#1@{#1}% % END_FOLD % BEGIN_FOLD Converter: convert a register name to its id @@ -162,19 +167,7 @@ \fi% % pre-set y position \yquant@for \idx := \idx to \numexpr \len -1\relax {% - \yquant@register@define% - \yquant@register@type@q% - {\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% - {}% - {}% - }% + \yquant@prepare@create\reg\idx\yquant@register@type@q% }% \endgroup% } @@ -680,7 +673,17 @@ \fi% } -\def\yquant@register@get@type@aux#1#2#3#4#5{#1} +\def\yquant@register@get@parent#1{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter\expandafter\expandafter% + \yquant@register@get@type@aux\csname\yquant@prefix register@#1\endcsname% + \else% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Tried to get parent of a non-connected wire.}% + \fi% +} + +\def\yquant@register@get@type@aux#1#2#3#4#5#6{#1} \def\yquant@register@get@x#1{% \ifcsname\yquant@prefix registermap@#1\endcsname% @@ -692,31 +695,38 @@ \fi% } -\def\yquant@register@get@x@aux#1#2#3#4#5{#2} +\def\yquant@register@get@x@aux#1#2#3#4#5#6{#2} \def\yquant@register@get@height#1{% - \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% + \expandafter\expandafter\expandafter% + \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@peek@height#1#2{% + \expandafter\expandafter\expandafter% + \yquant@register@get@height@aux\csname yquant@env#1@register@#2\endcsname% } -\def\yquant@register@get@height@aux#1#2#3#4#5{\@firstoftwo#3} +\def\yquant@register@get@height@aux#1#2#3#4#5#6{\@firstofthree#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% + \expandafter\expandafter\expandafter% + \yquant@register@get@depth@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@peek@depth#1#2{% + \expandafter\expandafter\expandafter% + \yquant@register@get@depth@aux\csname yquant@env#1@register@#2\endcsname% } -\def\yquant@register@get@depth@aux#1#2#3#4#5{\@secondoftwo#3} +\def\yquant@register@get@depth@aux#1#2#3#4#5#6{\@secondofthree#3} + +\def\yquant@register@get@multispace#1{% + \expandafter\expandafter\expandafter% + \yquant@register@get@multispace@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@get@multispace@aux#1#2#3#4#5#6{\@thirdofthree#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@y{% @@ -739,7 +749,7 @@ \fi% } -\def\yquant@register@get@y@aux#1#2#3#4#5{#3} +\def\yquant@register@get@y@aux#1#2#3#4#5#6{#3} % y distance between two registers. \def\yquant@register@get@ydist#1#2{% @@ -766,8 +776,8 @@ }% } -\protected\def\yquant@register@get@lastwire@aux#1#2#3#4#5#6{% - \def#6{#4}% +\protected\def\yquant@register@get@lastwire@aux#1#2#3#4#5#6#7{% + \def#7{#4}% } \def\yquant@register@get@style#1{% @@ -780,7 +790,28 @@ \fi% } -\def\yquant@register@get@style@aux#1#2#3#4#5{#5} +\def\yquant@register@get@style@aux#1#2#3#4#5#6{#5} + +\protected\long\def\yquant@register@execclear@lastgate#1#2{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \expandafter% + \yquant@register@execclear@lastgate@aux@i\csname\csname\yquant@prefix registermap@#1\endcsname\endcsname{#2}% + \else% + \expandafter% + \yquant@register@execclear@lastgate@aux@i\csname\yquant@prefix register@#1\endcsname{#2}% + \fi% +} + +\def\yquant@register@execclear@lastgate@aux@i#1{% + \expandafter\yquant@register@execclear@lastgate@aux@ii#1#1% +} + +\long\def\yquant@register@execclear@lastgate@aux@ii#1#2#3#4#5#6#7#8{% + \ifstrempty{#6}\relax{% + #6{#8}% + \xdef#7{\unexpanded{{#1}{#2}{#3}{#4}{#5}{}}}% + }% +} \def\yquant@register@get@typeywire#1{% \ifcsname\yquant@prefix registermap@#1\endcsname% @@ -797,10 +828,10 @@ }% } -\protected\def\yquant@register@get@typeywire@aux#1#2#3#4#5#6#7#8{% - \def#6{#1}% - \def#7{#3}% - \def#8{#4}% +\protected\def\yquant@register@get@typeywire@aux#1#2#3#4#5#6#7#8#9{% + \def#7{#1}% + \def#8{#3}% + \def#9{#4}% }% % Set #1 to the maximum x value found between #2 and #3 @@ -833,6 +864,12 @@ \endgroup% \expandafter\def\expandafter#1\expandafter{\the\dimen0}% } + +\protected\def\yquant@register@flag@clean#1{% + \ifstrequal{#1}{init}{% + \advance\count8 by 1 % + }\relax% +} % END_FOLD % BEGIN_FOLD Setters: change register information @@ -856,8 +893,8 @@ \yquant@register@set@type@aux% } -\long\def\yquant@register@set@type@aux#1#2#3#4#5#6{% - {#6}\unexpanded{{#2}{#3}{#4}{#5}}% +\long\def\yquant@register@set@type@aux#1#2#3#4#5#6#7{% + {#7}\unexpanded{{#2}{#3}{#4}{#5}{#6}}% } \protected\def\yquant@register@set@x#1{% @@ -876,23 +913,12 @@ \yquant@register@set@x@aux% } -\long\def\yquant@register@set@x@aux#1#2#3#4#5#6{% - \unexpanded{{#1}}{#6}\unexpanded{{#3}{#4}{#5}}% +\long\def\yquant@register@set@x@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}}{#7}\unexpanded{{#3}{#4}{#5}{#6}}% } \protected\def\yquant@register@update@height#1#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% + \unless\ifyquant@lang@attr@overlay@height% \ifdim#2>% \expandafter\expandafter\expandafter% \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% @@ -904,25 +930,22 @@ \fi% } -\long\def\yquant@register@set@height@aux#1#2#3#4#5#6{% +\protected\def\yquant@register@set@height@remote#1#2#3{% + \expandafter\yquant@register@set@@aux% + \csname yquant@env#1@register@#2\endcsname% + \yquant@register@set@height@aux{#3}% +} + +\long\def\yquant@register@set@height@aux#1#2#3#4#5#6#7{% \unexpanded{{#1}{#2}}% - {{#6}{\unexpanded\expandafter{\@secondoftwo#3}}}% - \unexpanded{{#4}{#5}}% + {{#7}% + {\unexpanded\expandafter{\@secondofthree#3}}% + {\unexpanded\expandafter{\@thirdofthree#3}}}% + \unexpanded{{#4}{#5}{#6}}% } \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% + \unless\ifyquant@lang@attr@overlay@depth% \ifdim#2>% \expandafter\expandafter\expandafter% \yquant@register@get@depth@aux\csname\yquant@prefix register@#1\endcsname% @@ -934,10 +957,75 @@ \fi% } -\long\def\yquant@register@set@depth@aux#1#2#3#4#5#6{% +\protected\def\yquant@register@set@depth@remote#1#2#3{% + \expandafter\yquant@register@set@@aux% + \csname yquant@env#1@register@#2\endcsname% + \yquant@register@set@depth@aux{#3}% +} + +\long\def\yquant@register@set@depth@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}}% + {{\unexpanded\expandafter{\@firstofthree#3}}% + {#7}% + {\unexpanded\expandafter{\@thirdofthree#3}}}% + \unexpanded{{#4}{#5}{#6}}% +} + +\protected\def\yquant@register@update@multispace#1#2#3{% + \unless\ifnum#1<#2 % + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Setting multispace part in wrong order.}% + \fi% + \unless\ifyquant@lang@attr@overlay@multi% + \begingroup% + \edef\tmp{% + \expandafter\expandafter\expandafter% + \yquant@register@get@multispace@aux\csname\yquant@prefix register@#1\endcsname% + }% + \let\old=\tmp% + \yquant@list@eupdateorinsert\tmp{#2}{#3}% + \unless\ifx\old\tmp% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + \yquant@register@set@multispace@aux\tmp% + \fi% + \endgroup% + \fi% +} + +\long\def\yquant@register@set@multispace@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}}% + {{\unexpanded\expandafter{\@firstofthree#3}}% + {\unexpanded\expandafter{\@secondofthree#3}}% + {#7}}% + \unexpanded{{#4}{#5}{#6}}% +} + +\protected\def\yquant@register@inject@extents#1#2{% + % enlarge the last subcircuit that was created previously by height #1 and depth #2. + % We enforce subcircuits to have registers, so no check needed. + \expandafter\yquant@register@set@@aux% + \csname yquant@env\the\yquant@env @register@1\endcsname% + \yquant@register@inject@height@aux{#1}% + \expandafter\yquant@register@set@@aux% + \csname yquant@env\the\yquant@env @register@\csname yquant@env\the\yquant@env @registers\endcsname\endcsname% + \yquant@register@inject@depth@aux{#2}% +} + +\long\def\yquant@register@inject@height@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}}% + {{\the\dimexpr\@firstofthree#3+#7\relax}% + {\unexpanded\expandafter{\@secondofthree#3}}% + {\unexpanded\expandafter{\@thirdofthree#3}}}% + \unexpanded{{#4}{#5}{#6}}% +} + +\long\def\yquant@register@inject@depth@aux#1#2#3#4#5#6#7{% \unexpanded{{#1}{#2}}% - {{\unexpanded\expandafter{\@firstoftwo#3}}{#6}}% - \unexpanded{{#4}{#5}}% + {{\unexpanded\expandafter{\@firstofthree#3}}% + {\the\dimexpr\@secondofthree#3+#7\relax}% + {\unexpanded\expandafter{\@thirdofthree#3}}}% + \unexpanded{{#4}{#5}{#6}}% } \protected\def\yquant@register@set@y#1{% @@ -956,8 +1044,8 @@ \yquant@register@set@y@aux% } -\long\def\yquant@register@set@y@aux#1#2#3#4#5#6{% - \unexpanded{{#1}{#2}}{#6}\unexpanded{{#4}{#5}}% +\long\def\yquant@register@set@y@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}}{#7}\unexpanded{{#4}{#5}{#6}}% } \protected\def\yquant@register@set@lastwire#1{% @@ -976,8 +1064,22 @@ \yquant@register@set@lastwire@aux% } -\long\def\yquant@register@set@lastwire@aux#1#2#3#4#5#6{% - \unexpanded{{#1}{#2}{#3}}{#6}\unexpanded{{#5}}% +\long\def\yquant@register@set@lastwire@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}{#3}}{#7}\unexpanded{{#5}{#6}}% +} + +\protected\def\yquant@register@set@typelastwire#1{% + \ifcsname\yquant@prefix registermap@#1\endcsname% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Setting type and lastwire was requested for a subcircuit.}% + \fi% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname% + \yquant@register@set@typelastwire@aux% +} + +\long\def\yquant@register@set@typelastwire@aux#1#2#3#4#5#6#7{% + {\@firstoftwo#7}\unexpanded{{#2}{#3}}{\@secondoftwo#7}\unexpanded{{#5}{#6}}% } \protected\def\yquant@register@set@style#1{% @@ -996,7 +1098,31 @@ \yquant@register@set@style@aux% } -\long\def\yquant@register@set@style@aux#1#2#3#4#5#6{% - \unexpanded{{#1}{#2}{#3}{#4}}{#6}% +\long\def\yquant@register@set@style@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}{#3}{#4}}{#7}\unexpanded{{#6}}% +} + +\protected\def\yquant@register@set@lastgate#1{% + \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@lastgate@aux% +} + +\long\def\yquant@register@set@lastgate@aux#1#2#3#4#5#6#7{% + \unexpanded{{#1}{#2}{#3}{#4}{#5}}{#7}% +} + +\long\def\yquant@register@set@typelastgate@aux#1#2#3#4#5#6#7{% + {\@firstoftwo#7}\unexpanded{{#2}{#3}{#4}{#5}}{\@secondoftwo#7}% } % END_FOLD
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex b/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex index 22b9601c4e0..88cddd66ddf 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-shapes.tex @@ -391,7 +391,7 @@ \fi% \else% \pgf@y=\dimexpr.5\ht\pgfnodeparttextbox+.5\dp\pgfnodeparttextbox+2pt\relax% - \ifyquant@config@operator@multi@main% + \ifyquant@config@internal@multi@main% \advance\pgf@y by 1.25mm % \fi% \ifdim\pgf@x<\pgf@y% @@ -400,7 +400,7 @@ \fi% }% \savedanchor\stext{% - \ifyquant@config@operator@multi@main% + \ifyquant@config@internal@multi@main% \pgfqpoint% {-.5\wd\pgfnodeparttextbox}% {\dp\pgfnodeparttextbox}% @@ -414,13 +414,13 @@ \pgf@x=\ht\pgfnodeparttextbox% }% \savedmacro\main{% - \ifyquant@config@operator@multi@main% - \def\main{\noexpand\yquant@config@operator@multi@maintrue}% + \ifyquant@config@internal@multi@main% + \def\main{\noexpand\yquant@config@internal@multi@maintrue}% \else% \ifdim\dimexpr\ht\pgfnodeparttextbox+\dp\pgfnodeparttextbox\relax=0pt% - \def\main{\noexpand\yquant@config@operator@multi@maintrue}% + \def\main{\noexpand\yquant@config@internal@multi@maintrue}% \else% - \def\main{\noexpand\yquant@config@operator@multi@mainfalse}% + \def\main{\noexpand\yquant@config@internal@multi@mainfalse}% \fi% \fi% }% @@ -430,7 +430,7 @@ \anchor{text}{% \stext% \main% - \ifyquant@config@operator@multi@main% + \ifyquant@config@internal@multi@main% \pgf@y=\dimexpr-\yradius+1pt+\pgf@y\relax% \fi% }% @@ -440,7 +440,7 @@ \beforebackgroundpath{% \main% % 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% + \ifyquant@config@internal@multi@main% % Make sure the meter does not extend beyond the box (we are in a scope here) \path [clip]% (-\xradius, \yradius) rectangle (\xradius, -\yradius);% @@ -529,9 +529,6 @@ } \pgfdeclareshape{yquant-line}{% - \savedanchor\shorten{% - \pgfqpoint\pgf@shorten@end@additional\pgf@shorten@start@additional% - }% \saveddimen\xradius{% % we only need this for the border anchor; the value is automatically correct in the paths. \pgf@x=.5\pgflinewidth% @@ -544,18 +541,343 @@ }% \inheritanchorborder[from=yquant-rectangle]% \backgroundpath{% - \shorten% - \pgf@xa=\dimexpr\yradius-\pgf@x\relax% - \pgf@ya=\dimexpr\yradius-\pgf@y\relax% + % manually shorten for the bounding box + \pgf@xa=\dimexpr\yradius-\pgf@shorten@end@additional\relax% + \pgf@ya=\dimexpr\yradius-\pgf@shorten@start@additional\relax% + \pgf@shorten@end@additional=0pt % + \pgf@shorten@start@additional=0pt % \pgfpathmoveto{\pgfqpoint{0pt}{\pgf@xa}}% \pgfpathlineto{\pgfqpoint{0pt}{-\pgf@ya}}% }% \clippath{% - \shorten% - \@tempdima=\dimexpr\yradius-\pgf@x\relax% - \@tempdimb=\dimexpr\yradius-\pgf@y\relax% + \@tempdima=\dimexpr\yradius-\pgf@shorten@end@additional\relax% + \@tempdimb=\dimexpr\yradius-\pgf@shorten@start@additional\relax% \pgfpathrectanglecorners% {\pgfqpoint{-.5\pgflinewidth}{\@tempdima}}% {\pgfqpoint{.5\pgflinewidth}{-\@tempdimb}}% }% +} + +% BEGIN_FOLD Gapped brace decoration +\def\pgfdecorationsegmentfromto{0-1}% + +\protected\def\yquant@gappedbrace@extract#1-#2\yquant@sep{% + \dimdef\from{#1\pgfdecoratedremainingdistance}% + \dimdef\to{#2\pgfdecoratedremainingdistance}% +} + +\def\yquant@gappedbrace@shiftloop#1{% + \yquant@gappedbrace@extract#1\yquant@sep% + \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance<\from % + \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance>\to % + % be careful about arch positions at the border + \ifdim\dimexpr\to-\from\relax<2\pgfdecorationsegmentamplitude % + % The arch is larger than the segment. We do not draw a line to it or an end line and place it in the mid of the segment, even if it is too short (this issues one extra \pgfpathmoveto command, but catching this rare case is not worth the effort). + \edef\pgfdecorationsegmentaspect{\pgfmath@tonumber{\dimexpr% + .5\dimexpr\from+\to\relax*65536/\pgfdecoratedremainingdistance% + \relax}}% + \else% + % The segment is large enough to cover the whole arch. But maybe we are too close at the border? + \ifdim\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax<\from % + \pgf@xc=\dimexpr\from+\pgfdecorationsegmentamplitude\relax% + \fi% + \ifdim\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax>\to % + \pgf@xc=\dimexpr\to-\pgfdecorationsegmentamplitude\relax% + \fi% + \edef\pgfdecorationsegmentaspect{\pgfmath@tonumber{\dimexpr% + \dimexpr\pgf@xc*65536/\pgfdecoratedremainingdistance% + \relax}}% + \fi% + \expandafter\expandafter\expandafter\listbreak% + \fi% + \fi% +} + +% Assumes all decoration macros and lengths are filled. Checks whether the arch is too close at a corner and shifts it appropriately. Upon exit, \pgfdecorationsegmentaspect is modified. +\protected\def\yquant@gappedbrace@calcshift{% + \pgf@xc=\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% + \expandafter\forcsvlist\expandafter\yquant@gappedbrace@shiftloop% + \expandafter{\pgfdecorationsegmentfromto}% +} + +\def\yquant@gappedbrace@loop#1{% + \yquant@gappedbrace@extract#1\yquant@sep% + \unless\ifdim\from=0pt % + \pgfpathmoveto{% + \pgfqpoint{\from}{.5\pgfdecorationsegmentamplitude}% + }% + \fi% + \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance<\from % + \unless\ifdim\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance>\to % + % be careful about arch positions at the border + \ifdim\dimexpr\to-\from\relax<2\pgfdecorationsegmentamplitude % + % The arch is larger than the segment. We do not draw a line to it or an end line and place it in the mid of the segment, even if it is too short (this issues one extra \pgfpathmoveto command, but catching this rare case is not worth the effort). + \pgfpathmoveto{% + \pgfqpoint{\dimexpr.5\dimexpr\from+\to\relax-\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }% + \edef\to{\the\pgfdecoratedremainingdistance}% to prevent the final line, we do not need "to" any more + \else% + % The segment is large enough to cover the whole arch. But maybe we are too close at the border? + \ifdim\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax<\from % + \pgf@xc=\dimexpr\from+\pgfdecorationsegmentamplitude\relax% + \fi% + \ifdim\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax>\to % + \pgf@xc=\dimexpr\to-\pgfdecorationsegmentamplitude\relax% + \fi% + % Both cases can't occur at the same time in this \else clause. + \pgfpathlineto{% + \pgfqpoint{\dimexpr\pgf@xc-\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }% + \fi% + \pgfpathcurveto{% + \pgfqpoint{\dimexpr\pgf@xc-.5\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\dimexpr\pgf@xc-.15\pgfdecorationsegmentamplitude\relax}% + {.7\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\pgf@xc}{\pgfdecorationsegmentamplitude}% + }% + \pgfpathcurveto{% + \pgfqpoint{\dimexpr\pgf@xc+.15\pgfdecorationsegmentamplitude\relax}% + {.7\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\dimexpr\pgf@xc+.5\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\dimexpr\pgf@xc+\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }% + \fi% + \fi% + \unless\ifdim\to=\pgfdecoratedremainingdistance % + \pgfpathlineto{% + \pgfqpoint{\to}{.5\pgfdecorationsegmentamplitude}% + }% + \fi% +} + +% This is a variant of the brace in pathreplacing that allows for holes +\pgfdeclaredecoration{gapped brace}{final}{% + \state{final}{% + \pgf@xc=\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% + \pgfpathmoveto\pgfpointorigin% required for "raise" key + \pgfpathcurveto{% + \pgfqpoint{.15\pgfdecorationsegmentamplitude}{.3\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{.5\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\pgfdecorationsegmentamplitude}{.5\pgfdecorationsegmentamplitude}% + }% + \expandafter\forcsvlist\expandafter\yquant@gappedbrace@loop% + \expandafter{\pgfdecorationsegmentfromto}% + \pgfpathlineto{% + \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }% + \pgfpathcurveto{% + \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-.5\pgfdecorationsegmentamplitude\relax}% + {.5\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\dimexpr\pgfdecoratedremainingdistance-.15\pgfdecorationsegmentamplitude\relax}% + {.3\pgfdecorationsegmentamplitude}% + }{% + \pgfqpoint{\pgfdecoratedremainingdistance}{0pt}% + }% + }% +}% + +\protected\def\yquant@gappedbrace@timer{% + \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}% + \pgfdecoratedremainingdistance=\pgfmathresult pt % + % now perform the transformation + \yquant@gappedbrace@calcshift% + % and finally let us return the desired position, just ignoring \tikz@time... + \pgftransformlineattime{\pgfdecorationsegmentaspect}{\tikz@timer@start}{\tikz@timer@end}% + \else% + \pgftransformlineattime{\tikz@time}{\tikz@timer@start}{\tikz@timer@end}% + \fi% +} + +\pgfkeys{% + /pgf/decoration/from to/.store in=\pgfdecorationsegmentfromto% +} +% END_FOLD + +\pgfdeclareshape{yquant-init}{% + \saveddimen\xradius{% + \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/tikz/x radius}}% + % inner xsep is between the brace tip and the right end of the text. Check if the decoration is raised (will define \def\tikz@dec@shift{\pgftransformyshift{#1}}) + \iftikz@decoratepath% + \ifx\tikz@dec@shift\relax% + \pgf@xa=\pgfdecorationsegmentamplitude % + \else% + \pgfmathsetlength\pgf@xa{\expandafter\@secondoftwo\tikz@dec@shift+\pgfdecorationsegmentamplitude}% + \fi% + \pgfmathaddtolength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \else% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \fi% + % outer xsep is (a lower bound) from the left end of the border to the left end of the text + \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/outer xsep}}% + \@tempdima=.5\dimexpr\wd\pgfnodeparttextbox+\pgf@xa+\pgf@xb\relax% + \ifdim\@tempdima>\pgf@x% + \pgf@x=\@tempdima% + \fi% + }% + \saveddimen\yradius{% + \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/tikz/y radius}}% + \@tempdima=.5\dimexpr\ht\pgfnodeparttextbox+\dp\pgfnodeparttextbox\relax% + \ifdim\@tempdima>\pgf@x% + \pgf@x=\@tempdima% + \fi% + \iftikz@decoratepath% + \ifdim2\pgfdecorationsegmentamplitude>\pgf@x% + \pgf@x=2\pgfdecorationsegmentamplitude% + \fi% + \fi% + }% + \savedanchor\stext{% + \iftikz@decoratepath% + % \pgf@x is still \yradius... + % first set \pgfdecoratedremainingdistance appropriately + \pgfdecoratedremainingdistance=2\pgf@x% + % now perform the transformation + \yquant@gappedbrace@calcshift% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}+\pgfdecorationsegmentamplitude}% + \unless\ifx\tikz@dec@shift\relax% + \pgfmathaddtolength\pgf@xa{\expandafter\@secondoftwo\tikz@dec@shift}% + \fi% + \pgfqpoint% + {-\dimexpr\wd\pgfnodeparttextbox+\pgf@xa\relax}% + {\dimexpr.5\pgfdecoratedremainingdistance% = \yradius + -\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% - aspect + -.5\ht\pgfnodeparttextbox+.5\dp\pgfnodeparttextbox% center there + \relax}% + \else% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \pgfqpoint% + {-\dimexpr\wd\pgfnodeparttextbox+\pgf@xa\relax}% + {-.5\dimexpr\ht\pgfnodeparttextbox-\dp\pgfnodeparttextbox\relax}% + \fi% + }% + % BEGIN_FOLD Operator anchors + \foreach \anc in {center, north, north east, east, south east, south, south west, west, north west} {% + \inheritanchor[from=yquant-rectangle]{\anc}% + }% + \anchor{text}{% + \stext% + \advance \pgf@x by \xradius\relax% + }% + \inheritanchorborder[from=yquant-rectangle]% + % END_FOLD + % BEGIN_FOLD Path + \backgroundpath{% + \pgfpathmoveto{\pgfqpoint{\xradius}{\yradius}}% + \pgfpathlineto{\pgfqpoint{\xradius}{-\yradius}}% + \pgfpointtransformed{\pgfqpoint{-\xradius}{\yradius}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgfpointtransformed{\pgfqpoint{-\xradius}{-\yradius}}% for rotations + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + }% + \clippath{% + \pgfpathrectanglecorners% + {\pgfqpoint{-\dimexpr\xradius\relax}% + {\dimexpr\yradius\relax}}% + {\pgfqpoint{\dimexpr\xradius+.5\pgflinewidth\relax}% + {-\dimexpr\yradius\relax}}% + }% + % END_FOLD +} + +\pgfdeclareshape{yquant-output}{% + % Almost the same as in yquant-input, only a minimal change in \stext's x position + \saveddimen\xradius{% + \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/tikz/x radius}}% + % inner xsep is from the brace tip and the left end of the text. Check if the decoration is raised (will define \def\tikz@dec@shift{\pgftransformyshift{#1}}) + \iftikz@decoratepath% + \ifx\tikz@dec@shift\relax% + \pgf@xa=\pgfdecorationsegmentamplitude % + \else% + \pgfmathsetlength\pgf@xa{\expandafter\@secondoftwo\tikz@dec@shift+\pgfdecorationsegmentamplitude}% + \fi% + \pgfmathaddtolength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \else% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \fi% + % outer xsep is (a lower bound) from the left end of the border to the left end of the text + \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/outer xsep}}% + \@tempdima=.5\dimexpr\wd\pgfnodeparttextbox+\pgf@xa+\pgf@xb\relax% + \ifdim\@tempdima>\pgf@x% + \pgf@x=\@tempdima% + \fi% + }% + \saveddimen\yradius{% + \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/tikz/y radius}}% + \@tempdima=.5\dimexpr\ht\pgfnodeparttextbox+\dp\pgfnodeparttextbox\relax% + \ifdim\@tempdima>\pgf@x% + \pgf@x=\@tempdima% + \fi% + \iftikz@decoratepath% + \ifdim2\pgfdecorationsegmentamplitude>\pgf@x% + \pgf@x=2\pgfdecorationsegmentamplitude% + \fi% + \fi% + }% + \savedanchor\stext{% + \iftikz@decoratepath% + % \pgf@x is still \yradius... + % first set \pgfdecoratedremainingdistance appropriately + \pgfdecoratedremainingdistance=2\pgf@x% + % now perform the transformation + \yquant@gappedbrace@calcshift% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}+\pgfdecorationsegmentamplitude}% + \unless\ifx\tikz@dec@shift\relax% + \pgfmathaddtolength\pgf@xa{\expandafter\@secondoftwo\tikz@dec@shift}% + \fi% + \pgfqpoint% + {\dimexpr\pgf@xa\relax}% + {\dimexpr.5\pgfdecoratedremainingdistance% = \yradius + -\pgfdecorationsegmentaspect\pgfdecoratedremainingdistance% - aspect + -.5\ht\pgfnodeparttextbox+.5\dp\pgfnodeparttextbox% center there + \relax}% + \else% + \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/inner xsep}}% + \pgfqpoint% + {\dimexpr\pgf@xa\relax}% + {-.5\dimexpr\ht\pgfnodeparttextbox-\dp\pgfnodeparttextbox\relax}% + \fi% + }% + % BEGIN_FOLD Operator anchors + \foreach \anc in {center, north, north east, east, south east, south, south west, west, north west} {% + \inheritanchor[from=yquant-init]{\anc}% + }% + \anchor{text}{% + \stext% + \advance \pgf@x by -\xradius\relax% + }% + \inheritanchorborder[from=yquant-init]% + % END_FOLD + % BEGIN_FOLD Path + \backgroundpath{% + \pgfpathmoveto{\pgfqpoint{-\xradius}{\yradius}}% + \pgfpathlineto{\pgfqpoint{-\xradius}{-\yradius}}% + \pgfpointtransformed{\pgfqpoint{\xradius}{\yradius}}% + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + \pgfpointtransformed{\pgfqpoint{\xradius}{-\yradius}}% for rotations + \pgf@protocolsizes{\pgf@x}{\pgf@y}% + }% + \clippath{% + \pgfpathrectanglecorners% + {\pgfqpoint{-\dimexpr\xradius+.5\pgflinewidth\relax}% + {\dimexpr\yradius\relax}}% + {\pgfqpoint{\dimexpr\xradius\relax}% + {-\dimexpr\yradius\relax}}% + }% + % END_FOLD }
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex index 5f7efe5e037..4b31a4e35ed 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex @@ -30,6 +30,11 @@ \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\@secondandthirdoffive#1#2#3#4#5{{#2}{#3}} +\long\def\@firstoffive#1#2#3#4#5{#1} % unused +\long\def\@secondoffive#1#2#3#4#5{#2} +\long\def\@thirdoffive#1#2#3#4#5{#3} +\long\def\@fourthoffive#1#2#3#4#5{#4} % unused \long\def\@fifthoffive#1#2#3#4#5{#5} % Loop #1 from min(#2, #3) to max(#2, #3), executing #4 @@ -184,6 +189,30 @@ \expandafter\yquant@sort@aux\expandafter0\expandafter{\the\numexpr\yquant@sort@count-1\relax}% } +% Returns the first item in the unordered sortlist when compared according to #1 and stores it in #2. +\protected\def\yquant@sort@findfirst#1#2{% + \ifnum\yquant@sort@count<1 % + \let#2=\empty% + \else% + \letcs#2{yquant@sort@item0}% + \count0=1 % + \loop% + \ifnum\count0<\yquant@sort@count\relax% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter#1% + \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{% + \expandafter\expandafter\expandafter#2% + \expandafter\expandafter\expandafter}% + \expandafter\expandafter\expandafter{% + \csname yquant@sort@item\the\count0\endcsname% + }% + \relax{% + \letcs#2{yquant@sort@item\the\count0}% + }% + \advance\count0 by 1 % + \repeat% + \fi% +} + \def\yquant@sort@ascending#1#2{% \ifnum#2>#1 % \expandafter\@firstoftwo% @@ -316,6 +345,7 @@ \begingroup \catcode`\|=3 +\catcode`\&=3 \gdef\yquant@list@delim{|} \protected\gdef\yquant@list@dequeue#1#2{% @@ -338,8 +368,78 @@ \expandafter\yquant@list@dequeue@i#1\etb@lst@q@end{#1}{#2}\gdef% }% } + +\protected\gdef\yquant@list@eupdateorinsert#1#2#3{% + % the list items are of the form <number>:<value>. If an item is present where <number> = #2, then set its <value> to #3, if #3 is greater. If no item is present, add it. + \begingroup% + \def\etb@tempa##1|#2:##2|##3&{% + \endgroup% + \ifstrempty{##3}{% + \eappto#1{#2:#3|}% + }{% + \ifdim##2<#3 % + \yquant@list@ereplace#1{#2:##2}{#2:#3}% + \fi% + }% + }% + \expandafter\etb@tempa\expandafter|#1|#2:#3|&% +} + +\protected\gdef\yquant@list@ereplace#1#2#3{% + \begingroup% + \def\etb@tempa##1|#2|##2&{% + \endgroup% + \ifstrempty{##1}{% + \edef#1{% + \unexpanded{##1}|#3|\unexpanded{##2}% + }% + }{% + \edef#1{% + \unexpanded\expandafter{\@gobble##1}|#3|\unexpanded{##2}% + }% + }% + }% + \expandafter\etb@tempa\expandafter|#1& +} + +% expands to the contents of a list ranging from #1 to #2 (ascending) +\gdef\yquant@list@range#1#2{% + \ifnum#1>#2 % + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi{}{% + #1|% + \expandafter\yquant@list@range\expandafter{\the\numexpr#1+1\relax}{#2}% + }% +} \endgroup +% performs #3 if #1 is a subset of #2; else, performs #4 +\protected\def\ifyquant@registersubset#1#2{% + \begingroup% + \let\yquant@register@multi=\@fourthoffour + \def\yquant@register@multi@contiguous##1##2##3{\yquant@list@range{##1}{##2}}% + \edef\listA{#1}% + \edef\listB{#2}% + \let\ifsuccess=\iftrue% + \forlistloop\yquant@registersubset@loop\listA% + \expandafter% + \endgroup% + \ifsuccess% + \expandafter\@firstoftwo% + \else% + \expandafter\@secondoftwo% + \fi% +} + +\protected\def\yquant@registersubset@loop#1{% + \ifinlist{#1}\listB\relax{% + \let\ifsuccess=\iffalse% + \listbreak% + }% +} + \def\ifyquant@OR#1#2{% #1% \expandafter\@firstoftwo% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant.sty b/Master/texmf-dist/tex/latex/yquant/yquant.sty index 2d6631b8f2b..ecbee654e01 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant.sty +++ b/Master/texmf-dist/tex/latex/yquant/yquant.sty @@ -1,7 +1,7 @@ % yquant.sty % Typesetting quantum circuits using a flow-oriented language % -% Copyright 2019-2020 Benjamin Desef +% Copyright 2019-2021 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 @@ -15,13 +15,27 @@ % % The Current Maintainer of this work is Benjamin Desef. \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{yquant}[2020/10/27 v0.3.3 Yet another quantum circuit library for LaTeX] +\ProvidesPackage{yquant}[2021/03/27 v0.4 Yet another quantum circuit library for LaTeX] \RequirePackage{etoolbox}[2018/02/11] \RequirePackage{tikz}[2015/08/29] \RequirePackage{trimspaces}[2009/09/17] +\RequirePackage{xkeyval}[2005/05/07] \usetikzlibrary{arrows.meta,decorations.pathreplacing,decorations.pathmorphing} +\define@choicekey+{yquant.sty}{compat}[\val\yquant@compat]{newest,0.3,0.4}{ + \ifnum\yquant@compat=0 % + \def\yquant@compat{2} % current version + \fi% +}{ + \PackageWarning{yquant.sty}{Invalid value for `compat` key specified. Using `0.3`.} +} +\ProcessOptionsX +\unless\ifdefined\yquant@compat + \PackageWarning{yquant.sty}{Please specify the `compat` key for yquant. Using `0.3`. Current version is `0.4`.} + \def\yquant@compat{1} +\fi + \newif\ifyquantdebug \input yquant-config.tex \input yquant-tools.tex @@ -29,6 +43,7 @@ \input yquant-env.tex \input yquant-langhelper.tex \input yquant-circuit.tex +\input yquant-prepare.tex \input yquant-draw.tex \input yquant-shapes.tex \input yquant-lang.tex diff --git a/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty index eaa848e03f2..d37aa6b9f0a 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty +++ b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-qasm.sty @@ -15,9 +15,9 @@ % % The Current Maintainer of this work is Benjamin Desef. \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{yquantlanguage-qasm}[2020/06/13 v0.3 yquant-qasm] +\ProvidesPackage{yquantlanguage-qasm}[2021/03/27 v0.4 yquant-qasm] -\RequirePackage{yquant}[2020/06/13] +\RequirePackage{yquant}[2021/03/27] % BEGIN_FOLD Environment definitions \begingroup @@ -222,17 +222,43 @@ \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{% +% Defines a yquant command for qasm +% #1: name of the command +% #2: number of controls +% #3: number of targets +% #4: name of the yquant command +% #5: pre-actions +\protected\def\qasm@langhelper@alias@yquant#1#2#3#4#5{% \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}% + \unexpanded{#5}% + \qasm@langhelper@declare@command@@fetchargs{#2}{#3}{##1}{\csname yquant@lang@#4\endcsname}% + \yquant@env@rescan% + }% + \endgroup% +} + +% Defining commands that accept registers and take an optional value +% #1: name of the argument +% #2: number of controls +% #3: number of targets +% #4: actions to be taken before parsing +% #5: actions to be taken after parsing +\protected\def\qasm@langhelper@declare@command#1#2#3#4#5{% + \begingroup% + \lowercase{\edef\cmd{#1}}% + \long\protected\csxdef{qasm@lang@\cmd}##1 ##2\qasm@end{% + \noexpand\yquant@langhelper@execclear@lastgatetrue% + \unexpanded{#4}% + \qasm@langhelper@declare@command@@fetchargs{#2}{#3}{##1}\yquant@circuit@operator% + \noexpand\ifyquant@langhelper@execclear@lastgate% + \yquant@for \noexpand\i := \noexpand\yquant@circuit@operator@minctrl to \noexpand\yquant@circuit@operator@maxctrl {% + \yquant@register@execclear@lastgate{\noexpand\i}{\cmd}% + }% + \noexpand\fi% + \unexpanded{#5}% \yquant@env@rescan% }% \endgroup% @@ -488,18 +514,40 @@ \process% }% \fi% - \yquant@lang@create@do{#1}[1][;% + \yquant@prepare@create{#1}0\yquant@lang@create@type% + \letcs\yquant@circuit@operator@maxtarget{\yquant@prefix registers}% + \numdef\yquant@circuit@operator@numtarget{1}% + \edef\yquant@circuit@operator@targets{\yquant@circuit@operator@maxtarget\yquant@list@delim}% + \let\yquant@circuit@operator@pctrls=\empty% + \def\yquant@circuit@operator@minpctrl{2147483647}% + \def\yquant@circuit@operator@maxpctrl{0}% + \let\yquant@circuit@operator@numpctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@nctrls=\empty% + \let\yquant@circuit@operator@minnctrl=\yquant@circuit@operator@minpctrl% + \let\yquant@circuit@operator@maxnctrl=\yquant@circuit@operator@maxpctrl% + \let\yquant@circuit@operator@numnctrl=\yquant@circuit@operator@numpctrl% + \let\yquant@circuit@operator@minctrl=\yquant@circuit@operator@mintarget% + \let\yquant@circuit@operator@maxctrl=\yquant@circuit@operator@maxtarget% + \def\yquant@attrs@remaining{internal/move label} + \def\yquant@config@operator@minimum@width{0pt}% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/every label, /yquant/every initial label,% + /yquant/every \yquant@lang@create@style\space label}% + \unless\ifx\yquant@lang@attr@value\empty% + \yquant@register@execclear@lastgate{\yquant@circuit@operator@maxtarget}{init}% + \fi% \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) + % we need to do a couple of case distinctions (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% + \noexpand\yquant@lang@phase% }% }% }{% @@ -519,32 +567,31 @@ % 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% + \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% + \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\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% \def\noexpand\yquant@lang@attr@value{\texcode}% - \noexpand\yquant@lang@@dmeter% + \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\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% \def\noexpand\yquant@lang@attr@value{\texcode}% - \noexpand\yquant@lang@@dmeter% + \noexpand\yquant@lang@dmeter% }% }% }{% \edef\process{% \def\expandafter\noexpand\csname qasm@lang@@def@\cmd\endcsname{% - \yquant@draw% - {$\unexpanded\expandafter{\texcode}$}% - {/yquant/operators/every box}% + \def\noexpand\yquant@lang@attr@value{$\unexpanded\expandafter{\texcode}$}% + \noexpand\yquant@lang@box% }% }% }% @@ -586,9 +633,8 @@ \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}% + \def\noexpand\yquant@lang@attr@value{$\unexpanded\expandafter{\texcode}$}% + \noexpand\yquant@lang@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{% @@ -602,73 +648,68 @@ \yquant@env@scan% } -\qasm@langhelper@declare@command{measure}{\expandafter\yquant@lang@@measure\@gobbletwo}01 +\qasm@langhelper@alias@yquant{measure}01{measure}{} -\qasm@langhelper@declare@command{H}\yquant@lang@@h01 +\qasm@langhelper@alias@yquant{h}01{h}{} -\qasm@langhelper@declare@command{X}\yquant@lang@@x01 +\qasm@langhelper@alias@yquant{x}01{x}{} -\qasm@langhelper@declare@command{Y}\yquant@lang@@y01 +\qasm@langhelper@alias@yquant{y}01{y}{} -\qasm@langhelper@declare@command{Z}\yquant@lang@@z01 +\qasm@langhelper@alias@yquant{z}01{z}{} -\qasm@langhelper@declare@command{S}\qasm@lang@@s01 -\def\qasm@lang@@s{% - \yquant@draw% +\qasm@langhelper@declare@command{S}01{}{% + \yquant@prepare% {$S$}% {/yquant/operators/every s}% } -\qasm@langhelper@declare@command{T}\qasm@lang@@t01 -\def\qasm@lang@@t{% - \yquant@draw% +\qasm@langhelper@declare@command{T}01{}{% + \yquant@prepare% {$T$}% {/yquant/operators/every t}% } -\qasm@langhelper@declare@command{nop}\qasm@lang@@nop01 -\def\qasm@lang@@nop#1#2#3{% +\qasm@langhelper@alias@yquant{nop}01{hspace}{% \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{% +\qasm@langhelper@alias@yquant{zero}01{init}{% \let\yquant@lang@attr@value=\qasm@config@zero% - \yquant@lang@@init{#3}% + \def\yquant@lang@attr@type{qubit}% } -\qasm@langhelper@declare@command{discard}{\expandafter\yquant@lang@@discard\@gobbletwo}01 +\qasm@langhelper@alias@yquant{discard}01{discard}{} -\qasm@langhelper@declare@command{slash}{\expandafter\yquant@lang@@slash\@gobbletwo}01 +\qasm@langhelper@alias@yquant{slash}01{slash}{} -\qasm@langhelper@declare@command{dmeter}{\expandafter\yquant@lang@@dmeter\@gobbletwo}01 +\qasm@langhelper@alias@yquant{dmeter}01{dmeter}{} -\qasm@langhelper@declare@command{cnot}\yquant@lang@@not11 +\qasm@langhelper@alias@yquant{cnot}11{not}{} -\qasm@langhelper@declare@command{c-z}\yquant@lang@@z11 +\qasm@langhelper@alias@yquant{c-z}11{z}{} -\qasm@langhelper@declare@command{c-x}\yquant@lang@@x11 +\qasm@langhelper@alias@yquant{c-x}11{x}{} -\qasm@langhelper@declare@command{toffoli}\yquant@lang@@not21 +\qasm@langhelper@alias@yquant{toffoli}21{not}{} -\qasm@langhelper@declare@command{ZZ}{\expandafter\yquant@lang@@zz\@gobbletwo}02 +\qasm@langhelper@alias@yquant{zz}02{zz}{} -\qasm@langhelper@declare@command{XX}\yquant@lang@@xx02 +\qasm@langhelper@alias@yquant{xx}02{xx}{} -\qasm@langhelper@declare@command{swap}\yquant@lang@@swap02 +\qasm@langhelper@alias@yquant{swap}02{swap}{} -\qasm@langhelper@declare@command{Utwo}\qasm@lang@@Utwo02 -\def\qasm@lang@@Utwo{% +\qasm@langhelper@declare@command{Utwo}02{% \yquant@register@get@allowmultitrue% - \yquant@draw% +}{% + \yquant@prepare% {$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 +\let\qasm@lang@space=\qasm@lang@nop % END_FOLD % some commands that might be used in boxes |