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/yquant/yquant-prepare.tex | |
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/yquant/yquant-prepare.tex')
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex | 883 |
1 files changed, 883 insertions, 0 deletions
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 |