diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/yquant/yquantlanguage-groups.sty | 527 |
1 files changed, 527 insertions, 0 deletions
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 |