diff options
author | Norbert Preining <norbert@preining.info> | 2021-08-18 03:00:59 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-08-18 03:00:59 +0000 |
commit | ae34f484404571c09a61f3bde45d083a51cb0ac5 (patch) | |
tree | 0038191529599d215201d6258d373a30fee6b530 /graphics/pgf/contrib/yquant | |
parent | a365f4320519cd6ebeb512575849a4582aae4f45 (diff) |
CTAN sync 202108180300
Diffstat (limited to 'graphics/pgf/contrib/yquant')
-rw-r--r-- | graphics/pgf/contrib/yquant/README.md | 75 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/doc/yquant-doc.pdf | bin | 680322 -> 711688 bytes | |||
-rw-r--r-- | graphics/pgf/contrib/yquant/doc/yquant-doc.tex | 428 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-config.tex | 22 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-draw.tex | 218 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-env.tex | 15 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-lang.tex | 77 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-langhelper.tex | 5 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-prepare.tex | 47 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-registers.tex | 1 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant-tools.tex | 104 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquant.sty | 11 | ||||
-rw-r--r-- | graphics/pgf/contrib/yquant/tex/yquantlanguage-groups.sty | 527 |
13 files changed, 1229 insertions, 301 deletions
diff --git a/graphics/pgf/contrib/yquant/README.md b/graphics/pgf/contrib/yquant/README.md index d8d8e1afaa..e8f39e3df0 100644 --- a/graphics/pgf/contrib/yquant/README.md +++ b/graphics/pgf/contrib/yquant/README.md @@ -7,16 +7,18 @@ It builds on and interacts with TiKZ, which brings an enourmous flexibility for A detailed reference with lots of examples is provided in the PDF version of this Readme. We will sketch some basic usage. -Now yquant also understands circuits written in the qasm language! +Now yquant also understands circuits written in the qasm language and provides a simple interface for circuit equations! -## License -This material is subject to the LaTeX Project Public License 1.3c. +Support the development: +- [![PayPal](https://img.shields.io/badge/donate-via%20PayPal-blue.svg?style=flat)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=UTR3MRBYJ825A&source=url) +- ![Bitcoin](https://img.shields.io/badge/donate-BTC-blue.svg?style=flat) 3KBFpoJuA4eSPLGXEf3jicqaV1czhK36fH +- ![Ethereum](https://img.shields.io/badge/donate-ETH-blue.svg?style=flat) 0xE0F774221290b1E41ea62c2dd9af5dbD3df7c685 ## Examples -Many more examples and explanations can be found in the [PDF version](https://github.com/projekter/yquant/raw/master/doc/latex/yquant/yquant-doc.pdf) of this Readme. +Many more examples and explanations can be found in the [PDF version](doc/latex/yquant/yquant-doc.pdf) of this Readme. ### Simple teleportation circuit -![ex-01.png](https://github.com/projekter/yquant/raw/master/markdown/ex-01.png) +![ex-01.png](markdown/ex-01.png) ```LaTeX \begin{tikzpicture} \begin{yquant} @@ -35,7 +37,7 @@ Many more examples and explanations can be found in the [PDF version](https://gi ``` ### Three-qubit phase estimation circuit with QFT and controlled-U -![ex-02.png](https://github.com/projekter/yquant/raw/master/markdown/ex-02.png) +![ex-02.png](markdown/ex-02.png) ```LaTeX \begin{tikzpicture} \begin{yquant} @@ -58,7 +60,7 @@ Many more examples and explanations can be found in the [PDF version](https://gi ``` ### Three-qubit FT QEC circuit with syndrome measurement -![ex-03.png](https://github.com/projekter/yquant/raw/master/markdown/ex-03.png) +![ex-03.png](markdown/ex-03.png) ```LaTeX \begin{tikzpicture} \begin{yquant} @@ -93,34 +95,39 @@ Many more examples and explanations can be found in the [PDF version](https://gi ``` ### Error correction -![ex-04.png](https://github.com/projekter/yquant/raw/master/markdown/ex-04.png) +![ex-04.png](markdown/ex-04.png) ```LaTeX -% \usetikzlibrary{fit, quotes} +% \usetikzlibrary{quotes} \begin{tikzpicture} \begin{yquant} qubit {} msg[3]; - [name=inits] - qubit {$\ket0$} syndrome[3]; - - [name=scnot0] - cnot syndrome[0] | msg[0]; - cnot syndrome[0] | msg[1]; - cnot syndrome[1] | msg[1]; - cnot syndrome[1] | msg[2]; - cnot syndrome[2] | msg[0]; - cnot syndrome[2] | msg[2]; - [name=smeas] - dmeter {$M_{\symbol{\numexpr`a+\idx}}$} syndrome; + nobit syndrome[3]; + + [this subcircuit box style={dashed, "Syndrome Measurement"}] + subcircuit { + qubit {} msg[3]; + [out] + qubit {$\ket0$} syndrome[3]; + + cnot syndrome[0] | msg[0]; + cnot syndrome[0] | msg[1]; + cnot syndrome[1] | msg[1]; + cnot syndrome[1] | msg[2]; + cnot syndrome[2] | msg[0]; + cnot syndrome[2] | msg[2]; + + dmeter {$M_{\symbol{\numexpr`a+\idx}}$} syndrome; + } (msg[-2], syndrome[-2]); + ["Recovery"] box {$\mathcal R$} (msg) | syndrome; discard syndrome; \end{yquant} - \node[draw, dashed, fit=(inits-2) (scnot0-p0) (smeas-2), "Syndrome Measurement"] {}; \end{tikzpicture} ``` ### Lots of controls -![ex-05.png](https://github.com/projekter/yquant/raw/master/markdown/ex-05.png) +![ex-05.png](markdown/ex-05.png) ```LaTeX \begin{tikzpicture} \begin{yquant*} @@ -133,4 +140,26 @@ Many more examples and explanations can be found in the [PDF version](https://gi discard a[2, 3]; \end{yquant*} \end{tikzpicture} +``` + +### Circuit equations +![ex-06.png](markdown/ex-06.png) +```LaTeX +% \useyquantlanguage{groups} +\begin{tikzpicture} + \begin{yquantgroup} + \registers{ + qubit {} q[2]; + } + \circuit{ + h -; + cnot q[1] | q[0]; + h -; + } + \equals + \circuit{ + cnot q[0] | q[1]; + } + \end{yquantgroup} +\end{tikzpicture} ```
\ No newline at end of file diff --git a/graphics/pgf/contrib/yquant/doc/yquant-doc.pdf b/graphics/pgf/contrib/yquant/doc/yquant-doc.pdf Binary files differindex 0a1e1d144a..29379b0f77 100644 --- a/graphics/pgf/contrib/yquant/doc/yquant-doc.pdf +++ b/graphics/pgf/contrib/yquant/doc/yquant-doc.pdf diff --git a/graphics/pgf/contrib/yquant/doc/yquant-doc.tex b/graphics/pgf/contrib/yquant/doc/yquant-doc.tex index 2b2469e463..218aabcbb7 100644 --- a/graphics/pgf/contrib/yquant/doc/yquant-doc.tex +++ b/graphics/pgf/contrib/yquant/doc/yquant-doc.tex @@ -18,7 +18,7 @@ \usepackage[compat=newest]{yquant} \usepackage{braket,hyphenat,microtype,hologo,minted,import,ragged2e} \usetikzlibrary{quotes,fit,shapes.symbols,backgrounds,quantikz} -\useyquantlanguage{qasm} +\useyquantlanguage{qasm,groups} \usepackage{amsmath,adjustbox,cleveref} \usepackage[framemethod=tikz]{mdframed} % END_FOLD @@ -217,7 +217,7 @@ This document outlines the scope and usage of the \Yquant{} package. It contains both a reference and a huge number of examples. \Yquant{} is a package that makes typesetting quantum circuits easy; the package is available on CTAN. - This beta version~0.4.1 \emph{should} be stable and interfaces are not very likely to change in an incompatible way in the future. + This beta version~0.5 \emph{should} be stable and interfaces are not very likely to change in an incompatible way in the future. \compat{New in 0.4}Sometimes, backwards\hyp incompatible changes are required or advisable, in which case a compatibility setting will allow to revert back to the old behavior (rather, to maximize compatibility, this is an opt\hyp in setting: unless you choose the new behavior, you will get the old one). Please do report all issues and desirable additions on \href{https://github.com/projekter/yquant/issues}{GitHub}. @@ -333,7 +333,7 @@ This allows certain features that are expected to break old layout or functionality to revert to their previous behavior. Every feature affected by the \texttt{compat} key is documented in this manual. Once a compatibility version is selected in a document, it cannot be changed any more. - Compatibility versions will include the major and minor, but not the patch level version number. + Compatibility versions will include the major and minor, but not the patch level version number (though not every major or minor version will necessarily introduce new compatibility versions). Bugs that clearly violated behavior described in this manual will be fixed without a possibility to revert back. Changes that are not supposed to result in a (more than marginally) different result will not be included in the compatibility layer. If you find this to be wrong in a particular case, please file a bug report. @@ -962,6 +962,34 @@ IndexSingle = ?number? | ( [ ?number? ], "-", [ ?number? ] ); Hence, the most prominent application of this key is if the wires before and after the subcircuit are \gate{nobit}s, which provides a clean way to build up circuit equations with perfectly aligned wires (examples can be found in \cref{sec:examples}). \end{option} + \begin{option}[New in 0.5]{operators/subcircuit/name mangling}!prefix or discard! + This option defines how named nodes within subcircuits are made available to the outer circuit: + \begin{itemize} + \item \texttt{prefix or discard} \\ + If the subcircuit itself has a name $s$ and the inner gate has a name $g$, the outer circuit can refer to the inner gate via the name \texttt{$s$-$g$}. + Note that $s$ itself may not only consist of the user\hyp specified name, but may instead already be suffixed by \texttt{-0}, \texttt{-1}, \dots, if the subcircuits were assigned to multiple targets. + + If the subcircuit itself has no name, works as \texttt{discard}. + \item \texttt{prefix or transparent} \\ + If the subcircuit itself has a name, as works as \texttt{prefix or discard}; else, works as \texttt{transparent}. + \item \texttt{transparent} \\ + The inner gates are always available in the outer circuit by their original names. + Note that this may potentially lead to naming conflicts, which are always resolved by the latest name overwriting all previous declarations without notice. + \item \texttt{discard} \\ + The inner gates will not be available in the outer circuit. + \end{itemize} + Note that if a new gate is defined via \tex!\yquantdefinegate!---which internally uses subcircuits---the value of this option at the time of declaration is the relevant one, not the one at the time of usage. + This can be influenced via \style{/yquant/operators/subcircuit/name mangling reset}. + \end{option} + + \begin{option}[New in 0.5]{operators/subcircuit/name mangling reset}!true! + The current value of \style{/yquant/operators/subcircuit/name mangling} will be reset at the beginning of a subcircuit to the value it had upon declaration of the subcircuit only if this option is \texttt{true} upon \emph{using} the subcircuit (which typically will only make a difference if the subcircuit was defined via \tex!\yquantdefinegate! at some earlier stage). + \begin{warning} + Setting this value to \tex!false! has the potential of breaking the corresponding subcircuit/custom gate, as it may internally reference gates by names that are no longer the correct ones. + Do not use this property without a very good reason and thorough understanding of what is happening. + \end{warning} + \end{option} + \begin{option}[New in 0.4]{operators/subcircuit/seamless}!/yquant/operators/subcircuit/frameless, /yquant/register/default name=, /yquant/circuit/seamless! This option carries out multiple actions that are responsible to let the current subcircuit appear in a ``seamless'' state: \begin{itemize} @@ -1024,6 +1052,7 @@ IndexSingle = ?number? | ( [ ?number? ], "-", [ ?number? ] ); All nodes in the subcircuit will then have the name \texttt{\textit{<subcircuit name>}-\textit{<name specified in the subcircuits>}}. Note that here, \texttt{\textit{<subcircuit name>}} is the \emph{full} name of the subcircuit, which includes the \tex!-\idx! suffix, \compat{New in 0.4.1}unless there is only a single target register. For nested subcircuits, you will get multiple prefixes. + \compat{New in 0.5}The prefixing behavior can be influenced by \style{/yquant/operators/subcircuit/name mangling}. \subsection{Shapes and the drawing pipeline} All \Yquant{} shapes have the anchors available you would typically expect from a \TikZ{} shape of the given outline. @@ -1402,6 +1431,8 @@ IndexSingle = ?number? | ( [ ?number? ], "-", [ ?number? ] ); \begin{itemize} \item \compat{New in 0.4}\yquant!frameless! \\ This \style{/yquant/operators/subcircuit/frameless} style is activated with this shorthand. + \item \compat{New in 0.5}\yquant!name mangling! \\ + This shorthand will pass the value of the attribute directly to the configuration key \style{/yquant/operators/subcircuit/name mangling}. \item \compat{New in 0.4}\yquant!seamless! \\ The \style{/yquant/operators/subcircuit/seamless} style is activated with this shorthand (implies \yquant!frameless!). \item \yquant!value=<subcircuit>! (required) \\ @@ -1871,42 +1902,27 @@ qubit {$\ket{q_{\idx}} = \Ifcase\idx\relax \ket\psi \Else \ket0 \Fi$} q[3]; As the \pkg{qcircuit} manual uses a bit larger separation between the operators than \Yquant's default, we globally say\\*\tex!\yquantset{operator/separation=1em}!. \subsubsection{I. Introduction} - \begin{example}<Updated in 0.4, 0.1.1>% + \begin{example}<Updated in 0.5, 0.4, 0.1.1>% \begin{codeexample*} -\begin{tikzpicture} - \begin{yquant}[operators/subcircuit/frameless] - nobit q[3]; - - subcircuit { - [out] - qubit {} q[3]; - box {$U$} q[2] | q[0, 1]; - } (q); - discard -; - - [draw=none] - box {$=$} (-); - - subcircuit { - [out] - qubit {} q[3]; - box {$V$} q[2] | q[1]; - cnot q[1] | q[0]; - box {$V^\dagger$} q[2] | q[1]; - cnot q[1] | q[0]; - box {$V$} q[2] | q[0]; - } (q); - discard -; - \end{yquant} -\end{tikzpicture} +% \useyquantlanguage{groups} +\begin{yquantgroup} + \registers{ + qubit {} q[3]; + } + \circuit{ + box {$U$} q[2] | q[0, 1]; + } + \equals + \circuit{ + box {$V$} q[2] | q[1]; + cnot q[1] | q[0]; + box {$V^\dagger$} q[2] | q[1]; + cnot q[1] | q[0]; + box {$V$} q[2] | q[0]; + } +\end{yquantgroup} \end{codeexample*} - The best way to realize circuit equalities is with the help of \texttt{frameless} subcircuits. - The \texttt{[frameless]} attribute can either be specified on each subcircuit individually or, as done here, globally via the corresponding style. - In this way, we can specify all subcircuits individually. - All wires that are identical in the circuits must be outer wires; but in fact, we do not want them to be visible outside of the subcircuits. - Consequently, we initialize them in the outer circuit as \gate{nobit}s, declare them with the \texttt{[out]} attribute, and discard them right after the subcircuit. - It is important not to discard them within the subcircuit, as the wires would then not extend to the same horizontal final position. - The equality sign is realized very easily by means of a \gate{box} gate that spans all registers and from which we remove the border. + The best way to realize circuit equalities is with the help of \pkg{groups} language extension, which is documented in \cref{sec:foreign:groups}. \end{example} \begin{example}<Updated in 0.4> @@ -2494,7 +2510,7 @@ qubit {$\ket{q_{\idx}} = \Ifcase\idx\relax \ket\psi \Else \ket0 \Fi$} q[3]; In general, any macros that are used within a \TikZ{} path or a \Yquant{} operation must not be fragile, or must be preceded with \tex!\protect!. In this example, \tex!\\! is a robust command (at least in newer kernels), so protection is not required. - Since it may occur quite frequently that \Yquant{} is used within a \tex!center! environment or in \tex!\centering! mode (in which \tex!\\! is still fragile), \Yquant{} takes care of this (it actually robustifies \tex!\@centercr!, which is the meaning of \tex!\\! in these surroundings). + Since it may occur quite frequently that \Yquant{} is used within a \tex!center! environment or in \tex!\centering! mode (in which \tex!\\! is still fragile), \Yquant{} takes care of this (it actually robustifies \tex!\@centercr!, which is the meaning of \tex!\\! in these surroundings---and which is now incorporated into the \LaTeX{} kernel as of June~2021). In order to change the style of an individual wire, we use \gate{addstyle}. To make the final line shorter, we change the operator separation by issuing \tex!\yquantset! at the end. @@ -2824,7 +2840,6 @@ qubit {$\ket{q_{\idx}} = \Ifcase\idx\relax \ket\psi \Else \ket0 \Fi$} q[3]; \Yquant{} does not provide a mechanism for vertical labels, but you may of course just insert line breaks at appropriate positions (and set the \texttt{align} property of the labels). - \clearpage \subsubsection{VI. Spacing} \paragraph{A. Local adjustment}\leavevmode \begin{example}<Updated in 0.4> @@ -2872,6 +2887,7 @@ qubit {$\ket{q_{\idx}} = \Ifcase\idx\relax \ket\psi \Else \ket0 \Fi$} q[3]; Also note that the \style{/yquant/operator/minimum width} style is unsuitable for the given task: it would not change the visual width, only what \Yquant{} assumes its width to be. \end{example} + \clearpage \paragraph{B. Global Adjustment}\leavevmode \begin{example} \begin{codeexample*} @@ -2902,7 +2918,7 @@ qubit {$\ket{q_{\idx}} = \Ifcase\idx\relax \ket\psi \Else \ket0 \Fi$} q[3]; \clearpage \paragraph{C. Alignment}\leavevmode - \begin{example}<Updated in 0.4> + \begin{example}<Updated in 0.5, 0.4> \begin{codeexample} \begin{tikzpicture} \begin{yquant*} @@ -2920,123 +2936,84 @@ $=$ \end{codeexample} Not specifying anything for the vertical alignment will lead to the common \TikZ{} problem: the baseline will be at the bottom, which is particularly bad in this case due to the missing $X$ gate. The keys for minimal register sizes do not help here, since they only affect \Yquant's internal handling, but not the bounding box calculated by \TikZ. - The recommended way to draw circuit equations is always with \texttt{frameless} \gate{subcircuit}s; only this will guarantee perfect wire alignment in all cases. + The recommended way to draw circuit equations is always with the \pkg{groups} language extension. \begin{codeexample} -\begin{tikzpicture} - \begin{yquant} - nobit q[2]; - - [frameless] - subcircuit { - [out] - qubit {} q[2]; - x q[0]; - cnot q[1] | q[0]; - } (q); - discard -; - - [draw=none] - box {$=$} (q); - - [frameless] - subcircuit { - [out] - qubit {} q[2]; - cnot q[1] | q[0]; - x q; - } (q); - discard -; - \end{yquant} -\end{tikzpicture} +% \useyquantlanguage{groups} +\begin{yquantgroup} + \registers{ + qubit {} q[2]; + } + \circuit{ + x q[0]; + cnot q[1] | q[0]; + } + \equals + \circuit{ + cnot q[1] | q[0]; + x q; + } +\end{yquantgroup} \end{codeexample} \end{example} - \begin{example}<New in 0.4> + \clearpage + \begin{example}<Updated in 0.5\\New in 0.4> \begin{codeexample*} -\begin{tikzpicture} - \begin{yquant} - qubit {$\ket x$} q; - qubit {$\ket y$} q[+1]; - - [seamless] - subcircuit { - [in] - qubit {} q[2]; - - h q[0]; - cnot q[1] | q[0]; - output {\quad$\mapsto$} (-); - } (q); - - [draw=none, inner sep=0pt] - box {$\ket{\psi_{x, y}}$} (q); - - [seamless] - subcircuit { - [out] - qubit {} q[2]; +% \useyquantlanguage{groups} +\begin{yquantgroup} + \registers{ + qubit {} q[2]; + } + \circuit{ + init {$\ket x$} q[0]; + init {$\ket y$} q[1]; - init {$\mapsto$\quad} (q); - cnot q[1] | q[0]; - h q[0]; - } (q); + h q[0]; + cnot q[1] | q[0]; + output {} (-); + } + \equals[$\mapsto\quad\ket{\psi_{x, y}}\quad\mapsto$] + \circuit{ + init {} (q); + cnot q[1] | q[0]; + h q[0]; output {$\ket x$} q[0]; output {$\ket y$} q[1]; - \end{yquant} -\end{tikzpicture} + } +\end{yquantgroup} \end{codeexample*} Here, we do not have a circuit equation (i.e., logical statements involving multiple rather independent circuits), but a circuit progression. - We start with some ``outer'' states (note we could again have used the \tex!\symbol! trick to make the declaration a bit shorter), let them enter into the first subcircuit and define an output of this. - In the opposite way, we proceed after giving the state. - Where to put the actual labels (e.g., the \gate{box} could also have contained $\mapsto \ket{\psi_{x, y}} \mapsto$ and the \gate{output} and \gate{init} gates could have been empty) is up to the user. - - Note that we used \texttt{seamless} instead of \texttt{frameless}, which gives a tighter spacing that is more suitable if initializers or outputs are present. + Since only in one circuit we have a description of the registers, we declare them without an initial text and put their initialization into \gate{init} gates. + The mapping in between is done by using the optional argument of the \tex!\equals! macro. + In order to obtain the braces at the ends, we use empty \gate{output} and \gate{init} gates. \end{example} \clearpage \subparagraph{1. Perfecting Vertical Alignment}\leavevmode - \begin{example}<Updated in 0.4> + \begin{example}<Updated in 0.5, 0.4> \begin{codeexample*} -\begin{tikzpicture} - \begin{yquant} - nobit q[2]; - - [frameless] - subcircuit { - [out] - qubit {} q; - [out] - qubit {$\ket0$} q[+1]; - - cnot q[0] | q[1]; - cnot q[1] | q[0]; - cnot q[0] | q[1]; - } (q); - discard -; - - [draw=none] - box {$=$} (q); - - [frameless] - subcircuit { - [out] - qubit {} q; - [out] - qubit {$\ket0$} q[+1]; - - cnot q[1] | q[0]; - cnot q[0] | q[1]; - } (q); - discard -; - \end{yquant} -\end{tikzpicture} +% \useyquantlanguage{groups} +\begin{yquantgroup} + \registers{ + qubit {} q; + qubit {$\ket0$} q[+1]; + } + \circuit{ + cnot q[0] | q[1]; + cnot q[1] | q[0]; + cnot q[0] | q[1]; + } + \equals + \circuit{ + cnot q[1] | q[0]; + cnot q[0] | q[1]; + } +\end{yquantgroup} \end{codeexample*} - Using \gate{subcircuit}s here looks like an overkill, but it is the best way both for logical consistency and also to achieve perfect horizontal alignment. \end{example} - \clearpage \paragraph{D. Scaling}\leavevmode \begin{example} \begin{codeexample*} @@ -3054,6 +3031,7 @@ $=$ In earlier versions, there was a bug that required \Yquant{} to reset the \texttt{transform shape} key for \texttt{label}s, which would then require you to scale those manually. \end{example} + \clearpage \subsubsection{VII. Typesetting} \paragraph{A. Global Styling}\leavevmode \begin{example} @@ -3106,7 +3084,6 @@ $=$ \Yquant{} properly splits discontiguous multi\hyp qubit operations. \end{example} - \clearpage \paragraph{B. Per-Gate Styling}\leavevmode \begin{example}<Updated in 0.4> \begin{codeexample} @@ -3200,7 +3177,6 @@ $=$ Here, we used the key \style{/yquant/this subcircuit box style} to influence only the style of the subcircuit box itself instead of providing global options that apply to every object in the subcircuit (you wouldn't want the label be assigned to every single gate). \end{example} - \clearpage \begin{example}<Updated in 0.4> \begin{codeexample*} % \usetikzlibrary{quotes} @@ -3278,9 +3254,167 @@ $=$ \end{example} \endgroup - \section{Foreign language support}\label{sec:foreign} + \section{Foreign language support and extensions}\label{sec:foreign} \Yquant{} is built in various modules, so that it is not hard to use the quantum circuit rendering backend, but expose a different language frontend. \compat{New in 0.3}\Yquant{} not only understands its own language, but also others. + \compat{New in 0.5}Although we refer to ``foreign languages,'' additional extension packages of the \Yquant{} language itself are also covered in this section and can be loaded by the same syntax. + + \subsection[groups]{\compat{New in 0.5}groups}\label{sec:foreign:groups} + By saying \tex!\useyquantlanguage{groups}! in the preamble after loading \Yquant{} itself, additional support for groups of \Yquant{} circuits is loaded. + Various circuits in a group share a common set of registers, are appropriately aligned horizontally if on the same line and can also be aligned vertically among multiple lines. + The main intended use is for circuit equations. + + This extension provides the environment \tex!yquantgroup!. + You may use this environment within a \tex!tikzpicture!; in this case, all page\hyp break related features are not available. + You may alternatively use the environment outside of a \tex!tikzpicture!; in this case, it will start and end the pictures appropriately. + + As with \tex!yquant!, the environment accepts optional options that are passed to \tex!\yquantset!; a starred form is available that allows for the lazy creation of registers---but note that \emph{shared} registers must always be created explicitly; only if some circuits in the group have additional registers, the lazy creation applies. + + \subsubsection{General usage} + \begin{minted}{tex} +% preamble: +% \usepackage[compat=<version>]{yquant} +% \useyquantlanguage{groups} +\begin{tikzpicture}% tikz options possible. This environment may be omitted. + % tikz commands go here + \begin{yquantgroup}% yquant(group) options possible. + \registers{ + % arbitrary shared register declaration go here + } + % any of \circuit, \equals, \\, \shiftright + % if the tikzpicture environment was omitted: also allows + % \pagebreak, \newpage, \clearpage, \cleardoublepage + % in most cases, TikZ commands are also allowed + \end{yquantgroup} + % tikz commands go here +\end{tikzpicture} + \end{minted} + + \subsubsection{Special macros} + \paragraph*{\tex!\registers!} + The \tex!\registers! macro can and must only be used once in a \tex!yquantgroup! environment. + It contains the declaration of all the registers that are shared among the various circuits within a group. + Basically, if you follow the convention in a usual \Yquant{} circuit to first declare all the registers, then use the gates, then you would put the declaration part in the \tex!\registers! macro. + However, note that it is in principle also possible to mix register declarations with other gates and \TikZ{} commands. + + In case you do not use the \gate{import} gate in any of the circuits within the group and you do not declare own registers, the behavior is very straightforward: basically, the content of \tex!\registers! is copied verbatim at the beginning of each circuit. + Otherwise, the general rule is: importing a register will ensure that all non\hyp declaration commands that preceded this register declaration are executed; and importing the last register will additionally execute all succeeding commands within \tex!\registers!. + + \paragraph*{\tex!\circuit[<style>]{<content>}!} + The \tex!\circuit! macro can be thought of as starting a \tex!yquant! (or \tex!yquant*!) environment and using its mandatory argument \tex!<content>! as the content of the circuit; the optional \tex!<style>! is used to apply additional styling options to the circuit. + + This is not entirely accurate: In reality, the content is put into a \gate{subcircuit} and \tex!<style>! is passed as arguments to the subcircuit. + + The default style \style{/yquant/operators/every group circuit} is applied to the circuit. + This style is configured such that the illusion of working in a top\hyp level \tex!yquant! environment is very convincing: The circuit is frameless by default and uses the transparent name mangling scheme. + + All the registers that were previously defined via \tex!\registers! are automatically available within the circuit, as if their declaration had been copied. + In fact, \Yquant{} will make a register available the first time it is referenced in some gate; if at the end of a circuit some of the shared registers were not used, they will be imported before exiting the circuit. + Consequently, if you define own registers just for a single circuit, these will always be at the very top. + This can be influenced by means of the \gate{import} gate, which is only available in group \tex!\circuit!s. + This gate allows to import a declared register at an arbitrary position. + + \paragraph*{\tex!\equals*[<content>]!}\label{sec:foreign:groups:equals} + The \tex!\equals! macro inserts a blank text---internally, a \gate{box}\hyp like gate with the style \style{/yquant/operators/every group equals}---that contains \tex!<content>!. + If omitted, \tex!<content>! is given by \tex!$=$!. + + The optional star will put a horizontal alignment mark at the position where the box is inserted. + Similar to the \tex!&! operation in \pkg{amsmath}'s \tex!align! environment or the \tex!\>! in \TeX's native \tex!tabbing!, \Yquant{} will now remember the horizontal position of the box internally and will allow you to directly jump to this position in the next line. + Note that you may well have multiple alignment marks in a single line, which \Yquant{} internally numbers \texttt{1}, \texttt{2}, \dots. + + \paragraph*{\tex!\\[<separation>]!} + The \tex!\\! macro inserts a line break (never a page break), so that the next \tex!\circuit! or \tex!\equals! will be put below all circuits that were output before, and it will again start at the same left position as the first circuit. + The default vertical distance is given by \style{/yquant/group/line separation}, but it may be overwritten by the optional \tex!<separation>! argument, which must be a \TeX{} dimension. + + Note that if you \emph{set} new alignment marks in a new line, this will delete the alignment marks that were previously set. + + If the option \style{/yquant/group/aligned} is passed to the \tex!yquantgroup! environment, the command \tex!\shiftright! is implied after each linebreak. + + \paragraph*{\tex!\shiftright*[<where>]!} + The \tex!\shiftright! command will put the ``cursor,'' i.e., the horizontal position at which the next \tex!\circuit! or \tex!\equals! will start, at the position specified by \tex!<where>!. + By default, \tex!<where>! is \tex!1!. + If the optional star is present, \Yquant{} will additionally put an alignment mark at this position (see the documentation for \hyperref[sec:foreign:groups:equals]{\tex!\equals!}). + If the option \style{/yquant/group/aligned} is passed to the \tex!yquantgroup! environment, the command \tex!\shiftright! is implied after each linebreak or starred page break. + + The option \tex!<where>! can take various forms: + \begin{itemize} + \item It may be a natural number \texttt{1}, \texttt{2}, \dots, denoting the number of an alignment mark specified in a previous line. + \item It may be the number \texttt{0}, denoting the very beginning of the line; this is useful if the \style{/yquant/group/aligned} option is given, but for a specific line, no alignment should be performed. + \item It may be a \TeX{} dimension, in which case this dimension is directly added to the cursor (so it is a relative value). + This is where passing the optional star makes most sense. + If you want to position absolutely, you may first issue \tex!\shiftright[0]! followed by a shift by the dimension that you want. + \end{itemize} + + \begin{warning} + The macro is named \tex!\shiftright!; however, \Yquant{} does not enforce that the actual position is to the right of the current position. + You may indeed be able to create overlapping circuits if you shift back to a previous position. + \end{warning} + + \paragraph*{\tex!\pagebreak*!, \tex!\newpage*!, \tex!\clearpage*!, \tex!\cleardoublepage*!} + The page breaking commands are available only if the \tex!yquantgroup! was not enclosed in a \tex!tikzpicture!. + They will end the current picture environment, issue the original page breaking command, and start a new picture. + Hence, if you want to pass options globally to the picture, you should use the \style{/yquant/preamble} option for the \tex!yquantgroup!; the content of this key will be passed as options for every implicitly started \tex!tikzpicture!. + + Usually, remembering the horizontal alignment marks on a new page does not make much sense. + For this reason, the commands will delete all alignment; use their starred versions to retain them. + If the option \style{/yquant/group/aligned} is passed to the \tex!yquantgroup! environment, the command \tex!\shiftright! is implied after the starred version of the page break. + + Typically, you will not want to refer to named gates in a circuit on a different page; remember that if you need this feature, you must pass the \texttt{remember picture} key in the \style{/yquant/preamble} option, as this is a reference to another \tex!tikzpicture!. + Also don't forget to use the (\TikZ) \texttt{overlay} key on the corresponding path that references the node in order not to mess up with the bounding box (see the \TikZ{} documentation for those two keys). + + \subsubsection{Configuration} + Loading the \pkg{groups} language extension will define several new configuration keys. + + \begin{option}{group/every group}!! + Style that is installed for every \tex!yquantgroup! and \tex!yquantgroup*! environment, as if it had been given as an option. + The style's default path is \texttt{/tikz}. + \end{option} + + \begin{option}{group/line separation}!5mm! + This is the default vertical line separation that is inserted whenever a new line is issued in a \tex!yquantgroup!. + \end{option} + + \begin{option}{group/aligned}!false! + This boolean flag defines whether \tex!\shiftright! is automatically issued after \tex!\\! and the starred page breaking commands. + \end{option} + + \begin{option}{preamble}!! + This style may only be passed to the \tex!yquantgroup! alignment directly as an option; it is not available via \tex!\yquantset! and the like. + It is only relevant if the \tex!yquantgroup! is not contained in a \tex!tikzpicture!. + The content of this style will be given as an optional argument to the \tex!tikzpicture!; this is the recommended way to specify \TikZ{} options, as they are automatically preserved among page breaks. + \end{option} + + \begin{option}{operators/every group circuit}!/yquant/operators/every subcircuit, /yquant/operators/subcircuit/frameless, /yquant/operators/subcircuit/name mangling=transparent! + This style is installed for the \gate{subcircuit} that implicitly wraps each \tex!\circuit!. + Note that some magic is carried out to ensure that the name mangling setting only applies to the \emph{direct} content of the \tex!\circuit!; any \gate{subcircuit}s within the \tex!\circuit! will use the default name mangling scheme. + \end{option} + + \begin{option}{operators/every group equals}!shape=yquant-rectangle, align=center, inner xsep=1mm, x radius=2mm, y radius=2.47mm! + This style is installed for every \tex!\equals!, which is internally realized similarly to a \gate{box} gate. + \end{option} + + \subsubsection{Gates and operations} + No gates or operations may be used directly within the \tex!yquantgroup! environment, but all the usual \Yquant{} gates and operations are available within \tex!\registers! and \tex!\circuit!. + Additionally, within \tex!\circuit!, the \gate{import} gate is available. + + \paragraph*{\yquant!import!}\label{gate:import}\leavevmode\\ + Syntax: \yquant!import <target>;! \\ + This is a pseudo\hyp gate that makes all the outer registers given in \tex!<target>! available in the current circuit. + Consequently, the register names that are specified in \tex!<target>!, also ranges, do not refer to the registers in the \emph{current} \tex!\circuit!, but instead to those defined via \tex!\registers!. + Therefore, it is for example possible to import all outer registers at once using \yquant!import -;!. + Vector registers can also be imported partially. + + If additional content (\TeX{} commands such as \TikZ{} paths, non\hyp creation gates) is used within \tex!\registers!, everything that comes \emph{before} the declaration of a register will be copied into the \tex!\circuit! when the register is imported; for a vector, this refers to the index zero. + Additionally, any additional content that comes \emph{after} the declaration of the last register will be copied directly after the last register was imported. + + \begin{warning}[Out-of-order importing] + Note that it is principle possible to import registers out\hyp of\hyp order. + Since matching outer and inner wires in subcircuits is done in the order in which they appear, this will lead to inner registers with names that do not match their outer registers and is probably highly undesirable. + \end{warning} + + Usually, this gate will not be needed as \Yquant{} will automatically import an outer register upon its first use. + + \emph{Possible attributes:} none \subsection{qasm}\label{sec:foreign:qasm} By saying \tex!\useyquantlanguage{qasm}! in the preamble after loading \Yquant{} itself, the parser for \pkg{qasm} (not OpenQASM) is loaded. @@ -3342,7 +3476,8 @@ $=$ The following command is then used to print all of them: \begin{minted}{tex} % preamble: -% \usepackage{yquant,import} +% \usepackage[compat=<version>]{yquant} +% \usepackage{import} % \useyquantlanguage{qasm} \def\yquantimportpath{qasm/} \foreach \circuitno in {1, ..., 18} { @@ -3429,9 +3564,18 @@ $=$ \subsection*{2021-03-27: Version 0.4} New gate: \gate{inspect}. Various bug fixes. \\ Introduce the \texttt{direct control} feature: \gate{measure} gates can now substitute positive controls of future gates. - + \subsection*{2021-07-03: Version 0.4.1} Fix \href{https://github.com/projekter/yquant/issues/9}{\#9}: Output bracket misaligned. \\ Fix \href{https://github.com/projekter/yquant/issues/10}{\#10}: Unable to access node in subcircuit. As of this version, named nodes in subcircuits will also be properly aliased if there is only a single target subcircuit (so that you don't need to use the \texttt{-0} suffix for the subcircuit's name). + + \subsection*{2021-08-17: Version 0.5} + Improvement: Active outer canvas transformations (\TikZ{} shifts, scalings, rotations) should be supported more nicely (no guarantees!). \\ + Improvement: Custom gates (\tex!\yquantdefinegate!) can now contain \TikZ{} \tex!\path!\hyp like commands without the \tex!\noexpand! prefix. \\ + Improvement: Automatically discard wires \emph{inside} a subcircuit (even if they had the \texttt{out} or \texttt{inout} attribute) if they are discarded directly after the subcircuit \emph{and} they have output gates within the subcircuit (else, the wire would be re\hyp drawn from the output to the border of the subcircuit). \\ + Bugfix: Referencing named gates in nested subcircuits now works without producing an error (worked before, but gave errors). \\ + Bugfix: Properly handle the \texttt{direct control} feature if it was specified, but not used until the end of the (sub)circuit. \\ + Introduce name mangling options for subcircuits. \\ + Implement \href{https://github.com/projekter/yquant/issues/11}{\#11}: Circuit equations. As of this version, the \pkg{groups} language is available that allows to easily implement circuit equations. %END_FOLD \end{document}
\ No newline at end of file diff --git a/graphics/pgf/contrib/yquant/tex/yquant-config.tex b/graphics/pgf/contrib/yquant/tex/yquant-config.tex index d5844480ee..64979953ee 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-config.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-draw.tex b/graphics/pgf/contrib/yquant/tex/yquant-draw.tex index 7527e1ea05..574a45eec1 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-draw.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-env.tex b/graphics/pgf/contrib/yquant/tex/yquant-env.tex index 96ea7bbac3..c6e9f52b01 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-env.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-lang.tex b/graphics/pgf/contrib/yquant/tex/yquant-lang.tex index f19ebfcc38..8658d3af9f 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-lang.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-langhelper.tex b/graphics/pgf/contrib/yquant/tex/yquant-langhelper.tex index 72a5969cb6..56b671fb85 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-langhelper.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-prepare.tex b/graphics/pgf/contrib/yquant/tex/yquant-prepare.tex index ba240dfc5e..fb46e4e7d1 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-prepare.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-registers.tex b/graphics/pgf/contrib/yquant/tex/yquant-registers.tex index 2c44fd039b..97762cf3dd 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-registers.tex +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquant-tools.tex b/graphics/pgf/contrib/yquant/tex/yquant-tools.tex index 4b31a4e35e..65880b995f 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant-tools.tex +++ b/graphics/pgf/contrib/yquant/tex/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 - <desired y> \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 - <desired y> \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/graphics/pgf/contrib/yquant/tex/yquant.sty b/graphics/pgf/contrib/yquant/tex/yquant.sty index e98878845c..e10d86a287 100644 --- a/graphics/pgf/contrib/yquant/tex/yquant.sty +++ b/graphics/pgf/contrib/yquant/tex/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/graphics/pgf/contrib/yquant/tex/yquantlanguage-groups.sty b/graphics/pgf/contrib/yquant/tex/yquantlanguage-groups.sty new file mode 100644 index 0000000000..e8330d731e --- /dev/null +++ b/graphics/pgf/contrib/yquant/tex/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 |