From d08faae51fbb21827ca2fe7b782112631fff7b53 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 12 Aug 2018 21:56:33 +0000 Subject: nicematrix (12aug18) git-svn-id: svn://tug.org/texlive/trunk@48395 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/nicematrix/nicematrix.dtx | 2811 +++++++++++++------- .../source/latex/nicematrix/nicematrix.ins | 4 +- 2 files changed, 1865 insertions(+), 950 deletions(-) (limited to 'Master/texmf-dist/source') diff --git a/Master/texmf-dist/source/latex/nicematrix/nicematrix.dtx b/Master/texmf-dist/source/latex/nicematrix/nicematrix.dtx index 18b1e89ad3a..753cebb6e9b 100644 --- a/Master/texmf-dist/source/latex/nicematrix/nicematrix.dtx +++ b/Master/texmf-dist/source/latex/nicematrix/nicematrix.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -% Copyright (C) 2017 by F. Pantigny +% Copyright (C) 2017-2018 by F. Pantigny % ----------------------------------- % % This file may be distributed and/or modified under the @@ -15,8 +15,8 @@ % % \fi % \iffalse -\def\myfileversion{2.0} -\def\myfiledate{2018/07/06} +\def\myfileversion{2.1} +\def\myfiledate{2018/08/12} % % %<*batchfile> @@ -44,7 +44,7 @@ version 2005/12/01 or later. \endgroup % % -%<@@=nicem> +%<@@=nm> %<*driver> \documentclass[dvipsnames]{l3doc}% dvipsnames is for xcolor (loaded by Tikz, loaded by nicematrix) \VerbatimFootnotes @@ -62,7 +62,10 @@ version 2005/12/01 or later. \titlespacing*{\subsection}{0pt}{4.5ex plus 1ex minus .2ex}{2ex plus .2ex} \usepackage{multicol} \setlength{\columnseprule}{0.4pt} +\usepackage{colortbl} +\usepackage{arydshln} \parindent 0pt + \DisableCrossrefs \begin{document} \DocInput{nicematrix.dtx} @@ -87,12 +90,9 @@ version 2005/12/01 or later. % % This package can be used with |xelatex|, |lualatex|, |pdflatex| but also by the classical workflow % |latex|-|dvips|-|ps2pdf| (or Adobe Distiller). Two or three compilations may be necessary. This package requires -% and loads the packages \pkg{expl3}, \pkg{l3keys2e}, \pkg{xparse}, \pkg{array}, \pkg{mathtools} and \pkg{tikz}. +% and loads the packages \pkg{expl3}, \pkg{l3keys2e}, \pkg{xparse}, \pkg{array}, \pkg{amsmath} and \pkg{tikz}. It +% also loads the Tikz library \pkg{fit}. % -% \tikzset{highlight/.style={rectangle, -% fill=red!15, -% blend mode = multiply, -% inner sep=1pt}} % % % \medskip @@ -110,14 +110,12 @@ version 2005/12/01 or later. % \begin{bNiceArrayRC}{CCCC}% % [code-for-last-col=\color{blue}\scriptstyle, % code-for-first-row=\color{blue}\scriptstyle, -% code-after = {\tikz \node [highlight,fit = (0-1) (0-4)] {}; -% \tikz \node [highlight,fit = (1-5) (4-5)] {};}, % columns-width = auto] % C_1 & C_2 & \Cdots & C_n \\ % a_{11} & a_{12} & \Cdots & a_{1n} & L_1 \\ % a_{21} & a_{22} & \Cdots & a_{2n} & L_2 \\ % \Vdots & \Vdots & \Ddots & \Vdots & \Vdots \\ -% a_{n1} & a_{n2} & \Cdots & a_{nn} & L_n \\ +% a_{n1} & a_{n2} & \Cdots & a_{nn} & L_n % \end{bNiceArrayRC} % }$ % @@ -131,8 +129,7 @@ version 2005/12/01 or later. % % \medskip % \begin{minipage}{10cm} -% For example, consider the following code which uses an environment |{pmatrix}| of \pkg{amsmath} (or -% \pkg{mathtools}). +% For example, consider the following code which uses an environment |{pmatrix}| of \pkg{amsmath}. % % \smallskip % \begin{BVerbatim} @@ -169,7 +166,6 @@ version 2005/12/01 or later. % 0 & \cdots & 0 & 1 % \end{pmatrix}$ % \end{scope} -% % % % \section{The environments of this extension} @@ -192,8 +188,8 @@ version 2005/12/01 or later. % % \medskip % By default, the environments |{NiceMatrix}|, |{pNiceMatrix}|, |{bNiceMatrix}|, |{BNiceMatrix}|, |{vNiceMatrix}| -% and |{VNiceMatrix}| behave almost exactly as the corresponding environments of \pkg{amsmath} (and -% \pkg{mathtools}): |{matrix}|, |{pmatrix}|, |{bmatrix}|, |{Bmatrix}|, |{vmatrix}| and |{Vmatrix}|. +% and |{VNiceMatrix}| behave almost exactly as the corresponding environments of \pkg{amsmath}: +% |{matrix}|, |{pmatrix}|, |{bmatrix}|, |{Bmatrix}|, |{vmatrix}| and |{Vmatrix}|. % % % \medskip @@ -284,7 +280,8 @@ version 2005/12/01 or later. % % \bigskip % In the first column of this exemple, there are two instructions |\Vdots| but only one dotted line is drawn (there -% is no overlapping graphic objects in the resulting \textsc{pdf}). +% is no overlapping graphic objects in the resulting \textsc{pdf}\footnote{And it's not possible to draw a |\Ldots| +% and a |\Cdots| line between the same cells.}). % % However, useless computations are performed by TeX before detecting that both instructions would eventually yield % the same dotted line. That's why the package \pkg{nicematrix} provides starred versions of |\Ldots|, |\Cdots|, @@ -353,7 +350,7 @@ version 2005/12/01 or later. % % Consider the following matrix composed classicaly with the environment |{pmatrix}|.\par\nobreak % \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=7cm] +% \begin{BVerbatim}[baseline=c,boxwidth=8cm] % $A = \begin{pmatrix} % a_0 & b \\ % a_1 & \\ @@ -376,7 +373,7 @@ version 2005/12/01 or later. % \bigskip % If we add |\vdots| instructions in the second column, the geometry of the matrix is modified.\par\nobreak % \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=7cm] +% \begin{BVerbatim}[baseline=c,boxwidth=8cm] % $B = \begin{pmatrix} % a_0 & b \\ % a_1 & \vdots \\ @@ -399,7 +396,7 @@ version 2005/12/01 or later. % By default, with \pkg{nicematrix}, if we replace |{pmatrix}| by |{pNiceMatrix}| and |\vdots| by % |\Vdots| (or |\Vdots*| for efficiency), the geometry of the matrix is not changed.\par\nobreak % \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=7cm] +% \begin{BVerbatim}[baseline=c,boxwidth=8cm] % $C = \begin{pNiceMatrix} % a_0 & b \\ % a_1 & \Vdots \\ @@ -423,7 +420,7 @@ version 2005/12/01 or later. % line in the second column. It's possible by using the option |nullify-dots| (and only one instruction |\Vdots| is % necessary).\par\nobreak % \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=7cm] +% \begin{BVerbatim}[baseline=c,boxwidth=8cm] % $D = \begin{pNiceMatrix}[~emphase#nullify-dots@] % a_0 & b \\ % a_1 & \Vdots \\ @@ -449,10 +446,11 @@ version 2005/12/01 or later. % \subsection{The command Hdotsfor} % % Some people commonly use the command |\hdotsfor| of \pkg{amsmath} in order to draw horizontal dotted lines in a -% matrix. In the environments of \pkg{nicematrix}, they should use instead the command |\Hdotsfor| and they will -% have the same style of dotted lines. We recommand not to use this command in new code since it's more coherent to -% use exclusively |\Cdots|, |\Vdots|, |\Ddots|, etc. However, it can be useful in adapting existing code, -% especially when using the option |transparent| (see below). +% matrix. In the environments of \pkg{nicematrix}, one should use instead |\Hdotsfor| in order to draw dotted lines similar +% to the other dotted lines drawn by the package \pkg{nicematrix}. +% +% As with the other commands of \pkg{nicematrix} (like |\Cdots|, |\Ldots|, |\Vdots|, etc.), the dotted line drawn +% with |\Hdotsfor| extends until the contents of the cells on both sides. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=7cm] @@ -470,9 +468,29 @@ version 2005/12/01 or later. % 1 & 2 & 3 & 4 & 5 \\ % \end{pNiceMatrix}$ % +% \bigskip +% However, if these cells are empty, the dotted line extends only in the cells specified by the argument of +% |\Hdotsfor| (by design). +% % \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=7cm] +% $\begin{pNiceMatrix} +% 1 & 2 & 3 & 4 & 5 \\ +% & ~emphase#\Hdotsfor{3}@ \\ +% 1 & 2 & 3 & 4 & 5 \\ +% 1 & 2 & 3 & 4 & 5 \\ +% \end{pNiceMatrix}$ +% \end{BVerbatim} +% $\begin{pNiceMatrix} +% 1 & 2 & 3 & 4 & 5 \\ +% & \Hdotsfor{3} \\ +% 1 & 2 & 3 & 4 & 5 \\ +% 1 & 2 & 3 & 4 & 5 \\ +% \end{pNiceMatrix}$ +% +% \bigskip % The command |\hdotsfor| of \pkg{amsmath} takes an optional argument (between square brackets) which is -% used for fine tuning of the space beetween two consecutive dots. For homogeneity, the command |\Hdotsfor| has +% used for fine tuning of the space beetween two consecutive dots. For homogeneity, |\Hdotsfor| has % also an optional argument but this argument is discarded silently. % % \subsection{How to generate the continuous dotted lines transparently} @@ -492,7 +510,7 @@ version 2005/12/01 or later. % |\iddots| is not a command of LaTeX but is defined by the package \pkg{nicematrix}. If |mathdots| is loaded, the % version of |mathdots| is used.} and |\hdotsfor| are redefined within the environments provided by \pkg{nicematrix} % and behave like |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots| and |\Hdotsfor|; the command |\dots| (``automatic -% dots'' of |amsmath| --- and |mathtools|) is also redefined to behave like |\Ldots|. +% dots'' of |amsmath|) is also redefined to behave like |\Ldots|. % % \item The option |renew-matrix|\par\nobreak % With this option, the environment |{matrix}| is redefined and behave like |{NiceMatrix}|, and so on for the five @@ -520,122 +538,6 @@ version 2005/12/01 or later. % 0 & \cdots & 0 & 1 % \end{pmatrix}$ % \end{scope} -% -% \section{The width of the columns} -% \label{width} -% -% In the environments with an explicit preamble (like |{NiceArray}|, |{pNiceArrayC}|, etc.), It's possible to fix the -% width of a given column with the standard letters |w| and |W| of the package \pkg{array}. -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% $\left(\begin{NiceArray}{~emphase#wc{1cm}@CC} -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{NiceArray}\right)$ -% \end{BVerbatim} -% $\left(\begin{NiceArray}{wc{1cm}CC} -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{NiceArray}\right)$ -% -% -% \bigskip -% It's also possible to fix the width of all the columns of a matrix directly with the option |columns-width| (in -% all the environments of \pkg{nicematrix}). -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% $\begin{pNiceMatrix}[~emphase#columns-width = 1cm@] -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{pNiceMatrix}$ -% \end{BVerbatim} -% $\begin{pNiceMatrix}[columns-width = 1cm] -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{pNiceMatrix}$ -% -% \medskip -% Note that the space inserted between two columns (equal to 2 |\arraycolsep|) is not suppressed. -% -% \bigskip -% It's possible to give the value |auto| to the option |columns-width|: all the columns of the array will -% have a width equal to the widest cell of the array. \textbf{Two or three compilations may be necessary.}\par\nobreak -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=10cm] -% $\begin{pNiceMatrix}[~emphase#columns-width = auto@] -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{pNiceMatrix}$ -% \end{BVerbatim} -% $\begin{pNiceMatrix}[columns-width = auto] -% 1 & 12 & -123 \\ -% 12 & 0 & 0 \\ -% 4 & 1 & 2 -% \end{pNiceMatrix}$ -% -% \bigskip -% It's possible to fix the width of the columns of all the matrices of a current scope with the command -% |\NiceMatrixOptions|.\par\nobreak -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] -% ~emphase#\NiceMatrixOptions{columns-width=10mm}@ -% $\begin{pNiceMatrix} -% a & b \\ c & d \\ -% \end{pNiceMatrix} -% = -% \begin{pNiceMatrix} -% 1 & 1245 \\ 345 & 2 \\ -% \end{pNiceMatrix}$ -% \end{BVerbatim} -% \begin{scope} -% \NiceMatrixOptions{columns-width=10mm} -% $\begin{pNiceMatrix} -% a & b \\ -% c & d \\ -% \end{pNiceMatrix} -% = -% \begin{pNiceMatrix} -% 1 & 1245 \\ -% 345 & 2 \\ -% \end{pNiceMatrix}$ -% \end{scope} -% -% -% \bigskip -% But it's also possible to fix a zone where all the matrices will have their columns of the same width, equal to -% the widest cell of all the matrices. This construction uses the environment |{NiceMatrixBlock}| with the option -% |auto-columns-width|.\footnote{At this time, this is the only usage of the environment |{NiceMatrixBlock}| but -% it may have other usages in the future.} -% -% \medskip -% \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] -% ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ -% $\begin{pNiceMatrix} -% a & b \\ c & d \\ -% \end{pNiceMatrix} -% = -% \begin{pNiceMatrix} -% 1 & 1245 \\ 345 & 2 \\ -% \end{pNiceMatrix}$ -% ~emphase#\end{NiceMatrixBlock}@ -% \end{BVerbatim} -% \begin{NiceMatrixBlock}[auto-columns-width] -% $\begin{pNiceMatrix} -% a & b \\ c & d \\ -% \end{pNiceMatrix} -% = -% \begin{pNiceMatrix} -% 1 & 1245 \\ 345 & 2 \\ -% \end{pNiceMatrix}$ -% \end{NiceMatrixBlock} -% % % \section{The Tikz nodes created by nicematrix} % @@ -663,10 +565,157 @@ version 2005/12/01 or later. % \tikz[remember picture,overlay] % \draw (mymatrix-2-2) circle (2mm) ; % -% % \medskip % Don't forget the options |remember picture| and |overlay|. % +% \bigskip +% In the following example, we have underlined all the nodes of the matrix. +% \begin{scope} +% \tikzset{every node/.style = {fill = red!15, inner sep = 0pt}} +% \[\begin{pNiceMatrix} +% a & a + b & a + b + c \\ +% a & a & a + b \\ +% a & a & a +% \end{pNiceMatrix}\] +% \end{scope} +% +% +% \bigskip +% In fact, the package \pkg{nicematrix} can create ``extra nodes''. These new nodes are created if the option +% |create-extra-nodes| is used. There are two series of extra nodes: the ``medium nodes'' and the ``large nodes''. +% +% \medskip +% The names of the ``medium nodes'' are constructed by adding the suffix ``|-medium|'' to the names of the ``normal +% nodes''. In the following example, we have underlined the ``medium nodes''. We consider that this example is self-explanatory. +% \[\begin{pNiceMatrix} +% [create-extra-nodes, +% code-after = {\begin{tikzpicture}% +% [every node/.style = {fill = red!15, +% blend mode = multiply, +% inner sep = -\pgflinewidth/2}, +% name suffix = -medium] +% \node [fit = (1-1)] {} ; +% \node [fit = (1-2)] {} ; +% \node [fit = (1-3)] {} ; +% \node [fit = (2-1)] {} ; +% \node [fit = (2-2)] {} ; +% \node [fit = (2-3)] {} ; +% \node [fit = (3-1)] {} ; +% \node [fit = (3-2)] {} ; +% \node [fit = (3-3)] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c \\ +% a & a & a + b \\ +% a & a & a +% \end{pNiceMatrix}\] +% +% +% \medskip +% The names of the ``large nodes'' are constructed by adding the suffix ``|-large|'' to the names of the ``normal +% nodes''. In the following example, we have underlined the ``large nodes''. We consider that this example is +% self-explanatory.\footnote{In the environments like |{pNiceArrayC}| and |{pNiceArrayRC}|, there is not ``large +% nodes'' created in the exterior row and column.} +% +% \[\begin{pNiceMatrix} +% [create-extra-nodes, +% code-after = {\begin{tikzpicture}% +% [every node/.style = {blend mode = multiply, +% inner sep = -\pgflinewidth/2}, +% name suffix = -large] +% \node [fit = (1-1),fill = red!15] {} ; +% \node [fit = (1-3),fill = red!15] {} ; +% \node [fit = (2-2),fill = red!15] {} ; +% \node [fit = (3-1),fill = red!15] {} ; +% \node [fit = (3-3),fill = red!15] {} ; +% \node [fit = (1-2),fill = blue!15] {} ; +% \node [fit = (2-1),fill = blue!15] {} ; +% \node [fit = (2-3),fill = blue!15] {} ; +% \node [fit = (3-2),fill = blue!15] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c \\ +% a & a & a + b \\ +% a & a & a +% \end{pNiceMatrix}\] +% +% +% \medskip +% The ``large nodes'' of the first column and last column may appear too small for some usage. That's why it's +% possible to use the options |left-margin| and |right-margin| to add space on both sides of the array and also +% space in the ``large nodes'' of the first column and last column. In the following example, we have used the +% options |left-margin| and |right-margin|.\footnote{The options |left-margin| and |right-margin| take dimensions +% as values but, if no value is given, the default value is used, which is |\arraycolsep|.} +% \[\begin{pNiceMatrix} +% [create-extra-nodes,left-margin,right-margin, +% code-after = {\begin{tikzpicture}% +% [every node/.style = {blend mode = multiply, +% inner sep = -\pgflinewidth/2}, +% name suffix = -large] +% \node [fit = (1-1),fill = red!15] {} ; +% \node [fit = (1-3),fill = red!15] {} ; +% \node [fit = (2-2),fill = red!15] {} ; +% \node [fit = (3-1),fill = red!15] {} ; +% \node [fit = (3-3),fill = red!15] {} ; +% \node [fit = (1-2),fill = blue!15] {} ; +% \node [fit = (2-1),fill = blue!15] {} ; +% \node [fit = (2-3),fill = blue!15] {} ; +% \node [fit = (3-2),fill = blue!15] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c \\ +% a & a & a + b \\ +% a & a & a +% \end{pNiceMatrix}\] +% +% \medskip +% It's also possible to add more space on both side of the array with the options |extra-left-margin| and +% |extra-right-margin|. These margins are not incorporated in the ``large nodes''. In the following example, we +% have used |extra-left-margin| and |extra-right-margin| with the value $3$~pt. +% \[\begin{pNiceMatrix} +% [create-extra-nodes,left-margin,right-margin,extra-right-margin=3pt,extra-left-margin=3pt, +% code-after = {\begin{tikzpicture}% +% [every node/.style = {blend mode = multiply, +% inner sep = -\pgflinewidth/2}, +% name suffix = -large] +% \node [fit = (1-1),fill = red!15] {} ; +% \node [fit = (1-3),fill = red!15] {} ; +% \node [fit = (2-2),fill = red!15] {} ; +% \node [fit = (3-1),fill = red!15] {} ; +% \node [fit = (3-3),fill = red!15] {} ; +% \node [fit = (1-2),fill = blue!15] {} ; +% \node [fit = (2-1),fill = blue!15] {} ; +% \node [fit = (2-3),fill = blue!15] {} ; +% \node [fit = (3-2),fill = blue!15] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c \\ +% a & a & a + b \\ +% a & a & a +% \end{pNiceMatrix}\] +% +% \medskip +% In this case, if we want a control over the height of the rows, we can add a |\strut| in each row of the array. +% \[\begin{pNiceMatrix} +% [create-extra-nodes,left-margin,right-margin,extra-right-margin=3pt,extra-left-margin=3pt, +% code-after = {\begin{tikzpicture}% +% [every node/.style = {blend mode = multiply, +% inner sep = -\pgflinewidth/2}, +% name suffix = -large] +% \node [fit = (1-1),fill = red!15] {} ; +% \node [fit = (1-3),fill = red!15] {} ; +% \node [fit = (2-2),fill = red!15] {} ; +% \node [fit = (3-1),fill = red!15] {} ; +% \node [fit = (3-3),fill = red!15] {} ; +% \node [fit = (1-2),fill = blue!15] {} ; +% \node [fit = (2-1),fill = blue!15] {} ; +% \node [fit = (2-3),fill = blue!15] {} ; +% \node [fit = (3-2),fill = blue!15] {} ; +% \end{tikzpicture}}] +% \strut a & a + b & a + b + c \\ +% \strut a & a & a + b \\ +% \strut a & a & a +% \end{pNiceMatrix}\] +% +% \bigskip +% We explain below how to fill the nodes created by \pkg{nicematrix}. +% % \section{The code-after} % % The option |code-after| may be used to give some code that will be excuted after the construction of the matrix @@ -675,7 +724,7 @@ version 2005/12/01 or later. % In the |code-after|, the Tikz nodes should be accessed by a name of the form $i$-$j$ (without the prefix of the % name of the environment). % -% Morevover, a special command, called |\line| is available to draw directly dotted lines between nodes. +% Moreover, a special command, called |\line| is available to draw directly dotted lines between nodes. % % \medskip % \begin{BVerbatim}[baseline=c,boxwidth=12cm] @@ -700,7 +749,8 @@ version 2005/12/01 or later. % |L|, |C| and~|R|\footnote{The column types |L|, |C| and |R| are defined locally inside |{NiceArray}| with % |\newcolumntype| of \pkg{array}. This definition overrides an eventual previous definition.} instead of |l|, |c| % and |r|. It's possible to use the constructions \verb|w{...}{...}|, \verb|W{...}{...}|, \verb+|+, |>{...}|, -% |<{...}|, |@{...}|, |!{...}| and |*{n}{...}| but the letters |p|, |m| and |b| should not be used. +% |<{...}|, |@{...}|, |!{...}| and |*{n}{...}| but the letters |p|, |m| and |b| should not be used.\footnote{In a +% command |\multicolumn|, one should also use the letters |L|, |C|, |R|.} % % \medskip % The environment |{NiceArray}| accepts the classical options |t|, |c| and |b| of |{array}| but also other options @@ -755,7 +805,7 @@ version 2005/12/01 or later. % % The environment |{pNiceArrayC}| takes a mandatory argument which is the preamble of the array. The types % of columns available are the same as for the environment |{NiceArray}|. \textbf{However, no specification must be -% given for the last column.} It will automatically (and necessarily) be a column~|L| column. +% given for the last column.} It will automatically (and necessarily) be a |L|~column. % % A special option, called |code-for-last-col|, specifies tokens that will be inserted before each cell of the last % column. The option |columns-width| doesn't apply to this external column. @@ -785,7 +835,7 @@ version 2005/12/01 or later. % % \bigskip % In fact, the environment |{pNiceArrayC}| and its variants are based upon an more general environment, called -% |{NiceArrayCwithDelims}|. The first two mandatory arguments of this environment are the left and right delimiter +% |{NiceArrayCwithDelims}|. The first two mandatory arguments of this environment are the left and right delimiters % used in the construction of the matrix. It's possible to use |{NiceArrayCwithDelims}| if we want to use atypical % delimiters. % @@ -815,10 +865,6 @@ version 2005/12/01 or later. % environment |{pNiceArrayC}|, no specification must be given for the last column (it will automatically be a |L| % column). % -% For technical reasons, the key |columns-width| is mandatory, with an numerical value (e.g. 1~cm) or with -% the special value |auto|. This implies that all the columns of an environment |{pNiceArrayRC}| have necessarily -% the same width. -% % A special option, called |code-for-first-row|, specifies tokens that will be inserted before each cell of the % first row. % @@ -826,8 +872,8 @@ version 2005/12/01 or later. % \begin{BVerbatim}[baseline=c,boxwidth=11cm] % $\begin{pNiceArrayRC}{CCC}% % [columns-width = auto, -% code-for-first-row = {\color{blue}}, -% code-for-last-col = {\color{blue}}] +% code-for-first-row = \color{blue}, +% code-for-last-col = \color{blue}] % C_1 & C_2 & C_3 \\ % 1 & 2 & 3 & L_1\\ % 4 & 5 & 6 & L_2\\ @@ -835,27 +881,25 @@ version 2005/12/01 or later. % \end{pNiceArrayRC}$ % \end{BVerbatim} % $\begin{pNiceArrayRC}{CCC}[columns-width=auto, -% code-for-first-row = {\color{blue}}, -% code-for-last-col = {\color{blue}}] +% code-for-first-row = \color{blue}, +% code-for-last-col = \color{blue}] % C_1 & C_2 & C_3 \\ % 1 & 2 & 3 & L_1 \\ % 4 & 5 & 6 & L_2 \\ % 7 & 8 & 9 & L_3 \\ % \end{pNiceArrayRC}$ % -% -% \bigskip -% For technical reasons, the first line of the array (which will be composed ``above'' the main matrix) -% must \emph{not} contain the command |\\| and no verbatim material. % % \bigskip % The first row of an environment |{pNiceArrayRC}| has the number $0$, and not $1$. This number is used for the % names of the Tikz nodes (the names of these nodes are used, for example, by the command |\line| in |code-after|). % +% For technical reasons, it's not possible to use the option of the command |\\| after the first row (the placement +% of the delimiters would be wrong). % % \bigskip % In fact, the environment |{pNiceArrayRC}| and its variants are based upon an more general environment, called -% |{NiceArrayRCwithDelims}|. The first two mandatory arguments of this environment are the left and right delimiter +% |{NiceArrayRCwithDelims}|. The first two mandatory arguments of this environment are the left and right delimiters % used in the construction of the matrix. It's possible to use |{NiceArrayRCwithDelims}| if we want to use atypical % delimiters. % @@ -877,91 +921,267 @@ version 2005/12/01 or later. % 7 & 8 & 9 % \end{NiceArrayRCwithDelims}$ % -% -% -% \section{Technical remarks} -% -% \subsection{Diagonal lines} % -% By default, all the diagonal lines\footnote{We speak of the lines created by |\Ddots| and not the lines created -% by a command |\line| in |code-after|.} of a same array are ``parallelized''. That means that the first diagonal -% line is drawn and, then, the other lines are drawn parallel to the first one (by rotation around the left-most -% extremity of the line). That's why the position of the instructions |\Ddots| in the array can have a marked -% effect on the final result. +% \bigskip +% If we want to write a linear system, we can use the following code, with a preamble \verb+CCC|C+: % -% \medskip -% In the following examples, the first |\Ddots| instruction is written in color: +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% $\begin{pNiceArrayRC}{~emphase#CCC|C@} +% C_1 & \Cdots & C_n \\ +% a_{11} & \Cdots & a_{1n} & b_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & b_n \\ +% \end{pNiceArrayRC}$ +% \end{BVerbatim} +% $\begin{pNiceArrayRC}{CCC|C} +% C_1 & \Cdots & C_n \\ +% a_{11} & \Cdots & a_{1n} & b_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & b_n \\ +% \end{pNiceArrayRC}$ % % \medskip -% \begin{scope} -% \begin{minipage}{9.5cm} -% Example with parallelization (default): -% \begin{Verbatim} -% $A = \begin{pNiceMatrix} -% 1 & \Cdots & & 1 \\ -% a+b & ~emphase#\Ddots@~ & & \Vdots \\ -% \Vdots & \Ddots & & \\ -% a+b & \Cdots & a+b & 1 -% \end{pNiceMatrix}$ -% \end{Verbatim} -% \end{minipage} -% $A = \begin{pNiceMatrix} -% 1 & \Cdots & & 1 \\ -% a+b & \Ddots & & \Vdots \\ -% \Vdots & \Ddots & & \\ -% a+b & \Cdots & a+b & 1 -% \end{pNiceMatrix}$ +% The resultat may seem disappointing. It's possible to suppress the vertical rule in the first row with the +% command |\multicolumn| in order to ``reconstruct'' the cell. % +% % \bigskip -% \NiceMatrixOptions{parallelize-diags=true}% -% \begin{minipage}{9.5cm} -% % \begin{Verbatim} -% $A = \begin{pNiceMatrix} -% 1 & \Cdots & & 1 \\ -% a+b & & & \Vdots \\ -% \Vdots & ~emphase#\Ddots@~ & \Ddots & \\ -% a+b & \Cdots & a+b & 1 -% \end{pNiceMatrix}$ -% \end{Verbatim} -% \end{minipage} -% $A = \begin{pNiceMatrix} -% 1 & \Cdots & & 1 \\ -% a+b & & & \Vdots \\ -% \Vdots & \Ddots & \Ddots & \\ -% a+b & \Cdots & a+b & 1 -% \end{pNiceMatrix}$ +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% $\begin{pNiceArrayRC}{CCC|C} +% C_1 & \Cdots & ~emphase#\multicolumn{1}{C}{C_n}@ \\ +% a_{11} & \Cdots & a_{1n} & b_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & b_n \\ +% \end{pNiceArrayRC}$ +% \end{BVerbatim} +% $\begin{pNiceArrayRC}{CCC|C} +% C_1 & \Cdots & \multicolumn{1}{C}{C_n} \\ +% a_{11} & \Cdots & a_{1n} & b_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & b_n +% \end{pNiceArrayRC}$ % % \bigskip -% It's possible to turn off the parallelization with the option |parallelize-diags| set to |false|: \par\nobreak +% On the other side, we may remark that an horizontal line (with |\hline| or |\hdashline| of \pkg{arydshln}) +% doesn't extend in the ``exterior column'' of an environment like |{pNiceArrayC}| or |{pNiceArrayRC}|. % % \medskip -% \NiceMatrixOptions{parallelize-diags=false}% -% \begin{minipage}{9.5cm} -% The same example without parallelization: -% \end{minipage} -% $A = \begin{pNiceMatrix} -% 1 & \Cdots & & 1 \\ -% a+b & \Ddots & & \Vdots \\ -% \Vdots & \Ddots & & \\ -% a+b & \Cdots & a+b & 1 -% \end{pNiceMatrix}$ -% -% -% \end{scope} -% -% \subsection{The ``empty'' cells} +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% $\begin{pNiceArrayC}{CCC} +% a_{11} & \Cdots & a_{1n} & L_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & L_n \\ +% ~emphase#\hdashline@ +% S_1 & \Cdots & S_n \\ +% \end{pNiceArrayC}$ +% \end{BVerbatim} +% $\begin{pNiceArrayC}{CCC} +% a_{11} & \Cdots & a_{1n} & L_1 \\ +% \Vdots & & \Vdots & \Vdots \\ +% a_{n1} & \Cdots & a_{nn} & L_n \\ +% \hdashline +% S_1 & \Cdots & S_n \\ +% \end{pNiceArrayC}$ % -% An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first non-empty cell on both -% sides\footnote{If \pkg{nicematrix} can't find these cells, an error |Imposible instruction| is raised. Nevertheless, -% with the option |silent|, these instructions are discarded silently.}. However, a empty cell is not necessarily a -% cell with no TeX content (that is to say a cell with no token between the two ampersands~|&|). Indeed, a cell -% with contents |\hspace*{1cm}| may be considered as empty. -% -% \interitem -% For \pkg{nicematrix}, the precise rules are as follow. % -% \begin{itemize} -% \item An implicit cell is empty. For example, in the following matrix: +% \section{The width of the columns} +% \label{width} +% +% In the environments with an explicit preamble (like |{NiceArray}|, |{pNiceArrayC}|, |{pNiceArrayRC}|, etc.), it's +% possible to fix the width of a given column with the standard letters |w| and |W| of the package \pkg{array}. +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=10cm] +% $\left(\begin{NiceArray}{~emphase#wc{1cm}@CC} +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{NiceArray}\right)$ +% \end{BVerbatim} +% $\left(\begin{NiceArray}{wc{1cm}CC} +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{NiceArray}\right)$ +% +% +% \bigskip +% It's also possible to fix the width of all the columns of a matrix directly with the option |columns-width| (in +% all the environments of \pkg{nicematrix}). +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=10cm] +% $\begin{pNiceMatrix}[~emphase#columns-width = 1cm@] +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{pNiceMatrix}$ +% \end{BVerbatim} +% $\begin{pNiceMatrix}[columns-width = 1cm] +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{pNiceMatrix}$ +% +% \medskip +% Note that the space inserted between two columns (equal to 2 |\arraycolsep|) is not suppressed. +% +% \bigskip +% It's possible to give the value |auto| to the option |columns-width|: all the columns of the array will +% have a width equal to the widest cell of the array. \textbf{Two or three compilations may be necessary.}\par\nobreak +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=10cm] +% $\begin{pNiceMatrix}[~emphase#columns-width = auto@] +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{pNiceMatrix}$ +% \end{BVerbatim} +% $\begin{pNiceMatrix}[columns-width = auto] +% 1 & 12 & -123 \\ +% 12 & 0 & 0 \\ +% 4 & 1 & 2 +% \end{pNiceMatrix}$ +% +% \bigskip +% It's possible to fix the width of the columns of all the matrices of a current scope with the command +% |\NiceMatrixOptions|.\par\nobreak +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] +% ~emphase#\NiceMatrixOptions{columns-width=10mm}@ +% $\begin{pNiceMatrix} +% a & b \\ c & d \\ +% \end{pNiceMatrix} +% = +% \begin{pNiceMatrix} +% 1 & 1245 \\ 345 & 2 \\ +% \end{pNiceMatrix}$ +% \end{BVerbatim} +% \begin{scope} +% \NiceMatrixOptions{columns-width=10mm} +% $\begin{pNiceMatrix} +% a & b \\ +% c & d \\ +% \end{pNiceMatrix} +% = +% \begin{pNiceMatrix} +% 1 & 1245 \\ +% 345 & 2 \\ +% \end{pNiceMatrix}$ +% \end{scope} +% +% +% \bigskip +% But it's also possible to fix a zone where all the matrices will have their columns of the same width, equal to +% the widest cell of all the matrices. This construction uses the environment |{NiceMatrixBlock}| with the option +% |auto-columns-width|.\footnote{At this time, this is the only usage of the environment |{NiceMatrixBlock}| but +% it may have other usages in the future.} +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=8.5cm] +% ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@ +% $\begin{pNiceMatrix} +% a & b \\ c & d \\ +% \end{pNiceMatrix} +% = +% \begin{pNiceMatrix} +% 1 & 1245 \\ 345 & 2 \\ +% \end{pNiceMatrix}$ +% ~emphase#\end{NiceMatrixBlock}@ +% \end{BVerbatim} +% \begin{NiceMatrixBlock}[auto-columns-width] +% $\begin{pNiceMatrix} +% a & b \\ c & d \\ +% \end{pNiceMatrix} +% = +% \begin{pNiceMatrix} +% 1 & 1245 \\ 345 & 2 \\ +% \end{pNiceMatrix}$ +% \end{NiceMatrixBlock} +% +% +% \section{Technical remarks} +% +% \subsection{Diagonal lines} +% +% By default, all the diagonal lines\footnote{We speak of the lines created by |\Ddots| and not the lines created +% by a command |\line| in |code-after|.} of a same array are ``parallelized''. That means that the first diagonal +% line is drawn and, then, the other lines are drawn parallel to the first one (by rotation around the left-most +% extremity of the line). That's why the position of the instructions |\Ddots| in the array can have a marked +% effect on the final result. +% +% \medskip +% In the following examples, the first |\Ddots| instruction is written in color: +% +% \medskip +% \begin{scope} +% \begin{minipage}{9.5cm} +% Example with parallelization (default): +% \begin{Verbatim} +% $A = \begin{pNiceMatrix} +% 1 & \Cdots & & 1 \\ +% a+b & ~emphase#\Ddots@~ & & \Vdots \\ +% \Vdots & \Ddots & & \\ +% a+b & \Cdots & a+b & 1 +% \end{pNiceMatrix}$ +% \end{Verbatim} +% \end{minipage} +% $A = \begin{pNiceMatrix} +% 1 & \Cdots & & 1 \\ +% a+b & \Ddots & & \Vdots \\ +% \Vdots & \Ddots & & \\ +% a+b & \Cdots & a+b & 1 +% \end{pNiceMatrix}$ +% +% \bigskip +% \NiceMatrixOptions{parallelize-diags=true}% +% \begin{minipage}{9.5cm} +% % \begin{Verbatim} +% $A = \begin{pNiceMatrix} +% 1 & \Cdots & & 1 \\ +% a+b & & & \Vdots \\ +% \Vdots & ~emphase#\Ddots@~ & \Ddots & \\ +% a+b & \Cdots & a+b & 1 +% \end{pNiceMatrix}$ +% \end{Verbatim} +% \end{minipage} +% $A = \begin{pNiceMatrix} +% 1 & \Cdots & & 1 \\ +% a+b & & & \Vdots \\ +% \Vdots & \Ddots & \Ddots & \\ +% a+b & \Cdots & a+b & 1 +% \end{pNiceMatrix}$ +% +% \bigskip +% It's possible to turn off the parallelization with the option |parallelize-diags| set to |false|: \par\nobreak +% +% \medskip +% \NiceMatrixOptions{parallelize-diags=false}% +% \begin{minipage}{9.5cm} +% The same example without parallelization: +% \end{minipage} +% $A = \begin{pNiceMatrix} +% 1 & \Cdots & & 1 \\ +% a+b & \Ddots & & \Vdots \\ +% \Vdots & \Ddots & & \\ +% a+b & \Cdots & a+b & 1 +% \end{pNiceMatrix}$ +% +% +% \end{scope} +% +% \subsection{The ``empty'' cells} +% +% An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first non-empty cells on both sides. However, +% a empty cell is not necessarily a cell with no TeX content (that is to say a cell with no token between the two +% ampersands~|&|). Indeed, a cell with contents |\hspace*{1cm}| may be considered as empty. +% +% \interitem +% For \pkg{nicematrix}, the precise rules are as follow. +% +% \begin{itemize} +% \item An implicit cell is empty. For example, in the following matrix: % % \begin{Verbatim} % \begin{pmatrix} @@ -977,7 +1197,7 @@ version 2005/12/01 or later. % % \medskip % \item A cell which contains a command |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots| or |\Iddots| and their starred -% versions is empty. We recall that theses commands should be used alone in a cell. +% versions is empty. We recall that these commands should be used alone in a cell. % % \medskip % \item A cell with a command |\Hspace| (or |\Hspace*|) is empty. This command |\Hspace| is a command defined by @@ -986,9 +1206,6 @@ version 2005/12/01 or later. % with \pkg{nicematrix}. % % \end{itemize} % -% \interitem -% A dotted line must be delimited by two non-empty cells. If it's not possible to find one of these cells whitin -% the boundaries of the matrix, an error is issued and the instruction is ignored. % % \subsection{The option exterior-arraycolsep} % @@ -999,17 +1216,96 @@ version 2005/12/01 or later. % (perhaps we should instead remove it from array in general, but that's a harder task).} It's possible to suppress % these spaces for a given environment |{array}| with a construction like |\begin{array}{@{}ccccc@{}}|.} % -% The environment |{matrix}| and its variants (|{pmatrix}|, |{vmatrix}|, etc.) of \pkg{amsmath} and \pkg{mathtools} -% prefer to delete these spaces with explicit instructions |\hskip -\arraycolsep| and |{NiceArray}| does likewise. +% The environment |{matrix}| and its variants (|{pmatrix}|, |{vmatrix}|, etc.) of \pkg{amsmath} prefer to delete +% these spaces with explicit instructions |\hskip -\arraycolsep| and |{NiceArray}| does likewise. % -% However, the user can change this behaviour with the boolean option |exterior-arraycolsep|. With this option, -% |{NiceArray}| will insert the same horizontal spaces as the environment |{array}|. This -% option can be set for a given environment or globally with the command |\NiceMatrixOptions|. +% However, the user can change this behaviour with the boolean option |exterior-arraycolsep| of the command +% |\NiceMatrixOptions|. With this option, |{NiceArray}| will insert the same horizontal spaces as the environment +% |{array}|. % +% This option is also for ``compatibility'' since the package \pkg{nicematrix} provides a more precise control with +% the options |left-margin|, |right-margin|, |extra-left-margin| and |extra-right-margin|. +% +% +% \subsection{A technical problem with the argument of \textbackslash\textbackslash} +% +% For technical, reasons, if you use the optional argument of the command |\\|, the vertical space added will also +% be added to the ``normal'' node corresponding at the previous node. +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% \begin{pNiceMatrix} +% a & \frac AB \\~emphase#[2mm]@ +% b & c +% \end{pNiceMatrix} +% \end{BVerbatim} +% $\begin{pNiceMatrix} +% [code-after = {\tikz \node [inner sep = 0pt, +% fill = red!15, +% blend mode = multiply, +% fit = (1-2) ] {} ; } ] +% a & \frac AB \\[2mm] +% b & c +% \end{pNiceMatrix}$ +% +% \bigskip +% There are two solutions to solve this problem. The first solution is to use a TeX command to insert space between +% the rows. +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% \begin{pNiceMatrix} +% a & \frac AB \\ +% ~emphase#\noalign{\kern2mm}@ +% b & c +% \end{pNiceMatrix} +% \end{BVerbatim} +% $\begin{pNiceMatrix} +% [code-after = {\tikz \node [inner sep = 0pt, +% fill = red!15, +% blend mode = multiply, +% fit = (1-2) ] {} ; } ] +% a & \frac AB \\ +% \noalign{\kern2mm} +% b & c +% \end{pNiceMatrix}$ % -% \section{Examples} % % \bigskip +% The other solution is to use the command |\multicolumn| in the previous cell. +% +% \medskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% \begin{pNiceMatrix} +% a & ~emphase#\multicolumn1C{\frac AB}@ \\[2mm] +% b & c +% \end{pNiceMatrix} +% \end{BVerbatim} +% $\begin{pNiceMatrix} +% [code-after = {\tikz \node [inner sep = 0pt, +% fill = red!15, +% blend mode = multiply, +% fit = (1-2) ] {} ; } ] +% a & \multicolumn1C{\frac AB} \\[2mm] +% b & c +% \end{pNiceMatrix}$ +% +% +% \subsection{A remark concerning a bug of Tikz} +% +% Due to a bug in Tikz, the construction |-- cycle| in a Tikz path is incompatible with the use of |name prefix| +% and |name suffix|.\footnote{cf. |tex.stackexchange.com/questions/327007/tikz-fill-not-being-drawn-using-named-coordinates|} +% +% \bigskip +% Since |name prefix| is implicitly used in the |code-after| of \pkg{nicematrix}, it's not +% possible to use |-- cycle| in |code-after|. +% +% +% \section{Examples} +% +% \subsection{Dotted lines} +% +% \medskip % A tridiagonal matrix: % % \bigskip @@ -1060,8 +1356,7 @@ version 2005/12/01 or later. % % \vspace{2cm} % -% An example with |\Iddots|: -% +% An example with |\Iddots|: \par\nobreak % \bigskip % \begin{BVerbatim}[baseline=c] % $\begin{pNiceMatrix} @@ -1079,29 +1374,72 @@ version 2005/12/01 or later. % 1 & 0 & \Cdots & 0 % \end{pNiceMatrix}$ % -% \vspace{2cm} % -% An example for the resultant of two polynoms : +% \vspace{2cm} +% An example with |\multicolumn|:\par\nobreak +% \bigskip +% \begin{BVerbatim} +% \begin{pNiceMatrix}[nullify-dots] +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ +% \Cdots & & ~emphase#\multicolumn{6}{C}{10 \text{ other rows}}@ & \Cdots \\ +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 +% \end{pNiceMatrix} +% \end{BVerbatim} +% +% \bigskip +% \[\begin{pNiceMatrix}[nullify-dots] +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10\\ +% \Cdots & & \multicolumn{6}{C}{10 \text{ other rows}} & \Cdots \\ +% 1 & 2 & 3 & 4 & 5 & 6 & 7 & 8 & 9 & 10 +% \end{pNiceMatrix}\] +% +% \vspace{2cm} +% An example with |\Hdotsfor|:\par\nobreak +% \bigskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% \begin{pNiceMatrix}[nullify-dots] +% 0 & 1 & 1 & 1 & 1 & 0 \\ +% 0 & 1 & 1 & 1 & 1 & 0 \\ +% \Vdots & ~emphase#\Hdotsfor{4}@ & \Vdots \\ +% & ~emphase#\Hdotsfor{4}@ & \\ +% & ~emphase#\Hdotsfor{4}@ & \\ +% & ~emphase#\Hdotsfor{4}@ & \\ +% 0 & 1 & 1 & 1 & 1 & 0 +% \end{pNiceMatrix} +% \end{BVerbatim} +% $\begin{pNiceMatrix}[nullify-dots] +% 0 & 1 & 1 & 1 & 1 & 0 \\ +% 0 & 1 & 1 & 1 & 1 & 0 \\ +% \Vdots & \Hdotsfor{4} & \Vdots \\ +% & \Hdotsfor{4} & \\ +% & \Hdotsfor{4} & \\ +% & \Hdotsfor{4} & \\ +% 0 & 1 & 1 & 1 & 1 & 0 +% \end{pNiceMatrix}$ % +% \vspace{2cm} +% An example for the resultant of two polynoms (the dashed line has been drawn with \pkg{arydshln}):\par\nobreak % \bigskip % \begin{BVerbatim} % \setlength{\extrarowheight}{1mm} -% \[\begin{vNiceMatrix}[columns-width=6mm] -% a_0 & && &b_0 & & \\ -% a_1 &\Ddots && &b_1 &\Ddots & \\ -% \Vdots &\Ddots && &\Vdots &\Ddots &b_0 \\ -% a_p & &&a_0 & & &b_1 \\ -% &\Ddots &&a_1 &b_q & &\Vdots\\ -% & &&\Vdots & &\Ddots & \\ -% & &&a_p & & &b_q \\ -% \end{vNiceMatrix}\] +% \[\begin{NiceArray}{|CCCC:CCC|}[columns-width=6mm] +% a_0 & && &b_0 & & \\ +% a_1 &\Ddots&& &b_1 &\Ddots& \\ +% \Vdots&\Ddots&& &\Vdots &\Ddots&b_0 \\ +% a_p & &&a_0 & & &b_1 \\ +% &\Ddots&&a_1 &b_q & &\Vdots\\ +% & &&\Vdots & &\Ddots& \\ +% & &&a_p & & &b_q \\ +% \end{NiceArray}\] % \end{BVerbatim} % % \bigskip % % \begin{scope} % \setlength{\extrarowheight}{1mm} -% \[\begin{vNiceMatrix}[columns-width=6mm] +% \[\begin{NiceArray}{|CCCC:CCC|}[columns-width=6mm] % a_0 & && &b_0 & & \\ % a_1 &\Ddots&& &b_1 &\Ddots& \\ % \Vdots&\Ddots&& &\Vdots &\Ddots&b_0 \\ @@ -1109,12 +1447,14 @@ version 2005/12/01 or later. % &\Ddots&&a_1 &b_q & &\Vdots\\ % & &&\Vdots & &\Ddots& \\ % & &&a_p & & &b_q \\ -% \end{vNiceMatrix}\] +% \end{NiceArray}\] % \end{scope} % % -% \vspace{2cm} -% In the following example, we use the environment |{NiceMatrixBlock}| with the option |auto-columns-width| because +% \subsection{Width of the columns} +% +% \medskip +% In the following example, we use |{NiceMatrixBlock}| with the option |auto-columns-width| because % we want the same automatic width for all the columns of the matrices. % % \bigskip @@ -1193,32 +1533,104 @@ version 2005/12/01 or later. % \end{NiceMatrixBlock} % \end{multicols} % -% \vspace{2cm} +% +% \subsection{How to highlight cells of the matrix} +% +% \medskip +% In order to highlight a cell of a matrix, it's possible to ``draw'' one of the correspond nodes (the ``normal +% node'', the ``medium node'' or the ``large node''). In the following example, we use the ``large nodes'' of the +% diagonal of the matrix (with the Tikz key ``|name suffix|'', it's easy to use the ``large nodes''). In order to +% have the continuity of the lines, we have to set |inner sep = -\pgflinewidth/2|. +% +% \begin{Verbatim} +% $\left(\,\begin{NiceArray}{>{\strut}CCCC} +% [create-extra-nodes,left-margin,right-margin, +% code-after = {\begin{tikzpicture} +% [~emphase#name suffix = -large@, +% every node/.style = {draw, +% ~emphase#inner sep = -\pgflinewidth/2@}] +% \node [fit = (1-1)] {} ; +% \node [fit = (2-2)] {} ; +% \node [fit = (3-3)] {} ; +% \node [fit = (4-4)] {} ; +% \end{tikzpicture}}] +% a_{11} & a_{12} & a_{13} & a_{14} \\ +% a_{21} & a_{22} & a_{23} & a_{24} \\ +% a_{31} & a_{32} & a_{33} & a_{34} \\ +% a_{41} & a_{42} & a_{43} & a_{44} +% \end{NiceArray}\,\right)$ +% \end{Verbatim} +% % -% In the following example, we want to highlight a row of the matrix. To do so, we create a rectangular Tikz node -% which encompasses the nodes of the second row with the Tikz library |fit|. This Tikz node is filled -% after the construction of the matrix. In order to see the text \emph{under} this node, we have to use -% transparency with the |blend mode| equal to |multiply|. +% \[\left(\,\begin{NiceArray}{>{\strut}CCCC} +% [create-extra-nodes,left-margin,right-margin, +% code-after = {\begin{tikzpicture}[name suffix = -large, +% every node/.style = {draw, +% inner sep = -\pgflinewidth/2}] +% \node [fit = (1-1)] {} ; +% \node [fit = (2-2)] {} ; +% \node [fit = (3-3)] {} ; +% \node [fit = (4-4)] {} ; +% \end{tikzpicture}}] +% a_{11} & a_{12} & a_{13} & a_{14} \\ +% a_{21} & a_{22} & a_{23} & a_{24} \\ +% a_{31} & a_{32} & a_{33} & a_{34} \\ +% a_{41} & a_{42} & a_{43} & a_{44} +% \end{NiceArray}\,\right)\] % +% +% \vspace{1cm} +% The package \pkg{nicematrix} is constructed upon the environment |{array}| and, therefore, it's possible to use +% the package \pkg{colortbl} in the environments of \pkg{nicematrix}. +% +% \medskip +% \begin{BVerbatim}[baseline=c] +% $\begin{bNiceMatrix} +% 0 & \Cdots & 0 \\ +% ~emphase#\rowcolor{red!15}@ 1 & \Cdots & 1 \\ +% 0 & \Cdots & 0 \\ +% \end{bNiceMatrix}$ +% \end{BVerbatim} +% \hspace{2cm} +% $\begin{bNiceMatrix} +% 0 & \Cdots & 0 \\ +% \rowcolor{red!15} 1 & \Cdots & 1 \\ +% 0 & \Cdots & 0 \\ +% \end{bNiceMatrix}$ +% +% \medskip +% The result may be disappointing. We therefore propose another method to highlight a row of the matrix. We +% create a rectangular Tikz node which encompasses the nodes of the second row with the Tikz library \pkg{fit}. This +% Tikz node is filled after the construction of the matrix. In order to see the text \emph{under} this node, we +% have to use transparency with the |blend mode| equal to |multiply|. Warning: some \textsc{pdf} readers are not +% able to render transparency correctly. +% +% \tikzset{highlight/.style={rectangle, +% fill=red!15, +% blend mode = multiply, +% rounded corners = 0.5 mm, +% inner sep=1pt}} +% % \medskip % \begin{Verbatim} % \tikzset{highlight/.style={rectangle, % fill=red!15, % ~emphase#blend mode = multiply@, +% rounded corners = 0.5 mm, % inner sep=1pt}} % -% $\begin{pNiceMatrix}[~emphase#code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}@] +% $\begin{bNiceMatrix}[~emphase#code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}@] % 0 & \Cdots & 0 \\ % 1 & \Cdots & 1 \\ % 0 & \Cdots & 0 \\ -% \end{pNiceMatrix}$ +% \end{bNiceMatrix}$ % \end{Verbatim} % -% \[\begin{pNiceMatrix}[code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}] +% \[\begin{bNiceMatrix}[code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}] % 0 & \Cdots & 0 \\ % 1 & \Cdots & 1 \\ % 0 & \Cdots & 0 \\ -% \end{pNiceMatrix}\] +% \end{bNiceMatrix}\] % % % \bigskip @@ -1226,7 +1638,7 @@ version 2005/12/01 or later. % following code, in the preamble, should activate blend modes in this way of compilation. % % -% +% \begin{scope} \small % |\ExplSyntaxOn| % % |\makeatletter| @@ -1240,6 +1652,173 @@ version 2005/12/01 or later. % |\makeatother| % % |\ExplSyntaxOff| +% \end{scope} +% +% \vspace{1cm} +% Considerer now the following matrix which we have named |example|. +% +% \medskip +% \begin{Verbatim} +% $\begin{pNiceArrayC}{CCC}[~emphase#name=example@,create-extra-nodes] +% a & a + b & a + b + c & L_1\\ +% a & a & a + b & L_2 \\ +% a & a & a & L_3 +% \end{pNiceArrayC}$ +% \end{Verbatim} +% +% \[\begin{pNiceArrayC}{CCC} +% a & a + b & a + b + c & L_1\\ +% a & a & a + b & L_2 \\ +% a & a & a & L_3 +% \end{pNiceArrayC}\] +% +% \bigskip +% If we want to highlight each row of this matrix, we can use the previous technique three times. +% +% \begin{Verbatim} +% \tikzset{myoptions/.style={remember picture, +% overlay, +% name prefix = example-, +% every node/.style = {fill = red!15, +% blend mode = multiply, +% inner sep = 0pt}}} +% \end{Verbatim} +% +% +% \tikzset{myoptions/.style={remember picture, +% overlay, +% name prefix = example-, +% every node/.style = {fill = red!15, +% blend mode = multiply, +% inner sep = 0pt}}} +% +% \begin{Verbatim} +% \begin{tikzpicture}[myoptions] +% \node [fit = (1-1) (1-3)] {} ; +% \node [fit = (2-1) (2-3)] {} ; +% \node [fit = (3-1) (3-3)] {} ; +% \end{tikzpicture} +% \end{Verbatim} +% +% \medskip +% We obtain the following matrix. +% +% \[\begin{pNiceArrayC}{CCC} +% [create-extra-nodes, +% code-after = {\begin{tikzpicture}[every node/.style = {fill = red!15, +% blend mode = multiply, +% inner sep = 0pt}] +% \node [fit = (1-1) (1-3)] {} ; +% \node [fit = (2-1) (2-3)] {} ; +% \node [fit = (3-1) (3-3)] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c & L_1\\ +% a & a & a + b & L_2 \\ +% a & a & a & L_3 +% \end{pNiceArrayC}\] +% +% \medskip +% The result may seem disappointing. We can improve it by using the ``medium nodes'' instead of the ``normal nodes''. +% +% \begin{Verbatim} +% \begin{tikzpicture}[myoptions, ~emphase#name suffix = -medium@] +% \node [fit = (1-1) (1-3)] {} ; +% \node [fit = (2-1) (2-3)] {} ; +% \node [fit = (3-1) (3-3)] {} ; +% \end{tikzpicture} +% \end{Verbatim} +% +% \medskip +% We obtain the following matrix. +% +% \[\begin{pNiceArrayC}{CCC} +% [create-extra-nodes, +% code-after = {\begin{tikzpicture}[every node/.style = {fill = red!15, +% blend mode = multiply, +% inner sep = 0pt}, +% name suffix = -medium] +% \node [fit = (1-1) (1-3)] {} ; +% \node [fit = (2-1) (2-3)] {} ; +% \node [fit = (3-1) (3-3)] {} ; +% \end{tikzpicture}}] +% a & a + b & a + b + c & L_1\\ +% a & a & a + b & L_2 \\ +% a & a & a & L_3 +% \end{pNiceArrayC}\] +% +% +% \vspace{1cm} +% +% In the following example, we use the ``large nodes'' to highlight a zone of the matrix.\par\nobreak +% \begin{Verbatim} +% \left(\,\begin{NiceArray}{>{\strut}CCCC} +% [create-extra-nodes,left-margin,right-margin, +% code-after = {\tikz \path [~emphase#name suffix = -large@, +% fill = red!15, +% blend mode = multiply] +% (1-1.north west) +% |- (2-2.north west) +% |- (3-3.north west) +% |- (4-4.north west) +% |- (4-4.south east) +% |- (1-1.north west) ; } ] +% A_{11} & A_{12} & A_{13} & A_{14} \\ +% A_{21} & A_{22} & A_{23} & A_{24} \\ +% A_{31} & A_{32} & A_{33} & A_{34} \\ +% A_{41} & A_{42} & A_{43} & A_{44} +% \end{NiceArray}\,\right) +% \end{Verbatim} +% +% \[\left(\,\begin{NiceArray}{>{\strut}CCCC} +% [create-extra-nodes,left-margin,right-margin, +% code-after = {\tikz \path [name suffix = -large, +% fill = red!15, +% blend mode = multiply] +% (1-1.north west) +% |- (2-2.north west) +% |- (3-3.north west) +% |- (4-4.north west) +% |- (4-4.south east) +% |- (1-1.north west) ; } ] +% A_{11} & A_{12} & A_{13} & A_{14} \\ +% A_{21} & A_{22} & A_{23} & A_{24} \\ +% A_{31} & A_{32} & A_{33} & A_{34} \\ +% A_{41} & A_{42} & A_{43} & A_{44} +% \end{NiceArray}\,\right)\] +% +% +% \subsection{Block matrices} +% +% \medskip +% In the following example, we use the ``large nodes'' to construct a block matrix (the dashed lines have been +% drawn with \pkg{arydshln}). +% \begin{Verbatim} +% \left(\begin{NiceArray}{CC:CC} +% [create-extra-nodes, +% ~emphase#code-after = { \tikz \node [fit = (1-1-large) (2-2-large), inner sep = 0 pt]@ +% ~emphase# {$0_{22}$} ; }@ ] +% & & a_{13} & a_{14} \\ +% & & a_{23} & a_{24} \\ +% \hdashline +% a_{31} & a_{32} & a_{33} & a_{34} \\ +% a_{41} & a_{42} & a_{34} & a_{44} +% \end{NiceArray}\right) +% \end{Verbatim} +% +% +% \[D = \left(\begin{NiceArray}{CC:CC} +% [create-extra-nodes, +% code-after = { \tikz \node [fit = (1-1-large) (2-2-large), inner sep = 0 pt] +% {$0_{22}$} ; } ] +% & & a_{13} & a_{14} \\ +% & & a_{23} & a_{24} \\ +% \hdashline +% a_{31} & a_{32} & a_{33} & a_{34} \\ +% a_{41} & a_{42} & a_{34} & a_{44} +% \end{NiceArray}\right)\] +% +% +% % % \section{Implementation} % @@ -1248,8 +1827,7 @@ version 2005/12/01 or later. % \smallskip % However, when the option |renew-dots| is used, the commands |\cdots|, |\ldots|, |\dots|, |\vdots|, |\ddots| and % |\iddots| are redefined in the environments provided by \pkg{nicematrix} as explained previously. In the same way, -% if the option |renew-matrix| is used, the environment |{matrix}| of \pkg{amsmath} (and \pkg{mathtools}) is -% redefined. +% if the option |renew-matrix| is used, the environment |{matrix}| of \pkg{amsmath} is redefined. % % \smallskip % On the other hand, the environment |{array}| is never redefined. @@ -1264,6 +1842,16 @@ version 2005/12/01 or later. % % \subsection{Declaration of the package and extensions loaded} % +% First, \pkg{tikz} and the Tikz library |fit| are loaded before the |\ProvidesExplPackage|. +% They are loaded this way because |\usetifkzlibrary| in |expl3| code fails.\footnote{cf. +% |tex.stackexchange.com/questions/57424/using-of-usetikzlibrary-in-an-expl3-package-fails|} +% +% +% \begin{macrocode} +\RequirePackage{tikz} +\usetikzlibrary{fit} +% \end{macrocode} +% % We give the traditionnal declaration of a package written with |expl3|: % \begin{macrocode} \RequirePackage{l3keys2e} @@ -1271,28 +1859,42 @@ version 2005/12/01 or later. {nicematrix} {\myfiledate} {\myfileversion} - {Draws nice dotted lines in matrix environments} + {Several features to improve the typesetting of mathematical matrices with TikZ} % \end{macrocode} % % The command for the treatment of the options of |\usepackage| is at the end of this package for technical reasons. % % \bigskip -% We load \pkg{array}, \pkg{mathtools} (\pkg{mathtools} may be considered as the successor of \pkg{amsmath}) and \pkg{tikz}. +% We load \pkg{array} and \pkg{amsmath}. % \begin{macrocode} \RequirePackage{array} -\RequirePackage{mathtools} -\RequirePackage{tikz} +\RequirePackage{amsmath} % \end{macrocode} % % \bigskip % The package \pkg{xparse} will be used to define the environment |{NiceMatrix}|, its variants and the % document-level commands (|\NiceMatrixOptions|, etc.). -% \begin{macrocode} +% \begin{macrocode} \RequirePackage{xparse} % \end{macrocode} % % \subsection{Technical definitions} +% +% \begin{macrocode} +\cs_new_protected:Nn \@@_msg_error:n + {\msg_error:nn {nicematrix} {#1}} +\cs_new_protected:Nn \@@_msg_error:nn + {\msg_error:nn {nicematrix} {#1} {#2}} +% \end{macrocode} % +% \medskip +% \begin{macrocode} +\cs_new_protected:Nn \@@_bool_new:N + {\bool_if_exist:NTF #1 + {\bool_set_false:N #1} + {\bool_new:N #1}} +% \end{macrocode} +% % First, we define a command |\iddots| similar to |\ddots| ($\ddots$) but with dots going forward ($\iddots$). We % use |\ProvideDocumentCommand| of \pkg{xparse}, and so, if the command |\iddots| has already been defined (for % example by the package \pkg{mathdots}), we don't define it again. @@ -1311,17 +1913,6 @@ version 2005/12/01 or later. % % This definition is a variant of the standard definition of |\ddots|. % -% \bigskip -% In the environment |{NiceMatrix}|, the command |\multicolumn| will be linked to the following command -% |\@@_multicolumn:nn| but only if the option |renew-matrix| is not set. Indeed, if the option |renew-matrix| is used, -% we want to let the possibility to the user to use |\multicolumn| in some matrices without dotted lines and to -% have the automatic dotted lines of \pkg{nicematrix} in other matrices. -% \begin{macrocode} -\cs_new_protected:Nn \@@_multicolumn:nn - {\msg_error:nn {nicematrix} {Multicolumn~forbidden}} -% \end{macrocode} -% This command |\@@_multicolumn:nn| takes two arguments, and therefore, the first two arguments of |\column| will -% be gobbled. % % \bigskip % The following counter will count the environments |{NiceArray}|. The value of this counter will be used to @@ -1339,47 +1930,40 @@ version 2005/12/01 or later. % % \bigskip % The sequence |\g_@@_names_seq| will be the list of all the names of environments used (via the option |name|) in -% the document : two environments must not have the same name. +% the document: two environments must not have the same name. % \begin{macrocode} \seq_new:N \g_@@_names_seq % \end{macrocode} % % \bigskip -% The integer |\l_@@_number_of_first_row_int| is the number of the first row of the array. With a value of $0$ (the -% default), the first row of the array will have the number~$1$. Within the environment |{NiceArrayRC}|, we will give -% the value $-1$ to |\l_@@_number_of_first_row_int| and, therefore, the first row of the array will have the number~$0$. +% The integer |\l_@@_nb_first_row_int| is the number of the first row of the array. The default value is $1$, but, +% in the environments like |{pNiceArrayRC}|, the value will be~$0$. % \begin{macrocode} -\int_new:N \l_@@_number_of_first_row_int +\int_new:N \l_@@_nb_first_row_int +\int_set:Nn \l_@@_nb_first_row_int 1 % \end{macrocode} % % \bigskip -% The flag |\l_@@_direct_NiceArray_bool| will indicate if the current environment |{NiceArray}| is ``direct'' : that -% means that it is not encompassed in another environment of the extension \pkg{nicematrix} like |{NiceMatrix}| or -% |{pNiceArrayC}|. +% The flag |\l_@@_exterior_column_bool| will indicate if we are in an environment of the type of |{pNiceArrayC}| or +% |{pNiceArrayRC}|. It will be used for the creation of the ``large nodes''. % \begin{macrocode} -\bool_new:N \l_@@_direct_NiceArray_bool -\bool_set_true:N \l_@@_direct_NiceArray_bool +\bool_new:N \l_@@_exterior_column_bool % \end{macrocode} % -% \bigskip -% The token list |\l_@@_code_for_cell_tl| is a code that will be inserted in the beginning of each cell of the -% array (before the symbol |$| of the mathematical mode). -% \begin{macrocode} -\tl_new:N \l_@@_code_for_cell_tl -% \end{macrocode} -% +% \bigskip % \subsection{The options} % % The token list |\l_@@_pos_env_tl| will contain one of the three values |t|, |c| or |b| and will indicate the -% position of the environment as in the option of the environment |{array}|. For the environment |{NiceMatrix}| -% (and its variants) and |{pNiceArrayC}| (and its variants), the value will programmatically be fixed to |c|. For the +% position of the environment as in the option of the environment |{array}|. For the environment |{pNiceMatrix}|, +% |{pNiceArrayC}|,|{pNiceArrayRC}| and their variants, the value will programmatically be fixed to |c|. For the % environment |{NiceArray}|, however, the three values |t|, |c| and |b| are possible. % \begin{macrocode} \tl_new:N \l_@@_pos_env_tl \tl_set:Nn \l_@@_pos_env_tl c % \end{macrocode} % -% The boolean |\l_@@_exterior_arraycolsep_bool| corresponds to the option |exterior-arraycolsep|. If this option is +% \bigskip +% The flag |\l_@@_exterior_arraycolsep_bool| corresponds to the option |exterior-arraycolsep|. If this option is % set, a space equal to |\arraycolsep| will be put on both sides of an environment |{NiceArray}| (but neither for % |{NiceMatrix}|, |{pNiceArrayC}|, |{pNiceArrayRC}| and their variants even if these environments rely upon |{NiceArray}|). % \begin{macrocode} @@ -1402,11 +1986,6 @@ version 2005/12/01 or later. \bool_new:N \l_@@_nullify_dots_bool % \end{macrocode} % -% \bigskip -% The flag |\l_@@_renew_matrix_bool| will be raised if the option |renew-matrix| is used. -% \begin{macrocode} -\bool_new:N \l_@@_renew_matrix_bool -% \end{macrocode} % % \bigskip % The following flag will be used when the current options specify that all the columns of the array must have the @@ -1423,14 +2002,44 @@ version 2005/12/01 or later. \tl_new:N \l_@@_code_for_last_col_tl % \end{macrocode} % - % \bigskip -% The token list |\g_@@_name_tl| will contain the optional name of the environment : this name can be used to -% access to the Tikz nodes created in the array from outside the environment. This variable is global for technical -% reasons (some commands will be executed in an |\aftergroup| because we don't want to patch the commands of the -% package \pkg{array}). +% We don't want to patch any existing code. That's why some code must be executed in a |\aftergroup|. That's why +% the parameters used in that code must be transfered outside the current group. To do this, we copy those +% quantities in global variables just before the |\aftergroup|. Therefore, for those quantities, we have two +% parameters, one local and one global. For example, we have |\l_@@_name_tl| and |\g_@@_name_tl|. +% +% \bigskip +% The token list |\l_@@_name_tl| will contain the optional name of the environment: this name can be used to +% access to the Tikz nodes created in the array from outside the environment. % \begin{macrocode} \tl_new:N \g_@@_name_tl +\tl_new:N \l_@@_name_tl +% \end{macrocode} +% +% \bigskip +% The boolean |\l_@@_extra_nodes_bool| will be used to indicate wether the ``medium nodes'' and ``large nodes'' are +% created in the array. +% \begin{macrocode} +\bool_new:N \l_@@_extra_nodes_bool +\bool_new:N \g_@@_extra_nodes_bool +% \end{macrocode} +% +% \bigskip +% The dimensions |\l_@@_left_margin_dim| and |\l_@@_right_margin_dim| correspond to the options |left-margin| and |right-margin|. +% \begin{macrocode} +\dim_new:N \l_@@_left_margin_dim +\dim_new:N \l_@@_right_margin_dim +\dim_new:N \g_@@_left_margin_dim +\dim_new:N \g_@@_right_margin_dim +% \end{macrocode} +% +% \bigskip +% The dimensions |\l_@@_extra_left_margin_dim| and |\l_@@_extra_right_margin_dim| correspond to the options +% |extra-left-margin| and |extra-right-margin|. +% \begin{macrocode} +\dim_new:N \l_@@_extra_left_margin_dim +\dim_new:N \l_@@_extra_right_margin_dim +\dim_new:N \g_@@_extra_right_margin_dim % \end{macrocode} % % \bigskip @@ -1458,8 +2067,7 @@ version 2005/12/01 or later. % With the option |renew-matrix|, the environment |{matrix}| of \pkg{amsmath} and its variants are redefined to % behave like the environment |{NiceMatrix}| and its variants. % \begin{macrocode} - renew-matrix .code:n = {\cs_set_eq:NN \env@matrix \NiceMatrix - \bool_set_true:N \l_@@_renew_matrix_bool}, + renew-matrix .code:n = \@@_renew_matrix:, renew-matrix .value_forbidden:n = true, RenewMatrix .meta:n = renew-matrix, transparent .meta:n = {renew-dots,renew-matrix}, @@ -1477,17 +2085,6 @@ version 2005/12/01 or later. NullifyDots .meta:n = nullify-dots, % \end{macrocode} % -% -% \bigskip -% With the option |silent|, no error is generated for the impossible instructions. This option can be useful when -% adapting an existing code. -% \begin{macrocode} - silent .code:n = {\msg_redirect_name:nnn {nicematrix} - {Impossible~instruction} - {none}} , - silent .value_forbidden:n = true, - Silent .meta:n = silent, -% \end{macrocode} % % \bigskip % The following option is only for the environment |{pNiceArrayC}| and its variants. It will contain code inserted @@ -1507,20 +2104,33 @@ version 2005/12/01 or later. % \end{macrocode} % % \bigskip -% If the option |columns-width| is used, all the columns will have the same width. In |\NiceMatrixOptions|, the -% special value |auto| is not available. +% If the option |columns-width| is used, all the columns will have the same width. +% +% In |\NiceMatrixOptions|, the special value |auto| is not available. +% \begin{macrocode} + columns-width .code:n = \str_if_eq:nnTF {#1} {auto} + {\@@_msg_error:n {Option~auto~for~columns-width}} + {\dim_set:Nn \l_@@_columns_width_dim {#1}}, +% \end{macrocode} +% +% \bigskip % \begin{macrocode} - columns-width .code:n = \str_if_eq:nnTF {#1} {auto} - {\msg_error:nn {nicematrix} - {Option~auto~for~columns-width}} - {\dim_set:Nn \l_@@_columns_width_dim {#1}}, + create-extra-nodes .bool_set:N = \l_@@_extra_nodes_bool, + create-extra-nodes .default:n = true, % \end{macrocode} % % \bigskip % \begin{macrocode} - unknown .code:n = \msg_error:nn {nicematrix} {Unknown~key~for~NiceMatrixOptions}} + left-margin .dim_set:N = \l_@@_left_margin_dim, + left-margin .default:n = \arraycolsep, + right-margin .dim_set:N = \l_@@_right_margin_dim, + right-margin .default:n = \arraycolsep, % \end{macrocode} % +% \bigskip +% \begin{macrocode} + unknown .code:n = \@@_msg_error:n {Unknown~key~for~NiceMatrixOptions}} +% \end{macrocode} % \begin{macrocode} \msg_new:nnnn {nicematrix} {Unknown~key~for~NiceMatrixOptions} @@ -1531,10 +2141,12 @@ version 2005/12/01 or later. {The~available~keys~are~(in~alphabetic~order):~ code-for-last-col,~ exterior-arraycolsep,~ + left-margin,~ nullify-dots,~ parallelize-diags,~ renew-dots,~ - renew-matrix~ + renew-matrix,~ + right-margin,~ and~transparent} % \end{macrocode} % @@ -1564,7 +2176,7 @@ version 2005/12/01 or later. nullify-dots .bool_set:N = \l_@@_nullify_dots_bool , nullify-dots .default:n = true, % \end{macrocode} -% The option |columns-width| is the width of the columns it we want the same width for all the columns of the +% The option |columns-width| is the width of the columns if we want the same width for all the columns of the % array. A value of 0~pt means that the width of the column will be the natural width of the column. % \begin{macrocode} columns-width .code:n = \str_if_eq:nnTF {#1} {auto} @@ -1572,20 +2184,30 @@ version 2005/12/01 or later. \l_@@_auto_columns_width_bool} {\dim_set:Nn \l_@@_columns_width_dim {#1}}, name .code:n = {\seq_if_in:NnTF \g_@@_names_seq {#1} - {\msg_error:nnn {nicematrix} - {Duplicate~name} - {#1}} + {\@@_msg_error:nn {Duplicate~name} {#1}} {\seq_gput_left:Nn \g_@@_names_seq {#1}} - \tl_gset:Nn \g_@@_name_tl {#1}}, + \tl_set:Nn \l_@@_name_tl {#1}}, name .value_required:n = true, -% \end{macrocode} -% Since we don't want to modify or patch any existing code, the ``code after'' will be inserted with an -% |\aftergroup|. Thus, we can't use a local variable for the ``code after'' and that's why we use a global variable. -% \begin{macrocode} - code-after .tl_gset:N = \g_@@_code_after_tl, + code-after .tl_set:N = \l_@@_code_after_tl, code-after .initial:n = \c_empty_tl, code-after .value_required:n = true, - unknown .code:n = \msg_error:nn {nicematrix} {Unknown~option~for~NiceMatrix}} +% \end{macrocode} +% +% The key |create-extra-nodes| indicates wether the ``medium nodes'' and ``large nodes'' will be created for each +% cell of the array. +% \begin{macrocode} + create-extra-nodes .bool_set:N = \l_@@_extra_nodes_bool, + create-extra-nodes .default:n = true, +% \end{macrocode} +% +% \begin{macrocode} + left-margin .dim_set:N = \l_@@_left_margin_dim, + left-margin .default:n = \arraycolsep, + right-margin .dim_set:N = \l_@@_right_margin_dim, + right-margin .default:n = \arraycolsep, + extra-left-margin .dim_set:N = \l_@@_extra_left_margin_dim, + extra-right-margin .dim_set:N = \l_@@_extra_right_margin_dim, + unknown .code:n = \@@_msg_error:n {Unknown~option~for~NiceMatrix}} % \end{macrocode} % % \begin{macrocode} @@ -1598,14 +2220,32 @@ version 2005/12/01 or later. {The~available~options~are~(in~alphabetic~order):~ code-after,~ columns-width,~ + create-extra-nodes,~ + extra-left-margin,~ + extra-right-margin,~ + left~margin,~ name,~ nullify-dots,~ - parallelize-diags~ - and~renew-dots.} + parallelize-diags,~ + renew-dots~ + and~right-margin.} % \end{macrocode} % % \bigskip % \begin{macrocode} +\msg_new:nnnn {nicematrix} + {Duplicate~name} + {The~name~"#1"~is~already~used~and~you~shouldn't~use~ + the~same~environment~name~twice.~You~can~go~on,~but,~ + maybe,~you~will~have~incorrect~results~especially~ + if~you~use~"columns-width=auto".\\ + For~a~list~of~the~names~already~used,~type~H~.} + {The~names~already~defined~in~this~document~are:~ + \seq_use:Nnnn~\g_@@_names_seq~{,~} {,~} {~and~}.} +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} \keys_define:nn {NiceMatrix/NiceArray} {parallelize-diags .bool_set:N = \l_@@_parallelize_diags_bool, parallelize-diags .default:n = true, @@ -1613,18 +2253,14 @@ version 2005/12/01 or later. renew-dots .default:n = true, nullify-dots .bool_set:N = \l_@@_nullify_dots_bool , nullify-dots .default:n = true, - exterior-arraycolsep .bool_set:N = \l_@@_exterior_arraycolsep_bool , - exterior-arraycolsep .default:n = true, - columns-width .code:n = \str_if_eq:nnTF {#1} {auto} - {\bool_set_true:N \l_@@_auto_columns_width_bool} - {\dim_set:Nn \l_@@_columns_width_dim {#1}}, + columns-width .code:n = \str_if_eq:nnTF {#1} {auto} + {\bool_set_true:N \l_@@_auto_columns_width_bool} + {\dim_set:Nn \l_@@_columns_width_dim {#1}}, columns-width .value_required:n = true, name .code:n = {\seq_if_in:NnTF \g_@@_names_seq {#1} - {\msg_error:nnn {nicematrix} - {Duplicate~name} - {#1}} + {\@@_msg_error:nn {Duplicate~name} {#1}} {\seq_gput_left:Nn \g_@@_names_seq {#1}} - \tl_gset:Nn \g_@@_name_tl {#1}}, + \tl_set:Nn \l_@@_name_tl {#1}}, name .value_required:n = true, % \end{macrocode} % @@ -1635,10 +2271,18 @@ version 2005/12/01 or later. c .code:n = \tl_set:Nn \l_@@_pos_env_tl c, t .code:n = \tl_set:Nn \l_@@_pos_env_tl t, b .code:n = \tl_set:Nn \l_@@_pos_env_tl b, - code-after .tl_gset:N = \g_@@_code_after_tl, + code-after .tl_set:N = \l_@@_code_after_tl, code-after .initial:n = \c_empty_tl, code-after .value_required:n = true, - unknown .code:n = \msg_error:nn {nicematrix} {Unknown~option~for~NiceArray}} + create-extra-nodes .bool_set:N = \l_@@_extra_nodes_bool, + create-extra-nodes .default:n = true, + left-margin .dim_set:N = \l_@@_left_margin_dim, + left-margin .default:n = \arraycolsep, + right-margin .dim_set:N = \l_@@_right_margin_dim, + right-margin .default:n = \arraycolsep, + extra-left-margin .dim_set:N = \l_@@_extra_left_margin_dim, + extra-right-margin .dim_set:N = \l_@@_extra_right_margin_dim, + unknown .code:n = \@@_msg_error:n {Unknown~option~for~NiceArray}} % \end{macrocode} % % \begin{macrocode} @@ -1652,33 +2296,43 @@ version 2005/12/01 or later. b,~ c,~ code-after,~ + create-extra-nodes,~ columns-width,~ - exterior-arraycolsep,~ + extra-left-margin,~ + extra-right-margin,~ + left-margin,~ name,~ nullify-dots,~ parallelize-diags,~ - renew-dots~ + renew-dots,~ + right-margin,~ and~t.} % \end{macrocode} % % \subsection{The environments \{NiceArray\} and \{NiceMatrix\}} % -% The pseudo-environment |\@@_Cell:n|--|\@@_end_Cell:| will be used to format the cells of the array. In the code, +% The pseudo-environment |\@@_Cell:|--|\@@_end_Cell:| will be used to format the cells of the array. In the code, % the affectations are global because this pseudo-environment will be used in the cells of a |\halign| (via an % environment |{array}|). % -% The argument of |\@@_Cell:n| is a letter |l|, |c| or |r| that describes the type of column: we store this letter -% at the end of |\g_@@_preamble_aux_tl| (see the redefinition of |\ialign| in the environment |{NiceArray}| for -% explanations). % \begin{macrocode} -\cs_new_protected:Nn \@@_Cell:n - {\tl_gput_right:Nn \g_@@_preamble_aux_tl {#1} +\cs_new_protected:Nn \@@_Cell: + { % \end{macrocode} % We increment |\g_@@_column_int|, which is the counter of the columns. % \begin{macrocode} \int_gincr:N \g_@@_column_int +% \end{macrocode} +% Now, we increment the counter of the rows. We don't do this incrementation in the |\everycr| because some +% packages, like \pkg{arydsln}, creates special rows in the |\halign| that we don't want to take into account. +% \begin{macrocode} + \int_compare:nNnT \g_@@_column_int = 1 + {\int_gincr:N \g_@@_row_int} + \int_gset:Nn \g_@@_column_total_int + {\int_max:nn \g_@@_column_total_int \g_@@_column_int} \hbox_set:Nw \l_tmpa_box $ % $ - \l_@@_code_for_cell_tl } + \int_compare:nNnT \g_@@_row_int = 0 + \l_@@_code_for_first_row_tl} % \end{macrocode} % % \begin{macrocode} @@ -1692,20 +2346,31 @@ version 2005/12/01 or later. % \begin{macrocode} \dim_gset:Nn \g_@@_max_cell_width_dim {\dim_max:nn \g_@@_max_cell_width_dim {\box_wd:N \l_tmpa_box}} - \tl_if_empty:NTF \g_@@_name_tl - {\tikz[remember~picture, inner~sep = 0pt, minimum~width = 0pt, baseline] - \node [anchor = base, - name = nm-\int_use:N \g_@@_env_int- - \int_use:N \g_@@_row_int- - \int_use:N \g_@@_column_int] } - {\tikz[remember~picture, inner~sep = 0pt, minimum~width = 0pt, baseline] +% \end{macrocode} +% +% +% \begin{macrocode} + \int_compare:nNnT \g_@@_row_int = 0 + {\dim_gset:Nn \g_@@_max_dp_row_zero_dim + {\dim_max:nn \g_@@_max_dp_row_zero_dim {\box_dp:N \l_tmpa_box}} + \dim_gset:Nn \g_@@_max_ht_row_zero_dim + {\dim_max:nn \g_@@_max_ht_row_zero_dim {\box_ht:N \l_tmpa_box}}} + \int_compare:nNnT \g_@@_row_int = 1 + {\dim_gset:Nn \g_@@_max_ht_row_one_dim + {\dim_max:nn \g_@@_max_ht_row_one_dim {\box_ht:N \l_tmpa_box}}} +% \end{macrocode} +% +% Now, we can create the Tikz node of the cell. +% \begin{macrocode} + \tikz[remember~picture, inner~sep = 0pt, minimum~width = 0pt, baseline] \node [anchor = base, name = nm-\int_use:N \g_@@_env_int- \int_use:N \g_@@_row_int- \int_use:N \g_@@_column_int, - alias = \tl_use:N \g_@@_name_tl- - \int_use:N \g_@@_row_int- - \int_use:N \g_@@_column_int] } + alias = \tl_if_empty:NF \l_@@_name_tl + {\tl_use:N \l_@@_name_tl- + \int_use:N \g_@@_row_int- + \int_use:N \g_@@_column_int} ] \bgroup \box_use:N \l_tmpa_box \egroup ;} @@ -1732,22 +2397,21 @@ version 2005/12/01 or later. % Here's the definition of |{NiceMatrix}|: % \begin{macrocode} \NewDocumentEnvironment {NiceMatrix} {O{}} - {\bool_set_false:N \l_@@_direct_NiceArray_bool - \tl_gclear:N \g_@@_code_after_tl - \keys_set:nn {NiceMatrix/NiceMatrix} {#1} + {\keys_set:nn {NiceMatrix/NiceMatrix} {#1} \tl_set:Nn \l_@@_pos_env_tl c \bool_set_false:N \l_@@_exterior_arraycolsep_bool \NiceArray{*\c@MaxMatrixCols{C}} } {\endarray - \skip_horizontal:n {-\arraycolsep}} + \skip_horizontal:n {-\arraycolsep} + \skip_horizontal:n {\g_@@_right_margin_dim + \g_@@_extra_right_margin_dim}} % \end{macrocode} % % \interitem % For the definition of |{NiceArray}| (just below), we have the following constraints: % \begin{itemize} % \item we must use |\array| in the first part of |{NiceArray}| and, therefore, |\endarray| in the second part; -% \item we have to put a |\aftergroup \@@_draw_lines:| in the first part of |{NiceArray}| so that |\@@_draw_lines| +% \item we have to put a |\aftergroup \@@_after_array:| in the first part of |{NiceArray}| so that |\@@_draw_lines| % will be executed at the end of the current environment (either |{NiceArray}| or |{NiceMatrix}|). % \end{itemize} % @@ -1755,15 +2419,25 @@ version 2005/12/01 or later. \cs_generate_variant:Nn \dim_set:Nn {Nx} % \end{macrocode} % +% +% \bigskip +% \begin{macrocode} +\msg_new:nnn {nicematrix} + {We~are~yet~in~an~environment~NiceArray} + {Environments~\{NiceArray\}~(or~\{NiceMatrix\},~etc.)~can't~be~ + nested.~We~can~go~on,~but,~maybe,~you~will~have~errors~or~an~incorrect~ + result.} +% \end{macrocode} % \bigskip % First, we test if we are yet in an environment |{NiceArray}| (nested environment are forbidden). It's easy to % test whether we are in an environment |{NiceArray}| : a special command |\@@_in_NiceArray:| is defined. % \begin{macrocode} \NewDocumentEnvironment {NiceArray} {O{} m O{}} {\cs_if_exist:NT \@@_in_NiceArray: - {\msg_error:nn {nicematrix} {We~are~yet~in~an~environment~NiceArray}} + {\@@_msg_error:n {We~are~yet~in~an~environment~NiceArray}} \cs_set:Npn \@@_in_NiceArray: {--Void--} - \aftergroup \@@_draw_lines: + \aftergroup \@@_after_array: + \tl_gclear_new:N \g_@@_lines_to_draw_tl % \end{macrocode} % % We increment the counter |\g_@@_env_int| which counts the environments |{NiceArray}|. @@ -1772,12 +2446,15 @@ version 2005/12/01 or later. \bool_if:NF \l_@@_block_auto_columns_width_bool {\dim_gzero_new:N \g_@@_max_cell_width_dim} % \end{macrocode} -% Maybe, an encompassing environment |{NiceMatrix}| or |{pNiceArrayC}| (for example) has already set the value for -% |\g_@@_code_after_tl| (via the option |code-after|) and we don't want to erase this value. Thanks to the flag -% |\l_@@_direct_NiceArray_bool|, it's possible. +% +% For the following variables, maybe we should create it only if we use the environment |{pNiceArrayRC}| or its variants. +% \begin{macrocode} + \dim_gzero_new:N \g_@@_max_dp_row_zero_dim + \dim_gzero_new:N \g_@@_max_ht_row_zero_dim + \dim_gzero_new:N \g_@@_max_ht_row_one_dim +% \end{macrocode} +% % \begin{macrocode} - \bool_if:NT \l_@@_direct_NiceArray_bool - {\tl_gclear:N \g_@@_code_after_tl} \keys_set:nn {NiceMatrix/NiceArray} {#1,#3} % \end{macrocode} % @@ -1796,36 +2473,35 @@ version 2005/12/01 or later. % |_@@_name_cell_width|{\ttfamily\slshape name} (the value will be the correct value even if the number of the % environment has changed (for example because the user has created or deleted an environment before the current one). % \begin{macrocode} - \tl_if_empty:NF \g_@@_name_tl - {\cs_if_free:cF {_@@_max_cell_width_\g_@@_name_tl} + \tl_if_empty:NF \l_@@_name_tl + {\cs_if_free:cF {_@@_max_cell_width_\l_@@_name_tl} {\dim_set:Nx \l_@@_columns_width_dim - {\use:c {_@@_max_cell_width_\g_@@_name_tl}}}} + {\use:c {_@@_max_cell_width_\l_@@_name_tl}}}} } % \end{macrocode} +% We don't want to patch any code and that's why some code is excuted in a |\aftergroup|. In particular, in this +% |\aftergroup|, we will have to know the value of some parameters like |\l_@@_extra_nodes_bool|. That's why we transit via a global +% version for some variables. +% \begin{macrocode} + \bool_gset_eq:NN \g_@@_extra_nodes_bool \l_@@_extra_nodes_bool + \dim_gset_eq:NN \g_@@_left_margin_dim \l_@@_left_margin_dim + \dim_gset_eq:NN \g_@@_right_margin_dim \l_@@_right_margin_dim + \dim_gset_eq:NN \g_@@_extra_right_margin_dim \l_@@_extra_right_margin_dim + \tl_gset_eq:NN \g_@@_code_after_tl \l_@@_code_after_tl + \tl_gset_eq:NN \g_@@_name_tl \l_@@_name_tl +% \end{macrocode} % The environment |{array}| uses internally the command |\ialign| and, in particular, this command |\ialign| sets -% |\everycr| to |{}|. However, we want to use |\everycr| in our array (in particular to increment |\g_@@_row_int|). +% |\everycr| to |{}|. However, we want to use |\everycr| in our array. % The solution is to give to |\ialign| a new definition (giving to |\everycr| the value we want) % that will revert automatically to its default definition after the first utilisation.\footnote{With this programmation, we will % have, in the cells of the array, a clean version of |\ialign|. That's necessary: the user will probably not employ directly % |\ialign| in the array... but more likely environments that utilize |\ialign| internally (e.g.: |{substack}|)} % \begin{macrocode} \cs_set:Npn \ialign - {\everycr{\noalign{\int_gincr:N \g_@@_row_int - \int_gzero:N \g_@@_column_int -% \end{macrocode} -% We want to have the preamble of the array in |\g_@@_preamble_tl| at the end of the array. However, some rows of the array -% may be shorter (that is to say without all the ampersands) and it's not possible to know which row will be the -% longest. That's why, during the construction of a row, we retrieve the corresponding preamble in -% |\g_@@_preamble_aux_tl|. At the end of the array, we are sure that the longest value will be the real preamble of -% the array (stored in |\g_@@_preamble_tl|). -% \begin{macrocode} - \int_compare:nNnT {\tl_count:N \g_@@_preamble_aux_tl} - > {\tl_count:N \g_@@_preamble_tl} - {\tl_gset_eq:NN \g_@@_preamble_tl \g_@@_preamble_aux_tl} - \tl_gclear:N \g_@@_preamble_aux_tl}} - \skip_zero:N \tabskip + {\everycr{\noalign{\int_gzero:N \g_@@_column_int}} + \tabskip = \c_zero_skip \cs_set:Npn \ialign {\everycr{} - \skip_zero:N \tabskip + \tabskip = \c_zero_skip \halign} \halign} % \end{macrocode} @@ -1834,9 +2510,9 @@ version 2005/12/01 or later. % |{NiceArray}|. % \begin{macrocode} \dim_compare:nNnTF \l_@@_columns_width_dim = \c_zero_dim - {\newcolumntype{L}{>{\@@_Cell:n l}l<{\@@_end_Cell:}} - \newcolumntype{C}{>{\@@_Cell:n c}c<{\@@_end_Cell:}} - \newcolumntype{R}{>{\@@_Cell:n r}r<{\@@_end_Cell:}}} + {\newcolumntype{L}{>{\@@_Cell:}l<{\@@_end_Cell:}} + \newcolumntype{C}{>{\@@_Cell:}c<{\@@_end_Cell:}} + \newcolumntype{R}{>{\@@_Cell:}r<{\@@_end_Cell:}}} % \end{macrocode} % If there is an option that specify that all the columns must have the same width, the column types~|L|, |C| % and~|R| are in fact defined upon the column type~|w| of array which is, in fact, redefined below. @@ -1857,14 +2533,14 @@ version 2005/12/01 or later. % \begin{macrocode} \newcolumntype{w}[2] {>{\hbox_set:Nw \l_tmpa_box - \@@_Cell:n ##1} + \@@_Cell:} c <{\@@_end_Cell: \hbox_set_end: \makebox[##2][##1]{\box_use:N \l_tmpa_box}}} \newcolumntype{W}[2] {>{\hbox_set:Nw \l_tmpa_box - \@@_Cell:n ##1} + \@@_Cell:} c <{\@@_end_Cell: \hbox_set_end: @@ -1880,29 +2556,19 @@ version 2005/12/01 or later. \cs_set_eq:NN \Ddots \@@_Ddots \cs_set_eq:NN \Iddots \@@_Iddots \cs_set_eq:NN \Hspace \@@_Hspace: - \cs_set_eq:NN \NiceMatrixEndPoint \@@_NiceMatrixEndPoint: \cs_set_eq:NN \Hdotsfor \@@_Hdotsfor + \cs_set_eq:NN \multicolumn \@@_multicolumn:nnn \bool_if:NT \l_@@_renew_dots_bool {\cs_set_eq:NN \ldots \@@_Ldots \cs_set_eq:NN \cdots \@@_Cdots \cs_set_eq:NN \vdots \@@_Vdots \cs_set_eq:NN \ddots \@@_Ddots \cs_set_eq:NN \iddots \@@_Iddots + \cs_set_eq:NN \dots \@@_Ldots \cs_set_eq:NN \hdotsfor \@@_Hdotsfor} - \bool_if:NF \l_@@_renew_matrix_bool - {\cs_set_eq:NN \multicolumn \@@_multicolumn:nn} % \end{macrocode} % % -% We have to remind the types of the columns (|l|, |c| or |r|) because we will use this information when we will -% draw the vertical dotted lines. That's why we store the types of the columns in |\g_@@_preamble_tl| (for example, -% if the preamble of |{NiceArray}| is |L*4{C}R|, the final value of |\g_@@_preamble_tl| will be |lccccr| if the -% user really uses the six columns). -% \begin{macrocode} - \tl_clear_new:N \g_@@_preamble_tl - \tl_clear_new:N \g_@@_preamble_aux_tl -% \end{macrocode} -% % The sequence |\g_@@_empty_cells_seq| will contain a list of ``empty'' cells (not all the empty cells of the % matrix). If we want to indicate that the cell in row~$i$ and column~$j$ must be considered as empty, the token % list ``|i-j|'' will be put in this sequence. @@ -1910,23 +2576,30 @@ version 2005/12/01 or later. \seq_gclear_new:N \g_@@_empty_cells_seq % \end{macrocode} % -% The counter |\g_@@_instruction_int| will count the instructions (|\Cdots|, |\Vdots|, |\Ddots|, etc.) in the matrix. +% The sequence |\g_@@_multicolumn_cells_seq| will contain the list of the cells of the array where a command +% |\multicolumn{|$n$|}{...}{...}| with $n>1$ is issued. In |\g_@@_multicolumn_sizes_seq|, the ``sizes'' (that is to say +% the values of $n$) correspondant will be stored. These lists will be used for the creation of the ``medium nodes'' +% (if they are created). % \begin{macrocode} - \int_gzero_new:N \g_@@_instruction_int + \seq_gclear_new:N \g_@@_multicolumn_cells_seq + \seq_gclear_new:N \g_@@_multicolumn_sizes_seq % \end{macrocode} +% % % The counter |\g_@@_row_int| will be used to count the rows of the array (its incrementation will be in -% |\everycr|). At the end of the environment |{array}|, this counter will give the total number of rows of the matrix. +% the first cell of the row). At the end of the environment |{array}|, this counter will give the total number of +% rows of the matrix. % \begin{macrocode} \int_gzero_new:N \g_@@_row_int - \int_gset_eq:NN \g_@@_row_int \l_@@_number_of_first_row_int + \int_gset:Nn \g_@@_row_int {\l_@@_nb_first_row_int - 1} % \end{macrocode} % -% The counter |\g_@@_column_int| will be used to count the columns of the array (it will be set to zero in -% |\everycr|). This counter is updated in the command |\@@_Cell:n| executed at the beginning of each cell. At the -% end of the array (in the beginning of |\@@_draw_lines:|), it will be set to the total number of columns of the array. +% The counter |\g_@@_column_int| will be used to count the columns of the array. Since we want to +% know the total number of columns of the matrix, we also create a counter |\g_@@_column_total_int|. +% These counters are updated in the command |\@@_Cell:| executed at the beginning of each cell. % \begin{macrocode} \int_gzero_new:N \g_@@_column_int + \int_gzero_new:N \g_@@_column_total_int \cs_set_eq:NN \@ifnextchar \new@ifnextchar % \end{macrocode} % @@ -1939,7 +2612,12 @@ version 2005/12/01 or later. {\skip_horizontal:n {-\arraycolsep}} % \end{macrocode} % -% Eventually, the environment |{NiceArray}| is defined upon the environment |{array}|. The token list |l_@@_pos_tl| +% \begin{macrocode} + \skip_horizontal:n {\l_@@_left_margin_dim + \l_@@_extra_left_margin_dim} +% \end{macrocode} +% +% +% Eventually, the environment |{NiceArray}| is defined upon the environment |{array}|. The token list |\l_@@_pos_tl| % will contain one of the values |t|, |c| or |b|. % \begin{macrocode} \array[\l_@@_pos_env_tl]{#2}} @@ -1949,7 +2627,8 @@ version 2005/12/01 or later. % \begin{macrocode} {\endarray \bool_if:NF \l_@@_exterior_arraycolsep_bool - {\skip_horizontal:n {-\arraycolsep}}} + {\skip_horizontal:n {-\arraycolsep}} + \skip_horizontal:n {\g_@@_right_margin_dim + \g_@@_extra_right_margin_dim}} % \end{macrocode} % % @@ -1996,22 +2675,22 @@ version 2005/12/01 or later. \cs_new_protected:Nn \@@_write_max_cell_width: {\bool_if:NF \l_@@_block_auto_columns_width_bool {\iow_now:Nn \@mainaux {\ExplSyntaxOn} - \iow_now:Nx \@mainaux {\cs_gset:cpn {_@@_max_cell_width_\int_use:N \g_@@_env_int} - {\dim_use:N \g_@@_max_cell_width_dim} } + \iow_now:Nx \@mainaux {\cs_gset:cpn + {@@_max_cell_width_\int_use:N \g_@@_env_int} + {\dim_use:N \g_@@_max_cell_width_dim} } % \end{macrocode} -% If the environment has a name, we also create an alias named |\_@@_max_cell_width_|{\ttfamily\slshape name}. +% If the environment has a name, we also create an alias named |\@@_max_cell_width_|{\ttfamily\slshape name}. % \begin{macrocode} - \iow_now:Nx \@mainaux {\cs_gset:cpn {_@@_max_cell_width_\g_@@_name_tl} + \iow_now:Nx \@mainaux {\cs_gset:cpn {@@_max_cell_width_\g_@@_name_tl} {\dim_use:N \g_@@_max_cell_width_dim} } - \iow_now:Nn \@mainaux {\ExplSyntaxOff}} - \tl_gclear:N \g_@@_name_tl} + \iow_now:Nn \@mainaux {\ExplSyntaxOff}}} % \end{macrocode} % % \interitem % The conditionnal |\@@_if_not_empty_cell:nnT| tests wether a cell is empty. The first two arguments must be LaTeX3 % counters for the row and the column of the considered cell. % \begin{macrocode} -\prg_set_conditional:Npnn \@@_if_not_empty_cell:nn #1#2 {T} +\prg_set_conditional:Npnn \@@_if_not_empty_cell:nn #1#2 {T,TF} % \end{macrocode} % If the cell is an implicit cell (that is after the symbol |\\| of end of row), the cell must, of course, be % considered as empty. It's easy to check wether we are in this situation considering the correspondant Tikz node. @@ -2045,83 +2724,76 @@ version 2005/12/01 or later. \dim_gset:Nn \g_tmpb_dim \pgf@x \end{pgfpicture} \dim_compare:nNnTF {\dim_abs:n {\g_tmpb_dim-\g_tmpa_dim}} < {0.5 pt} - {\prg_return_false:} - {\prg_return_true:} + \prg_return_false: + \prg_return_true: }} - {\prg_return_false:} + \prg_return_false: } % \end{macrocode} % -% \interitem -% For each drawing instruction in the matrix (like |\Cdots|, etc.), we create a global property list to store the -% informations corresponding to the instruction. Such an property list will have three fields: -% \begin{itemize} -% \item a field ``type'' with the type of the instruction (|cdots|, |vdots|, |ddots|, etc.); -% \item a field ``row'' with the number of the row of the matrix where the instruction appeared; -% \item a field ``column'' with the number of the column of the matrix where the instruction appeared. -% \end{itemize} +% \interitem +% The argument of the following command |\@@_instruction_of_type:n| is the type of the instruction (|Cdots|, +% |Vdots|, |Ddots|, etc.). This command writes in |\g_@@_lines_to_draw_tl| the instruction that will really draw +% the line after the construction of the matrix. +% +% \medskip +% For example, for the following matrix, +% +% \smallskip +% \begin{BVerbatim}[baseline=c,boxwidth=11cm] +% \begin{pNiceMatrix} +% 1 & 2 & 3 & 4 \\ +% 5 & \Cdots & & 6 \\ +% 7 & \Hdotsfor{2} \\ +% \end{pNiceMatrix} +% \end{BVerbatim} +% $\begin{pNiceMatrix} +% 1 & 2 & 3 & 4 \\ +% 5 & \Cdots & & 6 \\ +% 7 & \Hdotsfor{2} \\ +% \end{pNiceMatrix}$ +% +% the content of |\g_@@_lines_to_draw_tl| will be: +% +% \begin{scope} +% \color{gray} +% \verb|\@@_draw_Cdots:nn {2}{2}| % -% \interitem -% The argument of the following command |\@@_instruction_of_type:n| is the type of the instruction (|cdots|, -% |vdots|, |ddots|, etc.). This command creates the corresponding property list. +% \verb|\@@_draw_Hdotsfor:nnn {3}{2}{2}| +% \end{scope} +% % \begin{macrocode} \cs_new_protected:Nn \@@_instruction_of_type:n -% \end{macrocode} -% First, we increment the counter of the instructions (this counter is initialized in the beginning of the -% environment |{NiceMatrix}|). This incrementation is global because the command will be used in the cell of a |\halign|). -% \begin{macrocode} - {\int_gincr:N \g_@@_instruction_int - \prop_put:Nnn \l_tmpa_prop {type} {#1} - \prop_put:NnV \l_tmpa_prop {row} \g_@@_row_int - \prop_put:NnV \l_tmpa_prop {column} \g_@@_column_int -% \end{macrocode} -% The property list has been created in a local variable for convenience. Now, it will be stored in a -% global variable indicating the number of the instruction. -% \begin{macrocode} - \prop_gclear_new:c - {g_@@_instruction_\int_use:N\g_@@_instruction_int _prop} - \prop_gset_eq:cN - {g_@@_instruction_\int_use:N\g_@@_instruction_int _prop} - \l_tmpa_prop - } + {\tl_gput_right:Nx \g_@@_lines_to_draw_tl + {\exp_not:c {@@_draw_#1:nn} + {\int_use:N \g_@@_row_int} + {\int_use:N \g_@@_column_int}}} % \end{macrocode} % % -% \subsection{We draw the lines in the matrix} +% \subsection{After the construction of the array} % % \begin{macrocode} -\cs_new_protected:Nn \@@_draw_lines: +\cs_new_protected:Nn \@@_after_array: { % \end{macrocode} -% The last |\cr| in the array has incremented the counter |\g_@@_row_int|. That's why we decrement it to have the -% real number of rows. -% \begin{macrocode} - \int_decr:N \g_@@_row_int -% \end{macrocode} -% The counter |\g_@@_column_int| will now be the total number of columns in the array. +% Now, the definition of the counters |\g_@@_column_int| and |\g_@@_column_total_int| change: |\g_@@_column_int| +% will be the number of columns without the exterior column (in an environment like |{pNiceArrayC}|) and +% |\g_@@_column_total_int| will be the number of columns with this exterior column. % \begin{macrocode} - \int_set:Nn \g_@@_column_int {\tl_count:N \g_@@_preamble_tl} + \int_gset_eq:NN \g_@@_column_int \g_@@_column_total_int + \bool_if:NT \l_@@_exterior_column_bool {\int_gdecr:N \g_@@_column_int} % \end{macrocode} % -% The sequence |\l_@@_yet_drawn_seq| contains a list of lines which have been drawn previously in the matrix. We +% The sequence |\g_@@_yet_drawn_seq| contains a list of lines which have been drawn previously in the matrix. We % maintain this sequence because we don't want to draw two overlapping lines. % \begin{macrocode} - \seq_clear_new:N \l_@@_yet_drawn_seq -% \end{macrocode} -% -% -% The following variables will be used further. -% \begin{macrocode} - \int_zero_new:N \l_@@_type_int - \int_zero_new:N \l_@@_row_int - \int_zero_new:N \l_@@_column_int - \int_zero_new:N \l_@@_di_int - \int_zero_new:N \l_@@_dj_int + \seq_gclear_new:N \g_@@_yet_drawn_seq % \end{macrocode} % -% By befault, the diagonal lines will be parallelized\footnote{It's possible to use the option +% By default, the diagonal lines will be parallelized\footnote{It's possible to use the option % |parallelize-diags| to disable this parallelization.}. There are two types of diagonals lines: the $|\Ddots|$ -% diagonals and the |\Iddots| diagonals. We have to count both types in order to known wether a diagonal is the +% diagonals and the |\Iddots| diagonals. We have to count both types in order to know wether a diagonal is the % first of its type in the current |{NiceArray}| environment. % \begin{macrocode} \bool_if:NT \l_@@_parallelize_diags_bool @@ -2139,185 +2811,179 @@ version 2005/12/01 or later. \dim_zero_new:N \l_@@_delta_x_two_dim \dim_zero_new:N \l_@@_delta_y_two_dim} % \end{macrocode} -% -% \interitem -% The counter |\l_@@_instruction_int| will be the index of the loop over the instructions. The first value is~$1$. +% +% If the user has used the option |create-extra-nodes|, the ``medium nodes'' and ``large nodes'' are created. We +% recall that the command |\@@_create_extra_nodes:|, when used once, becomes no-op (in the current TeX group). % \begin{macrocode} - \int_zero_new:N \l_@@_instruction_int - \int_incr:N \l_@@_instruction_int + \bool_if:NT \g_@@_extra_nodes_bool \@@_create_extra_nodes: % \end{macrocode} -% -% \interitem -% We begin the loop over the instructions (the incrementation is at the end of the loop). +% +% \bigskip +% Now, we really draw the lines. The code to draw the lines has been constructed in the token list |\g_@@_lines_to_draw_tl|. % \begin{macrocode} - \int_until_do:nNnn \l_@@_instruction_int > \g_@@_instruction_int - { + \tl_if_empty:NF \g_@@_lines_to_draw_tl + {\int_zero_new:N \l_@@_initial_i_int + \int_zero_new:N \l_@@_initial_j_int + \int_zero_new:N \l_@@_final_i_int + \int_zero_new:N \l_@@_final_j_int + \@@_bool_new:N \l_@@_initial_open_bool + \@@_bool_new:N \l_@@_final_open_bool + \g_@@_lines_to_draw_tl} + \tl_gclear:N \g_@@_lines_to_draw_tl % \end{macrocode} % -% \interitem -% We extract from the property list of the current instruction the fields ``type'', ``row'' and ``column'' and we -% store these values. We have to do a conversion because the components of a property list are token lists (and not -% integers). +% \bigskip +% Now, the |code-after|. % \begin{macrocode} - \prop_get:cnN {g_@@_instruction_\int_use:N \l_@@_instruction_int _prop} - {type} \l_tmpa_tl - \int_set:Nn \l_@@_type_int {\l_tmpa_tl} - \prop_get:cnN {g_@@_instruction_\int_use:N \l_@@_instruction_int _prop} - {row} \l_tmpa_tl - \int_set:Nn \l_@@_row_int {\l_tmpa_tl} - \prop_get:cnN {g_@@_instruction_\int_use:N \l_@@_instruction_int _prop} - {column} \l_tmpa_tl - \int_set:Nn \l_@@_column_int {\l_tmpa_tl} + \group_begin: + \tikzset{every~picture/.style = {overlay, + remember~picture, + name~prefix = nm-\int_use:N \g_@@_env_int-}} + \cs_set_eq:NN \line \@@_line:nn + \g_@@_code_after_tl + \group_end:} % \end{macrocode} % -% \interitem -% We fix the values of |\l_@@_di_int| and |\l_@@_dj_int| which indicate the direction of the dotted line to draw in -% the matrix. -% \begin{macrocode} - \int_case:nn \l_@@_type_int - { 0 {\int_set:Nn \l_@@_di_int 0 - \int_set:Nn \l_@@_dj_int 1} - 1 {\int_set:Nn \l_@@_di_int 0 - \int_set:Nn \l_@@_dj_int 1} - 2 {\int_set:Nn \l_@@_di_int 1 - \int_set:Nn \l_@@_dj_int 0} - 3 {\int_set:Nn \l_@@_di_int 1 - \int_set:Nn \l_@@_dj_int 1} - 4 {\int_set:Nn \l_@@_di_int 1 - \int_set:Nn \l_@@_dj_int {-1}}} -% \end{macrocode} +% \bigskip +% A dotted line will be said \emph{open} in one of its extremity when it stops on the edge of the matrix and \emph{closed} +% otherwise. In the following matrix, the dotted line is closed on its left extremity and open on its right. +% \[ \begin{pNiceMatrix} +% a+b+c & a+b & a\\ +% a & \Cdots \\ +% a & a+b & a+b+c +% \end{pNiceMatrix}\] +% For a closed extremity, we use the normal node and for a open one, we use the ``medium node'' (the medium and +% large nodes are created with |\@@_create_extra_nodes:| if they have not been created yet). +% \[ \begin{pNiceMatrix}[code-after = {\begin{tikzpicture} +% \node [highlight, fit={(2-1)}] {} ; +% \node [highlight, fit={(2-3-medium)}] {} ; +% \end{tikzpicture} +% }] +% a+b+c & a+b & a\\ +% a & \Cdots \\ +% a & a+b & a+b+c +% \end{pNiceMatrix}\] % -% \interitem -% An instruction for a dotted line must have a initial cell and a final cell which are both not empty. If it's not -% the case, the instruction is said \emph{impossible}. An error will be raised if an impossible instruction is -% encountered. -% \begin{macrocode} - \bool_if_exist:NTF \l_@@_impossible_instruction_bool - {\bool_set_false:N \l_@@_impossible_instruction_bool} - {\bool_new:N \l_@@_impossible_instruction_bool} -% \end{macrocode} +% +% \bigskip +% The command |\@@_find_extremities_of_line:nnnn| takes four arguments: % -% \interitem -% We will determine |\l_@@_final_i_int| and |\l_@@_final_j_int| which will be the ``coordinates'' of the end of the -% dotted line we have to draw. -% \begin{macrocode} - \int_zero_new:N \l_@@_final_i_int - \int_zero_new:N \l_@@_final_j_int - \int_set:Nn \l_@@_final_i_int \l_@@_row_int - \int_set:Nn \l_@@_final_j_int \l_@@_column_int - \bool_if_exist:NTF \l_@@_stop_loop_bool - {\bool_set_false:N \l_@@_stop_loop_bool} - {\bool_new:N \l_@@_stop_loop_bool} +% \begin{itemize} +% \item the first argument is the row of the cell where the command was issued; +% \item the second argument is the column of the cell where the command was issued; +% \item the third argument is the $x$-value of the orientation vector of the line; +% \item the fourth argument is the $y$-value the orientation vector of the line; +% \end{itemize} +% +% This command computes: +% +% \begin{itemize} +% \item |\l_@@_initial_i_int| and |\l_@@_initial_j_int| which are the coordinates of one extremity of the line; +% \item |\l_@@_final_i_int| and |\l_@@_final_j_int| which are the coordinates of the other extremity of the line; +% \item |\l_@@_initial_open_bool| and |\l_@@_final_open_bool| to indicate wether the extremities are open or not. +% \end{itemize} +% +% \begin{macrocode} +\cs_new_protected:Nn \@@_find_extremities_of_line:nnnn + {\int_set:Nn \l_@@_initial_i_int {#1} + \int_set:Nn \l_@@_initial_j_int {#2} + \int_set:Nn \l_@@_final_i_int {#1} + \int_set:Nn \l_@@_final_j_int {#2} + \bool_set_false:N \l_@@_initial_open_bool + \bool_set_false:N \l_@@_final_open_bool +% \end{macrocode} +% We will do two loops: one when determinating the initial cell and the other when determinating the final cell. +% The boolean |\l_@@_stop_loop_bool| will be used to control these loops. +% \begin{macrocode} + \@@_bool_new:N \l_@@_stop_loop_bool \bool_do_until:Nn \l_@@_stop_loop_bool - {\int_add:Nn \l_@@_final_i_int \l_@@_di_int - \int_add:Nn \l_@@_final_j_int \l_@@_dj_int + {\int_add:Nn \l_@@_final_i_int {#3} + \int_add:Nn \l_@@_final_j_int {#4} % \end{macrocode} % We test if we are still in the matrix. % \begin{macrocode} - \bool_if:nTF { \int_compare_p:nNn \l_@@_final_i_int < \l_@@_number_of_first_row_int - || \int_compare_p:nNn \l_@@_final_i_int > \g_@@_row_int - || \int_compare_p:nNn \l_@@_final_j_int < 1 - || \int_compare_p:nNn \l_@@_final_j_int > \g_@@_column_int} + \bool_if:nTF { \int_compare_p:nNn + \l_@@_final_i_int < {\l_@@_nb_first_row_int - 1} + || \int_compare_p:nNn + \l_@@_final_i_int > \g_@@_row_int + || \int_compare_p:nNn + \l_@@_final_j_int < 1 + || \int_compare_p:nNn + \l_@@_final_j_int > \g_@@_column_total_int} % \end{macrocode} -% If we are outside the matrix, the instruction is impossible and, of course, we stop the loop. +% If we are outside the matrix, we have found the extremity of the dotted line and it's a \emph{open} extremity. % \begin{macrocode} - {\bool_set_true:N \l_@@_impossible_instruction_bool + {\bool_set_true:N \l_@@_final_open_bool +% \end{macrocode} +% We do a step backwards because we will draw the dotted line upon the last cell in the matrix (we will use the +% ``medium node'' of this cell). +% \begin{macrocode} + \int_sub:Nn \l_@@_final_i_int {#3} + \int_sub:Nn \l_@@_final_j_int {#4} \bool_set_true:N \l_@@_stop_loop_bool} % \end{macrocode} % If we are in the matrix, we test if the cell is empty. If it's not the case, we stop the loop because we have % found the correct values for |\l_@@_final_i_int| and |\l_@@_final_j_int|. % \begin{macrocode} - {\@@_if_not_empty_cell:nnT \l_@@_final_i_int \l_@@_final_j_int + {\@@_if_not_empty_cell:nnT + \l_@@_final_i_int + \l_@@_final_j_int {\bool_set_true:N \l_@@_stop_loop_bool}} } % \end{macrocode} % % \interitem -% We will determine |\l_@@_initial_i_int| and |\l_@@_initial_j_int| which will be the ``coordinates'' of the -% beginning of the dotted line we have to draw. The programmation is similar to the previous one. -% \begin{macrocode} - \int_zero_new:N \l_@@_initial_i_int - \int_zero_new:N \l_@@_initial_j_int - \int_set:Nn \l_@@_initial_i_int \l_@@_row_int - \int_set:Nn \l_@@_initial_j_int \l_@@_column_int -% \end{macrocode} -% If we know that the instruction is impossible (because it was not possible to found the correct value for -% |\l_@@_final_i_int| and |\l_@@_final_j_int|), we don't do this loop. +% For |\l_@@_initial_i_int| and |\l_@@_initial_j_int| the programmation is similar to the previous one. % \begin{macrocode} - \bool_set_eq:NN \l_@@_stop_loop_bool \l_@@_impossible_instruction_bool + \bool_set_false:N \l_@@_stop_loop_bool \bool_do_until:Nn \l_@@_stop_loop_bool - {\int_sub:Nn \l_@@_initial_i_int \l_@@_di_int - \int_sub:Nn \l_@@_initial_j_int \l_@@_dj_int + {\int_sub:Nn \l_@@_initial_i_int {#3} + \int_sub:Nn \l_@@_initial_j_int {#4} \bool_if:nTF - { \int_compare_p:nNn \l_@@_initial_i_int < \l_@@_number_of_first_row_int - || \int_compare_p:nNn \l_@@_initial_i_int > \g_@@_row_int - || \int_compare_p:nNn \l_@@_initial_j_int < 1 - || \int_compare_p:nNn \l_@@_initial_j_int > \g_@@_column_int} - {\bool_set_true:N \l_@@_impossible_instruction_bool + { \int_compare_p:nNn + \l_@@_initial_i_int < \l_@@_nb_first_row_int + || \int_compare_p:nNn + \l_@@_initial_i_int > \g_@@_row_int + || \int_compare_p:nNn + \l_@@_initial_j_int < 1 + || \int_compare_p:nNn + \l_@@_initial_j_int > \g_@@_column_total_int} + {\bool_set_true:N \l_@@_initial_open_bool + \int_add:Nn \l_@@_initial_i_int {#3} + \int_add:Nn \l_@@_initial_j_int {#4} \bool_set_true:N \l_@@_stop_loop_bool} - {\@@_if_not_empty_cell:nnT \l_@@_initial_i_int \l_@@_initial_j_int + {\@@_if_not_empty_cell:nnT + \l_@@_initial_i_int + \l_@@_initial_j_int {\bool_set_true:N \l_@@_stop_loop_bool}} } % \end{macrocode} -% -% \interitem -% Now, we can determine wether we have to draw a line. -% If the line is impossible, of course, we won't draw any line. +% If we have at least one open extremity, we create the ``medium nodes'' in the matrix (in the case of an open +% extremity, the dotted line uses the ``medium node'' of the last empty cell). We remind that, when used once, the +% command |\@@_create_extra_nodes:| becomes no-op in the current TeX group. % \begin{macrocode} - \bool_if:NTF \l_@@_impossible_instruction_bool - {\msg_error:nn {nicematrix} {Impossible~instruction}} + \bool_if:nT {\l_@@_initial_open_bool || \l_@@_final_open_bool} + \@@_create_extra_nodes: } % \end{macrocode} % -% If the dotted line to draw is in the list of the previously drawn lines (|\l_@@_yet_drawn_seq|), we don't draw +% \interitem +% If the dotted line to draw is in the list of the previously drawn lines (|\g_@@_yet_drawn_seq|), we don't draw % (so, we won't have overlapping lines in the \textsc{pdf}). The token list |\l_tmpa_tl| is the $4$-uplet % characteristic of the line. % \begin{macrocode} +\prg_set_conditional:Npnn \@@_if_yet_drawn: {F} {\tl_set:Nx \l_tmpa_tl {\int_use:N \l_@@_initial_i_int- \int_use:N \l_@@_initial_j_int- \int_use:N \l_@@_final_i_int- \int_use:N \l_@@_final_j_int} - \seq_if_in:NVF \l_@@_yet_drawn_seq \l_tmpa_tl -% \end{macrocode} -% -% If the dotted line to draw is not in the list, we add it the list |\l_@@_yet_drawn_seq|. -% \begin{macrocode} - {\seq_put_left:NV \l_@@_yet_drawn_seq \l_tmpa_tl -% \end{macrocode} -% -% \medskip -% The four following variables are global because we will have to do affectations in a Tikz instruction (in order -% to extract the coordinates of two extremities of the line to draw). -% \begin{macrocode} - \dim_zero_new:N \g_@@_x_initial_dim - \dim_zero_new:N \g_@@_y_initial_dim - \dim_zero_new:N \g_@@_x_final_dim - \dim_zero_new:N \g_@@_y_final_dim -% \end{macrocode} -% -% -% We draw the line. -% \begin{macrocode} - \int_case:nn \l_@@_type_int - {0 \@@_draw_ldots_line: - 1 \@@_draw_cdots_line: - 2 \@@_draw_vdots_line: - 3 \@@_draw_ddots_line: - 4 \@@_draw_iddots_line:}}} + \seq_if_in:NVTF \g_@@_yet_drawn_seq \l_tmpa_tl % \end{macrocode} % -% \bigskip -% Incrementation of the index of the loop (and end of the loop). +% If the dotted line to draw is not in the list, we add it to the list |\g_@@_yet_drawn_seq|. % \begin{macrocode} - \int_incr:N \l_@@_instruction_int - } - \group_begin: - \tikzset{every~picture/.style = {overlay, - remember~picture, - name~prefix = nm-\int_use:N \g_@@_env_int-}} - \cs_set_eq:NN \line \@@_line:nn - \g_@@_code_after_tl - \group_end: -} + {\prg_return_true:} + {\seq_gput_left:NV \g_@@_yet_drawn_seq \l_tmpa_tl + \prg_return_false:}} % \end{macrocode} % % @@ -2327,74 +2993,123 @@ version 2005/12/01 or later. % adjustment of one of the coordinates may be done.}. This command has four implicit arguments which are % |\l_@@_initial_i_int|, |\l_@@_initial_j_int|, |\l_@@_final_i_int| and |\l_@@_final_j_int|. % -% The two arguments of the command |\@@_retrieve_coords:nn| are the anchors that must be used for the two nodes. +% The two arguments of the command |\@@_retrieve_coords:nn| are the prefix and the anchor that must be used for the +% two nodes. % % The coordinates are stored in |\g_@@_x_initial_dim|, |\g_@@_y_initial_dim|, |\g_@@_x_final_dim|, % |\g_@@_y_final_dim|. These variables are global for technical reasons: we have to do an affectation in an -% environment |{pgfpicture}|. +% environment |{tikzpicture}|. % \begin{macrocode} \cs_new_protected:Nn \@@_retrieve_coords:nn - {\begin{tikzpicture}[remember~picture] + {\dim_gzero_new:N \g_@@_x_initial_dim + \dim_gzero_new:N \g_@@_y_initial_dim + \dim_gzero_new:N \g_@@_x_final_dim + \dim_gzero_new:N \g_@@_y_final_dim + \begin{tikzpicture}[remember~picture] \tikz@parse@node\pgfutil@firstofone (nm-\int_use:N \g_@@_env_int- \int_use:N \l_@@_initial_i_int- - \int_use:N \l_@@_initial_j_int.#1) + \int_use:N \l_@@_initial_j_int #1) \dim_gset:Nn \g_@@_x_initial_dim \pgf@x \dim_gset:Nn \g_@@_y_initial_dim \pgf@y \tikz@parse@node\pgfutil@firstofone (nm-\int_use:N \g_@@_env_int- \int_use:N \l_@@_final_i_int- - \int_use:N \l_@@_final_j_int.#2) + \int_use:N \l_@@_final_j_int #2) \dim_gset:Nn \g_@@_x_final_dim \pgf@x \dim_gset:Nn \g_@@_y_final_dim \pgf@y \end{tikzpicture} } +\cs_generate_variant:Nn \@@_retrieve_coords:nn {xx} % \end{macrocode} % % \interitem % \begin{macrocode} -\cs_new_protected:Nn \@@_draw_ldots_line: - {\@@_retrieve_coords:nn {south~east} {south~west} - \@@_draw_tikz_line:} +\cs_new_protected:Nn \@@_draw_Ldots:nn + {\@@_find_extremities_of_line:nnnn {#1} {#2} 0 1 + \@@_if_yet_drawn:F \@@_actually_draw_Ldots:} % \end{macrocode} -% -% \bigskip -% \begin{macrocode} -\cs_new_protected:Nn \@@_draw_cdots_line: - {\@@_retrieve_coords:nn {mid~east} {mid~west} - \@@_draw_tikz_line:} -% \end{macrocode} -% -% \bigskip -% For the vertical dotted lines, there is a problem because we want really vertical lines. If the type of the -% column is |c| (from a type |C| in |{NiceArray}|), all the Tikz nodes of the column have the same $x$-value for the -% anchors |south| and |north|. However, if the type of the column is |l| or |r| (from a type |L| or |R| in -% |{NiceArray}|), the geometric line from the anchors |south| and |north| would probably not be really vertical. -% That's why we need to known the type of the column and that's why we have constructed a token list -% |\g_@@_preamble_tl| to store the types (|l|, |c| or |r|) of all the columns. -% \begin{macrocode} -\cs_new_protected:Nn \@@_draw_vdots_line: - {\@@_retrieve_coords:nn {south} {north} -% \end{macrocode} -% We store in |\t_tmpa_tl| the type of the column (|l|, |c| or |r|). -% \begin{macrocode} - \tl_set:Nx \l_tmpa_tl {\tl_item:Nn \g_@@_preamble_tl \l_@@_initial_j_int} -% \end{macrocode} -% If the column is of type |l|, we will draw the dotted line on the left-most abscissa. +% +% \medskip +% The command |\@@_actually_draw_Ldots:| actually draws the |Ldots| line using |\l_@@_initial_i_int|, +% |\l_@@_initial_j_int|, |\l_@@_initial_open_bool|, |\l_@@_final_i_int|, |\l_@@_final_j_int| and +% |\l_@@_final_open_bool|. We have a dedicated command because if is used also by |\Hdotsfor|. +% \begin{macrocode} +\cs_new_protected:Nn \@@_actually_draw_Ldots: + {\@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.base~west} + {.base~east}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.base~east} + {.base~west}} + \bool_if:NT \l_@@_initial_open_bool + {\dim_gset_eq:NN \g_@@_y_initial_dim \g_@@_y_final_dim } + \bool_if:NT \l_@@_final_open_bool + {\dim_gset_eq:NN \g_@@_y_final_dim \g_@@_y_initial_dim } +% \end{macrocode} +% We raise the line of a quantity equal to the radius of the dots because we want the dots really ``on'' the line +% of texte. +% \begin{macrocode} + \dim_gadd:Nn \g_@@_y_initial_dim {0.53pt} + \dim_gadd:Nn \g_@@_y_final_dim {0.53pt} + \@@_draw_tikz_line:} +% \end{macrocode} +% +% \bigskip +% \begin{macrocode} +\cs_new_protected:Nn \@@_draw_Cdots:nn + {\@@_find_extremities_of_line:nnnn {#1} {#2} 0 1 + \@@_if_yet_drawn:F + {\@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.mid~west} + {.mid~east}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.mid~east} + {.mid~west}} + \bool_if:NT \l_@@_initial_open_bool + {\dim_gset_eq:NN \g_@@_y_initial_dim \g_@@_y_final_dim } + \bool_if:NT \l_@@_final_open_bool + {\dim_gset_eq:NN \g_@@_y_final_dim \g_@@_y_initial_dim } + \@@_draw_tikz_line:}} +% \end{macrocode} +% +% \bigskip +% For the vertical dots, we have to distinguish different instances because we want really vertical lines. Be +% careful: it's not possible to insert the command |\@@_retrieve_coords:nn| in the arguments |T| and |F| of the +% \pkg{expl3} commands (why?). % \begin{macrocode} - \str_if_eq:VnT \l_tmpa_tl {l} - {\dim_set:Nn \g_@@_x_initial_dim {\dim_min:nn \g_@@_x_initial_dim \g_@@_x_final_dim} - \dim_set_eq:NN \g_@@_x_final_dim \g_@@_x_initial_dim} -% \end{macrocode} -% If the column is of type |r|, we will draw the dotted line on the right-most abscissa. +\cs_new_protected:Nn \@@_draw_Vdots:nn + {\@@_find_extremities_of_line:nnnn {#1} {#2} 1 0 + \@@_if_yet_drawn:F + {\@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.north~west} + {.south~west}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.south~west} + {.north~west}} +% \end{macrocode} +% The boolean |\l_tmpa_bool| indicates wether the column is of type |l| (|L| of |{NiceArray}|) or may be considered +% as if. % \begin{macrocode} - \str_if_eq:VnT \l_tmpa_tl {r} - {\dim_set:Nn \g_@@_x_initial_dim {\dim_max:nn \g_@@_x_initial_dim \g_@@_x_final_dim} - \dim_set_eq:NN \g_@@_x_final_dim \g_@@_x_initial_dim} -% \end{macrocode} -% Now, the coordinates of the line to draw are computed in |\g_@@_x_initial_dim|, |\g_@@_y_initial_dim|, -% |\g_@@_x_final_dim| and |\g_@@_y_final_dim|. We can draw the line with |\l_@@_draw_tikz_line:| as usual. + \bool_set:Nn \l_tmpa_bool + {\dim_compare_p:nNn \g_@@_x_initial_dim = \g_@@_x_final_dim} + \@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.north} + {.south}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.south} + {.north}} +% \end{macrocode} +% The boolean |\l_tmpb_bool| indicates wether the column is of type |c| (|C| of |{NiceArray}|) or may be considered +% as if. % \begin{macrocode} - \@@_draw_tikz_line:} + \bool_set:Nn \l_tmpb_bool + {\dim_compare_p:nNn \g_@@_x_initial_dim = \g_@@_x_final_dim} + \bool_if:NF \l_tmpb_bool + {\dim_gset:Nn \g_@@_x_initial_dim + {\bool_if:NTF \l_tmpa_bool \dim_min:nn \dim_max:nn + \g_@@_x_initial_dim \g_@@_x_final_dim} + \dim_gset_eq:NN \g_@@_x_final_dim \g_@@_x_initial_dim} + \@@_draw_tikz_line:}} % \end{macrocode} % % \interitem @@ -2402,8 +3117,15 @@ version 2005/12/01 or later. % lines. The first diagonal line is drawn and then, all the other diagonal lines are drawn parallel to the first % one. % \begin{macrocode} -\cs_new_protected:Nn \@@_draw_ddots_line: - {\@@_retrieve_coords:nn {south~east} {north~west} +\cs_new_protected:Nn \@@_draw_Ddots:nn + {\@@_find_extremities_of_line:nnnn {#1} {#2} 1 1 + \@@_if_yet_drawn:F + {\@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.north~west} + {.south~east}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.south~east} + {.north~west}} % \end{macrocode} % We have retrieved the coordinates in the usual way (they are stored in |\g_@@_x_initial_dim|, etc.). % If the parallelization of the diagonals is set, we will have (maybe) to adjust the fourth coordinate. @@ -2431,24 +3153,31 @@ version 2005/12/01 or later. % \end{macrocode} % Now, we can draw the dotted line (after a possible change of |\g_@@_y_initial_dim|). % \begin{macrocode} - \@@_draw_tikz_line:} + \@@_draw_tikz_line:}} % \end{macrocode} % % \bigskip % We draw the |\Iddots| diagonals in the same way. % \begin{macrocode} -\cs_new_protected:Nn \@@_draw_iddots_line: - {\@@_retrieve_coords:nn {south~west} {north~east} - \bool_if:NT \l_@@_parallelize_diags_bool - {\int_incr:N \l_@@_iddots_int - \int_compare:nNnTF \l_@@_iddots_int = 1 - {\dim_set:Nn \l_@@_delta_x_two_dim {\g_@@_x_final_dim - \g_@@_x_initial_dim } - \dim_set:Nn \l_@@_delta_y_two_dim {\g_@@_y_final_dim - \g_@@_y_initial_dim }} - {\dim_gset:Nn \g_@@_y_final_dim - {\g_@@_y_initial_dim + - (\g_@@_x_final_dim - \g_@@_x_initial_dim) - * \dim_ratio:nn \l_@@_delta_y_two_dim \l_@@_delta_x_two_dim }}} - \@@_draw_tikz_line:} +\cs_new_protected:Nn \@@_draw_Iddots:nn + {\@@_find_extremities_of_line:nnnn {#1} {#2} 1 {-1} + \@@_if_yet_drawn:F + {\@@_retrieve_coords:xx {\bool_if:NTF \l_@@_initial_open_bool + {-medium.north~east} + {.south~west}} + {\bool_if:NTF \l_@@_final_open_bool + {-medium.south~west} + {.north~east}} + \bool_if:NT \l_@@_parallelize_diags_bool + {\int_incr:N \l_@@_iddots_int + \int_compare:nNnTF \l_@@_iddots_int = 1 + {\dim_set:Nn \l_@@_delta_x_two_dim {\g_@@_x_final_dim - \g_@@_x_initial_dim} + \dim_set:Nn \l_@@_delta_y_two_dim {\g_@@_y_final_dim - \g_@@_y_initial_dim}} + {\dim_gset:Nn \g_@@_y_final_dim + {\g_@@_y_initial_dim + + (\g_@@_x_final_dim - \g_@@_x_initial_dim) + * \dim_ratio:nn \l_@@_delta_y_two_dim \l_@@_delta_x_two_dim }}} + \@@_draw_tikz_line:}} % \end{macrocode} % % \bigskip @@ -2482,30 +3211,57 @@ version 2005/12/01 or later. % \end{macrocode} % The integer |\l_tmpa_int| is the number of dots of the dotted line. % \begin{macrocode} - {\int_set:Nn \l_tmpa_int {\dim_ratio:nn {\l_@@_l_dim - 0.54em} - {0.45em}} + {\bool_if:NTF \l_@@_initial_open_bool + {\bool_if:NTF \l_@@_final_open_bool + {\int_set:Nn \l_tmpa_int + {\dim_ratio:nn {\l_@@_l_dim} {0.45em}}} + {\int_set:Nn \l_tmpa_int + {\dim_ratio:nn {\l_@@_l_dim - 0.3em} {0.45em}}}} + {\bool_if:NTF \l_@@_final_open_bool + {\int_set:Nn \l_tmpa_int + {\dim_ratio:nn {\l_@@_l_dim - 0.3em} {0.45em}}} + {\int_set:Nn \l_tmpa_int + {\dim_ratio:nn {\l_@@_l_dim - 0.6em} {0.45em}}}} % \end{macrocode} % The dimensions |\l_tmpa_dim| and |\l_tmpb_dim| are the coordinates of the vector between two dots in the % dotted line. % \begin{macrocode} - \dim_set:Nn \l_tmpa_dim { (\g_@@_x_final_dim - \g_@@_x_initial_dim) + \dim_set:Nn \l_tmpa_dim {(\g_@@_x_final_dim - \g_@@_x_initial_dim) * \dim_ratio:nn {0.45em} \l_@@_l_dim} - \dim_set:Nn \l_tmpb_dim { (\g_@@_y_final_dim - \g_@@_y_initial_dim) + \dim_set:Nn \l_tmpb_dim {(\g_@@_y_final_dim - \g_@@_y_initial_dim) * \dim_ratio:nn {0.45em} \l_@@_l_dim} % \end{macrocode} +% +% The length $\ell$ is the length of the dotted line. We note $\Delta$ the length between two dots and $n$ the +% number of intervals between dots. We note $\delta = \frac12(\ell - n \Delta)$. +% The distance between the initial extremity of the line and the first dot will be equal to $k\cdot\delta$ where +% $k=0$, $1$ or $2$. We first compute this number $k$ in |\l_tmpb_int|. +% \begin{macrocode} + \int_set:Nn \l_tmpb_int + {\bool_if:NTF \l_@@_initial_open_bool + {\bool_if:NTF \l_@@_final_open_bool 1 0} + {\bool_if:NTF \l_@@_final_open_bool 2 1}} +% \end{macrocode} % In the loop over the dots (|\int_step_inline:nnnn|), the dimensions |\g_@@_x_initial_dim| and -% |\g_@@_y_initial_dim| will be used for the coordinates of the dots. +% |\g_@@_y_initial_dim| will be used for the coordinates of the dots. But, before the loop, we must move until the +% first dot. +% % \begin{macrocode} \dim_gadd:Nn \g_@@_x_initial_dim - { (\g_@@_x_final_dim - \g_@@_x_initial_dim) + { (\g_@@_x_final_dim - \g_@@_x_initial_dim) * \dim_ratio:nn {\l_@@_l_dim - 0.45 em * \l_tmpa_int} - {\l_@@_l_dim * 2}} + {\l_@@_l_dim * 2} + * \l_tmpb_int} +% \end{macrocode} +% (In a multiplication of a dimension and an integer, the integer must always be put in second position.) +% \begin{macrocode} \dim_gadd:Nn \g_@@_y_initial_dim - { (\g_@@_y_final_dim - \g_@@_y_initial_dim) + { (\g_@@_y_final_dim - \g_@@_y_initial_dim) * \dim_ratio:nn {\l_@@_l_dim - 0.45 em * \l_tmpa_int} - {\l_@@_l_dim * 2}} + {\l_@@_l_dim * 2} + * \l_tmpb_int} \begin{tikzpicture}[overlay] - \int_step_inline:nnn 0 \l_tmpa_int + \int_step_inline:nnnn 0 1 \l_tmpa_int { \pgfpathcircle{\pgfpoint{\g_@@_x_initial_dim} {\g_@@_y_initial_dim}} {0.53pt} @@ -2544,7 +3300,7 @@ version 2005/12/01 or later. % \pkg{nicematrix} rely upon |{NiceArray}|). % \begin{macrocode} \NewDocumentCommand \@@_Ldots {s} - {\IfBooleanF {#1} {\@@_instruction_of_type:n 0} + {\bool_if:nF {#1} {\@@_instruction_of_type:n {Ldots}} \bool_if:NF \l_@@_nullify_dots_bool {\phantom \@@_ldots} \@@_add_to_empty_cells:} % \end{macrocode} @@ -2552,7 +3308,7 @@ version 2005/12/01 or later. % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_Cdots {s} - {\IfBooleanF {#1} {\@@_instruction_of_type:n 1} + {\bool_if:nF {#1} {\@@_instruction_of_type:n {Cdots}} \bool_if:NF \l_@@_nullify_dots_bool {\phantom \@@_cdots} \@@_add_to_empty_cells:} % \end{macrocode} @@ -2560,7 +3316,7 @@ version 2005/12/01 or later. % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_Vdots {s} - {\IfBooleanF {#1} {\@@_instruction_of_type:n 2} + {\bool_if:nF {#1} {\@@_instruction_of_type:n {Vdots}} \bool_if:NF \l_@@_nullify_dots_bool {\phantom \@@_vdots} \@@_add_to_empty_cells:} % \end{macrocode} @@ -2568,7 +3324,7 @@ version 2005/12/01 or later. % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_Ddots {s} - {\IfBooleanF {#1} {\@@_instruction_of_type:n 3} + {\bool_if:nF {#1} {\@@_instruction_of_type:n {Ddots}} \bool_if:NF \l_@@_nullify_dots_bool {\phantom \@@_ddots} \@@_add_to_empty_cells:} % \end{macrocode} @@ -2576,7 +3332,7 @@ version 2005/12/01 or later. % \bigskip % \begin{macrocode} \NewDocumentCommand \@@_Iddots {s} - {\IfBooleanF {#1} {\@@_instruction_of_type:n 4} + {\bool_if:nF {#1} {\@@_instruction_of_type:n {Iddots}} \bool_if:NF \l_@@_nullify_dots_bool {\phantom \@@_iddots} \@@_add_to_empty_cells:} % \end{macrocode} @@ -2590,47 +3346,73 @@ version 2005/12/01 or later. \hspace} % \end{macrocode} % +% % \bigskip -% The command |\@@_NiceMatrixEndPoint:| will be linked to |\NiceMatrixEndPoint| in |{NiceArray}|. +% In the environment |{NiceArray}|, the command |\multicolumn| will be linked to the following command +% |\@@_multicolumn:nnn|. % \begin{macrocode} -\cs_new_protected:Nn \@@_NiceMatrixEndPoint: - {\kern 0.5pt} +\cs_set_eq:NN \@@_old_multicolumn \multicolumn +\cs_new:Nn \@@_multicolumn:nnn + {\@@_old_multicolumn{#1}{#2}{#3} + \int_compare:nNnT #1 > 1 + {\seq_gput_left:Nx \g_@@_multicolumn_cells_seq + {\int_eval:n {\g_@@_row_int} - + \int_use:N \g_@@_column_int} + \seq_gput_left:Nn \g_@@_multicolumn_sizes_seq {#1}} + \int_gadd:Nn \g_@@_column_int {#1-1}} % \end{macrocode} % +% % \bigskip -% The command |\@@_Hdotsfor| will be linked to |\Hdotsfor| in |{NiceArray}|. This command uses an optionnal +% The command |\@@_Hdotsfor| will be linked to |\Hdotsfor| in |{NiceArray}|. This command uses an optional % argument like |\hdotsfor| but this argument is discarded (in |\hdotsfor|, this argument is used for fine tuning % of the space beetween two consecutive dots). +% Tikz nodes are created for all the cells of the array, even the implicit cells of the |\Hdotsfor|. % \begin{macrocode} -\NewDocumentCommand \@@_Hdotsfor {O{} m} +\NewDocumentCommand {\@@_Hdotsfor} {O{} m} + {\tl_gput_right:Nx \g_@@_lines_to_draw_tl + {\exp_not:N \@@_draw_Hdotsfor:nnn + {\int_use:N \g_@@_row_int} + {\int_use:N \g_@@_column_int} + {#2}} + \prg_replicate:nn {#2-1} {&}} % \end{macrocode} -% First, we store in the |code-after| (that is in |\g_@@_code_after_tl|) a command |\line| to draw the dotted line -% after the construction of the matrix. +% +% \medskip % \begin{macrocode} - {\int_set:Nn \l_tmpa_int {\g_@@_column_int - 1} - \int_set:Nn \l_tmpb_int {\g_@@_column_int + #2} - \tl_gput_right:Nx \g_@@_code_after_tl - {\exp_not:N \line {\int_use:N\g_@@_row_int-\int_use:N\l_tmpa_int} - {\int_use:N\g_@@_row_int-\int_use:N\l_tmpb_int}} +\cs_new_protected:Nn \@@_draw_Hdotsfor:nnn + {\bool_set_false:N \l_@@_initial_open_bool + \bool_set_false:N \l_@@_final_open_bool % \end{macrocode} -% Then, we insert the correct number of ampersands (|&|). +% For the row, it's easy. % \begin{macrocode} - \prg_replicate:nn {#2-1} {&}} + \int_set:Nn \l_@@_initial_i_int {#1} + \int_set:Nn \l_@@_final_i_int {#1} % \end{macrocode} -% Tikz nodes are created for all the cells of the array, even the implicit cells of the |\Hdotsfor|. -% -% \subsection{We process the options} -% -% We process the options when the package is loaded (with |\usepackage|) but we recommend to use -% |\NiceMatrixOptions| instead. -% -% We must process these options after the definition of the environment |{NiceMatrix}| because the option -% |renew-matrix| execute the code |\cs_set_eq:NN \env@matrix \NiceMatrix|. -% -% Of course, the command |\NiceMatrix| must be defined before such an instruction is executed. +% For the column, it's a bit more complicated. % \begin{macrocode} -\ProcessKeysOptions {NiceMatrix} + \int_compare:nNnTF #2 = 1 + {\int_set:Nn \l_@@_initial_j_int 1 + \bool_set_true:N \l_@@_initial_open_bool} + {\int_set:Nn \l_tmpa_int {#2-1} + \@@_if_not_empty_cell:nnTF \l_@@_initial_i_int \l_tmpa_int + {\int_set:Nn \l_@@_initial_j_int {#2-1}} + {\int_set:Nn \l_@@_initial_j_int {#2} + \bool_set_true:N \l_@@_initial_open_bool}} + \int_compare:nNnTF {#2+#3-1} = \g_@@_column_int + {\int_set:Nn \l_@@_final_j_int {#2+#3-1} + \bool_set_true:N \l_@@_final_open_bool} + {\int_set:Nn \l_tmpa_int {#2+#3} + \@@_if_not_empty_cell:nnTF \l_@@_final_i_int \l_tmpa_int + {\int_set:Nn \l_@@_final_j_int {#2+#3}} + {\int_set:Nn \l_@@_final_j_int {#2+#3-1} + \bool_set_true:N \l_@@_final_open_bool}} + \bool_if:nT {\l_@@_initial_open_bool || \l_@@_final_open_bool} + \@@_create_extra_nodes: + \@@_actually_draw_Ldots:} % \end{macrocode} +% +% % % \subsection{The command \textbackslash line accessible in code-after} % @@ -2657,54 +3439,7 @@ version 2005/12/01 or later. % The commands |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, |\Iddots| don't use this command because they have to do % other settings (for example, the diagonal lines must be parallelized). % -% \subsection{The error messages} -% \begin{macrocode} -\msg_new:nnnn {nicematrix} - {Impossible~instruction} - {It's~not~possible~to~execute~the~instruction~ - \int_case:nn \l_@@_type_int - {0 {\token_to_str:N \Ldots} - 1 {\token_to_str:N \Cdots} - 2 {\token_to_str:N \Vdots} - 3 {\token_to_str:N \Ddots}}~in~the~row~\int_use:N\l_@@_row_int\ - ~and~the~column~\int_use:N\l_@@_column_int\space of~the~matrix~ - because~it's~impossible~to~find~one~of~its~extremities~ - (both~extremities~must~be~non~empty~cells~of~the~matrix).~ - If~you~go~on,~the~instruction~will~be~ignored.} - {You~can~specify~an~end~of~line~on~a~empty~cell~ - with~\token_to_str:N \NiceMatrixEndPoint.} -% \end{macrocode} -% -% \begin{macrocode} -\msg_new:nnn {nicematrix} - {Multicolumn~forbidden} - {The~command~\token_to_str:N \multicolumn\ - is~forbidden~in~the~environment~\{\@currenvir\}~ - and~its~variants.~The~command~\token_to_str:N \hdotsfor\ - of~amsmath~is~also~forbidden~since~it~uses~ - \token_to_str:N \multicolumn\ ~(but~you~can~use~\token_to_str:N \Hdotsfor\ - ~instead).~You~can~go~on~but~your~matrix~may~be~wrong.} -% \end{macrocode} -% -% \begin{macrocode} -\msg_new:nnn {nicematrix} - {We~are~yet~in~an~environment~NiceArray} - {Environments~\{NiceArray\}~(or~\{NiceMatrix\},~etc.)~can't~be~ - nested.~We~can~go~on,~but,~maybe,~you~will~have~errors~or~an~incorrect~ - result.} -% \end{macrocode} % -% \begin{macrocode} -\msg_new:nnnn {nicematrix} - {Duplicate~name} - {The~name~"#1"~is~already~used~and~you~shouldn't~use~ - the~same~environment~name~twice.~You~can~go~on,~but,~ - maybe,~you~will~have~incorrect~results~especially~ - if~you~use~"columns-width=auto".\\ - For~a~list~of~the~names~already~used,~type~H~.} - {The~names~already~defined~in~this~document~are:~ - \seq_use:Nnnn~\g_@@_names_seq~{,~} {,~} {~and~}.} -% \end{macrocode} % % \subsection{The environment \{NiceMatrixBlock\}} % @@ -2718,9 +3453,10 @@ version 2005/12/01 or later. % As of now, there is only one option available for the environment |{NiceMatrixBlock}|. % \begin{macrocode} \keys_define:nn {NiceMatrix/NiceMatrixBlock} - {auto-columns-width .code:n = {\bool_set_true:N \l_@@_block_auto_columns_width_bool - \dim_gzero_new:N \g_@@_max_cell_width_dim - \bool_set_true:N \l_@@_auto_columns_width_bool}} + {auto-columns-width .code:n = + {\bool_set_true:N \l_@@_block_auto_columns_width_bool + \dim_gzero_new:N \g_@@_max_cell_width_dim + \bool_set_true:N \l_@@_auto_columns_width_bool}} % \end{macrocode} % % \bigskip @@ -2738,9 +3474,9 @@ version 2005/12/01 or later. % \begin{macrocode} {\bool_if:NT \l_@@_block_auto_columns_width_bool {\iow_now:Nn \@mainaux {\ExplSyntaxOn} - \int_step_inline:nnn \l_@@_first_env_block_int \g_@@_env_int + \int_step_inline:nnnn \l_@@_first_env_block_int 1 \g_@@_env_int {\iow_now:Nx \@mainaux - {\cs_gset:cpn {_@@_max_cell_width_##1} + {\cs_gset:cpn {@@_max_cell_width_##1} {\dim_use:N \g_@@_max_cell_width_dim}}} \iow_now:Nn \@mainaux {\ExplSyntaxOff}}} % \end{macrocode} @@ -2769,16 +3505,22 @@ version 2005/12/01 or later. {\dim_set:Nn \l_@@_columns_width_dim {#1}}, columns-width .value_required:n = true, name .code:n = {\seq_if_in:NnTF \g_@@_names_seq {#1} - {\msg_error:nnn {nicematrix} - {Duplicate~name} - {#1}} + {\@@_msg_error:nn {Duplicate~name} {#1}} {\seq_gput_left:Nn \g_@@_names_seq {#1}} - \tl_gset:Nn \g_@@_name_tl {#1}}, + \tl_set:Nn \l_@@_name_tl {#1}}, name .value_required:n = true, - code-after .tl_gset:N = \g_@@_code_after_tl, - code-after .initial:n = \c_empty_tl, + code-after .tl_set:N = \l_@@_code_after_tl, + code-after .initial:n = \c_empty_tl, code-after .value_required:n = true, - unknown .code:n = \msg_error:nn {nicematrix} {Unknown~option~for~NiceArrayC}} + create-extra-nodes .bool_set:N = \l_@@_extra_nodes_bool, + create-extra-nodes .default:n = true, + left-margin .dim_set:N = \l_@@_left_margin_dim, + left-margin .default:n = \arraycolsep, + right-margin .dim_set:N = \l_@@_right_margin_dim, + right-margin .default:n = \arraycolsep, + extra-left-margin .dim_set:N = \l_@@_extra_left_margin_dim, + extra-right-margin .dim_set:N = \l_@@_extra_right_margin_dim, + unknown .code:n = \@@_msg_error:n {Unknown~option~for~NiceArrayC}} % \end{macrocode} % % \begin{macrocode} @@ -2792,10 +3534,15 @@ version 2005/12/01 or later. code-after,~ code-for-last-col,~ columns-width,~ + create-extra-nodes,~ + extra-left-margin,~ + extra-right-margin,~ + left-margin,~ name,~ nullify-dots,~ parallelize-diags~ - and~renew-dots.} + renew-dots~ + and~right-margin.} % \end{macrocode} % % \bigskip @@ -2809,7 +3556,7 @@ version 2005/12/01 or later. % |{NiceArrayRCwithDelims}|. % \begin{macrocode} \cs_new_protected:Nn \@@_NiceArrayC:n - { + {\bool_set_true:N \l_@@_exterior_column_bool \begin{NiceArray} % \end{macrocode} % The beginning of the preamble is the argument of the environment |{pNiceArrayC}|. @@ -2822,21 +3569,18 @@ version 2005/12/01 or later. % |\hbox_set:Nw \l_tmpa_box| ... |\hbox_set_end:|. % \begin{macrocode} >{\int_gincr:N \g_@@_column_int + \int_gset:Nn \g_@@_column_total_int + {\int_max:nn \g_@@_column_total_int \g_@@_column_int} \hbox_set:Nw \l_tmpa_box - \tl_if_empty:NTF \g_@@_name_tl - {\tikz[remember~picture, inner~sep = 0pt, minimum~width = 0pt, baseline] - \node [anchor=base, - name = nm-\int_use:N \g_@@_env_int- - \int_use:N \g_@@_row_int- - \int_use:N \g_@@_column_int] } - {\tikz[remember~picture, inner~sep = 0pt, minimum~width = 0pt, baseline] + \tikz[remember~picture, inner~sep=0pt, minimum~width=0pt, baseline] \node [anchor=base, name = nm-\int_use:N \g_@@_env_int- \int_use:N \g_@@_row_int- \int_use:N \g_@@_column_int, - alias = \g_@@_name_tl- - \int_use:N \g_@@_row_int- - \int_use:N \g_@@_column_int] } + alias = \tl_if_empty:NF \l_@@_name_tl + {\l_@@_name_tl- + \int_use:N \g_@@_row_int- + \int_use:N \g_@@_column_int}] \bgroup $ % $ \l_@@_code_for_last_col_tl } @@ -2852,25 +3596,24 @@ version 2005/12/01 or later. \dim_gset:Nn \g_@@_width_last_col_dim {\dim_max:nn \g_@@_width_last_col_dim {\box_wd:N \l_tmpa_box}} - \tl_gput_right:Nn \g_@@_preamble_aux_tl {#1} \skip_horizontal:n {-2\arraycolsep} % \end{macrocode} % The content of the cell is inserted in an overlapping position. % \begin{macrocode} \hbox_overlap_right:n - {\skip_horizontal:n {2\arraycolsep} + {\skip_horizontal:n + { 2\arraycolsep + \l_@@_right_margin_dim + + \l_@@_extra_right_margin_dim} \box_use:N \l_tmpa_box}}}} % \end{macrocode} % This ends the preamble of the array that will be constructed (a rather long preamble, indeed). % % \bigskip -% All the environments of the type of |{pNiceArrayC}| will be constructed over |{NiceArrayCwithDelims}|. The first +% The environments of the type of |{pNiceArrayC}| will be constructed over |{NiceArrayCwithDelims}|. The first % two arguments of this environment are the left and the right delimiter. % \begin{macrocode} \NewDocumentEnvironment{NiceArrayCwithDelims} {mm O{} m O{}} - {\bool_set_false:N \l_@@_direct_NiceArray_bool - \tl_gclear:N \g_@@_code_after_tl - \dim_gzero_new:N \g_@@_width_last_col_dim + {\dim_gzero_new:N \g_@@_width_last_col_dim \keys_set:nn {NiceMatrix/NiceArrayC} {#3,#5} \bool_set_false:N \l_@@_exterior_arraycolsep_bool \tl_set:Nn \l_@@_pos_env_tl c @@ -2921,64 +3664,6 @@ version 2005/12/01 or later. % % The code in this section can be removed without affecting the previous code. % -% \medskip -% -% If the environment is used with the option |columns-width=auto|, the construction -% -% \begin{Verbatim} -% \begin{pNiceArrayRC}{~slshape#preamble@}[columns-width=auto] -% ~slshape#first row@ \\ -% ~slshape#second row@ \\ -% ~slshape#third row@ \\ -% ~slshape#etc.@ \\ -% \end{pNiceArrayRC} -% \end{Verbatim} -% -% is transformed in the following construction : -% -% \begin{Verbatim} -% \begin{NiceMatrixBlock}[auto-columns-width] -% \vbox{\hbox{\hphantom{~slshape#an open parenthesis@} -% $\begin{NiceArray}{~slshape#preamble@} -% ~slshape#first row@ \\ -% \end{NiceArray}$} -% \hbox{$\begin{pNiceArrayC}{~slshape#preamble@} -% ~slshape#second row@ \\ -% ~slshape#third row@ \\ -% ~slshape#etc.@ \\ -% \end{pNiceArrayC}$}} -% \end{NiceMatrixBlock} -% \end{Verbatim} -% -% -% \bigskip -% If the environment is used with a numerical value for the option |columns-width|, the construction -% -% \begin{Verbatim} -% \begin{pNiceArrayRC}{~slshape#preamble@}[columns-width=~slshape#value@] -% ~slshape#first row@ \\ -% ~slshape#second row@ \\ -% ~slshape#third row@ \\ -% ~slshape#etc.@ \\ -% \end{pNiceArrayRC} -% \end{Verbatim} -% -% is transformed in the following contruction : -% -% \begin{Verbatim} -% \NiceMatrixOptions{columns-width=~slshape#value@} -% \vbox{\hbox{~slshape#skip of the width of a parenthesis@ -% $\begin{NiceArray}{~slshape#preamble@} -% ~slshape#first row@ \\ -% \end{NiceArray}$} -% \hbox{$\begin{pNiceArrayC}{~slshape#preamble@} -% ~slshape#second row@ \\ -% ~slshape#third row@ \\ -% ~slshape#etc.@ \\ -% \end{pNiceArrayC}$}} -% \end{Verbatim} -% -% (in the group created by the environment). % % \bigskip % \begin{macrocode} @@ -2992,15 +3677,25 @@ version 2005/12/01 or later. code-for-first-row .tl_set:N = \l_@@_code_for_first_row_tl, code-for-last-col .tl_set:N = \l_@@_code_for_last_col_tl, code-for-last-col .value_required:n = true, - columns-width .tl_set:N = \l_@@_columns_width_tl, + columns-width .code:n = \str_if_eq:nnTF {#1} {auto} + {\bool_set_true:N + \l_@@_auto_columns_width_bool} + {\dim_set:Nn \l_@@_columns_width_dim {#1}}, + columns-width .value_required:n = true, name .code:n = {\seq_if_in:NnTF \g_@@_names_seq {#1} - {\msg_error:nnn {nicematrix} - {Duplicate~name} - {#1}} + {\@@_msg_error:nn {Duplicate~name} {#1}} {\seq_gput_left:Nn \g_@@_names_seq {#1}} - \tl_gset:Nn \l_@@_name_tl {#1}}, - code-after .tl_set:N = \l_@@_code_after_tl, - unknown .code:n = \msg_error:nn {nicematrix} {Unknown~option~for~NiceArrayRC}} + \tl_set:Nn \l_@@_name_tl {#1}}, + code-after .tl_set:N = \l_@@_code_after_tl, + create-extra-nodes .bool_set:N = \l_@@_extra_nodes_bool, + create-extra-nodes .default:n = true, + left-margin .dim_set:N = \l_@@_left_margin_dim, + left-margin .default:n = \arraycolsep, + right-margin .dim_set:N = \l_@@_right_margin_dim, + right-margin .default:n = \arraycolsep, + extra-left-margin .dim_set:N = \l_@@_extra_left_margin_dim, + extra-right-margin .dim_set:N = \l_@@_extra_right_margin_dim, + unknown .code:n = \@@_msg_error:n {Unknown~option~for~NiceArrayRC}} % \end{macrocode} % % \begin{macrocode} @@ -3014,83 +3709,55 @@ version 2005/12/01 or later. code-after,~ code-for-last-col,~ code-for-first-row,~ - columns-width~(in~fact~mandatory),~ + columns-width,~ + create-extra-nodes,~ + extra-left-margin,~ + extra-right-margin,~ + left~margin,~ name,~ nullify-dots,~ - parallelize-diags~ - and~renew-dots.} + parallelize-diags,~ + renew-dots~ + and~right~margin.} % \end{macrocode} % -% \begin{macrocode} -\msg_new:nnn {nicematrix} - {The~key~columns-width~is~mandatory} - {In~the~environment~\{\@currenvir\}~you~must~use~the~ - key~"columns-width"~either~with~a~numerical~value~ - or~the~special~value~"auto".\\ - If~you~go~on,~the~value~"auto"~will~be~used~for~ - "columns-width".} -% \end{macrocode} % % The first and the second argument of the environment |{NiceArrayRCwithDelims}| are the delimiters which will be % used in the array. Usually, the final user will not use directly this environment |{NiceArrayRCwithDelims}| % because he will use one of the variants |{pNiceArrayRC}|, |{vNiceArrayRC}|, etc. +% % \begin{macrocode} -\NewDocumentEnvironment{NiceArrayRCwithDelims} {mm O{} m O{}} - {\tl_clear_new:N \l_@@_columns_width_tl - \tl_clear_new:N \l_@@_name_tl - \tl_clear_new:N \l_@@_code_after_tl - \keys_set:nn {NiceMatrix/NiceArrayRC} {#3,#5} - \tl_gset_eq:NN \g_@@_name_tl \l_@@_name_tl - \tl_if_empty:NT \l_@@_columns_width_tl - {\msg_error:nn {nicematrix} {The~key~columns-width~is~mandatory} - \tl_set:Nn \l_@@_columns_width_tl {auto}} - \str_if_eq:nVTF {auto} \l_@@_columns_width_tl - {\begin{NiceMatrixBlock}[auto-columns-width]} - {\NiceMatrixOptions{columns-width = \l_@@_columns_width_tl} } - \vbox\bgroup\hbox\bgroup -% \end{macrocode} -% Here, it would be possible to use a |\hphantom| but we prefer to use \pkg{expl3} instructions. -% \begin{macrocode} - \hbox_set:Nn \l_tmpa_box {$\left#1\vbox_to_ht:nn{2cm}{}\right.$} - \skip_horizontal:n {\box_wd:N \l_tmpa_box - \nulldelimiterspace} -% \end{macrocode} -% We give the value $-1$ to |\l_@@_number_of_first_row_int| and, therefore, the first row of the array will have -% the number $0$ (the final user will use this value when using, for example, the command |\line| in |code-after|). -% \begin{macrocode} - \int_set:Nn \l_@@_number_of_first_row_int {-1} - \tl_set_eq:NN \l_@@_code_for_cell_tl \l_@@_code_for_first_row_tl -% \end{macrocode} -% We read staticly the first row of the array given by the user because we will use the first row to -% construct an environment |{NiceArray}|. \emph{We read until the first control sequence} |\\|. Therefore, it's not -% possible to use a sub-array with this control sequence in the first row of the array. -% \begin{macrocode} - \cs_set:Npn \@@_replace_first_line ##1\\{ - $\begin{NiceArray}{*\c@MaxMatrixCols{C}} - ##1 - \end{NiceArray}$ - \egroup \hbox\bgroup -% \end{macrocode} -% We decrement the number of the environment because we want the same number for both constructed environments. -% \begin{macrocode} - \int_gdecr:N \g_@@_env_int - \tl_gset_eq:NN \g_@@_name_tl \l_@@_name_tl - \tl_gset_eq:NN \g_@@_code_after_tl \l_@@_code_after_tl - \bool_set_false:N \l_@@_direct_NiceArray_bool - \dim_gzero_new:N \g_@@_width_last_col_dim - \bool_set_false:N \l_@@_exterior_arraycolsep_bool - \tl_set:Nn \l_@@_pos_env_tl c - $\left#1 % $ +\NewDocumentEnvironment {NiceArrayRCwithDelims} {mm O{} m O{}} + {\int_zero:N \l_@@_nb_first_row_int + \dim_gzero_new:N \g_@@_width_last_col_dim + \keys_set:nn {NiceMatrix/NiceArrayRC} {#3,#5} + \bool_set_false:N \l_@@_exterior_arraycolsep_bool + \tl_set:Nn \l_@@_pos_env_tl c + \box_clear_new:N \l_@@_the_array_box + \hbox_set:Nw \l_@@_the_array_box + $ % $ \@@_NiceArrayC:n {#4}} - \@@_replace_first_line + { \end{NiceArray} + $ % $ + \hbox_set_end: + \dim_set:Nn \l_tmpa_dim + { ( \dim_max:nn {12pt} + {\g_@@_max_ht_row_one_dim + \g_@@_max_dp_row_zero_dim}) + + \g_@@_max_ht_row_zero_dim + - \g_@@_max_ht_row_one_dim } + \hbox_set:Nn \l_tmpa_box + {$ % $ + \left#1 + \vcenter {\skip_vertical:n {- \l_tmpa_dim} + \box_use_drop:N \l_@@_the_array_box} + \right#2 + $ % $ + \skip_horizontal:n \g_@@_width_last_col_dim} + \box_set_ht:Nn \l_tmpa_box {\box_ht:N \l_tmpa_box + \l_tmpa_dim} + \box_use_drop:N \l_tmpa_box } - {\end{NiceArray} - \right#2$ % $ - \skip_horizontal:n \g_@@_width_last_col_dim - \egroup\egroup - \str_if_eq:nVT {auto} \l_@@_columns_width_tl - {\end{NiceMatrixBlock}} } % \end{macrocode} -% +% % \bigskip % In the following environments, we don't use the form with |\begin{...}| and |\end{...}| because we use % |\@currenvir| in the error message for an unknown option. @@ -3125,13 +3792,256 @@ version 2005/12/01 or later. % \end{macrocode} % % +% \subsection{The extra nodes} +% +% First, two variants of the functions |\dim_min:nn| and |\dim_max:nn|. +% \begin{macrocode} +\cs_generate_variant:Nn \dim_min:nn {vn} +\cs_generate_variant:Nn \dim_max:nn {vn} +% \end{macrocode} +% +% +% +% \bigskip +% For each row $i$, we compute two dimensions \texttt{l_@@_row_\textsl{i}_min_dim} and +% \texttt{l_@@_row_\textsl{i}_max_dim}. The dimension \texttt{l_@@_row_\textsl{i}_min_dim} is the minimal +% $y$-value of all the cells of the row~$i$. The dimension \texttt{l_@@_row_\textsl{i}_max_dim} is the maximal +% $y$-value of all the cells of the row~$i$. +% +% Similarly, for each column $j$, we compute two dimensions \texttt{l_@@_column_\textsl{j}_min_dim} and +% \texttt{l_@@_column_\textsl{j}_max_dim}. The dimension \texttt{l_@@_column_\textsl{j}_min_dim} is the minimal +% $x$-value of all the cells of the column~$j$. The dimension \texttt{l_@@_column_\textsl{j}_max_dim} is the maximal +% $x$-value of all the cells of the column~$j$. +% +% Since these dimensions will be computed as maximum or minimum, we initialize them to |\c_max_dim| or |-\c_max_dim|. +% \begin{macrocode} +\cs_new_protected:Nn \@@_create_extra_nodes: + {\begin{tikzpicture}[remember~picture,overlay] + \int_step_variable:nnnNn \l_@@_nb_first_row_int 1 \g_@@_row_int \@@_i + {\dim_zero_new:c {l_@@_row_\@@_i _min_dim} + \dim_set_eq:cN {l_@@_row_\@@_i _min_dim} \c_max_dim + \dim_zero_new:c {l_@@_row_\@@_i _max_dim} + \dim_set:cn {l_@@_row_\@@_i _max_dim} {-\c_max_dim}} + \int_step_variable:nnnNn 1 1 \g_@@_column_total_int \@@_j + {\dim_zero_new:c {l_@@_column_\@@_j _min_dim} + \dim_set_eq:cN {l_@@_column_\@@_j _min_dim} \c_max_dim + \dim_zero_new:c {l_@@_column_\@@_j _max_dim} + \dim_set:cn {l_@@_column_\@@_j _max_dim} {-\c_max_dim}} +% \end{macrocode} +% We begin the two nested loops over the rows and the columns of the array. +% \begin{macrocode} + \int_step_variable:nnnNn \l_@@_nb_first_row_int 1 \g_@@_row_int \@@_i + {\int_step_variable:nnnNn 1 1 \g_@@_column_total_int \@@_j +% \end{macrocode} +% Maybe the cell ($i$-$j$) is an implicit cell (that is to say a cell after implicit ampersands |&|). In this case, +% of course, we don't update the dimensions we want to compute. +% \begin{macrocode} + {\cs_if_exist:cT {pgf@sh@ns@nm-\int_use:N \g_@@_env_int-\@@_i-\@@_j} +% \end{macrocode} +% We retrieve the coordinates of the anchor |south west| of the (normal) node of the cell ($i$-$j$). They will be +% stored in |\pgf@x| and |\pgf@y|. +% \begin{macrocode} + {\tikz@parse@node \pgfutil@firstofone + (nm-\int_use:N \g_@@_env_int-\@@_i-\@@_j.south~west) + \dim_set:cn {l_@@_row_\@@_i _min_dim} + {\dim_min:vn {l_@@_row_\@@_i _min_dim} \pgf@y} + \seq_if_in:NxF \g_@@_multicolumn_cells_seq {\@@_i-\@@_j} + {\dim_set:cn {l_@@_column_\@@_j _min_dim} + {\dim_min:vn {l_@@_column_\@@_j _min_dim} \pgf@x}} +% \end{macrocode} +% We retrieve the coordinates of the anchor |north east| of the (normal) node of the cell ($i$-$j$). They will be +% stored in |\pgf@x| and |\pgf@y|. +% \begin{macrocode} + \tikz@parse@node \pgfutil@firstofone + (nm-\int_use:N \g_@@_env_int-\@@_i-\@@_j.north~east) + \dim_set:cn {l_@@_row_\@@_i _max_dim} + {\dim_max:vn {l_@@_row_\@@_i _max_dim} \pgf@y} + \seq_if_in:NxF \g_@@_multicolumn_cells_seq {\@@_i-\@@_j} + {\dim_set:cn {l_@@_column_\@@_j _max_dim} + {\dim_max:vn {l_@@_column_\@@_j _max_dim} \pgf@x}}} + }} +% \end{macrocode} +% Now, we can create the ``medium nodes''. We use a command |\@@_create_nodes:| because this command will also be used +% for the creation of the ``large nodes'' (after changing the value of |name-suffix|). +% \begin{macrocode} + \tikzset{name~suffix = -medium} + \@@_create_nodes: +% \end{macrocode} +% +% \bigskip +% For ``large nodes'', the eventual ``first row'' and ``last column'' (in environments like |{pNiceArrayRC}|) don't +% interfer. That's why the loop over the rows will start at 1 and the loop over the columns will stop at +% $|\g_@@_column_int|$ (and not |\g_@@_column_total_int|).\footnote{We recall that |\g_@@_column_total_int| is +% equal to |\g_@@_column_int| except if there is an exterior column. In this case, |\g_@@_column_total_int| is equal +% to |\g_@@_column_int|${}+1$.} +% \begin{macrocode} + \int_set:Nn \l_@@_nb_first_row_int 1 +% \end{macrocode} +% We have to change the values of all the dimensions \texttt{l_@@_row_\textsl{i}_min_dim}, +% \texttt{l_@@_row_\textsl{i}_max_dim}, \texttt{l_@@_column_\textsl{j}_min_dim} and +% \texttt{l_@@_column_\textsl{j}_max_dim}. +% \begin{macrocode} + \int_step_variable:nnnNn 1 1 {\g_@@_row_int-1} \@@_i + {\dim_set:cn {l_@@_row_\@@_i _min_dim} + {( \dim_use:c {l_@@_row_\@@_i _min_dim} + + \dim_use:c {l_@@_row_\int_eval:n{\@@_i+1}_max_dim}) / 2} + \dim_set_eq:cc {l_@@_row_\int_eval:n{\@@_i+1}_max_dim} + {l_@@_row_\@@_i _min_dim} } + \int_step_variable:nnnNn 1 1 {\g_@@_column_int-1} \@@_j + {\dim_set:cn {l_@@_column_\@@_j _max_dim} + {( \dim_use:c {l_@@_column_\@@_j _max_dim} + + \dim_use:c {l_@@_column_\int_eval:n{\@@_j+1}_min_dim}) / 2} + \dim_set_eq:cc {l_@@_column_\int_eval:n{\@@_j+1}_min_dim} + {l_@@_column_\@@_j _max_dim} } + \dim_sub:cn {l_@@_column_1_min_dim} \g_@@_left_margin_dim + \dim_add:cn {l_@@_column_\int_use:N \g_@@_column_int _max_dim} + \g_@@_right_margin_dim +% \end{macrocode} +% Now, we can actually create the ``large nodes''. +% \begin{macrocode} + \tikzset{name~suffix = -large} + \@@_create_nodes: + \end{tikzpicture} +% \end{macrocode} +% +% \medskip +% When used once, the command |\@@_create_extra_nodes:| must become no-op (in the current TeX group). That's why we +% put a nullification of the command. +% \begin{macrocode} + \cs_set:Nn \@@_create_extra_nodes: {}} +% \end{macrocode} +% +% +% \bigskip +% The control sequence |\@@_create_nodes:| is used twice: for the construction of the ``medium nodes'' and for the +% construction of the ``large nodes''. The nodes are constructed with the value of all the dimensions +% \texttt{l_@@_row_\textsl{i}_min_dim}, \texttt{l_@@_row_\textsl{i}_max_dim}, +% \texttt{l_@@_column_\textsl{j}_min_dim} and \texttt{l_@@_column_\textsl{j}_max_dim}. Between the +% construction of the ``medium nodes'' and the ``large nodes'', the values of these dimensions are changed. +% \begin{macrocode} +\cs_new_protected:Nn \@@_create_nodes: + {\int_step_variable:nnnNn \l_@@_nb_first_row_int 1 \g_@@_row_int \@@_i + {\int_step_variable:nnnNn 1 1 \g_@@_column_total_int \@@_j +% \end{macrocode} +% We create two ponctual nodes for the extremities of a diagonal of the rectangular node we want to create. These +% nodes |(@@~south~west)| and |(@@~north~east)| are not available for the user of \pkg{nicematrix}. That's why +% their names are independent of the row and the column. In the two nested loops, they will be overwritten until the +% last cell. +% \begin{macrocode} + {\coordinate (@@~south~west) + at (\dim_use:c {l_@@_column_\@@_j _min_dim}, + \dim_use:c {l_@@_row_\@@_i _min_dim}) ; + \coordinate (@@~north~east) + at (\dim_use:c {l_@@_column_\@@_j _max_dim}, + \dim_use:c {l_@@_row_\@@_i _max_dim}) ; +% \end{macrocode} +% We can eventually draw the rectangular node for the cell (|\@@_i|-|\@@_j|). This node is created with the Tikz library +% \pkg{fit}. Don't forget that the Tikz option |name suffix| has been set to |-medium| or |-large|. +% \begin{macrocode} + \draw node [fit = {(@@~south~west) (@@~north~east)}, + inner~sep=0pt, + name = nm-\int_use:N \g_@@_env_int-\@@_i-\@@_j, + alias = \tl_if_empty:NF \g_@@_name_tl + {\tl_use:N \g_@@_name_tl-\@@_i-\@@_j}] + {} ; + } + } +% \end{macrocode} +% Now, we create the nodes for the cells of the |\multicolumn|. We recall that we have stored in +% |\g_@@_multicolumn_cells_seq| the list of the cells where a |\multicolumn{|$n$|}{...}{...}| with $n$>1 was issued +% and in |\g_@@_multicolumn_sizes_seq| the correspondant values of $n$. +% \begin{macrocode} + \@@_seq_mapthread_function:NNN \g_@@_multicolumn_cells_seq + \g_@@_multicolumn_sizes_seq + \@@_node_for_multicolumn:nn + } +% \end{macrocode} +% +% +% +% \begin{macrocode} +\cs_set:Npn \@@_extract_coords: #1-#2\q_stop{\cs_set:Npn \@@_i {#1} + \cs_set:Npn \@@_j {#2}} +% \end{macrocode} +% +% The command |\@@_node_for_multicolumn:nn| takes two arguments. The first is the position of the cell where the +% command |\multicolumn{|$n$|}{...}{...}| was issued in the format $i$|-|$j$ and the second is the value of~$n$ (the +% length of the ``multi-cell''). +% \begin{macrocode} +\cs_new_protected:Nn \@@_node_for_multicolumn:nn + {\@@_extract_coords: #1\q_stop + \coordinate (@@~south~west) + at (\dim_use:c {l_@@_column_\@@_j _min_dim}, + \dim_use:c {l_@@_row_\@@_i _min_dim}) ; + \coordinate (@@~north~east) + at (\dim_use:c {l_@@_column_\int_eval:n{\@@_j+#2-1}_max_dim}, + \dim_use:c {l_@@_row_\@@_i _max_dim}) ; + \draw node [fit = {(@@~south~west) (@@~north~east)}, + inner~sep=0pt, + name = nm-\int_use:N \g_@@_env_int-\@@_i-\@@_j, + alias = \tl_if_empty:NF \g_@@_name_tl + {\tl_use:N \g_@@_name_tl-\@@_i-\@@_j}] + {} ; + } +% \end{macrocode} +% +% +% \subsection{We process the options} +% +% We process the options when the package is loaded (with |\usepackage|) but we recommend to use +% |\NiceMatrixOptions| instead. +% +% We must process these options after the definition of the environment |{NiceMatrix}| because the option +% |renew-matrix| execute the code |\cs_set_eq:NN \env@matrix \NiceMatrix|. +% +% Of course, the command |\NiceMatrix| must be defined before such an instruction is executed. +% \begin{macrocode} +\ProcessKeysOptions {NiceMatrix} +% \end{macrocode} +% +% \subsection{Code for \texttt{seq_mapthread_function:NNN}} +% +% In |\@@_create_nodes:| (used twice in |\@@_create_extra_nodes:| to create the ``medium nodes'' and ``large +% nodes''), we want to use |\seq_mapthread_function:NNN| which is in \pkg{l3candidates}). For security, we define a +% function |\@@_seq_mapthread_function:NNN|. We will delete the following code when |\seq_mapthread_function:NNN| +% will be in \pkg{l3seq}. +% \begin{macrocode} +\cs_new:Npn \@@_seq_mapthread_function:NNN #1#2#3 + {\group_begin: +% \end{macrocode} +% In the group, we can use |\seq_pop:NN| safely. +% \begin{macrocode} + \int_step_inline:nnnn 1 1 {\seq_count:N #1} + {\seq_pop:NN #1 \l_tmpa_tl + \seq_pop:NN #2 \l_tmpb_tl + \exp_args:NVV #3 \l_tmpa_tl \l_tmpb_tl} + \group_end: + } +% \end{macrocode} +% +% \begin{macrocode} +\cs_set:Nn \@@_renew_matrix: + {\RenewDocumentEnvironment {pmatrix} {} + {\begin{pNiceMatrix}} + {\end{pNiceMatrix}} + \RenewDocumentEnvironment {vmatrix} {} + {\begin{vNiceMatrix}} + {\end{vNiceMatrix}} + \RenewDocumentEnvironment {Vmatrix} {} + {\begin{VNiceMatrix}} + {\end{VNiceMatrix}} + \RenewDocumentEnvironment {bmatrix} {} + {\begin{bNiceMatrix}} + {\end{bNiceMatrix}} + \RenewDocumentEnvironment {Bmatrix} {} + {\begin{BNiceMatrix}} + {\end{BNiceMatrix}}} +% \end{macrocode} % % \section{History} % % \subsection{Changes between versions 1.0 and 1.1} % -% Option |silent| (with this option, the impossible instructions are discarded silently). -% % The dotted lines are no longer drawn with Tikz nodes but with Tikz circles (for efficiency). % % Modification of the code which is now twice faster. @@ -3144,8 +4054,6 @@ version 2005/12/01 or later. % % New environment |{pNiceArrayC}| and its variants. % -% We decrement |\g_@@_row_int| in |\@@_draw_lines:| to have the exact number of rows. -% % Correction of a bug in the definition of |{BNiceMatrix}|, |{vNiceMatrix}| and |{VNiceMatrix}| (in fact, it was a % typo). % @@ -3166,9 +4074,16 @@ version 2005/12/01 or later. % \subsection{Changes between version 1.4 and 2.0} % % The versions 1.0 to 1.4 of \pkg{nicematrix} were focused on the continuous dotted lines whereas the version 2.0 of -% \pkg{nicematrix} provides differents features to improve the typesetting of mathematical matrices. +% \pkg{nicematrix} provides different features to improve the typesetting of mathematical matrices. +% +% \subsection{Changes between version 2.0 and 2.1} +% +% New implementation of the environment |{pNiceArrayRC}|. With this new implementation, there is no restriction on +% the width of the columns. % +% The package \pkg{nicematrix} no longer loads \pkg{mathtools} but only \pkg{amsmath}. % +% Creation of ``medium nodes'' and ``large nodes''. % \endinput % Local Variables: % TeX-fold-mode: nil diff --git a/Master/texmf-dist/source/latex/nicematrix/nicematrix.ins b/Master/texmf-dist/source/latex/nicematrix/nicematrix.ins index ce8a59e12b8..625f62ef07c 100644 --- a/Master/texmf-dist/source/latex/nicematrix/nicematrix.ins +++ b/Master/texmf-dist/source/latex/nicematrix/nicematrix.ins @@ -1,5 +1,5 @@ %% -%% Copyright (C) 2017 by F. Pantigny +%% Copyright (C) 2017-2018 by F. Pantigny %% %% %% This file may be distributed and/or modified under the @@ -17,7 +17,7 @@ \usedir{tex/latex/nicematrix} \preamble -Copyright (C) 2017 by F. Pantigny +Copyright (C) 2017-2018 by F. Pantigny This file may be distributed and/or modified under the conditions of the LaTeX Project Public License, either -- cgit v1.2.3