From 2788d9fb9b228a993b9396b91c9fcd4845635b64 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Tue, 24 Mar 2020 20:57:29 +0000 Subject: yquant (24mar20) git-svn-id: svn://tug.org/texlive/trunk@54527 c570f23f-e606-0410-a88d-b1316a301751 --- .../tex/latex/yquant/yquant-registers.tex | 532 +++++++++++++++++++++ 1 file changed, 532 insertions(+) create mode 100644 Master/texmf-dist/tex/latex/yquant/yquant-registers.tex (limited to 'Master/texmf-dist/tex/latex/yquant/yquant-registers.tex') diff --git a/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex new file mode 100644 index 00000000000..7f640fe4996 --- /dev/null +++ b/Master/texmf-dist/tex/latex/yquant/yquant-registers.tex @@ -0,0 +1,532 @@ +\def\yquant@register@type@none{0} +\def\yquant@register@type@q{1} +\def\yquant@register@type@c{2} +\def\yquant@register@type@qs{3} + +% Internally, we store the register information in a single macro. Indeed, this is almost always faster than using multiple macros (at least in the way implemented here), apart from changing a single type of information, which is almost as fast. +% BEGIN_FOLD Constructor: create single register and cleanup environment + +% #1: type +% #2: x position +% #3: name +% #4: index +\protected\def\yquant@register@define#1#2#3#4{% + \csnumgdef{\yquant@prefix registers}% + {\csname\yquant@prefix registers\endcsname+1}% + \csxdef{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}{% + {#1}% type + {#2}% x pos + {\yquant@config@register@minimum@height}% height; at the end, the y position + {}% wire start positions + }% + \global\csletcs{\yquant@prefix registername@#3[#4]}{\yquant@prefix registers}% + \csxdef{\yquant@prefix registerhigh@\reg}{#4}% + \yquant@cleanup@csadd{\yquant@prefix register@\csname\yquant@prefix registers\endcsname}% + \yquant@cleanup@csadd{\yquant@prefix registername@#3[#4]}% + \ifnum0=#4\relax% + \yquant@cleanup@csadd{\yquant@prefix registerhigh@\reg}% + \fi% +} +% END_FOLD + +% BEGIN_FOLD Converter: convert a register name to its id +% store the number corresponding to register #2 into #1 +\protected\def\yquant@register@get@id#1#2{% + \ifcsname\yquant@prefix registername@#2\endcsname% + \letcs#1{\yquant@prefix registername@#2}% + \else% + \yquant@register@get@id@lazycreate{#2}% + \letcs#1{\yquant@prefix registers}% + \fi% +} + +% same as before, but resolves to the _index_ of the last register +\protected\def\yquant@register@get@id@high#1#2{% + \ifcsname\yquant@prefix registerhigh@#2\endcsname% + \letcs#1{\yquant@prefix registerhigh@#2}% + \else% + \yquant@register@get@id@lazycreate{#2}% + \letcs#1{\yquant@prefix registers}% + \fi% +} + +% In the lazy mode, we create all unknown registers on-the-fly. +\def\yquant@register@get@id@lazycreate#1{% + \ifyquant@env@lazy% + % In principle, we could just call \yquant@lang@@qubit. However, if access to a vector register is desired and a _part_ of this does already exist (though not the requested index), we only create the missing registers. + \yquant@register@get@id@lazycreate@parse#1[; + \else% + \PackageError{yquant.sty}{Register `#1' unknown}% + {You referred to an unknown register. + Declare registers first using `qubit' and friends.}% + \fi% +} + +\def\yquant@register@get@id@lazycreate@parse#1[#2;{% + \if\relax\detokenize{#2}\relax% + \yquant@register@get@id@lazycreate@do#1[0][;% + \else% + \yquant@register@get@id@lazycreate@do#1[#2;% + \fi% +} + +\protected\def\yquant@register@get@id@lazycreate@do#1[#2]#3[;{% + % parse length + \if\relax\detokenize{#3}\relax% + \yquant@langhelper@validate\len\count{#2}% + \numdef\len{\len+1}% + \else% + \PackageError{yquant.sty}{Invalid register name}% + {Register names must not contain `[' apart from register length indication.}% + \fi% + \edef\reg{\trim@spaces{#1}}% + % Was this register already defined? + \ifcsname\yquant@prefix registerhigh@\reg\endcsname% + \numdef\idx{\csname\yquant@prefix registerhigh@\reg\endcsname+1}% + \unless\ifnum\idx<\len\relax% + \PackageError{yquant.sty}{Internal inconsistency detected}% + {Tried to create a register on-the-fly that already existed.}% + \fi% + \else% + \def\idx{0}% + \fi% + \begingroup% + % pre-set y position + \yquant@for \idx := \idx to \numexpr \len -1\relax {% + \yquant@register@define% + \yquant@register@type@q% + {0pt}% + \reg\idx + % Prepare to shipout + \csxappto{\yquant@prefix draw}{% + \yquant@lang@create@draw{\csname\yquant@prefix registers\endcsname}% + {0pt}% + {qubit}% + {}% + {}% + }% + }% + \endgroup% +} + +\newif\ifyquant@register@get@allowmulti +% converts names to indices +% #1: comma-separated string of names or ranges +% range format: startname-endname +% Both startname and endname may be omitted, denoting the very first and last +% register, respectively +% If \ifyquant@register@get@allowmulti is set to true, multi-qubit registers are +% allowed, which are surrounded by parentheses. They may not appear in ranges. +% \yquant@register@get@ids@list, \yquant@register@get@ids@min, \yquant@register@get@ids@max and \yquant@register@get@ids@count will be set appropriately +\begingroup% +\catcode`[=\active% +\catcode`(=\active% +\protected\gdef\yquant@register@get@ids#1{% + \begingroup% + \let\yquant@register@get@ids@list=\empty% + \count0=2147483647 % minimal id + \count2=0 % maximal id + \count4=0 % number of total registers + \ifblank{#1}{}{% + \let\ifinmulti=\iffalse% + \let\do=\yquant@register@get@ids@outerlist% + \begingroup% + \catcode`[=\active% + \catcode`(=\active% + \def[##1]{\yquant@register@get@ids@@index{##1}}% + \def(##1){\yquant@register@get@ids@@multi{##1}}% + \edef\yquant@register@get@ids@retokenized{\scantokens{#1\noexpand}}% + \expandafter% + \endgroup% + \expandafter\docsvlist\expandafter{\yquant@register@get@ids@retokenized}% + }% + \global\let\yquant@register@get@ids@list=\yquant@register@get@ids@list% + \xdef\yquant@register@get@ids@min{\the\count0}% + \xdef\yquant@register@get@ids@max{\the\count2}% + \xdef\yquant@register@get@ids@count{\the\count4}% + \endgroup% +} +\endgroup + +\protected\def\yquant@register@get@ids@@index{} +\protected\def\yquant@register@get@ids@@multi{} + +\def\yquant@register@get@ids@outerlist#1{% + \ifyquant@firsttoken\yquant@register@get@ids@@multi{#1}{% + \unless\ifyquant@register@get@allowmulti% + \PackageError{yquant.sty}{Multi-register gate not allowed}% + {The selected gate can only be used in a single-register context.}% + \fi% + \yquant@register@get@ids@multi#1\yquant@sep% + }{% + \yquant@register@get@ids@checkrange#1-\yquant@sep% + }% +} + +\protected\def\yquant@register@get@ids@multi\yquant@register@get@ids@@multi#1\yquant@sep{% + \begingroup% + \let\yquant@register@get@ids@list=\empty% + \count0=2147483647 % minimal id + \count2=0 % maximal id + \count4=0 % number of total registers + \let\ifinmulti=\iftrue% + \let\do=\yquant@register@get@ids@multilist% + \docsvlist{#1}% + \edef\process{% + \endgroup% + \noexpand\listadd\noexpand\yquant@register@get@ids@list{% + \noexpand\yquant@register@multi% + {\the\count0}{\the\count2}{\the\count4}% + {\yquant@register@get@ids@list}% + }% + \noexpand\ifnum\count0>\the\count0\space% + \count0=\the\count0\space% + \noexpand\fi% + \noexpand\ifnum\count2<\the\count2\space% + \count2=\the\count2\space% + \noexpand\fi% + \advance\count4 by 1 % + }% + \process% +} + +\def\yquant@register@get@ids@multilist#1{% + \yquant@register@get@ids@checkrange#1-\yquant@sep% +} + +\def\yquant@register@get@ids@checkrange#1-#2\yquant@sep{% + \if\relax\detokenize{#2}\relax% + % the string does not contain a dash + \yquant@register@get@ids@norange{#1}% + \else% + % this is a range argument + \yquant@register@get@ids@range#1-#2\yquant@sep% + \fi% +} + +\def\yquant@register@get@ids@norange#1{% + % the register is not used within a range, which gives us full freedom with respect to sub-index selections + \yquant@register@get@ids@norange@checkindex% + #1% + \yquant@register@get@ids@@index% + \yquant@sep% +} + +\protected\def\yquant@register@get@ids@norange@checkindex#1\yquant@register@get@ids@@index#2\yquant@sep{% + \edef\current{\trim@spaces{#1}}% + \if\relax\detokenize{#2}\relax% + % the string does not contain a sub-index; we add the full register + \yquant@register@get@id\first{\current[0]}% + \letcs\high{\yquant@prefix registerhigh@\current}% + \yquant@register@get@id\last{\current[\high]}% + \ifnum\first<\count0 % + \count0=\first\relax% + \fi% + \ifnum\last>\count2 % + \count2=\last\relax% + \fi% + \advance\count4 by \numexpr\high+1\relax% + \yquant@for \i := 0 to \high {% + \yquant@register@get@id\idx{\current[\i]}% + \listeadd\yquant@register@get@ids@list{\idx}% + }% + \else% + \yquant@register@get@ids@norange@index#2% + \fi% +} + +\protected\def\yquant@register@get@ids@norange@index#1\yquant@register@get@ids@@index{% + \let\olddo=\do% + % the string contains sub-indices; since we are not in a range, multi-indices may still be allowed + \ifinmulti% + \let\do=\yquant@register@get@ids@subindex@nomulti% + \else% + \let\do=\yquant@register@get@ids@subindex@allowmulti% + \fi% + \docsvlist{#1}% + \let\do=\olddo% +} + +\def\yquant@register@get@ids@subindex@nomulti#1{% + \yquant@register@get@ids@subindex@checkrange#1-\yquant@sep% +} + +\def\yquant@register@get@ids@subindex@allowmulti#1{% + \ifyquant@firsttoken\yquant@register@get@ids@@multi{#1}{% + \unless\ifyquant@register@get@allowmulti% + \PackageError{yquant.sty}{Multi-register gate not allowed}% + {The selected gate can only be used in a single-register context.}% + \fi% + \yquant@register@get@ids@subindex@multi#1\yquant@sep% + }{% + \yquant@register@get@ids@subindex@checkrange#1-\yquant@sep% + }% +} + +\protected\def\yquant@register@get@ids@subindex@multi\yquant@register@get@ids@@multi#1\yquant@sep{% + \begingroup% + \let\yquant@register@get@ids@list=\empty% + \count0=2147483647 % minimal id + \count2=0 % maximal id + \count4=0 % number of total registers + \let\ifinmulti=\iftrue% + \let\do=\yquant@register@get@ids@subindex@nomulti% + \docsvlist{#1}% + \edef\process{% + \endgroup% + \noexpand\listadd\noexpand\yquant@register@get@ids@list{% + \noexpand\yquant@register@multi% + {\the\count0}{\the\count2}{\the\count4}% + {\yquant@register@get@ids@list}% + }% + \noexpand\ifnum\count0>\the\count0\space% + \count0=\the\count0\space% + \noexpand\fi% + \noexpand\ifnum\count2<\the\count2\space% + \count2=\the\count2\space% + \noexpand\fi% + \advance\count4 by 1 % + }% + \process% +} + +\def\yquant@register@get@ids@subindex@checkrange#1-#2\yquant@sep{% + \if\relax\detokenize{#2}\relax% + % the string does not contain a dash, this is a single sub-item + \yquant@register@get@ids@subindex@norange{\trim@spaces{#1}}% + \else% + % this is a range argument + \yquant@register@get@ids@subindex@range#1-#2\yquant@sep% + \fi% +} + +\protected\def\yquant@register@get@ids@subindex@norange#1{% + \yquant@register@get@id\idx{\current[#1]}% + \ifnum\idx<\count0 % + \count0=\idx\relax% + \fi% + \ifnum\idx>\count2 % + \count2=\idx\relax% + \fi% + \advance\count4 by 1\relax% + \listeadd\yquant@register@get@ids@list{\idx}% +} + +\protected\def\yquant@register@get@ids@subindex@range#1-#2-\yquant@sep{% + \ifblank{#1}{% + \def\first{0}% + }{% + \yquant@langhelper@validate\first\count{#1}% + }% + \ifblank{#2}{% + \yquant@register@get@id@high\last\current% + }{% + \yquant@langhelper@validate\last\count{#2}% + }% + \yquant@for \i := \first to \last {% + \yquant@register@get@ids@subindex@norange\i% + }% +} + +\protected\def\yquant@register@get@ids@range#1-#2-\yquant@sep{% + % being a range between two registers, those must be uniquely identifiable, i.e. either a single sub-indexed part of a vector register, or no vector specification at all. + \ifblank{#1}{% + \def\first{1}% + }{% + \yquant@register@get@ids@range@getfirst#1\yquant@register@get@ids@@index\yquant@sep% + }% + \ifblank{#2}{% + \letcs\last{\yquant@prefix registers}% + }{%% + \yquant@register@get@ids@range@getlast#2\yquant@register@get@ids@@index\yquant@sep% + }% + \ifnum\first<\last\relax% + \ifnum\first<\count0 % + \count0=\first\relax% + \fi% + \ifnum\last>\count2 % + \count2=\last\relax% + \fi% + \advance\count4 by \numexpr\last-\first+1\relax% + \else% + \ifnum\last<\count0 % + \count0=\last\relax% + \fi% + \ifnum\first>\count2 % + \count2=\first\relax% + \fi% + \advance\count4 by \numexpr\first-\last+1\relax% + \fi% + \yquant@for \i := \first to \last {% + \listeadd\yquant@register@get@ids@list{\i}% + }% +} + +\def\yquant@register@get@ids@range@getfirst#1\yquant@register@get@ids@@index#2\yquant@sep{% + \if\relax\detokenize{#2}\relax% + \yquant@register@get@id\first{\trim@spaces{#1}[0]}% + \else% + \yquant@register@get@ids@range@get\first#1\yquant@register@get@ids@@index#2% + \fi% +} + +\protected\def\yquant@register@get@ids@range@getlast#1\yquant@register@get@ids@@index#2\yquant@sep{% + \if\relax\detokenize{#2}\relax% + \yquant@register@get@id@high\last{\trim@spaces{#1}}% + \yquant@register@get@id\last{\trim@spaces{#1}[\last]}% + \else% + \yquant@register@get@ids@range@get\last#1\yquant@register@get@ids@@index#2% + \fi% +} + +\def\yquant@register@get@ids@range@get#1#2\yquant@register@get@ids@@index#3\yquant@register@get@ids@@index{% + \yquant@register@get@id#1{\trim@spaces{#2}[\trim@spaces{\trim@spaces#3}]}% +} + +\let\yquant@register@multi=\empty% +% END_FOLD + +% BEGIN_FOLD Getters: extract the requested information from the register with given id +\def\yquant@register@get@type#1{% + \expandafter\expandafter\expandafter% + \yquant@register@get@type@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@get@type@aux#1#2#3#4{#1} + +\def\yquant@register@get@x#1{% + \expandafter\expandafter\expandafter% + \yquant@register@get@x@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@get@x@aux#1#2#3#4{#2} + +\def\yquant@register@get@height#1{% + \expandafter\expandafter\expandafter% + \yquant@register@get@height@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@get@height@aux#1#2#3#4{#3} + +% The y parameter get macros exist in two forms: The protected one is used during the storage to the draw macro; it should never be executed. The env environment then maps them to their proper expandable forms. +\protected\def\yquant@register@get@@protected{% + \PackageError% + {yquant.sty}% + {Execution of a get-y macro in an illegal context}% + {get-y macros may not be called unless the yquant environment ends.}% +} + +\let\yquant@register@get@y=\yquant@register@get@@protected +\let\yquant@register@y=\yquant@register@get@@protected +% This plays a similar role: It must never be expanded before the tikz command is invoked (because it does not exist). +\let\nodepart=\yquant@register@get@@protected + +% getting the y position is the same as getting the height parameter, since we will reuse it at the end. +\let\yquant@register@get@y@unprotected=\yquant@register@get@height + +% y distance between two registers. +\def\yquant@register@get@ydist#1#2{% + \expandafter\yquant@abs\expandafter% + {\the\dimexpr\yquant@register@get@y{#2}-\yquant@register@get@y{#1}\relax}% +} + +% y position of the current register +\def\yquant@register@y@unprotected{0pt}% + +\protected\def\yquant@register@get@y@@expandable{% + \let\yquant@register@get@y=\yquant@register@get@y@unprotected% + \let\yquant@register@y=\yquant@register@y@unprotected% +} + +\def\yquant@register@get@lastwire#1{% + \expandafter\expandafter\expandafter% + \yquant@register@get@lastwire@aux\csname\yquant@prefix register@#1\endcsname% +} + +\def\yquant@register@get@lastwire@aux#1#2#3#4{#4} + +% Set #1 to the maximum x value found between #2 and #3 +\protected\def\yquant@register@get@maxxrange#1#2#3{% + \begingroup% + \dimen0=-16383.99999pt % + \yquant@for \yquant@register@get@maxx@i := #2 to #3 {% + \dimen2=\yquant@register@get@x{\yquant@register@get@maxx@i}\relax% + \ifdim\dimen0<\dimen2 % + \dimen0=\dimen2 % + \fi% + }% + \expandafter% + \endgroup% + \expandafter\def\expandafter#1\expandafter{\the\dimen0}% +} + +% Set #1 to the maximum x value found in the list #2 +\protected\def\yquant@register@get@maxxlist#1#2{% + \begingroup% + \dimen0=-16383.99999pt % + \def\do##1{% + \dimen2=\yquant@register@get@x{##1}\relax% + \ifdim\dimen0<\dimen2 % + \dimen0=\dimen2 % + \fi% + }% + \dolistloop{#2}% + \expandafter% + \endgroup% + \expandafter\def\expandafter#1\expandafter{\the\dimen0}% +} +% END_FOLD + +% BEGIN_FOLD Setters: change register information +\protected\long\def\yquant@register@set@@aux#1#2#3{% + \long\xdef#1{\expandafter#2#1{#3}}% +} + +\protected\def\yquant@register@set@type#1{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname\yquant@register@set@type@aux% +} + +\long\def\yquant@register@set@type@aux#1#2#3#4#5{% + {#5}{#2}{#3}{#4}% +} + +\protected\def\yquant@register@set@x#1{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname\yquant@register@set@x@aux% +} + +\long\def\yquant@register@set@x@aux#1#2#3#4#5{% + {#1}{#5}{#3}{#4}% +} + +\protected\def\yquant@register@update@height#1#2{% + \ifdim#2>\yquant@register@get@height{#1} % + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname\yquant@register@set@height@aux{#2}% + \fi% +} + +\protected\def\yquant@register@set@y#1{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname\yquant@register@set@height@aux% +} + +% Set the currently used register +\protected\def\yquant@register@use#1{% + \edef\yquant@register@y{\yquant@register@get@y{#1}}% +} + +\long\def\yquant@register@set@height@aux#1#2#3#4#5{% + {#1}{#2}{#5}{#4}% +} + +\protected\def\yquant@register@set@lastwire#1{% + \expandafter\yquant@register@set@@aux% + \csname\yquant@prefix register@#1\endcsname\yquant@register@set@lastwire@aux% +} + +\long\def\yquant@register@set@lastwire@aux#1#2#3#4#5{% + {#1}{#2}{#3}{#5}% +} +% END_FOLD \ No newline at end of file -- cgit v1.2.3