From 8b106792b613d953ddec1ff0e3f1f3da0e5fd8b3 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 17 Aug 2021 20:49:48 +0000 Subject: yquant (17aug21) git-svn-id: svn://tug.org/texlive/trunk@60259 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/tex/latex/yquant/yquant-config.tex | 22 +- Master/texmf-dist/tex/latex/yquant/yquant-draw.tex | 218 +++++++-- Master/texmf-dist/tex/latex/yquant/yquant-env.tex | 15 +- Master/texmf-dist/tex/latex/yquant/yquant-lang.tex | 77 +-- .../tex/latex/yquant/yquant-langhelper.tex | 5 + .../texmf-dist/tex/latex/yquant/yquant-prepare.tex | 47 +- .../tex/latex/yquant/yquant-registers.tex | 1 + .../texmf-dist/tex/latex/yquant/yquant-tools.tex | 104 ++-- Master/texmf-dist/tex/latex/yquant/yquant.sty | 11 +- .../tex/latex/yquant/yquantlanguage-groups.sty | 527 +++++++++++++++++++++ 10 files changed, 891 insertions(+), 136 deletions(-) create mode 100644 Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty (limited to 'Master/texmf-dist/tex/latex') diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-config.tex b/Master/texmf-dist/tex/latex/yquant/yquant-config.tex index d5844480ee0..64979953eeb 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-config.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-config.tex @@ -221,6 +221,17 @@ {\pgfkeysalso{/yquant/operators/subcircuit/frameless, /yquant/register/default name=}% \letcs\yquant@prevseamless{\yquant@prefix seamless}% \yquant@config@circuit@seamlesstrue}, + operators/subcircuit/name mangling/.is choice,% + operators/subcircuit/name mangling/prefix or discard/.code=% + {\def\yquant@config@operator@subcircuit@mangling{0}},% + operators/subcircuit/name mangling/prefix or transparent/.code=% + {\def\yquant@config@operator@subcircuit@mangling{1}},% + operators/subcircuit/name mangling/transparent/.code=% + {\def\yquant@config@operator@subcircuit@mangling{2}},% + operators/subcircuit/name mangling/discard/.code=% + {\def\yquant@config@operator@subcircuit@mangling{3}},% + operators/subcircuit/name mangling reset/.is if=% + yquant@config@operator@subcircuit@manglingreset, operators/every swap/.style=% {shape=yquant-swap, radius=.75mm, draw},% operators/every wave/.style=% @@ -272,4 +283,13 @@ \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 +\def\yquant@config@operator@subcircuit@mangling{0} +\newif\ifyquant@config@operator@subcircuit@manglingreset +\yquant@config@operator@subcircuit@manglingresettrue +\newif\ifyquant@config@operator@multi + +\protected\def\yquant@config@operator@subcircuit@mangling@set#1{% + \ifyquant@config@operator@subcircuit@manglingreset% + \def\yquant@config@operator@subcircuit@mangling{#1}% + \fi% +} \ 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 7527e1ea05f..574a45eec19 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-draw.tex @@ -9,16 +9,12 @@ \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 + \yquant@register@set@lastwire{#1}{% + {\yquant@draw@subcircuit@wirestart}{\yquant@draw@subcircuit@wirestart}{}% + {\unexpanded\expandafter\expandafter\expandafter{% + \expandafter\@fourthoffour\wirelast% + }}% + }% \fi% \yquant@register@set@type{#1}{#2}% \fi% @@ -476,51 +472,142 @@ \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. + \pgfkeysgetvalue{/tikz/name prefix}\yquant@draw@subcircuit@prevprefix% + % name mangling + \ifcase\yquant@config@operator@subcircuit@mangling\relax% + % prefix or discard: if we have an outer name, use it as the prefix; if not, discard all names + \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={\yquant@draw@subcircuit@prevprefix#2-}}% + \ifnum#3=1 % + \let\pgf@nodecallback=\yquant@draw@subcircuit@nodecallback% + \fi% + }% + \or% + % prefix or transparent: if we have an outer name, use it as a prefix; if not, directly use the outer namespace + \ifstrempty{#2}\relax{% + \pgfkeys{/tikz/name prefix/.expanded={\yquant@draw@subcircuit@prevprefix#2-}}% + \ifnum#3=1 % + \let\pgf@nodecallback=\yquant@draw@subcircuit@nodecallback% + \fi% + }% + \or% + % transparent: all names go directly in the outer namespace + \or% + % discard: no name will be visible in the outer namespace whatsoever \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-}}% - \ifnum#3=1 % - \let\pgf@nodecallback=\yquant@draw@subcircuit@nodecallback% - \fi% - }% + \else% + \PackageError{yquant.sty}{Assertion failure}{Unknown value for name mangling.}% + \fi% \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 % + \begingroup% + \csname\yquant@prefix draw\endcsname% + \endgroup% + % BEGIN_FOLD bounding box + % Completely empty wires did not yet affect the bounding box + % Problem: we compare an user-mode TikZ position (register y position) with a system-level pgf position (picture boundary box). If shifts or scalings are in effect, we must first transform the point appropriately. Note that negative scalings may upset our assumption of which is the minimum and which is the maximum! If additionally rotations are in effect, we must even consider those transformations for the leftmost and the rightmost point, which makes all of this far more complicated than it should be. For this reason, we have a shortcut in action in case no nontranslation transformations are present. + \ifpgf@pt@identity% + \dimen0=\dimexpr\yquant@register@get@y1+\pgf@pt@y\relax% + \ifdim\dimen0>\pgf@picmaxy % + \global\pgf@picmaxy=\dimen0 % + \fi% + \dimen0=\dimexpr\yquant@register@get@y{\csname\yquant@prefix registers\endcsname}+\pgf@pt@y\relax% + \ifdim\dimen0<\pgf@picminy % + \global\pgf@picminy=\dimen0 % + \fi% + \else% + % first wire, left end + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x-.5\dimexpr\@firstofthree#4\relax}{\yquant@register@get@y1\relax}}% + \ifdim\pgf@y>\pgf@picmaxy % + \global\pgf@picmaxy=\pgf@y % + \fi% + \ifdim\pgf@y<\pgf@picminy % negative scaling + \global\pgf@picminy=\pgf@y % + \fi% + % first wire, right end + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x+.5\dimenxpr\@firstofthree#4\relax}{\yquant@register@get@y1\relax}}% + \ifdim\pgf@y>\pgf@picmaxy % + \global\pgf@picmaxy=\pgf@y % + \fi% + \ifdim\pgf@y<\pgf@picminy % negative scaling + \global\pgf@picminy=\pgf@y % + \fi% + % last wire, left end + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x-.5\dimexpr\@firstofthree#4\relax}{\yquant@register@get@y{\csname\yquant@prefix registers\endcsname}\relax}}% + \ifdim\pgf@y>\pgf@picmaxy % + \global\pgf@picmaxy=\pgf@y % + \fi% + \ifdim\pgf@y<\pgf@picminy % negative scaling + \global\pgf@picminy=\pgf@y % + \fi% + % last wire, right end + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x+.5\dimenxpr\@firstofthree#4\relax}{\yquant@register@get@y{\csname\yquant@prefix registers\endcsname}\relax}}% + \ifdim\pgf@y>\pgf@picmaxy % + \global\pgf@picmaxy=\pgf@y % + \fi% + \ifdim\pgf@y<\pgf@picminy % negative scaling + \global\pgf@picminy=\pgf@y % + \fi% \fi% - \ifnum#3=1 % - % we must apply the aliasing to all the included nodes. We do this in this group, which still has the callback available, so that the aliased nodes will also be added to the list and can propagate (note that the number of node names is then exponential in the number of nested subcircuits) - \protected\def\yquant@draw@subcircuit@alias@do##1#2-##2\relax##3\relax{% - \ifstrempty{##1}{% - \pgfnodealias{\yquant@draw@subcircuit@alias@removezero#2-##2}{#2-##2}% - \@gobble% there is an additional \relax - }\relax% - }% - \forlistcsloop% - {\yquant@draw@subcircuit@alias{#2}}\yquant@draw@subcircuit@nodelist% + % END_FOLD + \ifnum\yquant@config@operator@subcircuit@mangling<2 % + % only bother with aliasing if the prefix is present at all + \ifnum#3=1 % + \ifstrempty{#2}\relax{% + % we must apply the aliasing to all the included nodes. We do this in this group, which still has the callback available, so that the aliased nodes will also be added to the list and can propagate (note that the number of node names is then exponential in the number of nested subcircuits) + \pgfkeysgetvalue{/tikz/name prefix}\yquant@draw@subcircuit@alias@prefix% + \expandafter\protected\expandafter\edef\expandafter% + \yquant@draw@subcircuit@alias@do\expandafter##\expandafter1\yquant@draw@subcircuit@alias@prefix##2\relax##3\relax{% + \noexpand\ifstrempty{##1}{% + \noexpand\pgfnodealias{\yquant@draw@subcircuit@prevprefix\yquant@draw@subcircuit@alias@removezero#2-##2}{\yquant@draw@subcircuit@alias@prefix##2}% + \noexpand\@gobble% there is an additional \relax + }\relax% + }% + \expandafter\forlistcsloop\expandafter% + {\expandafter\yquant@draw@subcircuit@alias\expandafter{% + \yquant@draw@subcircuit@alias@prefix}% + }\yquant@draw@subcircuit@nodelist% + }% + \fi% \fi% }}% + \ifpgf@pt@identity% + \dimen0=\dimexpr.5\pgf@picminy+.5\pgf@picmaxy-\pgf@pt@y\relax% + \dimen2=\dimexpr\pgf@picmaxy-\pgf@picminy\relax% + \else% + \begingroup% + \pgftransforminvert% + \pgfpointtransformed{\pgfqpoint{\pgf@picminx}{\pgf@picminy}}% + \@tempdima=\pgf@y% + \pgfpointtransform{\pgfqpoint{\pgf@picmaxx}{\pgf@picmaxy}}% + \edef\cmd{\@tempdima=\the\@tempdima\space\@tempdimb=\the\@tempdimb\space}% + \expandafter% + \endgroup% + \cmd% + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x}% + {.5\dimexpr\@tempdima+\@tempdimb\relax}}% + \dimen0=\pgf@y% + \pgfpointtransformed{\pgfqpoint{\yquant@draw@@x}% + {\dimexpr\@tempdimb-\@tempdima\relax}}% + \dimen2=\pgf@y% + \fi% \edef\cmd{% - \noexpand\path (\yquant@draw@@x, \the\dimexpr.5\pgf@picminy+.5\pgf@picmaxy\relax)% + \noexpand\path (\yquant@draw@@x, \the\dimen0)% 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#4 {}}};% + {\vbox to \the\dimen2 {\hbox to \@firstofthree#4 {}}};% }% \cmd% \unhbox\yquant@prepare@subcircuit@box% @@ -535,8 +622,40 @@ % 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{#5}% - \ifstrempty{#2}{% - % However, if the outer node was not named, no access to the inner nodes is desired, so we delete all nodes again. + % name mangling + \ifcase\yquant@config@operator@subcircuit@mangling\relax% + % prefix or discard + \ifstrempty{#2}{% + % However, if the outer node was not named, no access to the inner nodes is desired, so we delete all nodes again. + \def\do##1{% + \csgundef{pgf@sh@ns@##1}% + \csgundef{pgf@sh@np@##1}% + \csgundef{pgf@sh@nt@##1}% + \csgundef{pgf@sh@pi@##1}% + \csgundef{pgf@sh@ma@##1}% + }% + \dolistcsloop{\yquant@draw@subcircuit@nodelist}% + \csgundef\yquant@draw@subcircuit@nodelist% + }{% + \ifcsname\yquant@prefix draw@subcircuit@nodelist\endcsname% + \csxappto{\yquant@prefix draw@subcircuit@nodelist}% + {\csname\yquant@draw@subcircuit@nodelist\endcsname}% + \fi% + }% + \or% + % prefix or transparent: in any case, make everything available for mangling in the outer circuit + \ifcsname\yquant@prefix draw@subcircuit@nodelist\endcsname% + \csxappto{\yquant@prefix draw@subcircuit@nodelist}% + {\csname\yquant@draw@subcircuit@nodelist\endcsname}% + \fi% + \or% + % transparent: same + \ifcsname\yquant@prefix draw@subcircuit@nodelist\endcsname% + \csxappto{\yquant@prefix draw@subcircuit@nodelist}% + {\csname\yquant@draw@subcircuit@nodelist\endcsname}% + \fi% + \or% + % discard: remove them all \def\do##1{% \csgundef{pgf@sh@ns@##1}% \csgundef{pgf@sh@np@##1}% @@ -546,18 +665,15 @@ }% \dolistcsloop{\yquant@draw@subcircuit@nodelist}% \csgundef\yquant@draw@subcircuit@nodelist% - }{% - \ifcsname\yquant@prefix draw@subcircuit@nodelist\endcsname% - \csxappto{\yquant@prefix draw@subcircuit@nodelist}% - {\csname\yquant@draw@subcircuit@nodelist\endcsname}% - \fi% - }% + \else% + \PackageError{yquant.sty}{Assertion failure}{Unknown value for name mangling (2).}% + \fi% } \def\yquant@draw@subcircuit@alias@removezero#1-0{#1} \def\yquant@draw@subcircuit@alias#1#2{% - \yquant@draw@subcircuit@alias@do#2\relax#1-0-\relax\relax% + \yquant@draw@subcircuit@alias@do#2\relax#10-\relax\relax% } \protected\long\def\yquant@draw@subcircuit@single#1#2#3#4#5{% @@ -606,7 +722,7 @@ \yquant@softpath@extractmaxxat\nonaffectedpgfshapeclippathhorzresult% {\yquant@register@get@y\i}% \let\pgfshapeclippathhorzresult=\empty% - \yquant@circuit@extendwire\i{*}% + \yquant@circuit@extendwire\i*% }{% \let\pgfshapeclippathhorzresult=\nonaffectedpgfshapeclippathhorzresult% \yquant@circuit@extendwire\i{center}% @@ -767,9 +883,9 @@ \pgf@picmaxy=0pt % \fi% \pgftransforminvert% - \pgfpointtransformednonlinear{\pgfqpoint{\pgf@picminx}{\pgf@picminy}}% + \pgfpointtransformed{\pgfqpoint{\pgf@picminx}{\pgf@picminy}}% \global\@tempdima=\pgf@y% - \pgfpointtransformednonlinear{\pgfqpoint{\pgf@picmaxx}{\pgf@picmaxy}}% + \pgfpointtransformed{\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. diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex index 96ea7bbac37..c6e9f52b01c 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-env.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-env.tex @@ -48,6 +48,7 @@ \yquant@env@begin@generic\yquant% } +% sync with yquantlanguage-groups \long\protected\def\yquant@env@begin@generic#1[#2]{% \begingroup% \let\yquant@parent=\yquant@prefix% @@ -89,9 +90,12 @@ \protected\def\yquant@env@end{% \ifnum\csname\yquant@prefix registers\endcsname>0 % - \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% - \yquant@register@execclear@lastgate{\i}{@end}% - }% + \begingroup% + \let\yquant@circuit@operator@pctrls=\empty% + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + \yquant@register@execclear@lastgate{\i}{@end}% + }% + \endgroup% \csgappto{\yquant@prefix draw}{% \yquant@circuit@endwires% }% @@ -521,9 +525,8 @@ \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 % + % we will often access the bounding box, which is never transformed + \pgftransformreset% } % 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 f19ebfcc386..8658d3af9fa 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-lang.tex @@ -35,6 +35,10 @@ },% indirect control/.code={% \undef\yquant@lang@attr@directcontrol% + },% + name mangling/.code={% + \pgfkeysalso{/yquant/operators/subcircuit/name mangling={#1}}% + \appto\yquant@attrs@remaining{,/yquant/operators/subcircuit/name mangling={#1}}% }% } \yquant@langhelper@declare@attr@global{% @@ -289,23 +293,38 @@ } \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}% - \yquant@register@get@multiaslist% - {% - \let\noexpand\yquant@lang@attr@value=\expandafter\noexpand\csname yquant@lang@@#1\endcsname% - \yquant@prepare@subcircuit{/yquant/operators/every #1}% + \begingroup% + \yquant@prepare@ifs@set% + % usually, we will not be in a tikzpicture here, so all the commands that abbreviate some path operation are undefined! + \tikz@installcommands% + % While we want the content to be expanded, protect the most likely TikZ commands - the same ones that we usually substitute in \yquant@env@substikz. + \protected\def\path{}% + \let\scoped=\path% + \let\scope=\path% + \let\endscope=\path% + \let\stopscope=\path% + \protected@edef\yquantdefinegate@do{% + \endgroup% + \noexpand\pgfkeys{/yquant/operators/every #1/.code={% + \yquant@config@operator@subcircuit@mangling@set{% + \yquant@config@operator@subcircuit@mangling% + }% + \noexpand\pgfkeysalso{\unexpanded{#2}}% + }}% + \yquant@langhelper@declare@command% + {#1}% + \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{% + #3% }% - % This does not clear the attributes for redefines, but makes at least sure nothing is marked as required that should not be. - \yquant@langhelper@setup@attrs{#1}{}{}% - % Now define the gate's content as a macro - \def\expandafter\noexpand\csname yquant@lang@@#1\endcsname{% - #3% }% - }% \yquantdefinegate@do% } @@ -348,14 +367,16 @@ \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}% - {\unexpanded{#2}}% - {\yquant@prepare{#4}{/yquant/operators/every #1}}% - }% - \yquantdefinebox@do% + \begingroup% + \yquant@prepare@ifs@set% + \protected@edef\yquantdefinebox@do{% + \endgroup% + \yquant@langhelper@declare@command% + {#1}% + {\unexpanded{#2}}% + {\yquant@prepare{#4}{/yquant/operators/every #1}}% + }% + \yquantdefinebox@do% \yquant@langhelper@setup@attrs{#1}{}{}% } % END_FOLD @@ -391,7 +412,7 @@ {% \yquant@prepare@subcircuit{/yquant/operators/every subcircuit}% } -\yquant@langhelper@setup@attrs{subcircuit}{value}{frameless,seamless} +\yquant@langhelper@setup@attrs{subcircuit}{value}{frameless,seamless,name mangling} % END_FOLD % BEGIN_FOLD other geometric shapes @@ -565,7 +586,7 @@ \yquant@langhelper@declare@command@uncontrolled% {discard}% - {\yquant@langhelper@execclear@lastgatefalse}% + {}% {% \let\yquant@circuit@settype@to=\yquant@register@type@none% \yquant@circuit@actonwires% @@ -661,7 +682,7 @@ \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% @@ -682,7 +703,7 @@ \yquant@langhelper@declare@command@uncontrolled% {setstyle}% - {\yquant@langhelper@execclear@lastgatefalse}% + {}% {% \yquant@circuit@actonwires% \@gobbletwo% @@ -694,7 +715,7 @@ \yquant@langhelper@declare@command@uncontrolled% {addstyle}% - {\yquant@langhelper@execclear@lastgatefalse}% + {}% {% \yquant@circuit@actonwires% \@gobbletwo% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex index 72a5969cb60..56b671fb85a 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-langhelper.tex @@ -1,5 +1,7 @@ % BEGIN_FOLD Parsing attributes \let\yquant@langhelper@list@attrs=\empty +% gatecallback is called by every "standard" gate (which does not include the "create" type of gates) +\let\yquant@langhelper@gatecallback=\@gobble \protected\long\def\yquant@langhelper@check@attrs[#1]{% \appto\yquant@langhelper@list@attrs{#1,}% @@ -175,6 +177,7 @@ \PackageError{yquant.sty}{Unsupported yquant command: `#1'}% {You used a command that is unknown to yquant.}% \fi% + \edef\yquant@langhelper@cmd@original{#1}% % Provide the association with the correct attributes \csname yquant@langhelper@setup@attrs@set@\cmd\endcsname% % For "ordinary" uses of the quotes library (without additional options), it would be better not to load the library now, since then the original text (everything in quotes) is just appended to /yquant/operator style. However, then uses with options will break the pgfkeys parser, as they are invalid. For this reason, we must enable the quotes library already at this state, with the consequence that we store the longer version, i.e., the output of the quotes-parsed expression instead. @@ -225,6 +228,7 @@ \begingroup% \lowercase{\edef\cmd{#1}}% \long\protected\csxdef{yquant@lang@\cmd}##1##2##3{% + \noexpand\yquant@langhelper@gatecallback{\cmd}% \noexpand\yquant@langhelper@execclear@lastgatetrue% \unexpanded{#2}% \yquant@circuit@operator{##1}{##2}{##3}% @@ -252,6 +256,7 @@ \noexpand\ifstrempty{##2}\relax{% \noexpand\PackageError{yquant.sty}{Negative controls are not allowed for the command `\cmd`}{}% }% + \noexpand\yquant@langhelper@gatecallback{\cmd}% \noexpand\yquant@langhelper@execclear@lastgatetrue% \unexpanded{#2}% \yquant@circuit@operator{}{}{##3}% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex b/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex index ba240dfc5e3..fb46e4e7d13 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-prepare.tex @@ -198,7 +198,7 @@ } \protected\def\yquant@prepare@inject@discard#1{% - \csappto{\yquant@prefix draw}{% + \csgappto{\yquant@prefix draw}{% \yquant@draw@inject@outer{#1}% }% \csgundef{yquant@prepare@@injection@#1}% @@ -467,6 +467,13 @@ \fi% } +\protected\gdef\yquant@prepare@output@discard#1#2#3{% + \ifstrequal{#3}{discard}{% + % This notification is triggered in the main circuit if there was an output gate on a wire with [out] or [inout] modifier, but the wire was discarded directly after the subcircuit. Then, it would look weird to extend the wire from the output gate until the end of the subcircuit, so we change the modifier to [ancilla] (not really, this is an artificial state) or [out]. + \listcsxadd{#2inonly}{#1}% + }\relax% +} + \protected\long\def\yquant@prepare@output@single#1#2#3{% \yquant@sort@eadd{% \yquant@draw@output@single% @@ -474,6 +481,14 @@ {\nodename}% }% \listadd\yquant@prepare@list{#3}% + % we must be extra careful with outputs in subcircuits: Assume the wire is discarded after the subcircuit, then we don't want to extend it after our output label + \ifdefined\yquant@parent% + \ifinlistcs{#3}{\yquant@prefix inonly}\relax{% + \yquant@register@set@lastgate{#3}{% + \yquant@prepare@output@discard{#3}{\yquant@prefix}% + }% + }% + \fi% % determine the actual dimensions by a virtual draw command \pgfinterruptboundingbox% \yquant@config@operator@multifalse% @@ -500,6 +515,18 @@ \eappto\yquant@prepare@list{% \expandafter\yquant@list@range\@secondandthirdoffive#3% }% + % we must be extra careful with outputs in subcircuits: Assume the wire is discarded after the subcircuit, then we don't want to extend it after our output label + \ifdefined\yquant@parent% + \edef\first{\@secondoffive#3}% + \edef\last{\@thirdoffive#3}% + \yquant@for \i := \first to \last {% + \xifinlistcs\i{\yquant@prefix inonly}\relax{% + \yquant@register@set@lastgate\i{% + \yquant@prepare@output@discard{\i}{\yquant@prefix}% + }% + }% + }% + \fi% \pgfinterruptboundingbox% \yquant@config@operator@multitrue% \yquant@env@virtualize@path% @@ -605,6 +632,19 @@ \@gobblethree% three arguments for the endgroup } +\let\yquant@prepare@subcircuit@pgfpointanchor=\pgfpointanchor +\patchcmd\yquant@prepare@subcircuit@pgfpointanchor{% + \pgferror{No shape named `#1' is known}% +}{}\relax{% + \PackageWarning{yquant.sty}{Patching \string\pgfpointanchor\space for the purpose of subcircuits failed; using and referencing named nodes in subcircuits may lead to irrelevant errors.}% +} +\let\yquant@prepare@subcircuit@pgfpointshapeborder=\pgfpointshapeborder +\patchcmd\yquant@prepare@subcircuit@pgfpointshapeborder{% + \pgferror{No shape named `#1' is known}% +}{}\relax{% + \PackageWarning{yquant.sty}{Patching \string\pgfpointshapeborder\space for the purpose of subcircuits failed; using and referencing named nodes in subcircuits may lead to irrelevant errors.}% +} + \protected\def\yquant@prepare@subcircuit@hspace#1#2{% \yquant@prepare@subcircuit@getmaxx{#1}% \dimdef\newx{\newx+#2}% @@ -689,6 +729,9 @@ \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% + % We may have draw actions within the subcircuit which reference nodes that have been created within the same subcircuit - but they are not known at the stage of preparation! So we here hack into the node querying macros of pgf and just let every unknown node be equal to the origin. If the node is truely unknown, we will find out about this in the draw stage. + \let\pgfpointanchor=\yquant@prepare@subcircuit@pgfpointanchor% + \let\pgfpointshapeborder=\yquant@prepare@subcircuit@pgfpointshapeborder% \let\yquant@draw@alias=\@gobble% \let\yquant@draw@hspace=\yquant@prepare@subcircuit@hspace% \let\yquant@circuit@endwires=\yquant@prepare@subcircuit@endwires% @@ -713,7 +756,7 @@ \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. + % for seamless circuits, we do not have an initial separation. However, if there is a 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% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex index 2c44fd039bb..97762cf3dde 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex @@ -44,6 +44,7 @@ \protected\def\yquant@register@define#1#2#3{% \csnumgdef{\yquant@prefix registers}% {\csname\yquant@prefix registers\endcsname+1}% + % sync with yquantlanguage-groups/\yquantgroup@startenvironment \csxdef{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}{% {#1}% type {0pt}% x pos diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex index 4b31a4e35ed..65880b995f6 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex +++ b/Master/texmf-dist/tex/latex/yquant/yquant-tools.tex @@ -452,11 +452,12 @@ \fi% } -% #1 is a pgf soft path. We extract the maximum x position at the y position specified in #2 and assign it to \dimen0. +% #1 is a pgf soft path. We extract the maximum x position at the y position specified in #2 and assign it to \dimen0, which is translated to the user coordinate system. \protected\def\yquant@softpath@extractmaxxat#1#2{% \begingroup% \dimen0=-16000pt % \dimen2=#2 % + \pgftransforminvert% \let\pgfsyssoftpath@movetotoken=\yquant@softpath@extractmaxxat@moveto% \let\pgfsyssoftpath@linetotoken=\yquant@softpath@extractmaxxat@lineto% \let\pgfsyssoftpath@curvetosupportatoken=\yquant@softpath@extractmaxxat@curveto% @@ -476,51 +477,53 @@ } \protected\def\yquant@softpath@extractmaxxat@moveto#1#2{% - \dimen4=#1 % - \dimen6=#2 % + \pgfpointtransformed{\pgfqpoint{#1}{#2}}% + \dimen4=\pgf@x % + \dimen6=\pgf@y % } \protected\def\yquant@softpath@extractmaxxat@lineto#1#2{% - \ifyquant@OR{\ifdim\dimen4>\dimen0 }{\ifdim#1>\dimen0 }{% + \pgfpointtransformed{\pgfqpoint{#1}{#2}}% + \ifyquant@OR{\ifdim\dimen4>\dimen0 }{\ifdim\pgf@x>\dimen0 }{% \ifdim\dimen6=\dimen2 % \yquant@softpath@extractmaxxat@update{\dimen4}% \else% \ifdim\dimen6<\dimen2 % - \unless\ifdim#2<\dimen2 % + \unless\ifdim\pgf@y<\dimen2 % \expandafter\yquant@softpath@extractmaxxat@update\expandafter{\the\dimexpr% \dimen4+% x0 - \dimexpr#1-\dimen4\relax*% (x1-x0) - \dimexpr\dimen2-\dimen6\relax/\dimexpr#2-\dimen6\relax% (y-y0)/(y1-y0) + \dimexpr\pgf@x-\dimen4\relax*% (x1-x0) + \dimexpr\dimen2-\dimen6\relax/\dimexpr\pgf@y-\dimen6\relax% (y-y0)/(y1-y0) \relax}% \fi% \else% - \unless\ifdim#2>\dimen2 % + \unless\ifdim\pgf@y>\dimen2 % \expandafter\yquant@softpath@extractmaxxat@update\expandafter{\the\dimexpr% \dimen4+% x0 - \dimexpr#1-\dimen4\relax*% (x1-x0) - \dimexpr\dimen2-\dimen6\relax/\dimexpr#2-\dimen6\relax% (y-y0)/(y1-y0) + \dimexpr\pgf@x-\dimen4\relax*% (x1-x0) + \dimexpr\dimen2-\dimen6\relax/\dimexpr\pgf@y-\dimen6\relax% (y-y0)/(y1-y0) \relax}% \fi% \fi% \fi% }\relax% - \dimen4=#1 % - \dimen6=#2 % + \dimen4=\pgf@x% + \dimen6=\pgf@y% } -\protected\def\yquant@softpath@extractmaxxat@curveto@checkx#1#2#3{% +\protected\def\yquant@softpath@extractmaxxat@curveto@checkx{% % \dimen11 holds our only candidate for t. Is it within the curve? \unless\ifdim\dimen11<0pt % \unless\ifdim\dimen11>1pt % - % it is. \dimen4: x0, #1: xa, #2: xb, #3: x1 + % it is. \dimen4: x0, \pgf@xa: xa, \pgf@xb: xb, \pgf@xc: x1 \begingroup% \dimen12=\dimexpr1pt-\dimen11\relax% 1 - t \dimen13=\dimexpr\dimen11*\dimen11/65535\relax% t^2 \dimen14=\dimexpr\dimen12*\dimen12/65535\relax% (1 - t)^2 - \dimen255=\dimexpr\dimen13*\dimen11/65535*\dimexpr#3\relax/65535+% t^3 x1 - 3\dimen13*\dimen12/65535*\dimexpr#2\relax/65535+% t^2(1 - t) xb + \dimen255=\dimexpr\dimen13*\dimen11/65535*\pgf@xc/65535+% t^3 x1 + 3\dimen13*\dimen12/65535*\pgf@xb/65535+% t^2(1 - t) xb \dimen14*\dimen12/65535*\dimen4/65535+% (1 - t)^3 x0 - 3\dimen11*\dimen14/65535*\dimexpr#1\relax/65535% 3t(1 - t)^2 xa + 3\dimen11*\dimen14/65535*\pgf@xa/65535% 3t(1 - t)^2 xa \relax% \expandafter% \endgroup% @@ -536,19 +539,28 @@ % where x0 = \dimen4 (the moveto point), xa = #1, xb = #3, x1 = #5. % Likewise for y: % y0 = \dimen6 (the moveto point), ya = #2, yb = #4, y1 = #6. + \pgfpointtransformed{\pgfqpoint{#1}{#2}}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgfpointtransformed{\pgfqpoint{#3}{#4}}% + \pgf@xb=\pgf@x% + \pgf@yb=\pgf@y% + \pgfpointtransformed{\pgfqpoint{#5}{#6}}% + \pgf@xc=\pgf@x% + \pgf@yc=\pgf@y% % We first solve the third-order polynomial for t using the y value, then plug it back into the x value. % TODO: this is accurate to approx. 3 digits. Can this be improved by reformulating Cardanos formula to involve less divisions? \begingroup% % We need so may dimensions that we break with TeX's convention for their use. % for the multiplications with and divisions by dimensions, we exploit that eTeX fuses muldiv to 64 bits. Further note that each dimension has a scaling factor of 65535 for sp<->pt conversion. This is why don't factor out divisions (which would be more efficient, but not give the benefit of 64bit accuracy). % a = 3(ya - yb) + (y1 - y0) - \dimen1=\dimexpr3\dimexpr#2-#4\relax+#6-\dimen6\relax% + \dimen1=\dimexpr3\pgf@ya-3\pgf@yb+\pgf@yc-\dimen6\relax% \ifdim\dimen1=0pt % % this is only a quadratic curve! % b = 3(y0 - 2ya + yb) - \dimen3=\dimexpr3\dimexpr\dimen6-2\dimexpr#2\relax+#4\relax*65535\relax% + \dimen3=\dimexpr3\dimexpr\dimen6-2\pgf@ya+\pgf@yb\relax*65535\relax% % c: 3(ya - y0) - \dimen5=\dimexpr3\dimexpr#2-\dimen6\relax*65535\relax% + \dimen5=\dimexpr3\dimexpr\pgf@ya-\dimen6\relax*65535\relax% % d: y0 - \dimen7=\dimexpr\dimexpr\dimen6-\dimen2\relax*65535\relax% % check the discriminant of the equation @@ -558,17 +570,17 @@ \pgfmathsqrt@{\the\dimen8\@gobbletwo}% \dimen11=\dimexpr\dimexpr-\dimen5+\pgfmathresult pt\relax*65535/% \dimexpr2\dimen3\relax\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \dimen11=\dimexpr\dimexpr-\dimen5-\pgfmathresult pt\relax*65535/% \dimexpr2\dimen3\relax\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \fi% \else% % We will simplify by directly dividing all coefficients by a % b = 3(y0 - 2ya + yb) - \dimen3=\dimexpr3\dimexpr\dimen6-2\dimexpr#2\relax+#4\relax*65535/\dimen1\relax% + \dimen3=\dimexpr3\dimexpr\dimen6-2\pgf@ya+\pgf@yb\relax*65535/\dimen1\relax% % c: 3(ya - y0) - \dimen5=\dimexpr3\dimexpr#2-\dimen6\relax*65535/\dimen1\relax% + \dimen5=\dimexpr3\dimexpr\pgf@ya-\dimen6\relax*65535/\dimen1\relax% % d: y0 - \dimen7=\dimexpr\dimexpr\dimen6-\dimen2\relax*65535/\dimen1\relax% % Note that now our a value (\dimen1) is no longer needed, it is one. @@ -603,7 +615,7 @@ \pgfmathpow@{\the\dimexpr-\dimen13\relax\@gobbletwo}{.3333333333}% \dimen11=\dimexpr\dimen11-\pgfmathresult pt-.33333333333\dimen3\relax% \fi% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \else% \ifdim\dimen10=0pt % % easiest case, three real roots, two of which are equal: @@ -617,10 +629,10 @@ \dimen15=-\pgfmathresult pt % \fi% \dimen11=\dimexpr2\dimen15-.33333333333\dimen3\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% % check the next candidate \dimen11=\dimexpr-\dimen15-.33333333333\dimen3\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \else% % nastiest case, three distinct real roots which we can find only by taking a complex-valued cube root. % p + i q = cbrt(R + i sqrt(|D|)) @@ -643,11 +655,11 @@ % y_2 = -p - sqrt(3)q - b/3a % y_3 = -p + sqrt(3)q - b/3a \dimen11=\dimexpr2\dimen14-.33333333333\dimen3\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \dimen11=\dimexpr-\dimen14-1.732050808\dimen15-.33333333333\dimen3\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \dimen11=\dimexpr-\dimen14+1.732050808\dimen15-.33333333333\dimen3\relax% - \yquant@softpath@extractmaxxat@curveto@checkx{#1}{#3}{#5}% + \yquant@softpath@extractmaxxat@curveto@checkx% \fi% \fi% \fi% @@ -655,30 +667,34 @@ \expandafter% \endgroup% \expandafter\dimen\expandafter0\expandafter=\the\dimen0 % - \dimen4=#5 % - \dimen6=#6 % + \dimen4=\pgf@xc % + \dimen6=\pgf@yc % } \protected\def\yquant@softpath@extractmaxxat@rectto#1#2\pgfsyssoftpath@rectsizetoken#3#4{% % #1: lower left x, #2: lower left y, #3: width, #4: height - % note that neither width nor height need be positive! - \ifdim#4>0pt % - \unless\ifdim#2>\dimen2 % - \unless\ifdim\dimexpr#2+#4\relax<\dimen2 % - \ifdim#3>0pt % - \yquant@softpath@extractmaxxat@update{\dimexpr#1+#3\relax}% + \pgfpointtransformed{\pgfqpoint{#1}{#2}}% + \pgf@xa=\pgf@x% + \pgf@ya=\pgf@y% + \pgfpointtransformed{\pgfqpoint{\dimexpr#1+#3\relax}{\dimexpr#2+#4\relax}}% + % (\pgf@xa, \pgf@ya) one corner, (\pgf@x, \pgf@y) other corner + \ifdim\pgf@y>\pgf@ya % + \unless\ifdim\pgf@ya>\dimen2 % + \unless\ifdim\pgf@y<\dimen2 % + \ifdim\pgf@x>\pgf@xa % + \yquant@softpath@extractmaxxat@update\pgf@x% \else% - \yquant@softpath@extractmaxxat@update{#1}% + \yquant@softpath@extractmaxxat@update\pgf@xa% \fi% \fi% \fi% \else% - \unless\ifdim#2<\dimen2 % - \unless\ifdim\dimexpr#2+#4\relax>\dimen2 % - \ifdim#3>0pt % - \yquant@softpath@extractmaxxat@update{\dimexpr#1+#3\relax}% + \unless\ifdim\pgf@ya<\dimen2 % + \unless\ifdim\pgf@y>\dimen2 % + \ifdim\pgf@x>\pgf@xa % + \yquant@softpath@extractmaxxat@update\pgf@x% \else% - \yquant@softpath@extractmaxxat@update{#1}% + \yquant@softpath@extractmaxxat@update\pgf@xa% \fi% \fi% \fi% diff --git a/Master/texmf-dist/tex/latex/yquant/yquant.sty b/Master/texmf-dist/tex/latex/yquant/yquant.sty index e98878845ce..e10d86a2871 100644 --- a/Master/texmf-dist/tex/latex/yquant/yquant.sty +++ b/Master/texmf-dist/tex/latex/yquant/yquant.sty @@ -15,7 +15,7 @@ % % The Current Maintainer of this work is Benjamin Desef. \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{yquant}[2021/07/03 v0.4.1 Yet another quantum circuit library for LaTeX] +\ProvidesPackage{yquant}[2021/08/17 v0.5 Yet another quantum circuit library for LaTeX] \RequirePackage{etoolbox}[2018/02/11] \RequirePackage{tikz}[2015/08/29] @@ -32,7 +32,7 @@ } \ProcessOptionsX \unless\ifdefined\yquant@compat - \PackageWarning{yquant.sty}{Please specify the `compat` key for yquant. Using `0.3`. Current version is `0.4`.} + \PackageWarning{yquant.sty}{Please specify the `compat` key for yquant. Using `0.3`. Current compatibility version `0.4`.} \def\yquant@compat{1} \fi @@ -51,8 +51,11 @@ % usually, \\ is robust; but when using \centering, it is \let to \@centercr, which is not robust (probably because this happens only when not protecting). Fix this, so that \\ does not require \protect if a centered circuit is drawn. \robustify\@centercr -\outer\def\useyquantlanguage#1{% - \RequirePackage{yquantlanguage-#1} +\def\useyquantlanguage@#1{% + \RequirePackage{yquantlanguage-#1}% +} +\outer\def\useyquantlanguage{% + \forcsvlist\useyquantlanguage@ } \endinput diff --git a/Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty new file mode 100644 index 00000000000..e8330d731e5 --- /dev/null +++ b/Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty @@ -0,0 +1,527 @@ +% yquantlanguage-groups.sty +% Extend yquant for quick and simple circuit equations. +% +% Copyright 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 +% version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3c or later is part of all distributions of LaTeX version 2005/12/01 or +% later. +% +% This work has the LPPL maintenance status `author-maintained'. +% +% The Current Maintainer of this work is Benjamin Desef. +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{yquantlanguage-groups}[2021/08/14 v0.5 yquant-groups] + +\RequirePackage{yquant}[2021/08/14] + +% BEGIN_FOLD Config +\newif\ifyquantgroup@config@aligned +\pgfqkeys{/yquant}{% + group/every group/.style={},% + group/line separation/.code={% + \dimdef\yquantgroup@config@lineseparation{#1}% + },% + group/aligned/.is if=yquantgroup@config@aligned, + operators/every group circuit/.code={% + \pgfkeysalso{% + /yquant/operators/every subcircuit,% + /yquant/operators/subcircuit/frameless,% + }% + % we want no name mangling for the subcircuit that is responsible for the groups, but we want the original setting restored within (with the possibility to override this in the options). Since the outer option is queried in the preparation step and then fixes to what it is reset within the subcircuit, we just don't apply our name mangling rule during the preparation stage, only during execution. + \unless\ifyquantmeasuring% + \pgfkeysalso{% + /yquant/operators/subcircuit/name mangling=transparent% + }% + \fi% + },% + operators/every group equals/.style={shape=yquant-rectangle, align=center, inner xsep=1mm, x radius=2mm, y radius=2.47mm} +} +\def\yquantgroup@config@lineseparation{5mm}% +% END_FOLD + +\def\yquantgroup@prefix{yquantgroup@env@registers@}% +\def\yquantgroup@parent{yquantgroup@env@parent@}% + +% BEGIN_FOLD Environment +\newenvironment{yquantgroup}[1][]{% + \ifdefined\yquant@parent% + \PackageError{yquant.sty}{yquantgroup must be top-level}% + {You may not use the yquantgroup environment within a subcircuit or a user-defined gate.}% + \fi% + % macros that may have a meaning that we want to restore inside the circuits + \let\yquantgroup@save@registers=\registers% + \let\yquantgroup@save@circuit=\circuit% + \let\yquantgroup@save@equals=\equals% + \let\yquantgroup@save@shiftright=\shiftright% + \let\yquantgroup@save@linebreak=\\% + \let\yquantgroup@save@gatecallback=\yquant@langhelper@gatecallback% + % assign the new meaning + \let\registers=\yquantgroup@registers% + \let\circuit=\yquantgroup@circuit% + \let\equals=\yquantgroup@equals% + \let\shiftright=\yquantgroup@shiftright% + \let\\=\yquantgroup@linebreak% + % This is a bit inconsistent, we should check \iftikz@inside@picture, but this is no longer appropriately set since at pgf 3.1.2. + \let\ifyquantgroup@inpicture=\ifpgfpicture% + \pgfkeysgetvalue{/yquant/preamble}\yquantgroup@save@preamble% + \ifpgfpicture% + \let\pagebreak=\yquantgroup@nobreak% + \let\newpage=\yquantgroup@nobreak% + \let\clearpage=\yquantgroup@nobreak% + \let\cleardoublepage=\yquantgroup@nobreak% + \let\yquantgroup@start@tikzpicture=\relax% + \let\yquantgroup@end@tikzpicture=\relax% + \else% + \let\yquantgroup@save@pagebreak=\pagebreak% + \let\pagebreak=\yquantgroup@pagebreak% + \let\yquantgroup@save@newpage=\newpage% + \let\newpage=\yquantgroup@newpage% + \let\yquantgroup@save@clearpage=\clearpage% + \let\clearpage=\yquantgroup@clearpage% + \let\yquantgroup@save@cleardoublepage=\cleardoublepage% + \let\cleardoublepage=\yquantgroup@cleardoublepage% + \def\yquantgroup@start@tikzpicture{\tikzpicture \global\pgf@picminx=0pt }% + \def\yquantgroup@end@tikzpicture{\endtikzpicture}% + \pgfkeysdef{/yquant/preamble}{% + \def\yquantgroup@start@tikzpicture{\tikzpicture[{#1}] \global\pgf@picminx=0pt }% + }% + \fi% + \undef\yquantgroup% + \yquantset{#1, /tikz/.cd, /yquant/group/every group}% + \def\yquantgroup@alignments{0}% + \def\yquantgroup@currentxpos{-\yquant@config@operator@sep}% + \def\yquantgroup@currentypos{0pt}% + \let\yquantgroup@mangling=\yquant@config@operator@subcircuit@mangling% + \pgfkeyslet{/yquant/preamble}\yquantgroup@save@preamble% + \yquantgroup@start@tikzpicture% +}{% + \ifdefined\yquant@prefix% + \yquant@env@end% + \fi% + \ifcsname\yquantgroup@parent cleanup\endcsname% + \yquant@for \i := 1 to \csname\yquantgroup@prefix registers\endcsname {% + \csgundef{\yquantgroup@prefix import@\i}% + }% + \expandafter\expandafter\expandafter\yquant@cleanup\csname\yquantgroup@parent cleanup\endcsname|% + \csgundef{\yquantgroup@parent cleanup}% + \gundef\yquantgroup@start@yquant% + \else% + \PackageWarning{yquant.sty}{Empty yquantgroup}% + \fi% + \gundef\yquantgroup@alignments% + \yquantgroup@end@tikzpicture% +} + +\newenvironment{yquantgroup*}[1][]{% + \yquantgroup[{#1}]% + \yquant@env@lazytrue% +}{% + \endyquantgroup% +} +% END_FOLD + +% BEGIN_FOLD Register declaration +\protected\long\def\yquantgroup@registers#1{% + \begingroup% + \gdef\yquantgroup@registers@text{#1}% + \let\yquantgroup@save@lang@create@parse=\yquant@lang@create@parse@name% + \let\yquant@lang@create@parse@name=\yquantgroup@registers@create@parse% + \let\yquant@env@begin@generic=\yquantgroup@registers@env@generic% + \appto\yquant@langhelper@setup@attrs@set@nobit{% + \let\yquantgroup@registers@remember@attrs=\yquant@langhelper@list@attrs% + }% + \appto\yquant@langhelper@setup@attrs@set@qubit{% + \let\yquantgroup@registers@remember@attrs=\yquant@langhelper@list@attrs% + }% + \appto\yquant@langhelper@setup@attrs@set@cbit{% + \let\yquantgroup@registers@remember@attrs=\yquant@langhelper@list@attrs% + }% + \appto\yquant@langhelper@setup@attrs@set@qubits{% + \let\yquantgroup@registers@remember@attrs=\yquant@langhelper@list@attrs% + }% + \let\yquantgroup@registers@remember@attrs=\empty% + \setbox0=\hbox{% + \pgfinterruptboundingbox% + \yquant@envunstar[]% + #1% + \yquant@env@end% + \endpgfinterruptboundingbox% + }% + \def\registers{% + \PackageError{yquant.sty}{Double invocation of \string\registers}% + {All registers must be specified once at the beginning of the group. Multiple declarations or later additions are not allowed.}% + }% + \unless\ifx\yquantgroup@registers@text\empty% + \csxappto{\yquantgroup@prefix import@\csname\yquantgroup@prefix registers\endcsname}{% + \unexpanded\expandafter{\yquantgroup@registers@text}% + }% + \fi% + \gundef\yquantgroup@registers@text% + \endgroup% +} + +% sync with yquant-env +\let\yquantgroup@registers@env@generic=\yquant@env@begin@generic +\patchcmd\yquantgroup@registers@env@generic{% + \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% + \global\cslet{\yquant@prefix parameters}\empty% + \else% + \let\yquant@lang@reset@attrs@inputoutput=\yquant@lang@reset@attrs@inputoutput@subcircuit% + \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% +}{% + \unless\ifnum\yquant@env=0 % + \PackageError{yquant.sty}{Assertion failure}% + {Nested \string\registers-induced yquant environment found.}% + \fi% + \let\yquant@parent=\yquantgroup@parent% + \let\yquant@prefix=\yquantgroup@prefix% + \yquantmeasuringtrue% + \yquant@env@substikz#1% + \global\cslet{\yquant@prefix parameters}\empty% +}\relax{% + \PackageError{yquant.sty}{Internal error}% + {Unable to patch yquant environment for \string\registers.}% +} + +\protected\def\yquantgroup@registers@create@parse#1[#2;{% + \let\yquant@lang@create@type=\yquant@register@type@none% + \ifstrempty{#2}{% + \edef\yquantgroup@registers@splittext{% + \protected\long\def\noexpand\yquantgroup@registers@splittext####1% + \yquant@langhelper@cmd@original####2#1;####3% + \noexpand\yquantgroup@registers@splittext@end{% + \csgdef{\yquantgroup@prefix import@\the\numexpr\csname\yquant@prefix registers\endcsname+1\relax}{% + ####1\yquant@langhelper@cmd@original####2#1;% + }% + \gdef\noexpand\yquantgroup@registers@text{####3}% + }% + }% + \yquantgroup@registers@splittext% + \expandafter\yquantgroup@registers@splittext\yquantgroup@registers@text% + \yquantgroup@registers@splittext@end% + \yquant@lang@create@do#1[1][;% + }{% + \edef\yquantgroup@registers@splittext{% + \protected\long\def\noexpand\yquantgroup@registers@splittext####1% + \yquant@langhelper@cmd@original####2#1[\yquantgroup@registers@create@parse@extract#2];####3% + \noexpand\yquantgroup@registers@splittext@end{% + \csgdef{\yquantgroup@prefix import@\the\numexpr\csname\yquant@prefix registers\endcsname+1\relax}{% + ####1\yquant@langhelper@cmd@original####2#1[+1];% + }% + \ifnum\yquantgroup@registers@create@parse@extract#2>1 % + \noexpand\yquant@for \noexpand\i := 2 to \yquantgroup@registers@create@parse@extract#2 {% + \csgdef{\yquantgroup@prefix import@\noexpand\the\numexpr\csname\yquant@prefix registers\endcsname+\noexpand\i\relax}{% + [\yquantgroup@registers@remember@attrs]% + \yquant@langhelper@cmd@original####2#1[+1];% + }% + }% + \fi% + \gdef\noexpand\yquantgroup@registers@text{####3}% + }% + }% + \yquantgroup@registers@splittext% + \expandafter\yquantgroup@registers@splittext\yquantgroup@registers@text% + \yquantgroup@registers@splittext@end% + \yquant@lang@create@do#1[#2;% + }% +} + +\def\yquantgroup@registers@create@parse@extract#1][{#1} +% END_FOLD + +\protected\def\yquantgroup@startenvironments{% + \unless\ifcsname\yquantgroup@prefix registers\endcsname% + \PackageError{yquant.sty}{\string\circuit without \string\registers}% + {A circuit was invoked without preceding register definitions.}% + \fi% + % since \registers is in subcircuit mode, that the existence of the macro implies that it is greater than zero + \ifdef\yquant@prefix{% + % We already started the yquant environment - but this means that potentially, we could have changed our wire styles. The underlying subcircuit architecture will preserve these changes, but since in our context, we treat the circuits as independent, this is not the desired behavior: remove all styles. + \yquant@for \i := 1 to \csname\yquant@prefix registers\endcsname {% + % we don't really need to flush a wire, since it is discarded anyway + \csxappto{\yquant@prefix draw}{% + \yquant@register@set@style{\i}{}% + }% + }% + }{% + \yquant@env@begin[/tikz/shift={(\yquantgroup@currentxpos, \yquantgroup@currentypos)}]% + % we re-create all the outer registers, but without the names. + % sync with yquant-registers/\yquant@register@define + \global\csletcs{\yquant@prefix registers}{\yquantgroup@prefix registers}% + \yquant@for \i := 1 to \csname\yquantgroup@prefix registers\endcsname {% + \csxdef{\yquant@prefix register@\i}{% + {\yquant@register@type@none}% type + {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}% + }% + \yquant@cleanup@csadd{\yquant@prefix register@\i}% + \csxappto{\yquant@prefix draw}{% + \yquant@draw@init{\i}{\yquant@register@type@none}% + }% + }% + }% +} + +% BEGIN_FOLD Circuit +\def\yquantgroup@circuit{% + \@ifnextchar[\yquantgroup@circuit@i% + {\yquantgroup@circuit@i[]}% +} + +\long\def\yquantgroup@circuit@i[#1]#2{% + \yquantgroup@startenvironments% + \yquant [{#1}] group\space circuit {#2} (-);% + discard -; +} + +\yquant@langhelper@declare@command@uncontrolled% + {group circuit}% + \yquant@register@get@multiaslist% + {% + \let\yquant@lang@import=\yquantgroup@circuit@import% + \edef\yquantgroup@circuit@nonimported{% + \yquant@list@range{1}{\csname\yquantgroup@prefix registers\endcsname}% + }% + \let\yquant@langhelper@gatecallback=\yquantgroup@circuit@gatecallback% + \yquant@prepare@subcircuit{/yquant/operators/every group circuit}% + \gundef\yquantgroup@circuit@nonimported% + } +\yquant@langhelper@setup@attrs{group circuit}{value}{frameless,seamless} + +\yquant@langhelper@declare@command@uncontrolled{import}{% + \expandafter\ifstrequal\expandafter{\yquant@parent}{yquant@env1@}\relax{% + \PackageError{yquant.sty}{import gate in subcircuit}% + {The import gate can only be used in the top-level \string\circuit, but not in subcircuits.}% + }% + \let\yquantgroup@circuit@oldprefix=\yquant@prefix% + \let\yquant@prefix=\yquantgroup@prefix% +}{% + \let\yquant@prefix=\yquantgroup@circuit@oldprefix% + % we don't end the group here, so that potential attributes given to import will carry over + \undef\yquant@lang@attr@input% + \let\yquant@lang@attr@output=\relax% + \forlistloop\yquantgroup@circuit@directimport\yquant@circuit@operator@targets% +} +\let\yquantgroup@circuit@import=\yquant@lang@import +\undef\yquant@lang@import + +\protected\def\yquantgroup@circuit@directimport#1{% + \listgremove\yquantgroup@circuit@nonimported{#1}% + \ifx\yquantgroup@circuit@nonimported\empty% + \gundef\yquant@lang@import% + \global\let\yquant@langhelper@gatecallback=\yquantgroup@save@gatecallback% + \fi% + \expandafter\expandafter\expandafter\yquant% + \csname\yquantgroup@prefix import@#1\endcsname% +} + +\def\yquantgroup@circuit@restimport#1{% + % basically the same as directimport, but since we are doing all the remaining stuff, no need to check in between + \expandafter\expandafter\expandafter\yquant% + \csname\yquantgroup@prefix import@#1\endcsname% +} + +\protected\def\yquantgroup@circuit@gatecallback#1{% + \ifstrequal{#1}{import}\relax{% + % this is called by every standard gate - so we ensure that before the first standard gate is used, all outer registers are imported. Note that we are actually in a group that already contains all the relevant setup for the _current_ gate, which should not influence the implicit imports at all! So this means we do a state reset as for subcircuits. + \begingroup% + \let\yquant@langhelper@list@attrs=\empty% + \yquant@lang@reset@attrs% + \undef\yquant@lang@attr@input% + \let\yquant@lang@attr@output=\relax% + \forlistloop\yquantgroup@circuit@restimport\yquantgroup@circuit@nonimported% + \endgroup% + \global\let\yquantgroup@circuit@nonimported=\empty% + \gundef\yquant@lang@import% + \global\let\yquant@langhelper@gatecallback=\yquantgroup@save@gatecallback% + }% +} +% END_FOLD + +% BEGIN_FOLD Equals box +\yquant@langhelper@declare@command% + {group equals}% + \yquant@register@get@allowmultitrue% + {% + \expandafter\yquant@prepare% + \expandafter{\yquant@lang@attr@value}% + {/yquant/operators/every group equals}% + } +\yquant@langhelper@setup@attrs{group equals}{value}{} + +\def\yquantgroup@equals{% + \@ifstar{\yquantgroup@equals@i1}% + {\yquantgroup@equals@i0}% +} + +\def\yquantgroup@equals@i#1{% + \@ifnextchar[{\yquantgroup@equals@ii{#1}}% + {\yquantgroup@equals@ii{#1}[$=$]}% +} + +\protected\long\def\yquantgroup@equals@ii#1[#2]{% + \yquantgroup@startenvironments% + \ifx0#1% + \yquant group\space equals {#2} (-);% + \else% + \numgdef\yquantgroup@alignments{\yquantgroup@alignments+1}% + % hopefully no prefixes/suffixes are installed - if we reset them here, it will also reset them for the content, which we don't want to do; but this will then give an error when we try to access the node. Probably never a problem. + \yquant [name=yquantgroup@internal@alignment@\yquantgroup@alignments]% + group\space equals {#2} (-);% + \ifnum\yquantgroup@alignments>1 % + \pgfcoordinate{yquantgroup@internal@alignment@\the\numexpr\yquantgroup@alignments-1\relax}{west}% + \pgf@xa=\pgf@x% + \pgfcoordinate{yquantgroup@internal@alignment@\yquantgroup@alignments}{west}% + \unless\ifdim\pgf@x>\pgf@xa% + \PackageError{yquant.sty}{Invalid alignment mark position}% + {The desired alignment mark position would be to the left of an already existing mark.}% + \fi% + \fi% + \fi% +} +% END_FOLD + +% BEGIN_FOLD alignment +\def\yquantgroup@shiftright{% + \@ifstar{\yquantgroup@shiftright@i1}% + {\yquantgroup@shiftright@i0}% +} + +\def\yquantgroup@shiftright@i#1{% + \@ifnextchar[{\yquantgroup@shiftright@ii{#1}}% + {\yquantgroup@shiftright@ii{#1}[1]}% +} + +\def\yquantgroup@shiftright@ii#1[#2]{% + % first check whether #2 is a pure number or a dimension + \expandafter\expandafter\expandafter\ifstrempty\expandafter\expandafter\expandafter{% + \expandafter\yquantgroup@shiftright@removedim\the\dimexpr#2pt\relax\relax% + }{% + % #2 was no dimension (appending pt made it one) + \ifnum#2=0 % + \dimdef\yquantgroup@currentxpos{-\yquant@config@operator@sep}% + \else% + \ifnum\yquantgroup@alignments<#2 % + \PackageError{yquant.sty}{Unknown alignment point}% + {Alignment points must first be defined using \string\equals*.}% + \fi% + \pgfpointanchor{yquantgroup@internal@alignment@#2}{west}% + \dimdef\yquantgroup@currentxpos{\pgf@x-\yquant@config@operator@sep}% + \fi% + }{% + % #2 was a dimension (the pt\relax remained) + \dimdef\yquantgroup@currentxpos{\yquantgroup@currentxpos+#2}% + }% + \ifx1#1% + \ifnum\yquantgroup@alignments>0 % + \pgfcoordinate{yquantgroup@internal@alignment@\yquantgroup@alignments}{west}% + \unless\ifdim\dimexpr\yquantgroup@currentxpos+\yquant@config@operator@sep\relax>\pgf@x% + \PackageError{yquant.sty}{Invalid alignment mark position}% + {The desired alignment mark position would be to the left of an already existing mark.}% + \fi% + \fi% + \numgdef\yquantgroup@alignments{\yquantgroup@alignments+1}% + \pgfcoordinate{yquantgroup@internal@alignment@\yquantgroup@alignments}% + {\pgfqpoint{\dimexpr\yquantgroup@currentxpos+\yquant@config@operator@sep\relax}% + {\yquantgroup@currentypos}}% + \fi% +} + +\def\yquantgroup@shiftright@removedim#1\relax{} +% END_FOLD + +% BEGIN_FOLD breaks +\def\yquantgroup@linebreak{% + \@ifnextchar[\yquantgroup@linebreak@i% + {\yquantgroup@linebreak@i[\yquantgroup@config@lineseparation]}% +} + +\def\yquantgroup@linebreak@i[#1]{% + \ifdefined\yquant@prefix% + \yquant@env@end% + \else% + \PackageError{yquant.sty}{There is no line here to end}% + {You did not start a circuit before requesting a line break.}% + \fi% + \def\yquantgroup@currentxpos{-\yquant@config@operator@sep}% + \dimdef\yquantgroup@currentypos{\pgf@picminy-#1}% + \ifyquantgroup@config@aligned% + \yquantgroup@shiftright@ii0[1]% + \fi% +} + +\def\yquantgroup@nobreak{% + \PackageError{yquant.sty}{Page breaking disallowed in tikzpicture environment}% + {In order to allow for page breaking in a yquantgroup environment, move it outside of the tikzpicture.}% +} + +\def\yquantgroup@bigbreak#1{% + \@ifstar{\yquantgroup@bigbreak@i{#1}1}{\yquantgroup@bigbreak@i{#1}0}% +} + +\def\yquantgroup@bigbreak@i#1#2{% + \ifdefined\yquant@prefix% + \yquant@env@end% + \else% + \PackageError{yquant.sty}{There is no page here to end}% + {You did not start a circuit before requesting a page break.}% + \fi% + % there is no cleanup of names when leaving a tikzpicture, so all the shapes are still there - all we have to do is to remember the correct number, and also be aware of the fact that the minimum x value in the picture needs to be preserved - else and left margin will just be dropped. + \ifx1#2% + \edef\tmp{% + \unexpanded{% + \yquantgroup@end@tikzpicture% + \par#1% + \yquantgroup@start@tikzpicture% + }% + \global\pgf@picminx=\the\pgf@picminx\space% + \ifyquantgroup@config@aligned% + \noexpand\yquantgroup@shiftright@ii0[1]% + \fi% + }% + \else% + \def\tmp{% + \yquantgroup@end@tikzpicture% + \par#1% + \yquantgroup@start@tikzpicture% + \def\yquantgroup@alignments{0}% the assignments were global, so we must rather reset them + }% + \fi% + \tmp% +} + +\def\yquantgroup@pagebreak{% + \yquantgroup@bigbreak\yquantgroup@save@pagebreak% +} + +\def\yquantgroup@newpage{% + \yquantgroup@bigbreak\yquantgroup@save@newpage% +} + +\def\yquantgroup@clearpage{% + \yquantgroup@bigbreak\yquantgroup@save@clearpage% +} + +\def\yquantgroup@cleardoublepage{% + \yquantgroup@bigbreak\yquantgroup@save@cleardoublepage% +} +% END_FOLD + +\endinput \ No newline at end of file -- cgit v1.2.3