% \iffalse meta-comment % % Copyright (C) 2015 by Elmar Peise % ----------------------------------------- % % This package is distributed under the MIT license. % % \fi % % \iffalse %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{drawmatrix}[2015/11/26 v1.1.0 drawmatrix package] % %<*driver> \documentclass{ltxdoc} \usepackage{hypdoc} \usepackage{drawmatrix} \usepackage{xspace} \EnableCrossrefs \RecordChanges \CodelineIndex \OnlyDescription \begin{document} \DocInput{drawmatrix.dtx} \end{document} % % \fi % % \CheckSum{131} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \changes{v1.0.0}{2014/02/23}{Initial Version} % \changes{v1.0.1}{2014/09/08}{Bugfix: Collapsible bbox (label placement for % vectors)} % \changes{v1.0.2}{2015/03/20}{Bugfix: Bbox had a linewidth/2 offset} % \changes{v1.0.3}{2015/11/18}{Introduced |diag| option} % \changes{v1.1.0}{2015/11/26}{Separate lower and upper banding, externalization % control, fixed matrix style collection, lots of simplifications, moved % ``every'' keys to |/drawmatrix| path} % % % \GetFileInfo{drawmatrix.sty} % % \title{The \textsf{drawmatrix} package} % \author{Elmar Peise \\ \texttt{peise@aices.rwth-aachen.de}} % \date{\filedate \ \fileversion} % % \newenvironment{example}{ % \begin{center}\begin{minipage}{.9\textwidth} % \scriptsize % }{ % \end{minipage}\end{center} % } % \newcommand\TikZ{Ti{\it k}Z\xspace} % % \maketitle % % \begin{abstract} % \textsf{drawmatrix} provides macros to visually represent matrices. Various % options allow to change the visualizations, e.g., drawing rectangular, % triangular, or banded matrices. % \end{abstract} % % \tableofcontents % % \section{Introduction} % In many situations, visual representations of matrices facilitate the % understanding of linear algebra properties, relations, and operations % enormously. This package provides simple tools to bring such representations % to \LaTeX. For instance, % $$ % \drawmatrix[upper]A \; % \drawmatrix[width=.5]X + % \drawmatrix[width=.5]X \; % \drawmatrix[upper, size=.5, bbox height=1]B = % \drawmatrix[width=.5]C % $$ % is typeset as follows: % \begin{verbatim} % $$ % \drawmatrix[upper]A \; % \drawmatrix[width=.5]X + % \drawmatrix[width=.5]X \; % \drawmatrix[upper, size=.5, bbox height=1]B = % \drawmatrix[width=.5]C % $$ % \end{verbatim} % % % \section{Drawing Matrices} % \DescribeMacro\drawmatrix |\drawmatrix|\oarg{options}\marg{label} draws a % matrix labeled \meta{label}: |\drawmatrix A| produces \drawmatrix A. The % \meta{options}, which modify various aspects of drawn matrix through PGF's % key-value system, are introduced in the following sections. % % By default, the matrix is centered around its label, which is aligned with the % surrounding text. The label is typeset in the surrounding mode and style. % \begin{example} % |$\drawmatrix A$|: % $\drawmatrix A$ % % |{\bf \drawmatrix A}|: % {\bf \drawmatrix A} % % |{\large \drawmatrix A}|: % {\large \drawmatrix A} % \end{example} % In equations, parentheses (spanned with |\left| and |\right|), subscripts, and % superscripts naturally extend to the drawn shape: $\left(\drawmatrix{A}_i + % \drawmatrix{B}^{-1}\right) \drawmatrix{C}$. Used in matrix products such as % $\drawmatrix{A} \drawmatrix{B}$, a little space (|\;|) helps to yield a more % natural result: $\drawmatrix{A} \; \drawmatrix{B}$. % % \subsection{Size} % By default, matrices are $1 \times 1$ large in terms of \TikZ units. The % width and height of a matrix are set through, respectively, % \DescribeMacro{height} |width=|\meta{expr} and \DescribeMacro{width} % |height=|\meta{expr}. A width or height of 0 are useful to represent vectors: % \begin{example} % |\drawmatrix[width=0]A|: % \drawmatrix[width=0]A % \end{example} % % \DescribeMacro{size} |size=|\meta{expr} sets both the width and height to % \meta{expr}, resulting in a square matrix. % % \subsection{Shape} % By default matrices are rectangular. % \subsubsection{Triangular and Trapezoidal Matrices} % Lower and upper triangular matrices are obtained by, respectively, setting the % keys \DescribeMacro{lower} |lower| and \DescribeMacro{upper} |upper|. Hereby, % non-square matrices become trapezoidal. % \begin{example} % |\drawmatrix[lower]L|: % \drawmatrix[lower]L % % |\drawmatrix[upper, width=1.5]U|: % \drawmatrix[upper, width=1.5]U % \end{example} % % \subsubsection{Banded Matrices} % Matrices are drawn as banded through the key \DescribeMacro{banded} |banded|. % The band width, i.e., the horizontal/vertical extent from the diagonal, is % specified through \DescribeMacro{bandwidth} |bandwidth=|\meta{expra (default: % 0.3)}; % \begin{example} % |\drawmatrix[banded]B|: % \drawmatrix[banded]B % % |\drawmatrix[bandwidth=.5]B|: % \drawmatrix[bandwidth=.5]B % \end{example} % % Banding for the lower and upper part of the matrices can be specified % separately through \DescribeMacro{lower banded} |lower banded| and % \DescribeMacro{upper banded} |upper banded|. Separate bandwidths are set % through \DescribeMacro{lower bandwidth} |lower bandwidth=|\meta{expr} and % \DescribeMacro{upper bandwidth} |upper bandwidth=|\meta{expr}: % \begin{example} % |\drawmatrix[lower banded]B|: % \drawmatrix[lower banded]B % % |\drawmatrix[lower bandwidth=.5, upper bandwidth=.2]B|: % \drawmatrix[lower bandwidth=.5, upper bandwidth=.2]B % \end{example} % % Banding on rectangular matrices applies to the smaller of the two dimensions: % \begin{example} % |\drawmatrix[banded, width=.8]B|: % \drawmatrix[banded, width=.8]B % % |\drawmatrix[upper banded, height=.7]B|: % \drawmatrix[upper banded, height=.7]B % \end{example} % % |banded| can be combined with |lower| or |upper| to draw the intersection of % both shapes. % \begin{example} % |\drawmatrix[banded, lower]L|: % \drawmatrix[banded, lower]L % \end{example} % % \subsubsection{Diagonal Matrices} % \DescribeMacro{diag} |diag| is a shorthand for |banded| with |bandwidth=0|: % \begin{example} % |\drawmatrix[diag]D|: % \drawmatrix[diag]D % \end{example} % % \subsection{Colors and Style} % By default, matrices are drawn in gray and filled white. The \TikZ keys % |draw=|\meta{color} and |fill=|\meta{color} change these colors. In fact, all % keys not recognized by this package are passed to the \TikZ |\filldraw| % command drawing the matrix. % \begin{example} % |\drawmatrix[fill=yellow, draw=blue]A|: % \drawmatrix[fill=yellow, draw=blue]A % % |\drawmatrix[very thick, dashed]A|: % \drawmatrix[very thick, dashed]A % \end{example} % % \subsection{The Bounding Box} % All matrices are contained in a rectangular bounding box. To draw this % bounding box (e.g., to visualize the 0 entries in the matrix), use % \DescribeMacro{bbox style} |bbox style=|\marg{style}; this style is applied % to the \TikZ |\node| that is the bounding box. % \begin{example} % |\drawmatrix[lower, bbox style={fill=blue!10}]L|: % \drawmatrix[lower, bbox style={fill=blue!10}]L % \end{example} % % By default, the bounding box is just large enough to contain the matrix. Its % size is changed through the keys \DescribeMacro{bbox height} % |bbox height=|\meta{expr} and \DescribeMacro{bbox width} % |bbox width=|\meta{expr} (or \DescribeMacro{bbox size} |bbox size=|\meta{expr} % to set them both). The label of the matrix (and thus the alignment with % respect to the surrounding text) are fixed at the center of the bounding box, % while the matrix is positioned at its top-left corner. % \begin{example} % |\drawmatrixset{bbox style={fill=blue!10}}| % \drawmatrixset{bbox style={fill=blue!10}} % % |\drawmatrix[bbox width=2, bbox height=1.5]A|: % \drawmatrix[bbox width=2, bbox height=1.5]A % \end{example} % % \sloppy The matrix can be positioned within its bounding box through % \DescribeMacro{offset height} |offset height=|\meta{expr} and % \DescribeMacro{offset width} |offset width=|\meta{expr} (or just % \DescribeMacro{offset} |offset=|\meta{expr} to shift along the diagonal). % \begin{example} % |\drawmatrixset{bbox style={fill=blue!10}}| % \drawmatrixset{bbox style={fill=blue!10}} % % |\drawmatrix[bbox size=2, offset width=.5, offset height=.75]A|: % \drawmatrix[bbox size=2, offset width=.5, offset height=.75]A % \end{example} % % \subsection{Position of the Label and Baseline} % By default, the label's |mid| is positioned at the bounding box's |center| and % its |base| is used as the whole drawing's baseline. This is controlled by the % keys \DescribeMacro{label anchor} |label anchor=|\meta{anchor}, % \DescribeMacro{label pos} |label pos=|\meta{position}, and % \DescribeMacro{baseline} |baseline=|\meta{position}. Here, \meta{position} has % to be an anchor of one of the following nodes: |bbox| (the bounding box), % |matrix| (the matrix itself), or |label| (the label). % \begin{example} % |\drawmatrixset{bbox height=1, height=.5, bbox style={fill=blue!10}}| % \drawmatrixset{bbox height=1, height=.5, bbox style={fill=blue!10}} % % |\drawmatrix[label pos=bbox.south, label anchor=south]A|: % \drawmatrix[label pos=bbox.south, label anchor=south]A % % |\drawmatrix[label pos=matrix.north west]A|: % \drawmatrix[label pos=matrix.north west]A % % |\drawmatrix[baseline=label.north]A|: % \drawmatrix[baseline=label.north]A % % |\drawmatrix[baseline=bbox.south]A|: % \drawmatrix[baseline=bbox.south]A % \end{example} % % \section{Changing Defaults} % Specifying \meta{options} with \DescribeMacro{\drawmatrixset} % |\drawmatrixset|\marg{options} applies them to all following uses of % |\drawmatrix| within the current scope. % \begin{example} % |\drawmatrixset{height=.5, lower}| % \drawmatrixset{height=.5, lower} % % |$\drawmatrix A \; \drawmatrix B$|: % $\drawmatrix A \; \drawmatrix B$ % \end{example} % % Furthermore, \TikZ keys for the entire picture, the bounding box, the matrix % itself and the label can be set through the styles \DescribeMacro{every bbox} % |every bbox|, \DescribeMacro{every drawmatrix} |every drawmatrix|, and % \DescribeMacro{every label} |every label|. % \begin{example} % |\drawmatrixset{every drawmatrix/.append style={rounded corners=5pt}}| % \drawmatrixset{every drawmatrix/.append style={rounded corners=5pt}} % % |$\drawmatrix A \; \drawmatrix[lower]B$|: % $\drawmatrix A \; \drawmatrix[lower]B$ % \end{example} % % \section{Externalization} % |\drawmatrix| behaves as any other \TikZ picture, therefore when % externalization is enabled, all matrix visualizations are also externalized. % However, since there are usually many |\drawmatrix| pictures, each of which is % very small and fast to produce, their externalization would mean a tremendous % overhead. To avoid this overhead without explicitly dis- and re-enabling % externalization throughout the document, \DescribeMacro{externalize} % |externalize=false| disables externalization for all |\drawmatrix| pictures: % \begin{example} % |\drawmatrixset{externalize=false}| % \drawmatrixset{externalize=false} % \end{example} % % % \section{Implementation} % % \DoNotIndex{ % \@bboxheight, \@bboxwidth, \@currname, \@currval, \@height, \@labeltext, % \@lowerbandwidth, \@minsize, \@offsetheight, \@offsetwidth, % \@upperbandwidth, \@width, \@zero, \RequirePackage, \begin, \def, \edef, % \else, \end, \expandafter, \fi, \filldraw, \ifdrawmatrix@externalize, % \ifmmode, \ifx, \let, \newcommand, \newif, \node, \path, \pgfkeys, % \pgfkeysalso, \pgfkeyscurrentname, \pgfkeyscurrentvalue, \pgfkeysnovalue, % \pgflinewidth, \pgfmathsetmacro, \pgfqkeys, \tikz@library@external@loaded, % \tikzset, \undefined, % } % % This section describes the implementation details of the \textsf{drawmatrix} % package. % % \subsection{Package: \TikZ} % % The \textsf{tikz} package is used for drawing. % \begin{macrocode} \RequirePackage{tikz} % \end{macrocode} % % \subsection{If for externalization} % % \TeX{} |if| representing whether to explicitly disable \TikZ externalization. % \begin{macro}{\ifdrawmatrix@externalize} % \begin{macrocode} \newif\ifdrawmatrix@externalize % \end{macrocode} % \end{macro} % % \subsection{Key Declarations and Defaults} % % We rely on PGF keys as much as we can. % \begin{macrocode} \pgfkeys{ % \end{macrocode} % % Everything happens in the path |/drawmatrix|. % \begin{macrocode} drawmatrix/.is family, drawmatrix/.cd, % \end{macrocode} % % \begin{macro}{picture} % \begin{macro}{baseline} % |picture| is the style for the |\tikzpicture| in which the matrix is drawn. % |baseline| sets the baseline of the picture to a named coordinate of the % matrix (default: base of the label). % \begin{macrocode} picture/.style={}, baseline/.style={picture/.append style={baseline=(drawmatrix #1)}}, baseline=label.base, % \end{macrocode} % \end{macro}\end{macro} % % \begin{macro}{bbox}\begin{macro}{bbox style} % |bbox| is the style of the bounding box, to which |bbox style| appends keys. % \begin{macrocode} bbox/.style={}, bbox style/.style={bbox/.append style={#1}}, % \end{macrocode} % \end{macro}\end{macro} % % \begin{macro}{bbox height} % \begin{macro}{bbox width} % \begin{macro}{bbox size} % |bbox height| and |bbox width| don't have default values. |bbox size| sets % them both to the same value. % \begin{macrocode} bbox height/.initial, bbox width/.initial, bbox size/.style={bbox height=#1, bbox width=#1}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{offset height} % \begin{macro}{offset width} % \begin{macro}{offset} % |offset height| and |offset width| are |0| by default. |offset| sets them % both to the same value. % \begin{macrocode} offset height/.initial=0, offset width/.initial=0, offset/.style={offset height=#1, offset width=#1}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{height} % \begin{macro}{width} % \begin{macro}{size} % |width| and |height| are |1| (\TikZ unit) by default. |size| sets them both % to the same value. % \begin{macrocode} height/.initial=1, width/.initial=1, size/.style={height=#1, width=#1}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{lower bandwidth} % \begin{macro}{upper bandwidth} % \begin{macro}{bandwidth} % The |lower bandwidth| and |upper bandwidth| don't have default values. % |bandwidth| sets them both to the same value. % \begin{macrocode} lower bandwidth/.initial, upper bandwidth/.initial, bandwidth/.style={lower bandwidth=#1, upper bandwidth=#1}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{lower banded} % \begin{macro}{upper banded} % \begin{macro}{banded} % |lower banded| and |upper banded| are shortcuts to set the corresponding % bandwidths to the default value of |0.3| (\TikZ units). |banded| sets them % both. % \begin{macrocode} lower banded/.style={lower bandwidth=.3}, upper banded/.style={upper bandwidth=.3}, banded/.style={lower banded, upper banded}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{lower} % \begin{macro}{upper} % \begin{macro}{diag} % |lower| and |upper| are implemented by setting the opposite bandwidth to % |0|. |diag| sets them both. % \begin{macrocode} lower/.style={upper bandwidth=0}, upper/.style={lower bandwidth=0}, diag/.style={lower, upper}, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % \begin{macro}{externalize} % |externalize| sets a \TeX{} if (default: |true| = behave as all pictures). % \begin{macrocode} externalize/.is if=drawmatrix@externalize, externalize=true, % \end{macrocode} % \end{macro} % % \begin{macro}{label} % \begin{macro}{label pos} % \begin{macro}{label anchor} % |label| is the style for the label. |label pos| sets the label at a named % coordinate of the matrix (default: center of the bounding box). % |label anchor| sets the label's |anchor| (default: in the middle). % \begin{macrocode} label/.style={}, label pos/.style={label/.append style={at=(drawmatrix #1)}}, label pos=bbox.center, label anchor/.style={label/.append style={anchor=#1}}, label anchor=mid, % \end{macrocode} % \end{macro}\end{macro}\end{macro} % % Unknown keys are collected in |/drawmatrix/drawmatrix|. % \begin{macrocode} drawmatrix/.style={}, .unknown/.code={% \let\@currname\pgfkeyscurrentname% \let\@currval\pgfkeyscurrentvalue% \ifx#1\pgfkeysnovalue\pgfkeysalso{ drawmatrix/.append style/.expand once={\@currname} }\else\pgfkeysalso{ drawmatrix/.append style/.expand twice={% \expandafter\@currname\expandafter=\@currval% } }\fi% }, % \end{macrocode} % % \begin{macro}{every picture} % \begin{macro}{every bbox} % \begin{macro}{every drawmatrix} % \begin{macro}{every label} % The default style for matrices: |every picture| applies to all % |\tikzpicture|s the matrices are drawn in, |every bbox| applies to all % bounding boxes, |every drawmatrix| applies to the matrices themselves, and % |every label| applies to the labels. % \begin{macrocode} every picture/.style={}, every bbox/.style={ name=drawmatrix bbox, inner sep=0, }, every drawmatrix/.style={ fill=white, draw=gray, }, every label/.style={ name=drawmatrix label, outer sep=0, inner sep=0, } } % \end{macrocode} % \end{macro}\end{macro}\end{macro}\end{macro} % % \subsection{User Macros} % % |\drawmatrixset| as a simple shortcut like |\tikzset|. % \begin{macro}{\drawmatrixset} % \begin{macrocode} \newcommand\drawmatrixset[1]{\pgfqkeys{/drawmatrix}{#1}} % \end{macrocode} % \end{macro} % % Here we go, the main thing: |\drawmatrix|. First, check if we are in math % mode and apply the options. % \begin{macro}{\drawmatrix} % \begin{macrocode} \newcommand\drawmatrix[2][]{{% \ifmmode\def\@labeltext{$#2$}\else\def\@labeltext{#2}\fi% \drawmatrixset{#1}% % \end{macrocode} % % Disable externalization if |externalize=false|. % % \begin{macrocode} \ifdrawmatrix@externalize\else% \ifx\tikz@library@external@loaded\undefined\else% \tikzset{external/export=false}% \fi% \fi% % \end{macrocode} % % Extract the sizes from the PGF keys and parse width, height, the minimum % dimension and zero for comparison purposes. % % \begin{macrocode} \pgfqkeys{/drawmatrix}{ height/.get=\@height, width/.get=\@width, lower bandwidth/.get=\@lowerbandwidth, upper bandwidth/.get=\@upperbandwidth, offset height/.get=\@offsetheight, offset width/.get=\@offsetwidth, bbox height/.get=\@bboxheight, bbox width/.get=\@bboxwidth, }% \pgfmathsetmacro\@height{\@height + 0.0}% \pgfmathsetmacro\@width{\@width + 0.0}% \pgfmathsetmacro\@minsize{min(\@width, \@height)}% \pgfmathsetmacro\@zero{0.0}% % \end{macrocode} % % Prepare the band widths: First, if the matrix is not banded, the bandwidth is % set to the smaller matrix dimension. Then, the band width is limited by this % smaller dimension. % % \begin{macrocode} \expandafter\ifx\@lowerbandwidth\pgfkeysnovalue% \edef\@lowerbandwidth{\@minsize}% \fi% \expandafter\ifx\@upperbandwidth\pgfkeysnovalue% \edef\@upperbandwidth{\@minsize}% \fi% \pgfmathsetmacro\@lowerbandwidth{min(\@minsize, \@lowerbandwidth)}% \pgfmathsetmacro\@upperbandwidth{min(\@minsize, \@upperbandwidth)}% % \end{macrocode} % % Set the default bounding box size. % % \begin{macrocode} \expandafter\ifx\@bboxheight\pgfkeysnovalue% \pgfmathsetmacro\@bboxheight{\@height + \@offsetheight}% \fi% \expandafter\ifx\@bboxwidth\pgfkeysnovalue% \pgfmathsetmacro\@bboxwidth{\@width + \@offsetwidth}% \fi% % \end{macrocode} % % Begin with (drawing) the path for the bounding box. % % \begin{macrocode} \begin{tikzpicture}[/drawmatrix/every picture, /drawmatrix/picture] \node[/drawmatrix/every bbox, /drawmatrix/bbox, minimum height=\@bboxheight cm, minimum width=\@bboxwidth cm] {}; % \end{macrocode} % % Whether needed or not, declare all matrix corners. % \begin{macrocode} \path (drawmatrix bbox.north west) ++(\@offsetwidth, -\@offsetheight) ++(.5\pgflinewidth, -.5\pgflinewidth) coordinate (drawmatrix north west) ++(\@width, 0) +(-\@minsize + \@upperbandwidth, 0) coordinate (drawmatrix north) +(0, -\@minsize + \@upperbandwidth) coordinate (drawmatrix east) ++(0, -\@height) coordinate (drawmatrix south east) ++(-\@width, 0) +(\@minsize - \@lowerbandwidth, 0) coordinate (drawmatrix south) +(0, \@minsize - \@lowerbandwidth) coordinate (drawmatrix west); % \end{macrocode} % % Now, draw only what is needed of the matrix. Otherwise path modifications % (e.g.,such as rounded corners) might not work. % \begin{macrocode} \filldraw[/drawmatrix/every drawmatrix, /drawmatrix/drawmatrix] (drawmatrix north west) \ifx\@upperbandwidth\@zero \ifx\@width\@minsize\else -- (drawmatrix north) \fi \ifx\@height\@minsize\else -- (drawmatrix east) \fi \else -- (drawmatrix north) \ifx\@upperbandwidth\@minsize\else -- (drawmatrix east) \fi \fi -- (drawmatrix south east) \ifx\@lowerbandwidth\@zero \ifx\@width\@minsize\else -- (drawmatrix south) \fi \ifx\@height\@minsize\else -- (drawmatrix west) \fi \else -- (drawmatrix south) \ifx\@lowerbandwidth\@minsize\else -- (drawmatrix west) \fi \fi -- cycle; % \end{macrocode} % % Add an invisible node the size of the matrix. % \begin{macrocode} \node[minimum height=\@height cm, minimum width=\@width cm, anchor=north west] at (drawmatrix north west) (drawmatrix matrix) {}; % \end{macrocode} % % The label. % \begin{macrocode} \node[/drawmatrix/every label, /drawmatrix/label] {\@labeltext}; \end{tikzpicture}% }} % \end{macrocode} % \end{macro} % % \Finale % \PrintIndex % \PrintChanges % \endinput