From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/nicematrix/nicematrix.dtx | 6391 ++++++++++++++++++++++++
 1 file changed, 6391 insertions(+)
 create mode 100644 macros/latex/contrib/nicematrix/nicematrix.dtx

(limited to 'macros/latex/contrib/nicematrix/nicematrix.dtx')

diff --git a/macros/latex/contrib/nicematrix/nicematrix.dtx b/macros/latex/contrib/nicematrix/nicematrix.dtx
new file mode 100644
index 0000000000..8709af977d
--- /dev/null
+++ b/macros/latex/contrib/nicematrix/nicematrix.dtx
@@ -0,0 +1,6391 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2018-2019 by F. Pantigny
+% -----------------------------------
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either version 1.3
+% of this license or (at your option) any later version.
+% The latest version of this license is in:
+%
+% http://www.latex-project.org/lppl.txt
+%
+% and version 1.3 or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+% \fi
+% \iffalse
+\def\myfileversion{3.0}
+\def\myfiledate{2019/08/15}
+%
+%
+%<*batchfile>
+\begingroup
+\input l3docstrip.tex
+\keepsilent
+\usedir{tex/latex/nicematrix}
+\preamble
+
+Copyright (C) 2018-2019 by F. Pantigny
+-----------------------------------
+
+This file may be distributed and/or modified under the
+conditions of the LaTeX Project Public License, either version 1.3
+of this license or (at your option) any later version.
+The latest version of this license is in:
+
+http://www.latex-project.org/lppl.txt
+
+and version 1.3 or later is part of all distributions of LaTeX
+version 2005/12/01 or later.
+
+\endpreamble
+\askforoverwritefalse
+\endgroup
+%</batchfile>
+%
+%<*driver>
+\documentclass[dvipsnames]{l3doc}% dvipsnames is for xcolor (loaded by Tikz, loaded by nicematrix)
+\VerbatimFootnotes
+\usepackage{xltxtra}
+\usepackage[xetex]{geometry}
+\geometry{left=2.8cm,right=2.8cm,top=2.5cm,bottom=2.5cm,papersize={21cm,29.7cm}}
+
+\usepackage{colortbl}
+\usepackage{nicematrix}
+\usepackage{siunitx}
+
+\newbox\ExampleOne
+
+\setbox\ExampleOne\hbox{$\begin{NiceArray}{|*{4}{C|}}[hlines,first-row,first-col]
+  & e & a & b & c \\
+e & e & a & b & c \\
+a & a & e & c & b \\
+b & b & c & e & a \\
+c & c & b & a & e 
+\end{NiceArray}$}
+
+
+\NewDocumentEnvironment {scope} {} {} {}
+\def\interitem{\vskip 7mm plus 2 mm minus 3mm}          
+\def\emphase{\bgroup\color{RoyalPurple}\let\next=}
+\fvset{commandchars=\~\#\@,formatcom={\color{gray}}}
+\usepackage{titlesec}
+\titlespacing*{\section}{0pt}{6.5ex plus 1ex minus .2ex}{4.3ex plus .2ex}
+\titlespacing*{\subsection}{0pt}{4.5ex plus 1ex minus .2ex}{2ex plus .2ex}
+\usepackage{multicol}
+\usepackage{arydshln}
+\setlength{\columnseprule}{0.4pt}
+\usepackage{footnotehyper}
+\parindent 0pt
+
+\EnableCrossrefs
+\begin{document}
+\DocInput{nicematrix.dtx}
+\end{document}
+%</driver>
+% \fi 
+% \title{The package \pkg{nicematrix}\thanks{This document corresponds to the version~\myfileversion\space of \pkg{nicematrix},
+% at the date of~\myfiledate.}} \author{F. Pantigny \\ \texttt{fpantigny@wanadoo.fr}}
+%
+% \hypersetup{
+%   pdfinfo = {
+%      Title = { The extension 'nicematrix' },
+%      Subject = { A LaTeX extension } ,
+%      Author = { F. Pantigny }
+%   }
+% }
+%
+%
+% \maketitle
+%
+% \begin{abstract}
+% The LaTeX package \pkg{nicematrix} provides new environments similar to the
+% classical environments |{array}| and |{matrix}| but with some additional
+% features. Among these features are the possibilities to fix the width of the
+% columns and to draw continuous ellipsis dots between the cells of the array.
+% \end{abstract}
+%
+% \vspace{1cm}
+% \section{Presentation}
+%
+%
+% 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{amsmath}
+% and \pkg{tikz}. It also loads the Tikz library \pkg{fit}.
+%
+%
+%
+% \medskip
+% \begin{savenotes}
+% \begin{minipage}{0.6\linewidth}
+% This package provides some new tools to draw mathematical matrices. The main
+% features are the following:
+% 
+% \textbullet\ continuous dotted lines\footnote{If the class option |draft| is
+% used, these dotted lines will not be drawn for a faster compilation.};
+%
+% \textbullet\ exterior row and columns for labels;
+%
+% \textbullet\ a control of the width of the columns.
+% \end{minipage}
+% \end{savenotes}
+% \hspace{1.4cm}
+% $\begin{bNiceArray}{CCCC}[first-row,first-col,
+%                           code-for-first-col=\color{blue}\scriptstyle,
+%                           code-for-first-row=\color{blue}\scriptstyle,
+%                           columns-width = auto]
+%        & C_1     & C_2     & \Cdots  & C_n  \\
+% L_1    & a_{11}  & a_{12}  & \Cdots & a_{1n} \\
+% L_2    & a_{21}  & a_{22}  & \Cdots & a_{2n} \\
+% \Vdots & \Vdots & \Vdots & \Ddots & \Vdots\\
+% L_n    & a_{n1}  & a_{n2}  & \Cdots & a_{nn} 
+% \end{bNiceArray}$
+% 
+% \medskip
+% A command |\NiceMatrixOptions| is provided to fix the options (the scope of
+% the options fixed by this command is the current TeX group).
+%
+% 
+% \bigskip
+% \textbf{An example for the continuous dotted lines}
+%
+% \medskip
+% \begin{minipage}{10cm}
+% For example, consider the following code which uses an environment |{pmatrix}|
+% of \pkg{amsmath}.
+%
+% \smallskip
+% \begin{BVerbatim}
+% $A = \begin{pmatrix}
+% 1      & \cdots & \cdots & 1      \\
+% 0      & \ddots &        & \vdots \\
+% \vdots & \ddots & \ddots & \vdots \\
+% 0      & \cdots & 0      & 1
+% \end{pmatrix}$
+% \end{BVerbatim}
+%
+% \smallskip
+% This code composes the matrix $A$ on the right.
+% \end{minipage}\hspace{1cm}
+% $A = \begin{pmatrix}
+% 1      &\cdots &\cdots &1      \\
+% 0      &\ddots &       &\vdots \\
+% \vdots &\ddots &\ddots &\vdots \\
+% 0      &\cdots &0      &1
+% \end{pmatrix}$
+%
+% 
+% \bigskip
+% \begin{scope}
+% \NiceMatrixOptions{transparent}
+% \begin{minipage}{10cm}
+% Now, if we use the package \pkg{nicematrix} with the option\\ |transparent|, the
+% same code will give the result on the right.
+% \end{minipage}\hspace{1cm}
+% $A = \begin{pmatrix}
+% 1      & \cdots & \cdots & 1      \\
+% 0      & \ddots &        & \vdots \\
+% \vdots & \ddots & \ddots & \vdots \\
+% 0      & \cdots & 0      & 1
+% \end{pmatrix}$
+% \end{scope}
+%
+%
+% \section{The environments of this extension} 
+%
+% The extension \pkg{nicematrix} defines the following new environments.
+% 
+% \medskip
+% \begin{ttfamily}
+% \setlength{\tabcolsep}{3mm}
+% \begin{tabular}{llll}
+% \{NiceMatrix\}  & \{NiceArray\} & \{pNiceArray\}          \\
+% \{pNiceMatrix\} &               & \{bNiceArray\}          \\
+% \{bNiceMatrix\} &               & \{BNiceArray\}          \\
+% \{BNiceMatrix\} &               & \{vNiceArray\}          \\
+% \{vNiceMatrix\} &               & \{VNiceArray\}          \\
+% \{VNiceMatrix\} &               & \{NiceArrayWithDelims\} \\
+% \end{tabular}
+% \end{ttfamily}
+%
+%
+% \medskip
+% By default, the environments |{NiceMatrix}|, |{pNiceMatrix}|, |{bNiceMatrix}|,
+% |{BNiceMatrix}|, |{vNiceMatrix}| and |{VNiceMatrix}| behave almost exactly as
+% the corresponding environments of \pkg{amsmath}: |{matrix}|, |{pmatrix}|,
+% |{bmatrix}|, |{Bmatrix}|, |{vmatrix}| and |{Vmatrix}|.
+% 
+%
+% \medskip
+% The environment |{NiceArray}| is similar to the environment |{array}| of the
+% package |{array}|. However, for technical reasons, in the preamble of the
+% environment |{NiceArray}|, the user must use the letters |L|, |C| and~|R|
+% instead of |l|, |c| and |r|. It's possible to use the constructions
+% |w{...}{...}|, |W{...}{...}|\footnote{However, for the columns of type |w| and
+% |W|, the cells are composed in math mode (in the environments of
+% \pkg{nicematrix}) whereas in |{array}| of \pkg{array}, they are composed in text mode.}, "|",
+% |>{...}|, |<{...}|, |@{...}|, |!{...}| and |*{n}{...}| but the letters |p|,
+% |m| and |b| should not be used. The environment |{NiceArray}| and its variants
+% provide also options to draw exterior rows and columns. See p.~\pageref{NiceArray}
+% the section relating to |{NiceArray}|
+% 
+% 
+% \section{The continuous dotted lines}
+%
+% Inside the environments of the extension \pkg{nicematrix}, new commands are
+% defined: |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, and |\Iddots|. These commands
+% are intended to be used in place of |\dots|, |\cdots|, |\vdots|, |\ddots| and
+% |\iddots|.\footnote{The command |\iddots|, defined in \pkg{nicematrix}, is a
+% variant of |\ddots| with dots going forward: \smash{$\iddots$}. If |mathdots|
+% is loaded, the version of |mathdots| is used. It corresponds to the command
+% |\adots| of \pkg{unicode-math}.}
+% \newcounter{fniddots}
+% \setcounter{fniddots}{\thefootnote}
+%
+% \smallskip
+% Each of them must be used alone in the cell of the array and it draws a dotted
+% line between the first non-empty cells\footnote{The precise definition of a
+% ``non-empty cell'' is given below (cf. p.~\pageref{empty-cells}).} on both
+% sides of the current cell. Of course, for |\Ldots| and |\Cdots|, it's an
+% horizontal line; for |\Vdots|, it's a vertical line and for |\Ddots| and
+% |\Iddots| diagonal ones.\par\nobreak \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% a_1      & \Cdots &        & & a_1 \\
+% \Vdots   & a_2    & \Cdots & & a_2 \\
+%          & \Vdots & \Ddots \\
+% \\
+% a_1      & a_2    &        & & a_n 
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% a_1      & \Cdots &        & & a_1 \\
+% \Vdots   & a_2    & \Cdots & & a_2 \\
+%          & \Vdots & \Ddots \\
+% \\
+% a_1      & a_2    &        & & a_n 
+% \end{bNiceMatrix}$
+% 
+% \interitem
+% In order to represent the null matrix, one can use the following
+% codage:\par\nobreak \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% 0      & \Cdots & 0      \\
+% \Vdots &        & \Vdots \\
+% 0      & \Cdots & 0 
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% 0      & \Cdots & 0      \\
+% \Vdots &        & \Vdots \\
+% 0      & \Cdots & 0 
+% \end{bNiceMatrix}$
+%
+% \bigskip
+% However, one may want a larger matrix. Usually, in such a case, the users of
+% LaTeX add a new row and a new column. It's possible to use the same method
+% with \pkg{nicematrix}:\par\nobreak \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% 0      & \Cdots & \Cdots & 0      \\
+% \Vdots &        &        & \Vdots \\
+% \Vdots &        &        & \Vdots \\
+% 0      & \Cdots & \Cdots & 0 
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% 0      & \Cdots & \Cdots & 0      \\
+% \Vdots &        &        & \Vdots \\
+% \Vdots &        &        & \Vdots \\
+% 0      & \Cdots & \Cdots & 0 
+% \end{bNiceMatrix}$
+% 
+% \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}\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|,
+% etc.: |\Ldots*|, |\Cdots*|, etc. These versions are simply equivalent to
+% |\hphantom{\ldots}|, |\hphantom{\cdots}|, etc. The user should use these
+% starred versions whenever a classical version has already been used for the
+% same dotted line.\par\nobreak 
+%
+% \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% 0       & \Cdots & ~emphase#\Cdots*@ & 0       \\
+% \Vdots  &        &         & \Vdots  \\
+% ~emphase#\Vdots*@ &        &         & ~emphase#\Vdots*@ \\
+% 0       & \Cdots & ~emphase#\Cdots*@ & 0 
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% 0       & \Cdots &        & 0      \\
+% \Vdots  &        &        &        \\
+%         &        &        & \Vdots \\
+% 0       &        & \Cdots & 0 
+% \end{bNiceMatrix}$
+%
+% \bigskip
+% In fact, in this example, it would be possible to draw the same matrix without
+% starred commands with the following code:\par\nobreak
+% \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% 0       & \Cdots &        & 0      \\
+% \Vdots  &        &        &        \\
+%         &        &        & \Vdots \\
+% 0       &        & \Cdots & 0 
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% 0       & \Cdots &        & 0      \\
+% \Vdots  &        &        &        \\
+%         &        &        & \Vdots \\
+% 0       &        & \Cdots & 0 
+% \end{bNiceMatrix}$
+%
+% \bigskip 
+% There are also other means to change the size of the matrix. Someone might
+% want to use the optional argument of the command~|\\| for the vertical
+% dimension and a command~|\hspace*| in a cell for the horizontal
+% dimension.\footnote{Nevertheless, the best way to fix the width of a column is
+% to use the environment |{NiceArray}| (or one of its variants) with a column of
+% type~|w| or~|W|: see p.~\pageref{width}}
+% 
+% However, a command~|\hspace*| might interfer with the construction of the
+% dotted lines. That's why the package \pkg{nicematrix} provides a
+% command~|\Hspace| which is a variant of |\hspace| transparent for the dotted
+% lines of \pkg{nicematrix}.\par\nobreak
+% \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% \begin{bNiceMatrix}
+% 0      & \Cdots & ~emphase#\Hspace*{1cm}@ & 0      \\
+% \Vdots &        &               & \Vdots \\~emphase#[1cm]@
+% 0      & \Cdots &               & 0    
+% \end{bNiceMatrix}
+% \end{BVerbatim}
+% $\begin{bNiceMatrix}
+% 0      & \Cdots & \Hspace*{1cm} & 0      \\
+% \Vdots &        &               & \Vdots \\[1cm]
+% 0      & \Cdots &               & 0    
+% \end{bNiceMatrix}$
+% 
+% \subsection{The option nullify-dots}
+%
+% Consider the following matrix composed classicaly with the environment
+% |{pmatrix}| of \pkg{amsmath}.\par\nobreak 
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=8cm]
+% $A = \begin{pmatrix}
+% a_0 & b \\
+% a_1 &   \\
+% a_2 &   \\
+% a_3 &   \\
+% a_4 &   \\
+% a_5 & b
+% \end{pmatrix}$
+% \end{BVerbatim}
+% $A = \begin{pmatrix}
+% a_0 & b \\
+% a_1 &   \\
+% a_2 &   \\
+% a_3 &   \\
+% a_4 &   \\
+% a_5 & b
+% \end{pmatrix}$
+%
+%
+% \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=8cm]
+% $B = \begin{pmatrix}
+% a_0 & b      \\
+% a_1 & \vdots \\
+% a_2 & \vdots \\
+% a_3 & \vdots \\
+% a_4 & \vdots \\
+% a_5 & b
+% \end{pmatrix}$
+% \end{BVerbatim}
+% $B = \begin{pmatrix}
+% a_0 & b      \\
+% a_1 & \vdots \\
+% a_2 & \vdots \\
+% a_3 & \vdots \\
+% a_4 & \vdots \\
+% a_5 & b
+% \end{pmatrix}$
+%
+% \bigskip
+% 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=8cm]
+% $C = \begin{pNiceMatrix}
+% a_0 & b       \\
+% a_1 & \Vdots  \\
+% a_2 & \Vdots* \\
+% a_3 & \Vdots* \\
+% a_4 & \Vdots* \\
+% a_5 & b
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% $C = \begin{pNiceMatrix}
+% a_0 & b       \\
+% a_1 & \Vdots  \\
+% a_2 & \Vdots* \\
+% a_3 & \Vdots* \\
+% a_4 & \Vdots* \\
+% a_5 & b
+% \end{pNiceMatrix}$
+%
+% \bigskip
+% However, one may prefer the geometry of the first matrix $A$ and would like to
+% have such a geometry with a dotted 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=8cm]
+% $D = \begin{pNiceMatrix}[~emphase#nullify-dots@]
+% a_0 & b      \\
+% a_1 & \Vdots \\
+% a_2 &        \\
+% a_3 &        \\
+% a_4 &        \\
+% a_5 & b
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% $D = \begin{pNiceMatrix}[nullify-dots]
+% a_0 & b      \\
+% a_1 & \Vdots \\
+% a_2 &        \\
+% a_3 &        \\
+% a_4 &        \\
+% a_5 & b
+% \end{pNiceMatrix}$
+%
+% \medskip
+% The option |nullify-dots| smashes the instructions |\Ldots| (and the variants)
+% vertically but also horizontally.
+%
+% \medskip
+% \textbf{There must be no space before the opening bracket (|[|) of the options
+% of the environment.}
+%
+%
+% \subsection{The command \textbackslash 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}, 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]
+% $\begin{pNiceMatrix}
+% 1 & 2 & 3 & 4 & 5 \\
+% 1 & ~emphase#\Hdotsfor{3}@ & 5 \\
+% 1 & 2 & 3 & 4 & 5 \\
+% 1 & 2 & 3 & 4 & 5 
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% $\begin{pNiceMatrix}
+% 1 & 2 & 3 & 4 & 5 \\
+% 1 & \Hdotsfor{3} & 5 \\
+% 1 & 2 & 3 & 4 & 5 \\
+% 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, |\Hdotsfor| has also an optional argument
+% but this argument is discarded silently.
+%
+% Remark: Unlike the command |\hdotsfor| of \pkg{amsmath}, the command
+% |\Hdotsfor| may be used when the extension \pkg{colortbl} is loaded (but you
+% might have problem if you use |\rowcolor| on the same row as |\Hdotsfor|).
+% 
+% \subsection{How to generate the continuous dotted lines transparently}
+%
+% The package \pkg{nicematrix} provides an option called |transparent| for using
+% existing code transparently in the environments |{matrix}|. This option can be
+% set as option of |\usepackage| or with the command |\NiceMatrixOptions|.
+% 
+%
+% In fact, this option is an alias for the conjonction of two options:
+% |renew-dots| and |renew-matrix|.
+%
+% \smallskip
+%
+% \begin{itemize}
+% \item The option |renew-dots|\par\nobreak
+% With this option, the commands |\ldots|, |\cdots|, |\vdots|, |\ddots|,
+% |\iddots|\footnotemark[\thefniddots] 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|) 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 variants.
+% \end{itemize}
+%
+% \bigskip 
+% Therefore, with the option |transparent|, a classical code gives directly the
+% ouput of \pkg{nicematrix}.\par\nobreak
+% \bigskip
+% \begin{scope}
+% \NiceMatrixOptions{transparent}
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% ~emphase#\NiceMatrixOptions{transparent}@
+% \begin{pmatrix}
+% 1      & \cdots & \cdots & 1      \\
+% 0      & \ddots &        & \vdots \\
+% \vdots & \ddots & \ddots & \vdots \\
+% 0      & \cdots & 0      & 1
+% \end{pmatrix}
+% \end{BVerbatim}
+% $\begin{pmatrix}
+% 1      & \cdots & \cdots & 1      \\
+% 0      & \ddots &        & \vdots \\
+% \vdots & \ddots & \ddots & \vdots \\
+% 0      & \cdots & 0      & 1
+% \end{pmatrix}$
+% \end{scope}
+% 
+%
+% 
+% 
+% \section{The Tikz nodes created by nicematrix}
+% 
+% The package \pkg{nicematrix} creates a Tikz node for each cell of the
+% considered array. These nodes are used to draw the dotted lines between the
+% cells of the matrix. However, the user may wish to use directly these nodes.
+% It's possible. First, the user have to give a name to the array (with the key
+% called |name|). Then, the nodes are accessible through the names
+% ``\textsl{name}-$i$-$j$'' where \textsl{name} is the name given to the array
+% and $i$ and $j$ the numbers of the row and the column of the considered cell.
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=11cm]
+% $\begin{pNiceMatrix}[name=~emphase#mymatrix@]
+% 1 & 2 & 3 \\
+% 4 & 5 & 6 \\
+% 7 & 8 & 9 
+% \end{pNiceMatrix}$
+% \tikz[remember picture,overlay] 
+%      \draw ~emphase#(mymatrix-2-2)@ circle (2mm) ; 
+% \end{BVerbatim}
+% $\begin{pNiceMatrix}[name=mymatrix]
+% 1 & 2 & 3 \\
+% 4 & 5 & 6 \\
+% 7 & 8 & 9 
+% \end{pNiceMatrix}$
+% \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{There is no ``large nodes'' created in the exterior
+% rows and columns (for these rows and columns, cf. p.~\pageref{exterior}).}
+%
+% \[\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|. There is
+% also an option |margin| to fix both |left-margin| and |right-margin| to the
+% same value.}
+% \[\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''. It's possible to fix both values with the
+% option |extra-margin| and, in the following example, we use |extra-margin|
+% with the value $3$~pt.
+% \[\begin{pNiceMatrix}[
+%  create-extra-nodes,margin,extra-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} (cf. p. \pageref{highlight}).
+%
+% \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 (and, hence, after the construction of
+% all the Tikz nodes).
+%
+% 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).
+%
+% Moreover, a special command, called |\line| is available to draw directly
+% dotted lines between nodes.
+%
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=12cm]
+% $\begin{pNiceMatrix}[~emphase#code-after = {\line {1-1} {3-3}}@]
+% 0 & 0 & 0 \\
+% 0 &   & 0 \\
+% 0 & 0 & 0 
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% $\begin{pNiceMatrix}[code-after = {\line {1-1} {3-3}}]
+% 0 & 0 & 0 \\
+% 0 &   & 0 \\
+% 0 & 0 & 0 
+% \end{pNiceMatrix}$
+%
+% 
+% \section{The environment \{NiceArray\}}
+% \label{NiceArray}
+%
+% The environment |{NiceArray}| is similar to the environment |{array}|. As for
+% |{array}|, the mandatory argument is the preamble of the array. However, for
+% technical reasons, in this preamble, the user must use the letters |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. In fact, the column types |w| and |W| are
+% also redefined.} instead of |l|, |c| and |r|. It's possible
+% to use the constructions |w{...}{...}|, |W{...}{...}|, "|", |>{...}|,
+% |<{...}|, |@{...}|, |!{...}| 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 defined by \pkg{nicematrix} (|renew-dots|,
+% |columns-width|, etc.).
+%
+% 
+% \vspace{1cm}
+% An example with a linear system (we need |{NiceArray}| for the vertical rule):
+%
+% \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% $\left[\begin{NiceArray}{CCCC|C}
+% a_1    & ?      & \Cdots & ?       & ?     \\
+% 0      &        & \Ddots & \Vdots  & \Vdots\\
+% \Vdots & \Ddots & \Ddots & ? \\ 
+% 0      & \Cdots & 0      & a_n     & ?     
+% \end{NiceArray}\right]$
+% \end{BVerbatim}
+% $\left[\begin{NiceArray}{CCCC|C}
+% a_1    & ?      & \Cdots & ?       & ?     \\
+% 0      &        & \Ddots & \Vdots  & \Vdots\\
+% \Vdots & \Ddots & \Ddots & ? \\ 
+% 0      & \Cdots & 0      & a_n     & ?     
+% \end{NiceArray}\right]$
+%
+% \bigskip
+% In fact, there is also variants for the environment |{NiceArray}|:
+% |{pNiceArray}|, |{bNiceArray}|, |{BNiceArray}|, |{vNiceArray}| and
+% |{VNiceArray}|. 
+% 
+% In the following example, we use an environment |{pNiceArray}| (we don't use
+% |{pNiceMatrix}| because we want to use the types |L| and |R| 
+% --- in |{pNiceMatrix}|, all the columns are of type |C|).
+%
+% \bigskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10cm]
+% $\begin{pNiceArray}{LCR}
+% a_{11}    & \Cdots & a_{1n} \\
+% a_{21}    &        & a_{2n} \\
+% \Vdots    &        & \Vdots \\
+% a_{n-1,1} & \Cdots & a_{n-1,n} 
+% \end{pNiceArray}$
+% \end{BVerbatim}
+% $\begin{pNiceArray}{LCR}
+% a_{11}    & \Cdots & a_{1n} \\
+% a_{21}    &        & a_{2n} \\
+% \Vdots    &        & \Vdots \\
+% a_{n-1,1} & \Cdots & a_{n-1,n} 
+% \end{pNiceArray}$
+%
+%
+% \vspace{1cm}
+% With the environment |{NiceArray}| and its the variants, it's possible to
+% compose exterior rows and columns with the options |first-row|, |last-row|,
+% |first-col| and |last-col|. 
+% \label{exterior}
+%
+% There is no specification of column to provide for the potential ``first
+% column'' (it will automatically be a |R| column) and for the potential ``last
+% column'' (it will automatically be a |L| column).
+% 
+% \begin{Verbatim}
+% $\begin{pNiceArray}{CCCC}[~emphase#first-row,last-row,first-col,last-col@]
+%     & C_1    & C_2    & C_3    & C_4    &     \\
+% L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\
+% L_2 & a_{21} & a_{22} & a_{23} & a_{24} & L_2 \\
+% L_3 & a_{31} & a_{32} & a_{33} & a_{34} & L_3 \\
+% L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\
+%     & C_1    & C_2    & C_3    & C_4    &     
+% \end{pNiceArray}$
+% \end{Verbatim}
+%
+% \[\begin{pNiceArray}{CCCC}[first-row,last-row,first-col,last-col]
+%     & C_1    & C_2    & C_3    & C_4    &     \\
+% L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\
+% L_2 & a_{21} & a_{22} & a_{23} & a_{24} & L_2 \\
+% L_3 & a_{31} & a_{32} & a_{33} & a_{34} & L_3 \\
+% L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\
+%     & C_1    & C_2    & C_3    & C_4    &     
+% \end{pNiceArray}\]
+%
+% \bigskip
+% However, there is a particularity for the option |last-row|: when LaTeX
+% composes an array (with the TeX command |\halign|) it composes it row by row
+% and there is no direct way to know if we are at the last row before the
+% composition of that row. That's why \pkg{nicematrix} writes in the |aux| file
+% the number of rows of the array in order to use it at the next run.
+% Nevertheless, it's possible to give directly the number of rows as the value
+% of the key |last-row|. It that way, \pkg{nicematrix} will know the correct
+% value by the first compilation.
+%
+% \bigskip
+% It's possible to control the appearance of these rows and columns with options
+% |code-for-first-row|, |code-for-last-row|, |code-for-first-col| and
+% |code-for-last-col|. These options
+% specify tokens that will be inserted before each cell of the corresponding row
+% or column. 
+% 
+%
+% \begin{Verbatim}
+% \NiceMatrixOptions{~emphase#code-for-first-row@ = \color{red},
+%                    ~emphase#code-for-first-col@ = \color{blue},
+%                    ~emphase#code-for-last-row@ = \color{green},
+%                    ~emphase#code-for-last-col@ = \color{magenta}}
+% $\begin{pNiceArray}{CC|CC}[first-row,last-row=5,first-col,last-col]
+%     & C_1    & C_2    & C_3    & C_4    &     \\
+% L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\
+% L_2 & a_{21} & a_{22} & a_{23} & a_{24} & L_2 \\
+% \hline
+% L_3 & a_{31} & a_{32} & a_{33} & a_{34} & L_3 \\
+% L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\
+%     & C_1    & C_2    & C_3    & C_4    &     
+% \end{pNiceArray}$
+% \end{Verbatim}
+%
+% \begin{scope}
+% \NiceMatrixOptions{code-for-first-row = \color{red},
+%                    code-for-first-col = \color{blue},
+%                    code-for-last-row = \color{green},
+%                    code-for-last-col = \color{magenta}}
+% \[\begin{pNiceArray}{CC|CC}[first-row,last-row=5,first-col,last-col]
+%     & C_1    & \multicolumn1C{C_2}    & C_3    & C_4    &     \\
+% L_1 & a_{11} & a_{12} & a_{13} & a_{14} & L_1 \\
+% L_2 & a_{21} & a_{22} & a_{23} & a_{24} & L_2 \\
+% \hline
+% L_3 & a_{31} & a_{32} & a_{33} & a_{34} & L_3 \\
+% L_4 & a_{41} & a_{42} & a_{43} & a_{44} & L_4 \\
+%     & C_1    & \multicolumn1C{C_2}    & C_3    & C_4    &     
+% \end{pNiceArray}\]
+% \end{scope}
+%
+%
+% \emph{Remarks}
+% \begin{itemize}
+% \item As shown in the previous example, an horizontal rule (drawn by |\hline|)
+% doesn't extend in the exterior columns and a vertical rule (specified by a
+% ``\verb+|+'' in the preamble of the array) doesn't extend in the exterior
+% rows.\footnote{The latter is not true when the extension \pkg{arydshln} is
+% loaded besides \pkg{nicematrix}. In fact, \pkg{nicematrix} and \pkg{arydhsln}
+% are not totally compatible because \pkg{arydshln} redefines many internals of
+% \pkg{array}.} 
+% \item The ``first row'' of an environment |{pNiceArray}| has the number $0$, and not
+% $1$. Idem for the ``first column''. 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|). 
+% \item Logically, the potential option |columns-width| (described
+% p.~\pageref{width}) doesn't apply to the ``first column'' and ``last column''. 
+% \item For technical reasons, it's not possible to use the option of the command |\\|
+% after the ``first row'' or before the ``last row'' (the placement of the
+% delimiters would be wrong). 
+% \end{itemize}
+% 
+% 
+% 
+%
+% \bigskip
+% In fact, the environment |{pNiceArray}| and its variants are based upon a
+% more general environment, called |{NiceArrayWithDelims}|. 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
+% |{NiceArrayWithDelims}| if we want to use atypical delimiters.
+%
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=11cm]
+% $\begin{~emphase#NiceArrayWithDelims@}
+%    {\downarrow}{\downarrow}{CCC}[last-col]
+% 1 & 2 & 3 & L_1 \\
+% 4 & 5 & 6 & L_2 \\
+% 7 & 8 & 9 & L_3
+% \end{~emphase#NiceArrayWithDelims@}$
+% \end{BVerbatim}
+% $\begin{NiceArrayWithDelims}
+%    {\downarrow}{\downarrow}{CCC}[last-col]
+% 1 & 2 & 3 & L_1 \\
+% 4 & 5 & 6 & L_2 \\
+% 7 & 8 & 9 & L_3
+% \end{NiceArrayWithDelims}$
+%
+%
+%
+% \section{The dotted lines to separate rows or columns}
+%
+%
+% In the environments of the extension \pkg{nicematrix}, it's possible to use
+% the command |\hdottedline| (provided by \pkg{nicematrix}) which is a
+% counterpart of the classical commands |\hline| and |\hdashline| (the latter is
+% a command of\pkg{arydshln}).
+%
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=9.5cm]
+% \begin{pNiceMatrix}
+% 1 & 2 & 3 & 4 & 5 \\
+% ~emphase#\hdottedline@
+% 6 & 7 & 8 & 9 & 10 \\
+% 11 & 12 & 13 & 14 & 15 
+% \end{pNiceMatrix}
+% \end{BVerbatim}
+% $\begin{pNiceMatrix}
+% 1 & 2 & 3 & 4 & 5 \\
+% \hdottedline
+% 6 & 7 & 8 & 9 & 10 \\
+% 11 & 12 & 13 & 14 & 15 
+% \end{pNiceMatrix}$
+%
+%
+% \bigskip
+% In the environments with an explicit preamble (like |{NiceArray}|, etc.), it's
+% possible to draw a vertical dotted line with the specifier ``|:|''.
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=9.5cm]
+% \left(\begin{NiceArray}{CCCC~emphase#:@C}
+% 1 & 2 & 3 & 4 & 5 \\
+% 6 & 7 & 8 & 9 & 10 \\
+% 11 & 12 & 13 & 14 & 15 
+% \end{NiceArray}\right)
+% \end{BVerbatim}
+% $\left(\begin{NiceArray}{CCCC:C}
+% 1 & 2 & 3 & 4 & 5 \\
+% 6 & 7 & 8 & 9 & 10 \\
+% 11 & 12 & 13 & 14 & 15 
+% \end{NiceArray}\right)$
+%
+%
+% \bigskip
+% These dotted lines do \emph{not} extend in the potential exterior rows and columns.
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=9.5cm]
+% $\begin{pNiceArray}{CCC:C}[
+%     first-row,last-col, 
+%     code-for-first-row = \color{blue}\scriptstyle,
+%     code-for-last-col = \color{blue}\scriptstyle ]
+% C_1 & C_2 & C_3 & C_4 \\
+% 1 & 2 & 3 & 4 & L_1 \\
+% 5 & 6 & 7 & 8 & L_2 \\
+% 9 & 10 & 11 & 12 & L_3 \\
+% \hdottedline
+% 13 & 14 & 15 & 16 & L_4 
+% \end{pNiceArray}$
+% \end{BVerbatim}
+% $\begin{pNiceArray}{CCC:C}[
+%     first-row,last-col, 
+%     code-for-first-row = \color{blue}\scriptstyle,
+%     code-for-last-col = \color{blue}\scriptstyle ]
+% C_1 & C_2 & C_3 & C_4 \\
+% 1 & 2 & 3 & 4 & L_1 \\
+% 5 & 6 & 7 & 8 & L_2 \\
+% 9 & 10 & 11 & 12 & L_3 \\
+% \hdottedline
+% 13 & 14 & 15 & 16 & L_4 
+% \end{pNiceArray}$
+% 
+% \bigskip
+% It's possible to change in \pkg{nicematrix} the letter used to specify a
+% vertical dotted line with the option |letter-for-dotted-lines| available in
+% |\NiceMatrixOptions|. For example, in this document, we have loaded the
+% extension \pkg{arydshln} which uses the letter ``:'' to specify a vertical
+% dashed line. Thus, by using |letter-for-dotted-lines|, we can use the
+% vertical lines of both \pkg{arydshln} and \pkg{nicematrix}.
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=9.5cm]
+% \NiceMatrixOptions{letter-for-dotted-lines = V}
+% \left(\begin{NiceArray}{~emphase#C|C:CVC@}
+% 1 & 2 & 3 & 4 \\
+% 5 & 6 & 7 & 8 \\
+% 9 & 10 & 11 & 12
+% \end{NiceArray}\right)
+% \end{BVerbatim}
+% \begin{scope}
+% \NiceMatrixOptions{letter-for-dotted-lines = V}
+% $\left(\begin{NiceArray}{C|C:CVC}
+% 1 & 2 & 3 & 4 \\
+% 5 & 6 & 7 & 8 \\
+% 9 & 10 & 11 & 12
+% \end{NiceArray}\right)$
+% \end{scope}
+%
+% \section{The width of the columns}
+% \label{width}
+%
+% In the environments with an explicit preamble (like |{NiceArray}|,
+% |{pNiceArray}|, 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 (of course, it's possible to suppress this space by setting
+% |\arraycolsep| equal to $0$~pt).
+%
+% \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 option hlines}
+% 
+% You can add horizontal rules between rows in the environments of
+% \pkg{nicematrix} with the usual command |\hline|. But, by convenience, the
+% extension \pkg{nicematrix} provides the option |hlines|. With this option, all
+% the horizontal rules will be drawn (excepted, of course the rule before the
+% potential ``first row'' and the rule after the potential ``last row'').
+% 
+% \medskip
+% \begin{BVerbatim}[baseline=c,boxwidth=10.6cm]
+% $\begin{NiceArray}{|*{4}{C|}}[~emphase#hlines@,first-row,first-col]
+%   & e & a & b & c \\
+% e & e & a & b & c \\
+% a & a & e & c & b \\
+% b & b & c & e & a \\
+% c & c & b & a & e 
+% \end{NiceArray}$
+% \end{BVerbatim}
+% \raise-5mm\box\ExampleOne
+% 
+% \section{Utilisation of the column type S of siunitx}
+%
+% If the package \pkg{siunitx} is loaded (before or after \pkg{nicematrix}),
+% it's possible to use the |S| column type of \pkg{siunitx} in the environments
+% of \pkg{nicematrix}. The implementation doesn't use explicitly any private
+% macro of \pkg{siunitx}. The |d| columns of \pkg{dcolumn} are not supported by
+% \pkg{nicematrix}. 
+% 
+% 
+% \medskip
+% \begin{BVerbatim}[baseline = c, boxwidth = 10.5cm]
+% $\begin{pNiceArray}{~emphase#S@CWc{1cm}C}[nullify-dots,first-row]
+% {C_1} & \Cdots &  & C_n \\
+% 2.3  & 0 & \Cdots & 0 \\
+% 12.4 & \Vdots & & \Vdots \\
+% 1.45 \\
+% 7.2  & 0 & \Cdots & 0 
+% \end{pNiceArray}$
+% \end{BVerbatim}
+% $\begin{pNiceArray}{SCWc{1cm}C}[nullify-dots,first-row]
+% {C_1} & \Cdots &  & C_n \\
+% 2.3  & 0 & \Cdots & 0 \\
+% 12.4 & \Vdots & & \Vdots \\
+% 1.45 \\
+% 7.2  & 0 & \Cdots & 0 
+% \end{pNiceArray}$
+% 
+%
+% \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}
+% 
+% \label{empty-cells}
+% An instruction like |\Ldots|, |\Cdots|, etc. tries to determine the first
+% non-empty cells on both sides. However, an 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}
+% a & b \\
+% c \\
+% \end{pmatrix}
+% \end{Verbatim}
+% 
+% the last cell (second row and second column) is empty.
+%
+% \medskip
+% \item Each cell whose TeX ouput has a width less than 0.5~pt is empty.
+%
+% \medskip
+% \item A cell which contains a command |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|
+% or |\Iddots| and their starred 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 the package \pkg{nicematrix} with the same
+% meaning as |\hspace| except that the cell where it is used is considered as
+% empty. This command can be used to fix the width of some columns of the matrix
+% without interfering with \pkg{nicematrix}.
+% % \end{itemize}
+%
+%
+% \subsection{The option exterior-arraycolsep}
+% 
+% The environment |{array}| inserts an horizontal space equal to |\arraycolsep|
+% before and after each column. In particular, there is a space equal to
+% |\arraycolsep| before and after the array. This feature of the environment
+% |{array}| was probably not a good idea.\footnote{In the documentation of
+% |{amsmath}|, we can read: {\itshape The extra space of |\arraycolsep| that
+% \pkg{array} adds on each side is a waste so we remove it [in |{matrix}|]
+% (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} 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| of the command |\NiceMatrixOptions|. With this option,
+% |{NiceArray}| will insert the same horizontal spaces as the environment
+% |{array}|.  
+%
+% This option is only 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{The class option draft}
+%
+% The package \pkg{nicematrix} is rather slow when drawing the dotted lines
+% (generated by |\Cdots|, |\Ldots|, |\Ddots|, etc. but also by |\hdottedline| or
+% the specifier |:|).\footnote{The main reason is that we want dotted lines with
+% round dots (and not square dots) with the same space on both extremities of
+% the lines. To achieve this goal, we have to construct our own system of dotted
+% lines.} 
+%
+% That's why, when the class option |draft| is used, the dotted lines are not
+% drawn, for a faster compilation. 
+% 
+% \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}$
+%
+%
+% \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{Obsolete environments}      
+% 
+% The version 3.0 of \pkg{nicematrix} has introduced the environment
+% |{pNiceArray}| (and its variants) with the options |first-row|, |last-row|,
+% |first-col| and |last-col|. 
+%
+% Consequently the following environments present in previous versions of
+% \pkg{nicematrix} are deprecated:
+% %
+% \begin{itemize}
+% \item |{NiceArrayCwithDelims}| ;
+% \item |{pNiceArrayC}|, |{bNiceArrayC}|, |{BNiceArrayC}|, |{vNiceArrayC}|,
+% |{VNiceArrayC}| ;
+% \item |{NiceArrayRCwithDelims}| ;
+% \item |{pNiceArrayRC}|, |{bNiceArrayRC}|, |{BNiceArrayRC}|, |{vNiceArrayRC}|,
+% |{VNiceArrayRC}|.
+% \end{itemize}
+%       
+% They might be deleted in a future version of \pkg{nicematrix}.
+%
+% \section{Examples}
+%
+% \subsection{Dotted lines}
+%
+% \medskip
+% A tridiagonal matrix:
+% 
+% \bigskip
+% \begin{BVerbatim}[baseline=c]
+% $\begin{pNiceMatrix}[nullify-dots]
+% a      & b      & 0      &        & \Cdots & 0      \\ 
+% b      & a      & b      & \Ddots &        & \Vdots \\
+% 0      & b      & a      & \Ddots &        &        \\
+%        & \Ddots & \Ddots & \Ddots &        & 0      \\
+% \Vdots &        &        &        &        & b      \\
+% 0      & \Cdots &        & 0      & b      & a
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% \hspace{1.5cm}
+% $\begin{pNiceMatrix}[nullify-dots]
+% a      & b      & 0      &        & \Cdots & 0      \\ 
+% b      & a      & b      & \Ddots &        & \Vdots \\
+% 0      & b      & a      & \Ddots &        &        \\
+%        & \Ddots & \Ddots & \Ddots &        & 0      \\
+% \Vdots &        &        &        &        & b      \\
+% 0      & \Cdots &        & 0      & b      & a
+% \end{pNiceMatrix}$
+%
+% \vspace{2cm}
+%
+% A permutation matrix:
+%
+% \bigskip
+% \begin{BVerbatim}[baseline=c]
+% $\begin{pNiceMatrix}
+% 0       & 1 & 0 &        & \Cdots &   0    \\
+% \Vdots  &   &   & \Ddots &        & \Vdots \\
+%         &   &   & \Ddots &        &        \\
+%         &   &   & \Ddots &        &   0    \\
+% 0       & 0 &   &        &        &   1    \\
+% 1       & 0 &   & \Cdots &        &   0    
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% \hspace{2.5cm}
+% $\begin{pNiceMatrix}
+% 0       & 1 & 0 &        & \Cdots &   0    \\
+% \Vdots  &   &   & \Ddots &        & \Vdots \\
+%         &   &   & \Ddots &        &        \\
+%         &   &   & \Ddots &        &   0    \\
+% 0       & 0 &   &        &        &   1    \\
+% 1       & 0 &   & \Cdots &        &   0    
+% \end{pNiceMatrix}$
+%
+% \vspace{2cm}
+%
+% An example with |\Iddots|: \par\nobreak
+% \bigskip
+% \begin{BVerbatim}[baseline=c]
+% $\begin{pNiceMatrix}
+% 1       & \Cdots  &         & 1      \\
+% \Vdots  &         &         & 0      \\
+%         & ~emphase#\Iddots@ & ~emphase#\Iddots@ & \Vdots \\
+% 1       & 0       & \Cdots  & 0 
+% \end{pNiceMatrix}$
+% \end{BVerbatim}
+% \hspace{4cm}
+% $\begin{pNiceMatrix}
+% 1       & \Cdots  &         & 1      \\
+% \Vdots  &         &         & 0      \\
+%         & \Iddots & \Iddots & \Vdots \\
+% 1       & 0       & \Cdots  & 0 
+% \end{pNiceMatrix}$
+%
+%
+% \vspace{2cm}
+% An example with |\multicolumn|:\par\nobreak
+% \bigskip
+% \begin{BVerbatim}
+% \begin{BNiceMatrix}[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{BNiceMatrix}
+% \end{BVerbatim}
+% 
+% \bigskip
+% \[\begin{BNiceMatrix}[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{BNiceMatrix}\]
+% 
+% \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:\par\nobreak
+% \bigskip
+% \begin{BVerbatim}
+% \setlength{\extrarowheight}{1mm}
+% \[\begin{vNiceArray}{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{vNiceArray}\]
+% \end{BVerbatim}
+% 
+% \bigskip
+%
+% \begin{scope}
+% \setlength{\extrarowheight}{1mm}
+% \[\begin{vNiceArray}{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{vNiceArray}\]
+% \end{scope}   
+%
+% \vspace{2cm}
+% An example for a linear system:\par\nobreak
+%
+% \begin{Verbatim}
+% $\begin{pNiceArray}{*6C|C}[nullify-dots,last-col,code-for-last-col={\scriptstyle}]
+% 1      & 1 & 1 &\Cdots &   & 1      & 0      & \\
+% 0      & 1 & 0 &\Cdots &   & 0      &        & L_2 \gets L_2-L_1 \\
+% 0      & 0 & 1 &\Ddots &   & \Vdots &        & L_3 \gets L_3-L_1 \\
+%        &   &   &\Ddots &   &        & \Vdots & \Vdots \\
+% \Vdots &   &   &\Ddots &   & 0      & \\
+% 0      &   &   &\Cdots & 0 & 1      & 0      & L_n \gets L_n-L_1 
+% \end{pNiceArray}$
+% \end{Verbatim}
+% 
+% \[\begin{pNiceArray}{*6C|C}[nullify-dots,last-col,code-for-last-col={\scriptstyle}]
+% 1      & 1 & 1 &\Cdots &   & 1      & 0      & \\
+% 0      & 1 & 0 &\Cdots &   & 0      &        & L_2 \gets L_2-L_1 \\
+% 0      & 0 & 1 &\Ddots &   & \Vdots &        & L_3 \gets L_3-L_1 \\
+%        &   &   &\Ddots &   &        & \Vdots & \Vdots \\
+% \Vdots &   &   &\Ddots &   & 0      & \\
+% 0      &   &   &\Cdots & 0 & 1      & 0      & L_n \gets L_n-L_1 
+% \end{pNiceArray}\]
+%
+%
+% \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
+% \begin{BVerbatim}
+% ~emphase#\begin{NiceMatrixBlock}[auto-columns-width]@
+% \NiceMatrixOptions{code-for-last-col = \color{blue}\scriptstyle}
+% \setlength{\extrarowheight}{1mm}
+% \quad $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 2&4&8&16&9&\\
+% 3&9&27&81&36&\\
+% 4&16&64&256&100&
+% \end{pNiceArray}$
+% ...
+% ~emphase#\end{NiceMatrixBlock}@
+% \end{BVerbatim}
+% 
+% \bigskip
+% 
+% \begin{multicols}{2}
+% \begin{NiceMatrixBlock}[auto-columns-width]
+% \NiceMatrixOptions{code-for-last-col = \color{blue}\scriptstyle}
+% \setlength{\extrarowheight}{1mm}
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 2&4&8&16&9&\\
+% 3&9&27&81&36&\\
+% 4&16&64&256&100&
+% \end{pNiceArray}$
+%
+% \medskip
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 0&2&6&14&7&L_2\gets-2L_1+L_2 \\
+% 0&6&24&78&33&L_3\gets-3L_1+L_3 \\
+% 0&12&60&252&96&L_4\gets-4L_1+L_4 
+% \end{pNiceArray}$
+%
+% \medskip
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 0&1&3&7&\frac72&L_2\gets\frac12L_2\\
+% 0&3&12&39&\frac{33}2&L_3\gets\frac12L_3 \\
+% 0&1&5&21&8&L_4\gets\frac1{12}L_4 
+% \end{pNiceArray}$
+%
+% \medskip
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 0&1&3&7&\frac72&\\
+% 0&0&3&18&6&L_3 \gets -3L_2+L_3 \\
+% 0&0&-2&-14&-\frac92&L_4 \gets L_2-L_4 
+% \end{pNiceArray}$
+%
+% \medskip
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 0&1&3&7&\frac72&\\
+% 0&0&1&6&2&L_3 \gets \frac13L_3\\
+% 0&0&-2&-14&-\frac92&
+% \end{pNiceArray}$
+%
+% \medskip
+%
+% \enskip $\begin{pNiceArray}{CCCC:C}[last-col]
+% 1&1&1&1&1&\\
+% 0&1&3&7&\frac72&\\
+% 0&0&1&6&2& \\
+% 0&0&0&-2&-\frac12 & L_4 \gets 2L_3+L_4 
+% \end{pNiceArray}$
+% \end{NiceMatrixBlock}
+% \end{multicols}
+% 
+% 
+% \subsection{How to highlight cells of the matrix}
+%
+% \label{highlight}
+% \medskip
+% In order to highlight a cell of a matrix, it's possible to ``draw'' one of the
+% correspondant 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}
+% $\begin{pNiceArray}{>{\strut}CCCC}%
+%    [create-extra-nodes,margin,extra-margin = 2pt ,
+%     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{pNiceArray}$
+% \end{Verbatim}
+%
+%
+% \[\begin{pNiceArray}{>{\strut}CCCC}[
+%     create-extra-nodes,margin,extra-margin = 2pt,
+%     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{pNiceArray}\]
+% 
+%
+% \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}. However, it's not always easy to do a fine
+% tuning of \pkg{colortbl}. That's why we 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{bNiceMatrix}[~emphase#code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}@]
+% 0 & \Cdots & 0 \\
+% 1 & \Cdots & 1 \\
+% 0 & \Cdots & 0 
+% \end{bNiceMatrix}$
+% \end{Verbatim}
+% 
+% \[\begin{bNiceMatrix}[code-after = {\tikz \node[highlight, fit = (2-1) (2-3)] {} ;}]
+% 0 & \Cdots & 0 \\
+% 1 & \Cdots & 1 \\
+% 0 & \Cdots & 0 
+% \end{bNiceMatrix}\]
+% 
+%
+% \bigskip
+% This code fails with |latex|-|dvips|-|ps2pdf| because Tikz for |dvips|, as for now, doesn't support blend modes. However, the
+% following code, in the preamble, should activate blend modes in this way of compilation.
+%
+%
+% \begin{scope} \small
+% |\ExplSyntaxOn|
+%
+% |\makeatletter|
+%
+% |\tl_set:Nn \l_tmpa_tl {pgfsys-dvips.def}|
+%
+% |\tl_if_eq:NNT \l_tmpa_tl \pgfsysdriver|
+%
+% |  {\cs_set:Npn\pgfsys@blend@mode#1{\special{ps:~/\tl_upper_case:n #1~.setblendmode}}}|
+%
+% |\makeatother|
+%
+% |\ExplSyntaxOff|
+% \end{scope}
+% 
+% \vspace{1cm}
+% Considerer now the following matrix which we have named |example|.
+%
+% \medskip
+% \begin{Verbatim}
+% $\begin{pNiceArray}{CCC}[~emphase#name=example@,last-col,create-extra-nodes]
+% a & a + b & a + b + c & L_1\\
+% a & a     & a + b     & L_2 \\
+% a & a     & a         & L_3
+% \end{pNiceArray}$
+% \end{Verbatim}
+%                           
+% \[\begin{pNiceArray}{CCC}[last-col]
+% a & a + b & a + b + c & L_1\\
+% a & a     & a + b     & L_2 \\
+% a & a     & a         & L_3
+% \end{pNiceArray}\]
+% 
+% \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{pNiceArray}{CCC}[
+%      last-col,
+%      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{pNiceArray}\]
+%
+% \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{pNiceArray}{CCC}[
+%      last-col,
+%      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{pNiceArray}\]
+%
+%                           
+% \vspace{1cm}
+% 
+% In the following example, we use the ``large nodes'' to highlight a zone of the matrix.\par\nobreak
+% \begin{Verbatim}
+% \begin{pNiceArray}{>{\strut}CCCC}%
+%    [create-extra-nodes,margin,extra-margin=2pt,
+%     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{pNiceArray}
+% \end{Verbatim}
+%                              
+% \[ \begin{pNiceArray}{>{\strut}CCCC}[
+%     create-extra-nodes,margin,extra-margin=2pt,
+%     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{pNiceArray}\]
+%
+% 
+% \subsection{Direct utilisation of the Tikz nodes}
+%
+% In the following example, we illustrate the mathematical product of two matrices.
+%
+% \medskip
+% The utilisation of |{NiceMatrixBlock}| with the option |auto-columns-width|
+% gives the same width for all the columns and, therefore, a perfect alignment
+% of the two superposed matrices.
+% \begin{Verbatim}
+% \begin{NiceMatrixBlock}[auto-columns-width]
+% \end{Verbatim}
+%
+% \begin{Verbatim}
+% \NiceMatrixOptions{nullify-dots}
+% \end{Verbatim}
+%
+% The three matrices will be displayed using an environment |{array}| (an
+% environment |{tabular}| may also be possible).
+% \begin{Verbatim}
+% $\begin{array}{cc}
+% & 
+% \end{Verbatim}
+%
+% The matrix $B$ has a ``first row'' (for $C_j$) and that's why we use the key |first-row|.
+% \begin{Verbatim}
+% \begin{bNiceArray}{C>{\strut}CCCC}[name=B,first-row]
+%       &        & C_j \\
+% b_{11} & \Cdots & b_{1j} & \Cdots & b_{1n} \\
+% \Vdots &       & \Vdots &       & \Vdots \\
+%        &       & b_{kj}  \\
+%        &       & \Vdots \\
+%  b_{n1}  & \Cdots & b_{nj} & \Cdots & b_{nn} 
+% \end{bNiceArray} \\ \\
+% \end{Verbatim}
+%
+% The matrix $A$ has a ``first column'' (for $L_i$) and that's why we use the
+% key |first-col|.
+% \begin{Verbatim}
+% \begin{bNiceArray}{CC>{\strut}CCC}[name=A,first-col]
+%     & a_{11} & \Cdots &  &  & a_{nn} \\
+%     & \Vdots &       &  &  & \Vdots \\
+% L_i & a_{i1} & \Cdots & a_{ik} & \Cdots & a_{in} \\
+%     & \Vdots &       &  &  & \Vdots \\
+%     & a_{n1} & \Cdots &  &  & a_{nn} \\
+% \end{bNiceArray}
+% & 
+% \end{Verbatim}
+%
+% In the matrix product, the two dotted lines have an open extremity.
+% \begin{Verbatim}
+% \begin{bNiceArray}{CC>{\strut}CCC}
+%        &         & & & \\
+%        &         & \Vdots \\
+% \Cdots &         & c_{ij}  \\
+% \\
+% \\
+% \end{bNiceArray} 
+% \end{array}$
+%
+% \end{NiceMatrixBlock}
+% \end{Verbatim}
+%
+% \begin{Verbatim}                             
+% \begin{tikzpicture}[remember picture, overlay]
+%  \node [highlight, fit = (A-3-1) (A-3-5) ] {} ; 
+%  \node [highlight, fit = (B-1-3) (B-5-3) ] {} ; 
+%  \draw [color = gray] (A-3-3) to [bend left] (B-3-3) ; 
+% \end{tikzpicture}
+% \end{Verbatim}
+% 
+%
+% \begin{NiceMatrixBlock}[auto-columns-width]
+% \NiceMatrixOptions{nullify-dots}
+% $\begin{array}{cc}
+% & 
+% \begin{bNiceArray}{C>{\strut}CCCC}[name=B,first-row]
+%       &        & C_j \\
+% b_{11} & \Cdots & b_{1j} & \Cdots & b_{1n} \\
+% \Vdots &       & \Vdots &       & \Vdots \\
+%        &       & b_{kj}  \\
+%        &       & \Vdots \\
+%  b_{n1}  & \Cdots & b_{nj} & \Cdots & b_{nn} 
+% \end{bNiceArray} \\ \\
+% \begin{bNiceArray}{CC>{\strut}CCC}[name=A,first-col]
+%     & a_{11} & \Cdots &  &  & a_{nn} \\
+%     & \Vdots &       &  &  & \Vdots \\
+% L_i & a_{i1} & \Cdots & a_{ik} & \Cdots & a_{in} \\
+%     & \Vdots &       &  &  & \Vdots \\
+%     & a_{n1} & \Cdots &  &  & a_{nn} \\
+% \end{bNiceArray}
+% & 
+% \begin{bNiceArray}{CC>{\strut}CCC}
+%        &         & & & \\
+%        &         & \Vdots \\
+% \Cdots &         & c_{ij}  \\
+% \\
+% \\
+% \end{bNiceArray} 
+% \end{array}$
+%
+% \end{NiceMatrixBlock}
+%
+% \begin{tikzpicture}[remember picture, overlay]
+%  \node [highlight, fit = (A-3-1) (A-3-5) ] {} ; 
+%  \node [highlight, fit = (B-1-3) (B-5-3) ] {} ; 
+%  \draw [color = gray] (A-3-3) to [bend left] (B-3-3) ; 
+% \end{tikzpicture}
+%
+%
+% \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}
+% \NiceMatrixOptions{letter-for-dotted-lines = V}
+% \begin{pNiceArray}{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{pNiceArray}
+% \end{Verbatim}
+% 
+%                          
+% \begin{scope}    
+% \NiceMatrixOptions{letter-for-dotted-lines = V}
+% \[D = \begin{pNiceArray}{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{pNiceArray}\]
+% \end{scope}
+% 
+% 
+% 
+% \section{Implementation}
+%
+% By default, the package \pkg{nicematrix} doesn't patch any existing code.
+%
+% \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} is redefined. 
+%
+% \smallskip
+% On the other hand, the environment |{array}| is never redefined.
+%
+% \smallskip
+% Of course, the package \pkg{nicematrix} uses the features of the package
+% \pkg{array}. It tries to be independant of its implementation. Unfortunately,
+% it was not possible to be strictly independant: the package \pkg{nicematrix}
+% relies upon the fact that the package |{array}| uses |\ialign| to begin the |\halign|.
+% 
+% \smallskip
+% The desire to do no modification to existing code leads to complications in
+% the code of this extension.  
+%
+% \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 |\usetikzlibrary| in |expl3| code fails.\footnote{cf.
+% |tex.stackexchange.com/questions/57424/using-of-usetikzlibrary-in-an-expl3-package-fails|} 
+% 
+%    \begin{macrocode}
+%<@@=nm>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\RequirePackage{tikz}
+\usetikzlibrary{fit}
+\RequirePackage{expl3}[2019/02/15]
+%    \end{macrocode}
+% 
+% We give the traditionnal declaration of a package written with |expl3|:
+%    \begin{macrocode}
+\RequirePackage{l3keys2e}
+\ProvidesExplPackage
+  {nicematrix}
+  {\myfiledate}
+  {\myfileversion}
+  {Several features to improve the typesetting of mathematical matrices with TikZ}
+%    \end{macrocode}
+% 
+% \bigskip
+% We test if the class option |draft| has been used. In this case, we raise the
+% flag |\c_@@_draft_bool| because we won't draw the dotted lines if the option
+% |draft| is used. 
+%    \begin{macrocode}
+\bool_new:N \c_@@_draft_bool
+\DeclareOption { draft } { \bool_set_true:N \c_@@_draft_bool }
+\DeclareOption* { }
+\ProcessOptions \relax
+%    \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} and \pkg{amsmath}.
+%    \begin{macrocode}
+\RequirePackage { array }
+\RequirePackage { amsmath }
+\RequirePackage { xparse } [ 2018-10-17 ]
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_error:n { \msg_error:nn { nicematrix } }
+\cs_new_protected:Npn \@@_error:nn { \msg_error:nn { nicematrix } }
+\cs_new_protected:Npn \@@_fatal:n { \msg_fatal:nn { nicematrix } }
+\cs_new_protected:Npn \@@_fatal:nn { \msg_fatal:nn { nicematrix } }
+\cs_new_protected:Npn \@@_msg_new:nn { \msg_new:nnn { nicematrix } }
+\cs_new_protected:Npn \@@_msg_new:nnn { \msg_new:nnnn { nicematrix } }
+%    \end{macrocode}
+% 
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_msg_redirect_name:nn 
+  { \msg_redirect_name:nnn { nicematrix } }
+%    \end{macrocode}
+%
+%
+% \subsection{Technical  definitions}
+%
+% We test whether the current class is \cls{revtex4-1} or \cls{revtex4-2}
+% because these classes redefines |\array| (of \pkg{array}) in a way
+% incompatible with our programmation.
+%    \begin{macrocode}
+\bool_new:N \c_@@_revtex_bool
+\@ifclassloaded { revtex4-1 }
+  { \bool_set_true:N \c_@@_revtex_bool }
+  { }
+\@ifclassloaded { revtex4-2 }
+  { \bool_set_true:N \c_@@_revtex_bool }
+  { }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\@@_msg_new:nn { Draft~mode }
+  { The~compilation~is~in~draft~mode:~the~dotted~lines~won't~be~drawn. }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\bool_if:NT \c_@@_draft_bool 
+  { \msg_warning:nn { nicematrix }  { Draft~mode } }
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% 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. 
+% 
+%    \begin{macrocode}
+\ProvideDocumentCommand \iddots { }
+  { 
+    \mathinner
+      { 
+        \mkern 1 mu 
+        \raise \p@ \hbox:n { . }
+        \mkern 2 mu
+        \raise 4 \p@ \hbox:n { . }
+        \mkern 2 mu
+        \raise 7 \p@ \vbox { \kern 7 pt \hbox:n { . } } \mkern 1 mu 
+      } 
+  }
+%    \end{macrocode}
+%
+% This definition is a variant of the standard definition of |\ddots|.
+%
+%
+% \bigskip 
+% The following counter will count the environments |{NiceArray}|. The value of
+% this counter will be used to prefix the names of the Tikz nodes created in the
+% array. 
+%    \begin{macrocode}
+\int_new:N \g_@@_env_int
+%    \end{macrocode}
+% 
+% \bigskip
+% The dimension |\l_@@_columns_width_dim| will be used when the options specify
+% that all the columns must have the same width.
+%    \begin{macrocode}
+\dim_new:N \l_@@_columns_width_dim
+%    \end{macrocode}
+%
+% \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. However, it's possible to use the option
+% |allow-duplicate-names|.
+%    \begin{macrocode}
+\seq_new:N \g_@@_names_seq
+%    \end{macrocode}
+%
+
+% \bigskip
+% We want to know if we are in an environment of \pkg{nicematrix} because we
+% will raise an error if the user tries to use nested environments.
+%    \begin{macrocode}
+\bool_new:N \l_@@_in_env_bool
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% If the user uses |{NiceArray}| (and not another environment relying upon
+% |{NiceArrayWithDelims}| like |{pNiceArray}|), we will raise the flag
+% |\l_@@_NiceArray_bool|. We have to know that, because, in |{NiceArray}|, we
+% won't use a structure with |\left| and |\right| and we will use the option of
+% position (|t|, |b| or |c|). 
+%    \begin{macrocode}
+\bool_new:N \l_@@_NiceArray_bool
+\bool_new:N \g_@@_NiceArray_bool
+%    \end{macrocode}
+% 
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_test_if_math_mode:
+  { 
+    \if_mode_math: \else:
+      \@@_fatal:n { Outside~math~mode } 
+    \fi:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\@@_msg_new:nn { Yet~in~env }
+  { 
+    Environments~\{NiceArray\}~(or~\{NiceMatrix\},~etc.)~can't~be~
+    nested.\\
+    This~error~is~fatal.
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\@@_msg_new:nn { Outside~math~mode }
+  {
+    The~environment~\{\@currenvir\}~can~be~used~only~in~math~mode~
+    (and~not~in~\token_to_str:N \vcenter).\\
+    This~error~is~fatal.
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% We have to known whether if \pkg{colortbl} is loaded for the redefinition of
+% |\everycr|. 
+%    \begin{macrocode}
+\bool_new:N \c_@@_colortbl_loaded_bool 
+\AtBeginDocument 
+  { 
+    \@ifpackageloaded { colortbl }
+      { \bool_set_true:N \c_@@_colortbl_loaded_bool }
+      { } 
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% \subsubsection{Variables for the exterior rows and columns}
+%
+% The keys for the exterior rows and columns are |first-row|, |first-col|,
+% |last-row| and |last-col|. However, internally, these keys are not coded in a
+% similar way. 
+%
+% \bigskip
+% \begin{itemize} 
+% \item \textbf{First row}\par\nobreak
+% The integer |\l_@@_first_row_int| is the number of the first row of the
+% array. The default value is $1$, but, if the option |first-row| is used,
+% the value will be~$0$. As usual, the global version is for the passage in the
+% |\group_insert_after:N|. 
+%    \begin{macrocode}
+\int_new:N \l_@@_first_row_int
+\int_set:Nn \l_@@_first_row_int 1
+\int_new:N \g_@@_first_row_int
+%    \end{macrocode}
+%
+% \medskip
+% \item \textbf{First column}\par\nobreak
+% The integer |\l_@@_first_col_int| is the number of the first column of the
+% array. The default value is $1$, but, if the option |first-col| is used, 
+% the value will be~$0$. 
+%    \begin{macrocode}
+\int_new:N \l_@@_first_col_int
+\int_set:Nn \l_@@_first_col_int 1
+\int_new:N \g_@@_first_col_int
+%    \end{macrocode}
+% 
+% \medskip
+% \item \textbf{Last row}\par\nobreak
+% The counter |\l_@@_last_row_int| is the number of the eventual ``last row'',
+% as specified by the key |last-row|. A value of $-2$ means that there is no
+% ``last row''. A value of $-1$ means that there is a ``last row'' but we don't
+% know the number of that row (the key |last-row| has been used without value
+% and has not still been read in the |aux|).
+%    \begin{macrocode}
+\int_new:N \l_@@_last_row_int 
+\int_set:Nn \l_@@_last_row_int { -2 }
+\int_new:N \g_@@_last_row_int 
+%    \end{macrocode}
+%
+% \smallskip
+% If, in an environment like |{pNiceArray}|, the option |last-row| is used
+% without value, we will globally raise the following flag. It will be used to
+% know if we have, after the construction of the array, to write in the |aux|
+% file the number of the ``last row''.\footnote{We can't use
+% |\l_@@_last_row_int| for this usage because, if \pkg{nicematrix} has read its
+% value from the |aux| file, the value of the counter won't be $-1$ any longer.}
+%    \begin{macrocode}
+\bool_new:N \l_@@_last_row_without_value_bool
+\bool_new:N \g_@@_last_row_without_value_bool
+%    \end{macrocode}
+%
+% \medskip
+% \item \textbf{Last column}\par\nobreak
+%
+% For the eventual ``last column'', we have a boolean an not an integer.
+%    \begin{macrocode}
+\bool_new:N \l_@@_last_col_bool 
+%    \end{macrocode}
+%
+% However, we have also another boolean. Consider the following code: 
+% \begin{center}
+% \begin{BVerbatim}
+% \begin{pNiceArray}{CC}[last-col]
+% 1 & 2 \\
+% 3 & 4
+% \end{pNiceArray}
+% \end{BVerbatim}
+% \end{center}
+% In such a code, the ``last column'' specified by the key |last-col| is not
+% used. We want to be able to detect such a situation and we create a boolean
+% for that job.
+%    \begin{macrocode}
+\bool_new:N \g_@@_last_col_found_bool
+%    \end{macrocode}
+% This boolean is set to |false| at the end of |\@@_pre_array:|.
+% \end{itemize}
+%       
+% \bigskip
+% \subsubsection{The column S of siunitx}
+%
+% 
+% We want to know whether the package \pkg{siunitx} is loaded and, if it is
+% loaded, we redefine the |S| columns of \pkg{siunitx}.
+%    \begin{macrocode}
+\bool_new:N \c_@@_siunitx_loaded_bool 
+\AtBeginDocument 
+  { 
+    \@ifpackageloaded { siunitx }
+      { \bool_set_true:N \c_@@_siunitx_loaded_bool }
+      { } 
+  }
+%    \end{macrocode}
+% 
+% \medskip
+% The command |\NC@rewrite@S| is a LaTeX command created by \pkg{siunitx} in
+% connection with the |S| column. In the code of \pkg{siunitx}, this command is
+% defined by:
+% \begin{Verbatim}[commandchars=\~\!\+, formatcom = \small]
+% \renewcommand*{\NC@rewrite@S}[1][]
+%   {
+%     \@temptokena \exp_after:wN
+%       {
+%         \tex_the:D \@temptokena
+%         > { \__siunitx_table_collect_begin: S {#1} }
+%         c
+%         < { \__siunitx_table_print: }
+%       }
+%     \NC@find
+%   } 
+% \end{Verbatim}
+% We want to patch this command (in the environments of \pkg{nicematrix}) in
+% order to have:
+% \begin{Verbatim}[commandchars=\~\!\+, formatcom = \small]
+% \renewcommand*{\NC@rewrite@S}[1][]
+%   {
+%     \@temptokena \exp_after:wN
+%       {
+%         \tex_the:D \@temptokena
+%         > { ~emphase!\@@_Cell:+ \__siunitx_table_collect_begin: S {#1} }
+%         c
+%         < { \__siunitx_table_print: ~emphase!\@@_end_Cell:+ }
+%       }
+%     \NC@find
+%   } 
+% \end{Verbatim}
+% However, we don't want do use explicitly any private command of \pkg{siunitx}.
+% That's why we will extract the name of the two |\__siunitx...| commands by
+% their position in the code of |\NC@rewrite@S|. 
+%
+% Since the command |\NC@rewrite@S| appends some tokens to the \emph{toks} list
+% |\@temptokena|, we use the LaTeX command |\NC@rewrite@S| in a group
+% (|\group_begin:|--|\group_end:|) and we extract the two command names which
+% are in the toks |\@temptokena|. However, this extraction can be done only
+% when \pkg{siunitx} is loaded (and it may be loaded after \pkg{nicematrix})
+% and, in fact, after the beginning of the document --- because some instructions of
+% \pkg{siunitx} are executed in a |\AtBeginDocument|). That's why this
+% extraction will be done only at the first utilisation of an environment of
+% \pkg{nicematrix} with the command |\@@_adapt_S_column:|. 
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_adapt_S_column:
+  {
+%    \end{macrocode}
+% In the preamble of the LaTeX document, the boolean |\c_@@_siunitx_loaded_bool|
+% won't be known. That's why we test the existence of |\c_@@_siunitx_loaded_bool|
+% and not its value.\footnote{Indeed, \pkg{nicematrix} may be used
+% in the preamble of the LaTeX document. For example, in this document, we compose a
+% matrix in the box |\ExampleOne| before loading \pkg{arydshln} (because
+% \pkg{arydshln} is not totally compatible with \pkg{nicematrix}).}
+%    \begin{macrocode}   
+    \bool_if:NT \c_@@_siunitx_loaded_bool
+      { 
+        \group_begin:
+        \@temptokena = { }
+%    \end{macrocode}
+% We protect |\NC@find| which is at the end of |\NC@rewrite@S|.
+%    \begin{macrocode}
+        \cs_set_eq:NN \NC@find \prg_do_nothing:
+        \NC@rewrite@S { }
+%    \end{macrocode}
+% Conversion of the \emph{toks} |\@temptokena| in a token list of \pkg{expl3}
+% (the toks are not supported by \pkg{expl3} but we can, nevertheless, use the
+% option |V| for |\tl_gset:NV|).
+%    \begin{macrocode}
+        \tl_gset:NV \g_tmpa_tl \@temptokena 
+        \group_end:
+        \tl_new:N \c_@@_table_collect_begin_tl
+        \tl_set:Nx \l_tmpa_tl { \tl_item:Nn \g_tmpa_tl 2 }
+        \tl_gset:Nx \c_@@_table_collect_begin_tl { \tl_item:Nn \l_tmpa_tl 1 }
+        \tl_new:N \c_@@_table_print_tl
+        \tl_gset:Nx \c_@@_table_print_tl { \tl_item:Nn \g_tmpa_tl { -1 } }
+%    \end{macrocode}
+% The token lists |\c_@@_table_collect_begin_tl| and |\c_@@_table_print_tl| contain
+% now the two commands of \pkg{siunitx}.
+% 
+% \smallskip
+% If the adaptation has been done, the command |\@@_adapt_S_column:| becomes
+% no-op (globally). 
+%    \begin{macrocode}
+        \cs_gset_eq:NN \@@_adapt_S_column: \prg_do_nothing:
+      }
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% The command |\@@_renew_NC@rewrite@S:| will be used in each environment of
+% \pkg{nicematrix} in order to ``rewrite'' the |S| column in each environment
+% (only if the boolean |\c_@@_siunitx_loaded_bool| is raised, of course).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_renew_NC@rewrite@S:
+  {
+    \renewcommand*{\NC@rewrite@S}[1][]
+      {
+        \@temptokena \exp_after:wN
+          {
+            \tex_the:D \@temptokena
+            > { \@@_Cell: \c_@@_table_collect_begin_tl S {##1} }
+            c
+            < { \c_@@_table_print_tl \@@_end_Cell: }
+          }
+        \NC@find
+      }
+  }
+%    \end{macrocode}
+%                               
+%
+% \bigskip 
+% \subsection{The options}
+% 
+%    \begin{macrocode}
+\@@_msg_new:nn { Option~Transparent~suppressed }
+  { 
+    The~option~'Transparent'~has~been~renamed~'transparent'.\\
+    However,~you~can~go~on~for~this~time.
+  }
+\@@_msg_new:nn { Option~RenewMatrix~suppressed }
+  { 
+    The~option~'RenewMatrix'~has~been~renamed~'renew-matrix'.\\
+    However,~you~can~go~on~for~this~time.
+  }
+%    \end{macrocode}
+%
+%
+% The token list |\l_@@_pos_env_str| 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 |{pNiceMatrix}|,
+% |{pNiceArray}| 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}
+\str_new:N \l_@@_pos_env_str 
+\str_set:Nn \l_@@_pos_env_str c
+%    \end{macrocode}
+% 
+% \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}| (as it is done in
+% |{array}| of \pkg{array}).
+%    \begin{macrocode}
+\bool_new:N \l_@@_exterior_arraycolsep_bool
+%    \end{macrocode}
+%
+% \bigskip
+% The flag |\l_@@_parallelize_diags_bool| controls whether the diagonals are
+% parallelized. The initial value is~|true|.
+%    \begin{macrocode}
+\bool_new:N \l_@@_parallelize_diags_bool
+\bool_set_true:N \l_@@_parallelize_diags_bool
+%    \end{macrocode}
+%
+% \bigskip
+% The flag |\l_@@_hlines_bool| corresponds to the option |\hlines|.
+%    \begin{macrocode}
+\bool_new:N \l_@@_hlines_bool
+%    \end{macrocode}
+% 
+% \bigskip
+% The flag |\l_@@_nullify_dots_bool| corresponds to the option |nullify-dots|.
+% When the flag is down, the instructions like |\vdots| are inserted within a
+% |\hphantom| (and so the constructed matrix has exactly the same size as a
+% matrix constructed with the classical |{matrix}| and |\ldots|, |\vdots|,
+% etc.). 
+%    \begin{macrocode}
+\bool_new:N \l_@@_nullify_dots_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 same width equal to the largest width of a
+% cell of the array (except the cell of the potential exterior columns).
+%    \begin{macrocode}
+\bool_new:N \l_@@_auto_columns_width_bool
+%    \end{macrocode}
+% 
+% 
+% \bigskip
+% We don't want to patch any existing code. That's why some code must be
+% executed in a |\group_insert_after:N|. 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 |\group_insert_after:N|.
+% Therefore, for those quantities, we have two parameters, one local and one
+% global. For example, we have |\l_@@_name_str| and |\g_@@_name_str|. 
+%
+% \bigskip
+% The token list |\l_@@_name_str| 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}
+\str_new:N \l_@@_name_str
+\str_new:N \g_@@_name_str
+%    \end{macrocode}
+%
+% \bigskip
+% The boolean |\l_@@_extra_nodes_bool| will be used to indicate whether 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
+\dim_new:N \g_@@_width_last_col_dim
+\dim_new:N \g_@@_width_first_col_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
+% First, we define a set of keys ``|NiceMatrix / Global|'' which will be used
+% (with the mechanism of |.inherit:n|) by other sets of keys.
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / Global }
+  {
+    hlines .bool_set:N = \l_@@_hlines_bool ,
+    parallelize-diags .bool_set:N = \l_@@_parallelize_diags_bool ,
+    parallelize-diags .default:n = true ,
+%    \end{macrocode}
+%
+% \bigskip
+% With the option |renew-dots|, the command |\cdots|, |\ldots|, |\vdots| and
+% |\ddots| are redefined and behave like the commands |\Cdots|, |\Ldots|,
+% |\Vdots| and |\Ddots|. 
+%    \begin{macrocode}
+    renew-dots .bool_set:N = \l_@@_renew_dots_bool ,
+    renew-dots .default:n = true ,
+    nullify-dots .bool_set:N = \l_@@_nullify_dots_bool ,
+    nullify-dots .default:n = true ,
+%    \end{macrocode}
+%
+% \bigskip
+% An option to test whether the extra nodes will be created (these nodes are the
+% ``medium nodes'' and ``large nodes''). In some circonstancies, the extra nodes
+% are created automatically, for example when a dotted line has an ``open''
+% extremity.\footnote{In fact, we should not because, if there is a |w|~node,
+% the |w|~node is used instead of the ``medium'' node.} 
+%    \begin{macrocode}
+    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 ,
+    margin .meta:n = { left-margin = #1 , right-margin = #1 } ,
+    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 ,
+    extra-margin .meta:n = 
+     { extra-left-margin = #1 , extra-right-margin = #1 } ,
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% The following set of keys concerns the options to \emph{customize} the
+% exterior columns, that is to say the options |code-for-first-row|, etc.
+%    \begin{macrocode}     
+\keys_define:nn { NiceMatrix / Code }
+  {
+    code-for-first-col .tl_set:N = \l_@@_code_for_first_col_tl ,
+    code-for-first-col .value_required:n = true ,
+    code-for-last-col .tl_set:N = \l_@@_code_for_last_col_tl ,
+    code-for-last-col .value_required:n = true ,
+    code-for-first-row .tl_set:N = \l_@@_code_for_first_row_tl ,
+    code-for-first-row .value_required:n = true ,
+    code-for-last-row .tl_set:N = \l_@@_code_for_last_row_tl ,
+    code-for-last-row .value_required:n = true ,
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% We define a set of keys used by the environments of \pkg{nicematrix} (but not
+% by the command |\NiceMatrixOptions|). 
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / Env }
+  {
+    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 = 
+      \str_set:Nn \l_tmpa_str { #1 }
+      \seq_if_in:NVTF \g_@@_names_seq \l_tmpa_str
+         { \@@_error:nn { Duplicate~name } { #1 } }
+         { \seq_gput_left:NV \g_@@_names_seq \l_tmpa_str }
+      \str_set_eq:NN \l_@@_name_str \l_tmpa_str ,
+    name .value_required:n = true ,
+    code-after .tl_gset:N = \g_@@_code_after_tl ,
+    code-after .initial:n = \c_empty_tl ,
+    code-after .value_required:n = true ,
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% We begin the construction of the major sets of keys (used by the different
+% user commands and environments). 
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix }
+  { 
+    NiceMatrixOptions .inherit:n = 
+      {  
+        NiceMatrix / Global ,
+        NiceMatrix / Code 
+      } ,
+    NiceMatrix .inherit:n = 
+      { 
+        NiceMatrix / Global ,
+        NiceMatrix / Env 
+      } ,
+    NiceArray .inherit:n = 
+      { 
+        NiceMatrix / Global ,
+        NiceMatrix / Env ,
+        NiceMatrix / Code 
+      } ,
+    pNiceArray .inherit:n = 
+      { 
+        NiceMatrix / Global ,
+        NiceMatrix / Env ,
+        NiceMatrix / Code 
+      } 
+  }
+%    \end{macrocode}
+% 
+%
+% \bigskip
+% We finalise the definition of the set of keys 
+% ``|NiceMatrix / NiceMatrixOptions|'' with the options specific to
+% |\NiceMatrixOptions|.    
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / NiceMatrixOptions }
+  { 
+%    \end{macrocode}
+%                              
+% 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 = \@@_renew_matrix: ,
+    renew-matrix .value_forbidden:n = true ,
+    RenewMatrix .code:n = \@@_error:n { Option~RenewMatrix~suppressed } 
+                          \@@_renew_matrix: ,
+    transparent .meta:n = { renew-dots , renew-matrix } ,
+    transparent .value_forbidden:n = true,
+    Transparent .code:n = \@@_error:n { Option~Transparent~suppressed } 
+                          \@@_renew_matrix:
+                          \bool_set_true:N \l_@@_renew_dots_bool ,
+%    \end{macrocode}
+%                              
+%
+% \bigskip
+% The option |exterior-arraycolsep| will have effect only in |{NiceArray}| for
+% those who want to have for |{NiceArray}| the same behaviour as |{array}|.
+%    \begin{macrocode}
+    exterior-arraycolsep .bool_set:N = \l_@@_exterior_arraycolsep_bool ,
+    exterior-arraycolsep .default:n  = true ,
+%    \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.
+%    \begin{macrocode}
+    columns-width .code:n = 
+      \str_if_eq:nnTF { #1 } { auto }
+        { \@@_error:n { Option~auto~for~columns-width } }
+        { \dim_set:Nn \l_@@_columns_width_dim { #1 } } ,
+%    \end{macrocode}
+%
+% \bigskip
+% Usually, an error is raised when the user tries to give the same to name two
+% distincts environments of \pkg{nicematrix} (theses names are global and not
+% local to the current TeX scope). However, the option |allow-duplicate-names|
+% disables this feature. 
+%    \begin{macrocode}
+    allow-duplicate-names .code:n = 
+      \@@_msg_redirect_name:nn { Duplicate~name } { none } ,
+    allow-duplicate-names .value_forbidden:n = true ,
+%    \end{macrocode}
+%
+% \bigskip
+% By default, the specifier used in the preamble of the array (for example in
+% |{pNiceArray}|) to draw a vertical dotted line between two columns is the
+% colon ``|:|''. However, it's possible to change this letter with
+% |letter-for-dotted-lines| and, by the way, the letter ``|:|'' will remain free
+% for other packages (for example \pkg{arydshln}).
+%    \begin{macrocode}
+    letter-for-dotted-lines .code:n = 
+      {
+        \int_compare:nTF { \tl_count:n { #1 } = \c_one_int }
+          { \tl_set:Nx \l_@@_letter_for_dotted_lines_str { #1 } }
+          { \@@_error:n { Bad~value~for~letter~for~dotted~lines } } 
+      } ,
+    letter-for-dotted-lines .value_required:n = true ,
+    letter-for-dotted-lines .initial:n = \c_colon_str ,
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+    unknown .code:n  = \@@_error:n { Unknown~key~for~NiceMatrixOptions } }
+%    \end{macrocode}
+%
+%
+% \bigskip 
+%    \begin{macrocode}
+\@@_msg_new:nn { Bad~value~for~letter~for~dotted~lines }
+  { 
+    The~value~of~key~'\tl_use:N\l_keys_key_tl'~must~be~of~length~1.\\
+    If~you~go~on,~it~will~be~ignored. 
+  }
+%    \end{macrocode}
+%
+%
+% \bigskip
+%    \begin{macrocode}
+\@@_msg_new:nnn { Unknown~key~for~NiceMatrixOptions }
+  {
+    The~key~'\tl_use:N\l_keys_key_tl'~is~unknown~for~the~command~
+    \token_to_str:N \NiceMatrixOptions. \\
+    If~you~go~on,~it~will~be~ignored. \\
+    For~a~list~of~the~available~keys,~type~H~<return>.
+  }
+  { 
+    The~available~keys~are~(in~alphabetic~order):~
+    allow-duplicate-names,~
+    code-for-first-col,~
+    code-for-first-row,~
+    code-for-last-col,~
+    code-for-last-row,~
+    exterior-arraycolsep,~
+    hlines,~
+    left-margin,~
+    letter-for-dotted-lines,~
+    nullify-dots,~
+    parallelize-diags,~
+    renew-dots,~
+    renew-matrix,~
+    right-margin,~
+    and~transparent
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\@@_msg_new:nn { Option~auto~for~columns-width }
+  { 
+    You~can't~give~the~value~'auto'~to~the~option~'columns-width'~here.~
+    If~you~go~on,~the~option~will~be~ignored.
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% |\NiceMatrixOptions| is the command of the \pkg{nicematrix} package to fix
+% options at the document level. The scope of these specifications is the
+% current TeX group. 
+%    \begin{macrocode}
+\NewDocumentCommand \NiceMatrixOptions { m }
+  { \keys_set:nn { NiceMatrix / NiceMatrixOptions } { #1 } }
+%    \end{macrocode}
+%
+%
+% \bigskip
+% We finalise the definition of the set of keys 
+% ``|NiceMatrix / NiceMatrix|'' with the options specific to |{NiceMatrix}|.
+%
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / NiceMatrix }
+  { unknown .code:n = \@@_error:n { Unknown~option~for~NiceMatrix } }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\@@_msg_new:nnn { Unknown~option~for~NiceMatrix }
+  { 
+    The~option~'\tl_use:N\l_keys_key_tl'~is~unknown~for~the~environment~
+    \{NiceMatrix\}~and~its~variants. \\
+    If~you~go~on,~it~will~be~ignored. \\
+    For~a~list~of~the~available~options,~type~H~<return>.
+  }
+  { 
+    The~available~options~are~(in~alphabetic~order):~
+    code-after,~
+    columns-width,~
+    create-extra-nodes,~
+    extra-left-margin,~
+    extra-right-margin,~
+    hlines,~
+    left-margin,~
+    name,~
+    nullify-dots,~
+    parallelize-diags,~
+    renew-dots~
+    and~right-margin.
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+%    \begin{macrocode}
+\@@_msg_new:nnn { Duplicate~name }
+  { 
+    The~name~'\l_keys_value_tl'~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~<return>. \\ 
+    If~you~don't~want~to~see~this~message~again,~use~the~option~
+    'allow-duplicate-names'. 
+  }
+  {
+    The~names~already~defined~in~this~document~are:~
+    \seq_use:Nnnn \g_@@_names_seq { ,~ } { ,~ } { ~and~ }.
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% 
+% \bigskip
+% We finalise the definition of the set of keys 
+% ``|NiceMatrix / NiceArray|'' with the options specific to |{NiceArray}|.
+%
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / NiceArray }
+  {
+%    \end{macrocode}
+% 
+% \bigskip
+% The options |c|, |t| and |b| of the environment |{NiceArray}| have the same
+% meaning as the option of the classical environment |{array}|.
+%    \begin{macrocode}
+    c .code:n = \str_set:Nn \l_@@_pos_env_str c ,
+    t .code:n = \str_set:Nn \l_@@_pos_env_str t ,
+    b .code:n = \str_set:Nn \l_@@_pos_env_str b ,
+    first-col .code:n = \int_zero:N \l_@@_first_col_int , 
+    last-col .bool_set:N = \l_@@_last_col_bool ,
+    first-row .code:n = \int_zero:N \l_@@_first_row_int ,
+    last-row .int_set:N = \l_@@_last_row_int ,
+    last-row .default:n = -1 ,
+    unknown .code:n = \@@_error:n { Unknown~option~for~NiceArray } 
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\@@_msg_new:nnn { Unknown~option~for~NiceArray }
+  { 
+    The~option~'\tl_use:N\l_keys_key_tl'~is~unknown~for~the~environment~
+    \{NiceArray\}. \\
+    If~you~go~on,~it~will~be~ignored. \\
+    For~a~list~of~the~available~options,~type~H~<return>.
+  }
+  {
+    The~available~options~are~(in~alphabetic~order):~
+    b,~
+    c,~
+    code-after,~
+    code-for-first-col,~
+    code-for-first-row,~
+    code-for-last-col,~
+    code-for-last-row,~
+    columns-width,~
+    create-extra-nodes,~
+    extra-left-margin,~
+    extra-right-margin,~
+    hlines,~
+    left-margin,~
+    name,~
+    nullify-dots,~
+    parallelize-diags,~
+    renew-dots,~
+    right-margin,~
+    and~t.
+  }
+%    \end{macrocode}
+%
+%    
+%    \begin{macrocode}
+\keys_define:nn { NiceMatrix / pNiceArray }
+  { 
+    first-col .code:n = \int_zero:N \l_@@_first_col_int , 
+    last-col .bool_set:N = \l_@@_last_col_bool ,
+    first-row .code:n = \int_zero:N \l_@@_first_row_int ,
+    last-row .int_set:N = \l_@@_last_row_int ,
+    last-row .default:n = -1 ,
+    unknown .code:n = \@@_error:n { Unknown~option~for~pNiceArray } 
+  }
+%    \end{macrocode}
+%
+%
+%    \begin{macrocode}
+\@@_msg_new:nnn { Unknown~option~for~pNiceArray }
+  { 
+    The~option~'\tl_use:N\l_keys_key_tl'~is~unknown~for~the~environment~
+    \{\@currenvir\}. \\
+    If~you~go~on,~it~will~be~ignored. \\
+    For~a~list~of~the~available~options,~type~H~<return>.
+  }
+  {
+    The~available~options~are~(in~alphabetic~order):~
+    code-after,~
+    code-for-first-col,~
+    code-for-first-row,~
+    code-for-last-col,~
+    code-for-last-row,~
+    columns-width,~
+    create-extra-nodes,~
+    extra-left-margin,~
+    extra-right-margin,~
+    first-col,~
+    first-row,~
+    last-col,~
+    last-row,~
+    hlines,~
+    left-margin,~
+    name,~
+    nullify-dots,~
+    parallelize-diags,~
+    renew-dots,~
+    and~right-margin.
+  }
+%    \end{macrocode}
+%
+% \subsection{Code common to \{NiceArrayWithDelims\} and \{NiceMatrix\}}
+%
+% 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}|). 
+%
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_Cell:
+  { 
+%    \end{macrocode}
+% We increment |\g_@@_col_int|, which is the counter of the columns. 
+%    \begin{macrocode}
+    \int_gincr:N \g_@@_col_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{arydshln}, create special rows
+% in the |\halign| that we don't want to take into account. 
+%    \begin{macrocode}
+    \int_compare:nNnT \g_@@_col_int = \c_one_int
+      { 
+        \int_compare:nNnT \l_@@_first_col_int = \c_one_int
+          \@@_begin_of_row: 
+      }
+    \int_gset:Nn \g_@@_col_total_int 
+      { \int_max:nn \g_@@_col_total_int \g_@@_col_int }
+%    \end{macrocode}
+% The content of the cell is composed in the box |\l_tmpa_box| because we want
+% to compute some dimensions of the box. The |\hbox_set_end:| corresponding to
+% this |\hbox_set:Nw| will be in the |\@@_end_Cell:| (and the
+% |\c_math_toggle_token| also).
+%    \begin{macrocode}
+    \hbox_set:Nw \l_tmpa_box 
+    \c_math_toggle_token
+    \int_compare:nNnTF \g_@@_row_int = \c_zero_int 
+      \l_@@_code_for_first_row_tl   
+      {
+        \int_compare:nNnT \g_@@_row_int = \l_@@_last_row_int
+          \l_@@_code_for_last_row_tl 
+      }
+  }
+%    \end{macrocode}
+%
+% \interitem
+% The following macro |\@@_begin_of_row| is usually used in the cell
+% number~$1$ of the array. However, when the key |first-col| is used,
+% |\@@_begin_of_row| is executed in the cell number~$0$ of the array.
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_begin_of_row:
+  {
+    \int_gincr:N \g_@@_row_int 
+    \dim_gset_eq:NN \g_@@_dp_ante_last_row_dim \g_@@_dp_last_row_dim 
+    \dim_gzero:N \g_@@_dp_last_row_dim 
+    \dim_gzero:N \g_@@_ht_last_row_dim 
+  }
+%    \end{macrocode}
+% 
+%
+% \interitem
+% The following code is used in each cell of the array. It actualises quantities
+% that, at the end of the array, will give informations about the vertical
+% dimension of the two first rows and the two last rows.
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_actualization_for_first_and_last_row:
+  {
+    \int_compare:nNnT \g_@@_row_int = \c_zero_int
+      { 
+        \dim_gset:Nn \g_@@_dp_row_zero_dim
+          { \dim_max:nn \g_@@_dp_row_zero_dim { \box_dp:N \l_tmpa_box } }
+        \dim_gset:Nn \g_@@_ht_row_zero_dim
+          { \dim_max:nn \g_@@_ht_row_zero_dim { \box_ht:N \l_tmpa_box } } 
+      }
+    \int_compare:nNnT \g_@@_row_int = \c_one_int
+      { 
+        \dim_gset:Nn \g_@@_ht_row_one_dim
+          { \dim_max:nn \g_@@_ht_row_one_dim { \box_ht:N \l_tmpa_box } } 
+      }
+    \dim_gset:Nn \g_@@_ht_last_row_dim
+      { \dim_max:nn \g_@@_ht_last_row_dim { \box_ht:N \l_tmpa_box } } 
+    \dim_gset:Nn \g_@@_dp_last_row_dim
+      { \dim_max:nn \g_@@_dp_last_row_dim { \box_dp:N \l_tmpa_box } } 
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_end_Cell:
+  { 
+    \c_math_toggle_token 
+    \hbox_set_end:
+%    \end{macrocode}
+%
+% We want to compute in |\l_@@_max_cell_width_dim| the width of the widest cell
+% of the array (except the cells of the ``first column'' and the ``last
+% column''). 
+% 
+%    \begin{macrocode}
+    \dim_gset:Nn \g_@@_max_cell_width_dim
+      { \dim_max:nn \g_@@_max_cell_width_dim { \box_wd:N \l_tmpa_box } }
+%    \end{macrocode}
+%
+% The following computations are for the ``first row'' and the ``last row''.
+%    \begin{macrocode}
+    \@@_actualization_for_first_and_last_row:
+%    \end{macrocode}
+% 
+% Now, we can create the Tikz node of the cell.
+%    \begin{macrocode}
+    \tikz 
+      [ 
+        remember~picture , 
+        inner~sep = \c_zero_dim , 
+        minimum~width = \c_zero_dim , 
+        baseline 
+      ]
+    \node 
+      [
+        anchor = base ,
+        name = nm - \int_use:N \g_@@_env_int -
+                    \int_use:N \g_@@_row_int -
+                    \int_use:N \g_@@_col_int ,
+        alias = 
+          \str_if_empty:NF \l_@@_name_str
+            { 
+              \l_@@_name_str -
+              \int_use:N \g_@@_row_int -
+              \int_use:N \g_@@_col_int
+            } 
+      ] 
+    \bgroup 
+    \box_use:N \l_tmpa_box
+    \egroup ;
+  } 
+%    \end{macrocode}
+%
+% 
+%    \begin{macrocode}
+\cs_generate_variant:Nn \dim_set:Nn { N x }
+%    \end{macrocode}
+% 
+% \bigskip
+% In the environment |{NiceArrayWithDelims}|, we will have to redefine the
+% column types |w| and |W|. These definitions are rather long because we have to
+% construct the |w|-nodes in these columns. The redefinition of these two column
+% types are very close and that's why we use a macro |\@@_renewcolumntype:nn|.
+% The first argument is the type of the column (|w| or |W|) and the second
+% argument is a code inserted at a special place and which is the only
+% difference between the two definitions.
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_renewcolumntype:nn
+  {
+    \newcolumntype #1 [ 2 ]
+      { 
+        > { 
+            \hbox_set:Nw \l_tmpa_box
+            \@@_Cell:
+          }
+        c
+        < { 
+            \@@_end_Cell:
+            \hbox_set_end:
+            #2 
+            \hbox_set:Nn \l_tmpb_box 
+              { \makebox [ ##2 ] [ ##1 ] { \box_use:N \l_tmpa_box } }
+            \dim_set:Nn \l_tmpa_dim { \box_dp:N \l_tmpb_box }
+            \box_move_down:nn \l_tmpa_dim 
+              { 
+                \vbox:n
+                  { 
+                    \hbox_to_wd:nn { \box_wd:N \l_tmpb_box }
+                      { 
+                        \hfil 
+                        \tikz [ remember~picture , overlay ]
+                        \coordinate (@@~north~east) ; 
+                      }
+                    \hbox:n
+                      {
+                        \tikz [ remember~picture , overlay ]
+                        \coordinate (@@~south~west) ;
+                        \box_move_up:nn \l_tmpa_dim { \box_use:N \l_tmpb_box }
+                      }         
+                  }
+              }
+%    \end{macrocode}
+% The |w|-node is created using the Tikz library |fit| after construction of the
+% nodes |(@@~south~west)| and |(@@~north~east)|. It's not possible to construct
+% by a standard |node| instruction because such a construction give an erroneous
+% result with some engines (|XeTeX|, |LuaTeX|) although the result is good with
+% |pdflatex| (why?). 
+%    \begin{macrocode}
+            \tikz [ remember~picture , overlay ]
+            \node 
+              [
+                node~contents = { } ,
+                name = nm - \int_use:N \g_@@_env_int -
+                            \int_use:N \g_@@_row_int -
+                            \int_use:N \g_@@_col_int - w,
+                alias = 
+                  \str_if_empty:NF \l_@@_name_str
+                    { 
+                      \l_@@_name_str -
+                      \int_use:N \g_@@_row_int -
+                      \int_use:N \g_@@_col_int - w 
+                    } ,
+                inner~sep = \c_zero_dim ,
+                fit = (@@~south~west) (@@~north~east)
+              ] 
+            ;
+          }  
+      }
+  }
+%    \end{macrocode}
+% 
+% 
+% \interitem
+% The argument of the following command |\@@_instruction_of_type:n| defined
+% below 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}|
+%
+% \verb|\@@_draw_Hdotsfor:nnn {3}{2}{2}|
+% \end{scope} 
+% 
+%
+% We begin with a test of the flag |\c_@@_draft_bool| because, if the key
+% |draft| is used, the dotted lines are not drawn.
+%    \begin{macrocode}
+\bool_if:NTF \c_@@_draft_bool
+  { \cs_set_protected:Npn \@@_instruction_of_type:n #1 { } }
+  {
+    \cs_new_protected:Npn \@@_instruction_of_type:n #1
+      { 
+        \tl_gput_right:Nx \g_@@_lines_to_draw_tl 
+          { 
+            \use:c { @@ _ draw _ #1 : nn } 
+              { \int_use:N \g_@@_row_int } 
+              { \int_use:N \g_@@_col_int }
+          }
+      }  
+  }
+%    \end{macrocode}
+%
+%  
+% \bigskip
+% We want to use |\array| of \pkg{array}. However, if the class used is
+% \cls{revtex4-1} or \cls{revtex4-2}, we have to do some tuning and use the
+% command |\@array@array| instead of |\array| because these classes do a
+% redefinition of |\array| incompatible with our use of |\array|. 
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_array:
+  {
+    \bool_if:NTF \c_@@_revtex_bool
+      { 
+        \cs_set_eq:NN \@acoll \@arrayacol 
+        \cs_set_eq:NN \@acolr \@arrayacol 
+        \cs_set_eq:NN \@acol \@arrayacol 
+        \cs_set:Npn \@halignto { }
+        \@array@array
+      }
+      \array
+%    \end{macrocode}
+% |\l_@@_pos_env_str| may have the value |t|, |c| or |b|.
+%    \begin{macrocode}
+    [ \l_@@_pos_env_str ]
+  }
+%    \end{macrocode}
+%
+%
+% 
+% \bigskip
+% The following must \emph{not} be protected because it begins with |\noalign|. 
+%    \begin{macrocode}
+\cs_new:Npn \@@_everycr:
+  { \noalign { \@@_everycr_i: } }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_everycr_i:
+  { 
+    \int_gzero:N \g_@@_col_int 
+    \bool_if:NT \l_@@_hlines_bool
+      {
+%    \end{macrocode}
+% The counter |\g_@@_row_int| has the value $-1$ only if there is a ``first
+% row'' and that we are before that ``first row'', i.e. just before the
+% beginning of the array. 
+%    \begin{macrocode}
+        \int_compare:nNnT \g_@@_row_int > { -1 }
+          {
+            \int_compare:nNnF \g_@@_row_int = \g_@@_last_row_int  
+              { 
+                \hrule \@height \arrayrulewidth
+                \skip_vertical:n { - \arrayrulewidth }
+              }
+          } 
+      }
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% The following code |\@@_pre_array:| is used in |{NiceArray}| and in
+% |{NiceMatrix}|. It contains code that will be executed \emph{before} the
+% construction of the array.
+% \label{prearray}
+%
+%   \begin{macrocode}
+\cs_new_protected:Npn \@@_pre_array:
+  { 
+%    \end{macrocode}
+%
+% If the user requires all the columns to have a width equal to the widest cell
+% of the array, we read this length in the file |.aux| (of, course, this is
+% possible only on the second run of LaTeX: on the first run, the dimension
+% |\l_@@_columns_width_dim| will be set to zero --- and the columns will have
+% their natural width). Remark that, even if the environment has a name (see
+% just below) we have to write in the |aux| file the information with the number
+% of environment because of |auto-columns-width| of |{NiceMatrixBlock}|.
+%    \begin{macrocode}
+    \bool_if:NT \l_@@_auto_columns_width_bool
+      { 
+        \group_insert_after:N \@@_write_max_cell_width:
+        \cs_if_free:cTF { _@@_max_cell_width_ \int_use:N \g_@@_env_int }
+          { \dim_zero:N \l_@@_columns_width_dim }
+          { 
+            \dim_set:Nx \l_@@_columns_width_dim 
+              { \use:c { _@@_max_cell_width _ \int_use:N \g_@@_env_int } } 
+          } 
+%    \end{macrocode}
+% If the environment has a name, we read the value of the maximal value of the
+% columns from |_@@_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}
+        \str_if_empty:NF \l_@@_name_str
+          { 
+            \cs_if_free:cF { _@@_max_cell_width_ \l_@@_name_str }
+              { 
+                \dim_set:Nx \l_@@_columns_width_dim 
+                  { \use:c { _@@_max_cell_width_ \l_@@_name_str } }
+              }
+          }
+      }
+%    \end{macrocode}
+% We don't want to patch any code and that's why some code is executed in a
+% |\group_insert_after:N|. In particular, in this |\group_insert_after:N|, 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
+    \int_gset_eq:NN \g_@@_last_row_int \l_@@_last_row_int
+    \tl_gset_eq:NN \g_@@_name_str \l_@@_name_str
+    \int_gset_eq:NN \g_@@_first_row_int \l_@@_first_row_int 
+    \int_gset_eq:NN \g_@@_first_col_int \l_@@_first_col_int 
+    \bool_gset_eq:NN \g_@@_NiceArray_bool \l_@@_NiceArray_bool
+    \bool_gset_eq:NN \g_@@_last_row_without_value_bool 
+       \l_@@_last_row_without_value_bool
+%    \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. 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 
+       { 
+         \bool_if:NTF \c_@@_colortbl_loaded_bool
+           {
+             \CT@everycr 
+               { 
+                 \noalign { \global\let\CT@row@color\relax }
+                 \@@_everycr:
+               }
+           }
+           { \everycr { \@@_everycr: } }
+         \tabskip = \c_zero_skip
+         \cs_set:Npn \ialign 
+            { 
+              \everycr { } 
+              \tabskip = \c_zero_skip
+              \halign
+            }
+         \halign 
+       }
+%    \end{macrocode}
+%                                                   
+% We define the new column types |L|, |C| and |R| that must be used instead of
+% |l|, |c| and |r| in the preamble of |{NiceArray}|.
+%    \begin{macrocode}
+    \dim_compare:nNnTF \l_@@_columns_width_dim = \c_zero_dim
+       {
+        \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 \pkg{array} which is, in fact, redefined below. 
+%    \begin{macrocode}
+       {
+        \newcolumntype L { w l { \dim_use:N \l_@@_columns_width_dim } }
+        \newcolumntype C { w c { \dim_use:N \l_@@_columns_width_dim } }
+        \newcolumntype R { w r { \dim_use:N \l_@@_columns_width_dim } } 
+       }
+%    \end{macrocode}
+% 
+%
+%    \begin{macrocode}
+    \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 \hdottedline \@@_hdottedline:
+    \cs_set_eq:NN \Hspace \@@_Hspace:
+    \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:
+      }
+%    \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. 
+%    \begin{macrocode}
+    \seq_gclear_new:N  \g_@@_empty_cells_seq
+%    \end{macrocode}
+%
+% 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}
+    \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 the first cell of the row). 
+%    \begin{macrocode}
+    \int_gzero_new:N \g_@@_row_int 
+    \int_gset:Nn \g_@@_row_int { \l_@@_first_row_int - 1 }
+%    \end{macrocode}
+%
+% At the end of the environment |{array}|, |\g_@@_row_int| will be the total
+% number de rows and |\g_@@_row_total_int| will be the number or rows excepted
+% the last row (if |\l_@@_last_row_bool| has been raised with the option
+% |last-row|). 
+%    \begin{macrocode}
+    \int_gzero_new:N \g_@@_row_total_int
+%    \end{macrocode}
+%
+% The counter |\g_@@_col_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_@@_col_total_int|. These counters are updated in the
+% command |\@@_Cell:| executed at the beginning of each cell.  
+%    \begin{macrocode}
+    \int_gzero_new:N \g_@@_col_int 
+    \int_gzero_new:N \g_@@_col_total_int
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+    \cs_set_eq:NN \@ifnextchar \new@ifnextchar
+%    \end{macrocode}
+% We nullify the definitions of the column types |w| and |W| before their
+% redefinition because we want to avoid a warning in the log file for a
+% redefinition of a column type. We must put |\relax| and not |\prg_do_nothing:|.
+%    \begin{macrocode}
+    \cs_set_eq:NN \NC@find@w \relax
+    \cs_set_eq:NN \NC@find@W \relax
+    \@@_renewcolumntype:nn w { }
+    \@@_renewcolumntype:nn W { \cs_set_eq:NN \hss \hfil }
+    \dim_gzero_new:N \g_@@_dp_row_zero_dim
+    \dim_gzero_new:N \g_@@_ht_row_zero_dim
+    \dim_gzero_new:N \g_@@_ht_row_one_dim
+    \dim_gzero_new:N \g_@@_dp_ante_last_row_dim
+    \dim_gzero_new:N \g_@@_ht_last_row_dim
+    \dim_gzero_new:N \g_@@_dp_last_row_dim
+%    \end{macrocode}
+%                               
+% \bigskip
+% By default, the letter used to specify a dotted line in the preamble of an
+% environment of \pkg{nicematrix} (for example in |{pNiceArray}|) is the letter
+% |:|. However, this letter is used by some extensions, for example
+% \pkg{arydshln}. That's why it's possible to change the letter used by
+% \pkg{nicematrix} with the option |letter-for-dotted-lines| which changes the
+% value of |\l_@@_letter_for_dotted_lines_str|.
+%    \begin{macrocode}
+    \exp_args:Nx \newcolumntype \l_@@_letter_for_dotted_lines_str
+      {
+        !
+          {
+            \skip_horizontal:n { 0.53 pt }
+            \bool_gset_true:N \g_@@_extra_nodes_bool
+%    \end{macrocode}
+%
+% \medskip
+% Consider the following code:
+% \begin{center}
+% \begin{BVerbatim}
+% \begin{NiceArray}{C:CC:C}
+% a & b
+% c & d \\
+% e & f & g & h \\
+% i & j & k & l 
+% \end{NiceArray}
+% \end{BVerbatim}
+% \end{center}
+% The first ``|:|'' in the preamble will be encountered during the first row of
+% the environment |{NiceArray}| but the second one will be encountered only in
+% the third row. We have to issue a command |\vdottedline:n| in the |code-after|
+% only one time for each ``|:|'' in the preamble. That's why we keep a counter
+% |\g_@@_last_vdotted_col_int| and with this counter, we know whether a letter
+% ``|:|'' encountered during the parsing has already been taken into account in
+% the |code-after|.
+%    \begin{macrocode}
+            \int_compare:nNnT \g_@@_col_int > \g_@@_last_vdotted_col_int
+              {
+                \int_gset_eq:NN \g_@@_last_vdotted_col_int \g_@@_col_int
+                \tl_gput_right:Nx \g_@@_code_after_tl
+%    \end{macrocode}
+% The command |\@@_vdottedline:n| is protected, and, therefore, won't be expanded
+% before writing on |\g_@@_code_after_tl|.
+%    \begin{macrocode}
+                  { \@@_vdottedline:n { \int_use:N \g_@@_col_int } }
+              }
+          }
+      }
+    \int_gzero_new:N \g_@@_last_vdotted_col_int
+    \bool_if:NT \c_@@_siunitx_loaded_bool \@@_renew_NC@rewrite@S:
+    \int_gset:Nn \g_@@_last_vdotted_col_int { -1 }
+    \bool_gset_false:N \g_@@_last_col_found_bool 
+ }
+%    \end{macrocode}
+%
+%
+%
+% \bigskip
+% \subsection{The environment \{NiceArrayWithDelims\}}
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment { NiceArrayWithDelims } { m m O { } m ! O { } }
+  { 
+    \@@_adapt_S_column:
+    \@@_test_if_math_mode:
+    \bool_if:NT \l_@@_in_env_bool { \@@_fatal:n { Yet~in~env } } 
+    \bool_set_true:N \l_@@_in_env_bool
+%    \end{macrocode}
+%
+% We deactivate Tikz externalization (since we use Tikz pictures with the
+% options |overlay| and |remember picture|, there would be errors).
+%    \begin{macrocode}
+    \cs_if_exist:NT \tikz@library@external@loaded
+      { \tikzset { external / export = false } }
+%    \end{macrocode}
+% In |{NiceArrayWithDelims}|, it would have been possible to avoid the
+% |\group_insert_after:N| and to put |\@@_after_array| in the second
+% part of the environment |{NiceArrayWithDelims}|. However, it's not possible to
+% do that in |{NiceMatrix}| (because of the option |renew-matrix|) and that's
+% why we use this technique in |{NiceArrayWithDelims}| and in |{NiceMatrix}|.
+%   \begin{macrocode}
+    \group_insert_after:N \@@_after_array:
+    \tl_gclear_new:N \g_@@_lines_to_draw_tl 
+%    \end{macrocode}
+%
+% We increment the counter |\g_@@_env_int| which counts the environments
+% of the extension.
+%    \begin{macrocode}
+    \int_gincr:N \g_@@_env_int
+    \bool_if:NF \l_@@_block_auto_columns_width_bool
+      { \dim_gzero_new:N \g_@@_max_cell_width_dim }
+%    \end{macrocode}
+%
+% We do a redefinition of |\@arrayrule| because we want that the vertical rules
+% drawn by "|" in the preamble of the array don't extend in the potential
+% exterior rows.
+%    \begin{macrocode}
+    \cs_set_protected:Npn \@arrayrule { \@addtopreamble \@@_vline: }
+%    \end{macrocode}
+% 
+%
+% The set of keys is not exactly the same for |{NiceArray}| and for the variants
+% of |{NiceArray}| (|{pNiceArray}|, |{bNiceArray}|, etc.) because, for
+% |{NiceArray}|, we have the options |t|, |c| and |b|.
+%    \begin{macrocode}
+    \bool_if:NTF \l_@@_NiceArray_bool 
+      { \keys_set:nn { NiceMatrix / NiceArray } }
+      { \keys_set:nn { NiceMatrix / pNiceArray } }
+    { #3 , #5 } 
+%    \end{macrocode}
+%
+% A value of $-1$ for the counter |\l_@@_last_row_int| means that the user has
+% used the option |last-row| without value, that is to say without specifying
+% the number of that last row. In this case, we try to read that value from the
+% |aux| file (if it has been written on a previous run). 
+%
+%    \begin{macrocode}
+    \int_compare:nNnT \l_@@_last_row_int = { -1 }
+      {
+        \bool_set_true:N \l_@@_last_row_without_value_bool
+%    \end{macrocode}
+% A value based the name is more reliable than a value based on the number of
+% the environment.
+%    \begin{macrocode}
+        \str_if_empty:NTF \g_@@_name_str
+          {
+            \cs_if_exist:cT { @@_last_row_ \int_use:N \g_@@_env_int } 
+              { 
+                \int_set:Nn \l_@@_last_row_int 
+                  { \use:c { @@_last_row_ \int_use:N \g_@@_env_int } }
+              }  
+          }
+          {
+            \cs_if_exist:cT { @@_last_row_ \g_@@_name_str } 
+              { 
+                \int_set:Nn \l_@@_last_row_int 
+                  { \use:c { @@_last_row_ \g_@@_name_str } }
+              }  
+          }
+      }
+%    \end{macrocode}
+%
+% The code in |\@@_pre_array:| is common to |{NiceArrayWithDelims}| and |{NiceMatrix}|.
+%    \begin{macrocode}
+    \@@_pre_array:
+%    \end{macrocode}
+%
+% \medskip
+% We compute the width of the two delimiters.
+%    \begin{macrocode}
+    \dim_zero_new:N \g_@@_left_delim_dim
+    \dim_zero_new:N \g_@@_right_delim_dim
+    \bool_if:NTF \l_@@_NiceArray_bool
+      {
+        \dim_gset:Nn \g_@@_left_delim_dim { 2 \arraycolsep }
+        \dim_gset:Nn \g_@@_right_delim_dim { 2 \arraycolsep }
+      }
+      { 
+        \group_begin:
+        \dim_set_eq:NN \nulldelimiterspace \c_zero_dim
+        \hbox_set:Nn \l_tmpa_box
+          {
+            \c_math_toggle_token
+            \left #1 \vcenter to 1 cm { } \right.
+            \c_math_toggle_token
+
+          }
+        \dim_gset:Nn \g_@@_left_delim_dim { \box_wd:N \l_tmpa_box }
+        \hbox_set:Nn \l_tmpa_box
+          {
+            \dim_set_eq:NN \nulldelimiterspace \c_zero_dim
+            \c_math_toggle_token
+            \left. \vcenter to 1 cm { } \right #2
+            \c_math_toggle_token
+          }
+        \dim_gset:Nn \g_@@_right_delim_dim { \box_wd:N \l_tmpa_box }
+        \group_end:
+      }
+%    \end{macrocode}
+% 
+% \medskip
+% The array will be composed in a box (named |\l_@@_the_array_box|) because we
+% have to do manipulations concerning the potential exterior rows (such
+% construction in a box is not possible for |{NiceMatrix}|).
+%    \begin{macrocode}
+    \box_clear_new:N \l_@@_the_array_box
+%    \end{macrocode}
+%
+% \medskip
+% We construct the preamble of the array in |\l_tmpa_tl|.
+%    \begin{macrocode}
+    \tl_set:Nn \l_tmpa_tl { #4 }
+    \int_compare:nNnTF \l_@@_first_col_int = \c_zero_int
+      { \tl_put_left:NV \l_tmpa_tl \c_@@_preamble_first_col_tl }
+      {
+        \bool_if:NT \l_@@_NiceArray_bool
+          {
+            \bool_if:NF \l_@@_exterior_arraycolsep_bool
+              { \tl_put_left:Nn \l_tmpa_tl { @ { } } }
+          }
+      }
+    \bool_if:NTF \l_@@_last_col_bool
+      { \tl_put_right:NV \l_tmpa_tl \c_@@_preamble_last_col_tl }
+      { 
+        \bool_if:NT \l_@@_NiceArray_bool
+          {
+            \bool_if:NF \l_@@_exterior_arraycolsep_bool
+              { \tl_put_right:Nn \l_tmpa_tl { @ { } } }
+          }
+      }
+%    \end{macrocode}
+% Here is the beginning of the box which will contain the array. The
+% |\hbox_set_end:| corresponding to this |\hbox_set:Nw| will be in the second part of
+% the environment (and the closing |\c_math_toggle_token| also).
+%    \begin{macrocode}
+    \hbox_set:Nw \l_@@_the_array_box
+    \skip_horizontal:n \l_@@_left_margin_dim 
+    \skip_horizontal:n \l_@@_extra_left_margin_dim 
+    \c_math_toggle_token
+%    \end{macrocode}
+% Here is the call to |\array| (we have a dedicated macro |\@@_array:| because
+% of compatibility with \cls{revtex4-1} and \cls{revtex4-2}).
+%    \begin{macrocode}
+    \exp_args:NV \@@_array: \l_tmpa_tl
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% We begin the second part of the environment |{NiceArrayWithDelims}|.
+%    \begin{macrocode}
+  { 
+    \endarray
+    \c_math_toggle_token
+    \skip_horizontal:n \g_@@_right_margin_dim 
+    \skip_horizontal:n \g_@@_extra_right_margin_dim 
+    \hbox_set_end:
+%    \end{macrocode}
+% Now, we compute |\l_tmpa_dim| which is the vertical dimension of the ``first
+% row'' above the array (when the key |first-row| is used).
+%    \begin{macrocode}
+    \int_compare:nNnTF \l_@@_first_row_int = \c_zero_int
+      {
+        \dim_compare:nNnTF
+          { \g_@@_ht_row_one_dim + \g_@@_dp_row_zero_dim + \lineskiplimit } 
+            > \baselineskip
+          { 
+            \dim_set:Nn \l_tmpa_dim
+              { 
+                \g_@@_ht_row_one_dim + \g_@@_dp_row_zero_dim + \lineskip 
+                + \g_@@_ht_row_zero_dim - \g_@@_ht_row_one_dim 
+              } 
+          }
+          {
+            \dim_set:Nn \l_tmpa_dim
+             { \baselineskip + \g_@@_ht_row_zero_dim - \g_@@_ht_row_one_dim } 
+          }
+      }
+      { \dim_zero:N \l_tmpa_dim }
+%    \end{macrocode}
+% We compute |\l_tmpb_dim| which is the vertical dimension of the ``last row''
+% below the array (when the key |last-row| is used). A value of $-2$ for
+% |\l_@@_last_row_int| means that there is no ``last row''.\footnote{A value of
+% $-1$ for |\l_@@_last_row_int| means that there is a ``last row'' but the
+% number of that row is unknown (the user have not set the value with the option
+% |last row|).} 
+%    \begin{macrocode}
+    \int_compare:nNnTF \l_@@_last_row_int > { -2 }
+      {
+        \dim_compare:nNnTF
+          { 
+            \g_@@_ht_last_row_dim + \g_@@_dp_ante_last_row_dim + \lineskiplimit
+          } 
+          >
+          \baselineskip
+          {
+            \dim_set:Nn \l_tmpb_dim
+              { 
+                \g_@@_ht_last_row_dim + \g_@@_dp_ante_last_row_dim + \lineskip
+                + \g_@@_dp_last_row_dim - \g_@@_dp_ante_last_row_dim
+              }
+          } 
+          {
+            \dim_set:Nn \l_tmpb_dim
+              { 
+                \baselineskip 
+                + \g_@@_dp_last_row_dim - \g_@@_dp_ante_last_row_dim 
+              } 
+          }
+      }
+      { \dim_zero:N \l_tmpb_dim }
+%    \end{macrocode}
+% 
+% \bigskip
+% Now, we begin the real construction in the output flow of TeX. First, we take
+% into account a potential ``first column'' (we remind that this ``first
+% column'' has been constructed in an overlapping position and that we have computed
+% its width in |\g_@@_width_first_col_dim|: see p.~\pageref{overlap-left}).
+%    \begin{macrocode}
+    \int_compare:nNnT \g_@@_first_col_int = \c_zero_int
+      { 
+        \skip_horizontal:n \arraycolsep
+        \skip_horizontal:n \g_@@_width_first_col_dim 
+      }
+%    \end{macrocode}
+%
+% The construction of the real box is different in |{NiceArray}| and in its
+% variants (|{pNiceArray}|, etc.) because, in |{NiceArray}|, we have to take
+% into account the option of position (|t|, |c| or |b|). We begin with
+% |{NiceArray}|. 
+%    \begin{macrocode}
+    \bool_if:NTF \g_@@_NiceArray_bool
+      { 
+        \int_compare:nNnT \g_@@_first_row_int = \c_zero_int
+          { 
+            \str_if_eq:VnTF \l_@@_pos_env_str { t }
+              {
+                \box_move_up:nn 
+                  { \l_tmpa_dim - \g_@@_ht_row_zero_dim + \g_@@_ht_row_one_dim  }
+              }
+          }
+          {
+            \bool_if:NT \g_@@_last_row_int
+              {
+                \str_if_eq:VnT \l_@@_pos_env_str { b }
+                  {
+                    \box_move_down:nn
+                      { 
+                        \l_tmpb_dim 
+                        - \g_@@_dp_last_row_dim + \g_@@_dp_ante_last_row_dim 
+                      } 
+                  }
+              }
+          }
+        { \box_use_drop:N \l_@@_the_array_box }
+      } 
+%    \end{macrocode}
+%
+% Now, in the case of an environment |{pNiceArray}|, |{bNiceArray}|, etc.
+%    \begin{macrocode}
+      {
+        \hbox_set:Nn \l_tmpa_box
+          {
+            \c_math_toggle_token
+            \left #1
+            \vcenter 
+              { 
+%    \end{macrocode}
+% We take into account the ``first row'' (we have previously computed its size
+% in |\l_tmpa_dim|).
+%    \begin{macrocode}
+                \skip_vertical:n { - \l_tmpa_dim }
+                \hbox:n 
+                  { 
+                    \skip_horizontal:n { - \arraycolsep }
+                    \box_use_drop:N \l_@@_the_array_box
+                    \skip_horizontal:n { - \arraycolsep }
+                  }
+%    \end{macrocode}
+% We take into account the ``last row'' (we have previously computed its size
+% in |\l_tmpb_dim|).
+%    \begin{macrocode}
+                \skip_vertical:n { - \l_tmpb_dim }
+              }
+            \right #2 
+            \c_math_toggle_token
+          }
+        \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + \l_tmpa_dim }
+        \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + \l_tmpb_dim } 
+        \box_use_drop:N \l_tmpa_box
+      } 
+%    \end{macrocode}
+% We take into account a potential ``last column'' (this ``last
+% column'' has been constructed in an overlapping position and we have computed
+% its width in |\g_@@_width_last_col_dim|: see p.~\pageref{overlap-right}).
+%    \begin{macrocode}           
+    \bool_if:NT \g_@@_last_col_found_bool 
+      { 
+        \skip_horizontal:n \g_@@_width_last_col_dim 
+        \skip_horizontal:n \arraycolsep 
+      }
+  }
+%    \end{macrocode}
+% This is the end of the environment |{NiceArrayWithDelims}|.
+%
+% \interitem
+% Here is the preamble for the ``first column'' (if the user uses the key |first-col|)
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_preamble_first_col_tl
+  {
+    > 
+      { 
+        \@@_begin_of_row:
+%    \end{macrocode}
+% The contents of the cell is constructed in the box |\l_tmpa_box| because we
+% have to compute some dimensions of this box.
+%    \begin{macrocode}
+        \hbox_set:Nw \l_tmpa_box 
+        \c_math_toggle_token
+        \l_@@_code_for_first_col_tl
+      }
+    l
+    < 
+      { 
+        \c_math_toggle_token
+        \hbox_set_end:
+        \@@_actualization_for_first_and_last_row:
+%    \end{macrocode}
+% We actualise the width of the ``first column'' because we will use this width
+% after the construction of the array.
+%    \begin{macrocode}
+        \dim_gset:Nn \g_@@_width_first_col_dim
+          { 
+            \dim_max:nn 
+              \g_@@_width_first_col_dim
+              { \box_wd:N \l_tmpa_box }
+          }
+%    \end{macrocode}
+% The content of the cell is inserted in an overlapping position.
+% \label{overlap-left}
+%    \begin{macrocode}
+        \hbox_overlap_left:n
+          { 
+            \tikz 
+              [ 
+                remember~picture , 
+                inner~sep = \c_zero_dim , 
+                minimum~width = \c_zero_dim , 
+                baseline
+              ]
+            \node 
+              [ 
+                anchor = base ,
+                name = 
+                  nm -
+                  \int_use:N \g_@@_env_int -
+                  \int_use:N \g_@@_row_int -
+                  0 ,
+                alias = 
+                  \str_if_empty:NF \l_@@_name_str
+                    { 
+                      \l_@@_name_str -
+                      \int_use:N \g_@@_row_int -
+                      0
+                    }
+              ]
+              { \box_use:N \l_tmpa_box } ; 
+            \skip_horizontal:n
+              { 
+                \g_@@_left_delim_dim + 
+                \l_@@_left_margin_dim + 
+                \l_@@_extra_left_margin_dim
+              }
+          }
+        \skip_horizontal:n { - 2 \arraycolsep } 
+      }
+  }
+%    \end{macrocode}
+%
+%
+% Here is the preamble for the ``last column'' (if the user uses the key |last-col|).
+%    \begin{macrocode}
+\tl_const:Nn \c_@@_preamble_last_col_tl
+  {
+    > 
+      { 
+%    \end{macrocode}
+% With the flag |\g_@@_last_col_found_bool|, we will know that the ``last
+% column'' i s really used.
+%    \begin{macrocode}           
+        \bool_gset_true:N \g_@@_last_col_found_bool
+        \int_gincr:N \g_@@_col_int
+        \int_gset:Nn \g_@@_col_total_int
+          { \int_max:nn \g_@@_col_total_int \g_@@_col_int }
+%    \end{macrocode}
+% The contents of the cell is constructed in the box |\l_tmpa_box| because we
+% have to compute some dimensions of this box.
+%    \begin{macrocode}
+        \hbox_set:Nw \l_tmpa_box 
+          \c_math_toggle_token
+          \l_@@_code_for_last_col_tl
+      }
+    l
+    < 
+      { 
+        \c_math_toggle_token
+        \hbox_set_end:
+        \@@_actualization_for_first_and_last_row:
+%    \end{macrocode}
+% We actualise the width of the ``last column'' because we will use this width
+% after the construction of the array.
+%    \begin{macrocode}
+        \dim_gset:Nn \g_@@_width_last_col_dim
+           { 
+             \dim_max:nn 
+               \g_@@_width_last_col_dim
+               { \box_wd:N \l_tmpa_box }
+           }
+        \skip_horizontal:n { - 2 \arraycolsep }
+%    \end{macrocode}
+% The content of the cell is inserted in an overlapping position.
+% \label{overlap-right}
+%    \begin{macrocode}
+        \hbox_overlap_right:n
+          { 
+            \skip_horizontal:n
+              { 
+                \g_@@_right_delim_dim + 
+                \l_@@_right_margin_dim + 
+                \l_@@_extra_right_margin_dim
+              }
+            \tikz 
+              [ 
+                remember~picture , 
+                inner~sep = \c_zero_dim , 
+                minimum~width = \c_zero_dim , 
+                baseline
+              ]
+            \node 
+              [ 
+                anchor = base ,
+                name = 
+                  nm -
+                  \int_use:N \g_@@_env_int -
+                  \int_use:N \g_@@_row_int -
+                  \int_use:N \g_@@_col_int ,
+                alias = 
+                  \str_if_empty:NF \l_@@_name_str
+                    { 
+                      \l_@@_name_str -
+                      \int_use:N \g_@@_row_int -
+                      \int_use:N \g_@@_col_int
+                    }
+              ]
+              { \box_use:N \l_tmpa_box } ; 
+          } 
+      }
+  }
+%    \end{macrocode}
+%
+%
+% \interitem
+% The environment |{NiceArray}| is constructed upon the environment
+% |{NiceArrayWithDelims}| but, in fact, there is a flag |\l_@@_NiceArray_bool|.
+% In |{NiceArrayWithDelims}|, some special code will be executed if this flag is raised.
+%    \begin{macrocode}
+\NewDocumentEnvironment { NiceArray } { }
+  { 
+    \bool_set_true:N \l_@@_NiceArray_bool
+%    \end{macrocode}
+% We put . and . for the delimiters but, in fact, that doesn't matter because
+% these arguments won't be used in |{NiceArrayWithDelims}| (because the flag
+% |\l_@@_NiceArray_bool| is raised).
+%    \begin{macrocode} 
+    \NiceArrayWithDelims . . 
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%               
+% 
+% \interitem
+% We create the variants of the environment |{NiceArrayWithDelims}|. These
+% variants exist since the version 3.0 of \pkg{nicematrix}.
+%
+%   \begin{macrocode}
+\NewDocumentEnvironment { pNiceArray } { }
+  {
+    \@@_test_if_math_mode:
+    \NiceArrayWithDelims ( )
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%               
+%   \begin{macrocode}
+\NewDocumentEnvironment { bNiceArray } { }
+  {
+    \@@_test_if_math_mode:
+    \NiceArrayWithDelims [ ]
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%               
+%   \begin{macrocode}
+\NewDocumentEnvironment { BNiceArray } { }
+  {
+    \@@_test_if_math_mode:
+    \NiceArrayWithDelims \{ \}
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%               
+%   \begin{macrocode}
+\NewDocumentEnvironment { vNiceArray } { }
+  {
+    \@@_test_if_math_mode:
+    \NiceArrayWithDelims | |
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%               
+%   \begin{macrocode}
+\NewDocumentEnvironment { VNiceArray } { }
+  {
+    \@@_test_if_math_mode:
+    \NiceArrayWithDelims \| \|
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%
+% \bigskip
+% \subsection{The environment \{NiceMatrix\} and its variants}
+%
+% Our environment |{NiceMatrix}| must have the same second part as the
+% environment |{matrix}| of \pkg{amsmath} (because of the programmation of the
+% option |renew-matrix|). Hence, this second part is the following: 
+% 
+% \begin{Verbatim}
+%          \endarray
+%          \skip_horizontal:n { - \arraycolsep }
+% \end{Verbatim}
+% 
+% That's why in the definition of |{NiceMatrix}|, we have to use |\array| and
+% not |\begin{array}|. This command |\array| is in |\@@_array:| (we have written
+% this command because of the redefinition of |\array| done in \cls{revtex4-1}
+% and \cls{revtex4-2}).
+%
+% In order to execute code after the array, we use a command
+% |\group_insert_after:N|. 
+% 
+% \medskip
+% Here's the definition of |{NiceMatrix}|:
+%    \begin{macrocode}
+\NewDocumentEnvironment { NiceMatrix } { ! O { } }
+  { 
+    \@@_test_if_math_mode:
+    \bool_if:NT \l_@@_in_env_bool { \@@_fatal:n { Yet~in~env } } 
+    \bool_set_true:N \l_@@_in_env_bool
+%    \end{macrocode}
+% We have to deactivate the potential externalisation of Tikz because
+% \pkg{nicematrix} uses Tikz with |remember picture|.
+%    \begin{macrocode} 
+    \cs_if_exist:NT \tikz@library@external@loaded
+      { \tikzset { external / export = false } }
+%    \end{macrocode}
+% The instruction for actual drawing of the dotted lines must be in a
+% |\group_insert_after:N| because the second part of the environment must be the
+% same as in |{array}| (for the option |renew-matrix|).
+%    \begin{macrocode}
+    \group_insert_after:N \@@_after_array:
+    \tl_gclear_new:N \g_@@_lines_to_draw_tl
+    \int_gincr:N \g_@@_env_int
+    \bool_if:NF \l_@@_block_auto_columns_width_bool
+      { \dim_gzero_new:N \g_@@_max_cell_width_dim }
+    \keys_set:nn { NiceMatrix / NiceMatrix } { #1 }
+%    \end{macrocode}
+% The macro |\@@_pre_array:| is defined above (see p.~\pageref{prearray}). It
+% is also used in |{NiceArrayWithDelims}|.
+%    \begin{macrocode}      
+    \@@_pre_array:
+    \skip_horizontal:n { - \arraycolsep } 
+    \skip_horizontal:n \l_@@_left_margin_dim 
+    \skip_horizontal:n \l_@@_extra_left_margin_dim 
+    \str_set:Nn \l_@@_pos_env_str c
+    \bool_set_false:N \l_@@_exterior_arraycolsep_bool
+    \@@_array: { * \c@MaxMatrixCols C }
+  }
+  { 
+    \endarray
+    \skip_horizontal:n { - \arraycolsep } 
+%    \end{macrocode}
+% The two following lines are, of course, not in the second part of |{array}|,
+% but that doesn't matter because, when |renew-matrix| is used, 
+% |\g_@@_right_margin_dim| and |\g_@@_extra_right_margin_dim| will be equal to $0$~pt.
+%    \begin{macrocode}
+    \skip_horizontal:n \g_@@_right_margin_dim
+    \skip_horizontal:n \g_@@_extra_right_margin_dim
+  }
+%    \end{macrocode}
+%
+% \interitem
+% We create the variants of the environment |{NiceMatrix}|.
+%    \begin{macrocode}
+\NewDocumentEnvironment { pNiceMatrix } { }
+   { 
+     \@@_test_if_math_mode: 
+     \left( \begin{NiceMatrix} 
+   }
+   { \end{NiceMatrix} \right) }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment { bNiceMatrix } { }
+   { 
+     \@@_test_if_math_mode: 
+     \left[ \begin{NiceMatrix} 
+   }
+   { \end{NiceMatrix} \right] }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment { BNiceMatrix } { }
+   { 
+     \@@_test_if_math_mode: 
+     \left\{ \begin{NiceMatrix} 
+   }
+   { \end{NiceMatrix} \right\} }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment { vNiceMatrix } { }
+   { 
+     \@@_test_if_math_mode: 
+     \left\lvert \begin{NiceMatrix} 
+   }
+   { \end{NiceMatrix} \right\rvert }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\NewDocumentEnvironment { VNiceMatrix } { }
+   { 
+     \@@_test_if_math_mode: 
+     \left\lVert \begin{NiceMatrix} 
+   }
+   { \end{NiceMatrix} \right\rVert }
+%    \end{macrocode}
+%
+%
+% \bigskip
+% \subsection{Automatic width of the cells}
+%
+% For the option |columns-width=auto| (or the option |auto-columns-width|
+% of the environment |{NiceMatrixBlock}|), we want to know the maximal width of
+% the cells of the array (except the cells of the ``exterior'' column of an
+% environment of the kind of |{pNiceAccayC}|). This length can be known only
+% after the end of the construction of the array (or at the end of the
+% environment |{NiceMatrixBlock}|). That's why we store this value in the main
+% |.aux| file and it will be available in the next run. We write a dedicated
+% command for this because it will be called in a~|\group_insert_after:N|. 
+%    \begin{macrocode}
+\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 } 
+          }
+%    \end{macrocode}
+% If the environment has a name, we also create an alias named
+% |\@@_max_cell_width_|{\ttfamily\slshape name}.
+%    \begin{macrocode}
+        \str_if_empty:NF \g_@@_name_str
+          {
+            \iow_now:Nx \@mainaux 
+              {
+                \cs_gset:cpn { @@_max_cell_width_ \g_@@_name_str } 
+                  { \dim_use:N \g_@@_max_cell_width_dim } 
+              } 
+          }
+        \iow_now:Nn \@mainaux \ExplSyntaxOff  
+      } 
+  }
+%    \end{macrocode}
+% 
+% \bigskip
+% \subsection{How to know whether a cell is ``empty''}
+%
+% The conditionnal |\@@_if_not_empty_cell:nnT| tests whether 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 , 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 whether we
+% are in this situation considering the correspondant Tikz node. 
+%    \begin{macrocode}
+  { 
+    \cs_if_free:cTF 
+      { pgf@sh@ns@nm -\int_use:N \g_@@_env_int - \int_use:N #1 - \int_use:N #2 }
+      \prg_return_false:
+%    \end{macrocode}
+% We manage a list of ``empty cells'' called |\g_@@_empty_cells_seq|. In fact,
+% this list is not a list of all the empty cells of the array but only those
+% explicitly declared empty for some reason. It's easy to check if the current
+% cell is in this list. 
+%    \begin{macrocode}
+      { 
+        \seq_if_in:NxTF \g_@@_empty_cells_seq { \int_use:N #1 - \int_use:N #2 }
+          \prg_return_false:
+%    \end{macrocode}
+% In the general case, we consider the width of the Tikz node corresponding to
+% the cell. In order to compute this width, we have to extract the coordinate of
+% the west and east anchors of the node. This extraction needs a command
+% environment |{pgfpicture}| but, in fact, nothing is drawn.  
+%    \begin{macrocode}
+          { 
+            \begin { pgfpicture }
+%    \end{macrocode}
+% We store the name of the node corresponding to the cell in |\l_tmpa_tl|.
+%    \begin{macrocode}
+            \tl_set:Nx \l_tmpa_tl 
+               { nm - \int_use:N \g_@@_env_int - \int_use:N #1 - \int_use:N #2 }
+            \pgfpointanchor \l_tmpa_tl { east }
+            \dim_gset:Nn \g_tmpa_dim \pgf@x
+            \pgfpointanchor \l_tmpa_tl { west }
+            \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:
+          }
+      }
+  }
+%    \end{macrocode}
+%
+% 
+% \subsection{After the construction of the array}
+%
+% The macro |\@@_after_array:| is called (via 
+% |\group_insert_after:N|) in |{NiceArrayWithDelims}| and
+% |{NiceMatrix}|. 
+%
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_after_array:
+  { 
+    \int_compare:nNnTF \g_@@_row_int > \c_zero_int
+      \@@_after_array_i:
+      { \@@_error:n { Zero~row } }
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\@@_msg_new:nn { Zero~row }
+  { 
+    There~is~a~problem.~Maybe~your~environment~\{\@currenvir\}~is~empty.~
+    Maybe~you~have~used~l,~c~and~r~instead~of~L,~C~and~R~in~the~preamble~
+    of~your~environment. \\
+    If~you~go~on,~the~result~may~be~incorrect.
+  }
+%    \end{macrocode}
+%
+% \medskip
+% We deactivate Tikz externalization (since we use Tikz pictures with the
+% options |overlay| and |remember picture|, there would be errors).
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_after_array_i:
+  { 
+    \group_begin:
+    \cs_if_exist:NT \tikz@library@external@loaded
+      { \tikzset { external / export = false } } 
+%    \end{macrocode}
+% Now, the definition of |\g_@@_col_int| and
+% |\g_@@_col_total_int| change: |\g_@@_col_int| will be the number of
+% columns without the ``last column''; |\g_@@_col_total_int| will be the
+% number of columns with this ``last column''.\footnote{We remind that the
+% potential ``first column'' has the number~$0$.}
+%    \begin{macrocode}
+    \int_gset_eq:NN \g_@@_col_int \g_@@_col_total_int
+    \bool_if:nT \g_@@_last_col_found_bool { \int_gdecr:N \g_@@_col_int } 
+%    \end{macrocode}
+%
+% We fix also the value of |\g_@@_row_int| and |\g_@@_row_total_int| with the
+% same principle.
+%    \begin{macrocode}
+    \int_gset_eq:NN \g_@@_row_total_int \g_@@_row_int
+    \int_compare:nNnT \g_@@_last_row_int > { -1 }
+      { \int_gsub:Nn \g_@@_row_int \c_one_int }
+%    \end{macrocode}
+%
+% In the user has used the option |last-row| without value, we write in the
+% |aux| file the number of that last row for the next run.
+%    \begin{macrocode}
+    \bool_if:NT \g_@@_last_row_without_value_bool
+      {
+        \iow_now:Nn \@mainaux \ExplSyntaxOn 
+        \iow_now:Nx \@mainaux 
+          { 
+            \cs_gset:cpn { @@_last_row_ \int_use:N \g_@@_env_int } 
+              { \int_use:N \g_@@_row_total_int }
+          }  
+%    \end{macrocode}
+% If the environment has a name, we also write a value based on the name
+% because it's more reliable than a value based on the number of the
+% environment. 
+%    \begin{macrocode}
+        \str_if_empty:NF \g_@@_name_str
+          { 
+            \iow_now:Nx \@mainaux 
+              { 
+                \cs_gset:cpn { @@_last_row_ \g_@@_name_str } 
+                  { \int_use:N \g_@@_row_total_int }
+              }  
+          }
+        \iow_now:Nn \@mainaux \ExplSyntaxOff 
+      }
+%    \end{macrocode}
+% 
+% 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_gclear_new:N \g_@@_yet_drawn_seq
+%    \end{macrocode}
+%
+% 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 know whether a diagonal is
+% the first of its type in the current |{NiceArray}| environment.
+%    \begin{macrocode}
+    \bool_if:NT \l_@@_parallelize_diags_bool
+      { 
+        \int_zero_new:N \l_@@_ddots_int
+        \int_zero_new:N \l_@@_iddots_int
+%    \end{macrocode}
+%
+% The dimensions |\l_@@_delta_x_one_dim| and |\l_@@_delta_y_one_dim| will
+% contain the $\Delta_x$ and $\Delta_y$ of the first |\Ddots| diagonal. We have
+% to store these values in order to draw the others |\Ddots| diagonals parallel
+% to the first one. Similarly |\l_@@_delta_x_two_dim| and
+% |\l_@@_delta_y_two_dim| are the $\Delta_x$ and $\Delta_y$ of the first
+% |\Iddots| diagonal. 
+%    \begin{macrocode}
+        \dim_zero_new:N \l_@@_delta_x_one_dim
+        \dim_zero_new:N \l_@@_delta_y_one_dim
+        \dim_zero_new:N \l_@@_delta_x_two_dim
+        \dim_zero_new:N \l_@@_delta_y_two_dim
+      }
+%    \end{macrocode}
+%
+% 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}
+    \bool_if:NT \g_@@_extra_nodes_bool \@@_create_extra_nodes:
+%    \end{macrocode}
+% 
+% \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}
+    \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_set_false:N \l_@@_initial_open_bool
+        \bool_set_false:N \l_@@_final_open_bool
+        \g_@@_lines_to_draw_tl
+      }
+    \tl_gclear:N \g_@@_lines_to_draw_tl
+%    \end{macrocode}
+%
+% \bigskip
+% Now, the |code-after|.
+%    \begin{macrocode}
+    \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 
+    \tl_gclear:N \g_@@_code_after_tl
+    \group_end:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% A dotted line will be said \emph{open} in one of its extremities 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'' or, if it exists, the |w|~node (the medium and large nodes are
+% created with |\@@_create_extra_nodes:| if they have not been created yet).
+% \[ \begin{pNiceMatrix}[create-extra-nodes,
+%                        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}\]
+%
+% 
+% \bigskip
+% The command |\@@_find_extremities_of_line:nnnn| takes four arguments:
+%
+% \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 of 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 whether
+% 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 }
+%    \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_set_false:N \l_@@_stop_loop_bool
+    \bool_do_until:Nn \l_@@_stop_loop_bool 
+      { 
+        \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_set_false:N \l_@@_final_open_bool
+        \int_compare:nNnTF \l_@@_final_i_int > \g_@@_row_int
+          {
+            \int_compare:nNnT { #3 } = 1
+              { \bool_set_true:N \l_@@_final_open_bool }
+          }
+          {
+            \int_compare:nNnTF \l_@@_final_j_int < 1
+              { 
+                \int_compare:nNnT { #4 } = { -1 }
+                  { \bool_set_true:N \l_@@_final_open_bool }
+              }
+              {
+                \int_compare:nNnT \l_@@_final_j_int > \g_@@_col_int
+                  { 
+                    \int_compare:nNnT { #4 } = 1
+                      { \bool_set_true:N \l_@@_final_open_bool }
+                  }
+              }
+          }
+        \bool_if:NTF \l_@@_final_open_bool 
+%    \end{macrocode}
+% If we are outside the matrix, we have found the extremity of the dotted line
+% and it's a \emph{open} extremity. 
+%    \begin{macrocode}
+          { 
+%    \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
+              { \bool_set_true:N \l_@@_stop_loop_bool }
+          }
+      }
+%    \end{macrocode}
+% 
+% \interitem
+% For |\l_@@_initial_i_int| and |\l_@@_initial_j_int| the programmation is
+% similar to the previous one.
+%    \begin{macrocode}
+    \bool_set_false:N \l_@@_stop_loop_bool
+    \bool_do_until:Nn \l_@@_stop_loop_bool 
+      { 
+        \int_sub:Nn \l_@@_initial_i_int { #3 }
+        \int_sub:Nn \l_@@_initial_j_int { #4 }
+        \bool_set_false:N \l_@@_initial_open_bool
+        \int_compare:nNnTF \l_@@_initial_i_int < 1
+          {
+            \int_compare:nNnT { #3 } = 1
+              { \bool_set_true:N \l_@@_initial_open_bool }
+          }
+          { 
+            \int_compare:nNnTF \l_@@_initial_j_int < 1
+              { 
+                \int_compare:nNnT { #4 } = 1
+                  { \bool_set_true:N \l_@@_initial_open_bool }
+              }
+              { 
+                \int_compare:nNnT \l_@@_initial_j_int > \g_@@_col_int
+                  { 
+                    \int_compare:nNnT { #4 } = { -1 }
+                      { \bool_set_true:N \l_@@_initial_open_bool }
+                  }
+              }
+          }
+        \bool_if:NTF \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
+              { \bool_set_true:N \l_@@_stop_loop_bool }
+          }
+      }
+%    \end{macrocode}
+% If we have at least one open extremity, we create the ``medium nodes'' in the
+% matrix\footnote{We should change this. Indeed, for an open extremity of an
+% \emph{horizontal} dotted line, we use the |w|~node, if, it exists, and not the
+% ``medium node''.}. We remind that, when used once, the command 
+% |\@@_create_extra_nodes:| becomes no-op in the current TeX group. 
+%    \begin{macrocode}
+    \bool_if:nT { \l_@@_initial_open_bool || \l_@@_final_open_bool }
+      \@@_create_extra_nodes: 
+  }
+%    \end{macrocode}
+%
+% \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$-list 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:NVTF \g_@@_yet_drawn_seq \l_tmpa_tl
+%    \end{macrocode}
+%
+% If the dotted line to draw is not in the list, we add it to the list
+% |\g_@@_yet_drawn_seq|. 
+%    \begin{macrocode}
+      \prg_return_true:
+      {
+        \seq_gput_left:NV \g_@@_yet_drawn_seq \l_tmpa_tl
+        \prg_return_false:
+      }
+  }
+%    \end{macrocode}
+%
+%
+% \interitem 
+% The command |\@@_retrieve_coords:nn| retrieves the Tikz coordinates of the two
+% extremities of the dotted line we will have to draw \footnote{In fact, with
+% diagonal lines, or vertical lines in columns of type |L| or |R|, an 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 suffix 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
+% |{tikzpicture}|. 
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_retrieve_coords:nn
+  { 
+    \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 )
+      \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 )
+      \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 { x x }
+%    \end{macrocode}
+%
+% \interitem
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_draw_Ldots:nn
+  { 
+    \@@_find_extremities_of_line:nnnn { #1 } { #2 } \c_zero_int \c_one_int 
+    \@@_if_yet_drawn:F \@@_actually_draw_Ldots:
+  }
+%    \end{macrocode}
+% 
+% \medskip
+% The command |\@@_actually_draw_Ldots:| 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
+              {
+%    \end{macrocode}
+% If a |w| node exists (created when the key |columns-width| is used), we use
+% the |w| node for the extremity.
+%    \begin{macrocode}
+                \cs_if_exist:cTF
+                  { 
+                    pgf@sh@ns@nm 
+                    - \int_use:N \g_@@_env_int 
+                    - \int_use:N \l_@@_initial_i_int 
+                    - \int_use:N \l_@@_initial_j_int - w 
+                  }
+                  { - w.base~west }
+                  { - medium.base~west }
+              }
+              { .base~east }
+          }
+          {
+            \bool_if:NTF \l_@@_final_open_bool
+              {
+                \cs_if_exist:cTF
+                  { 
+                    pgf@sh@ns@nm 
+                    - \int_use:N \g_@@_env_int 
+                    - \int_use:N \l_@@_final_i_int 
+                    - \int_use:N \l_@@_final_j_int - w 
+                  }
+                  { - w.base~east }
+                  { - 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.53 pt }
+    \dim_gadd:Nn \g_@@_y_final_dim { 0.53 pt }
+    \@@_draw_tikz_line:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_draw_Cdots:nn
+  { 
+    \@@_find_extremities_of_line:nnnn { #1 } { #2 } \c_zero_int \c_one_int 
+    \@@_if_yet_drawn:F
+      { 
+        \@@_retrieve_coords:xx 
+          { 
+            \bool_if:NTF \l_@@_initial_open_bool
+              {
+                \cs_if_exist:cTF
+                  { 
+                    pgf@sh@ns@nm 
+                    - \int_use:N \g_@@_env_int 
+                    - \int_use:N \l_@@_initial_i_int 
+                    - \int_use:N \l_@@_initial_j_int - w 
+                  }
+                  { - w.mid~west }
+                  { - medium.mid~west }
+              }
+              { .mid~east }
+          }
+          {
+            \bool_if:NTF \l_@@_final_open_bool
+              {
+                \cs_if_exist:cTF
+                  { 
+                    pgf@sh@ns@nm 
+                    - \int_use:N \g_@@_env_int 
+                    - \int_use:N \l_@@_final_i_int 
+                    - \int_use:N \l_@@_final_j_int - w 
+                  }
+                  { - w.mid~east }
+                  { - 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}      
+\cs_new_protected:Nn \@@_draw_Vdots:nn
+  { 
+    \@@_find_extremities_of_line:nnnn { #1 } { #2 } \c_one_int \c_zero_int
+    \@@_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 whether the column is of type |l| (|L| of
+% |{NiceArray}|) or may be considered as if.
+%    \begin{macrocode}      
+        \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 whether the column is of type |c| (|C| of
+% |{NiceArray}|) or may be considered as if.
+%    \begin{macrocode}      
+        \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
+% For the diagonal lines, the situation is a bit more complicated because, by
+% default, we parallelize the diagonals 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:nn
+  { 
+    \@@_find_extremities_of_line:nnnn { #1 } { #2 } \c_one_int \c_one_int
+    \@@_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. 
+%    \begin{macrocode}
+        \bool_if:NT \l_@@_parallelize_diags_bool
+          { 
+            \int_incr:N \l_@@_ddots_int
+%    \end{macrocode}
+% We test if the diagonal line is the first one (the counter |\l_@@_ddots_int|
+% is created for this usage). 
+%    \begin{macrocode}
+            \int_compare:nNnTF \l_@@_ddots_int = \c_one_int
+%    \end{macrocode}
+% If the diagonal line is the first one, we have no adjustment of the line to do
+% but we store the $\Delta_x$ and the $\Delta_y$ of the line because these
+% values will be used to draw the others diagonal lines parallels to the first
+% one. 
+%    \begin{macrocode}
+              { 
+                \dim_set:Nn \l_@@_delta_x_one_dim 
+                  { \g_@@_x_final_dim - \g_@@_x_initial_dim }
+                \dim_set:Nn \l_@@_delta_y_one_dim 
+                  { \g_@@_y_final_dim - \g_@@_y_initial_dim }
+              }
+%    \end{macrocode}
+% If the diagonal line is not the first one, we have to adjust the second
+% extremity of the line by modifying the coordinate |\g_@@_y_initial_dim|.
+%    \begin{macrocode}
+              { 
+                \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_one_dim \l_@@_delta_x_one_dim 
+                  }
+              }
+          }
+%    \end{macrocode}
+% Now, we can draw the dotted line (after a possible change of
+% |\g_@@_y_initial_dim|). 
+%    \begin{macrocode}
+        \@@_draw_tikz_line:
+      }
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% We draw the |\Iddots| diagonals in the same way.
+%    \begin{macrocode}
+\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 = \c_one_int
+              { 
+                \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
+% \subsection{The actual instructions for drawing the dotted line with Tikz}
+%
+% The command |\@@_draw_tikz_line:| draws the line using four implicit arguments: 
+%
+% \quad |\g_@@_x_initial_dim|, |\g_@@_y_initial_dim|, |\g_@@_x_final_dim| and |\g_@@_y_final_dim|. 
+% These variables are global for technical reasons: their first affectation was in an instruction |\tikz|.
+%
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_draw_tikz_line:
+  { 
+%    \end{macrocode}
+% The dimension |\l_@@_l_dim| is the length $\ell$ of the line to draw. We use
+% the floating point reals of \pkg{expl3} to compute this length.
+%    \begin{macrocode}
+    \dim_zero_new:N \l_@@_l_dim
+    \dim_set:Nn \l_@@_l_dim
+      { 
+        \fp_to_dim:n 
+          { 
+            sqrt 
+             ( 
+               (   \dim_use:N \g_@@_x_final_dim 
+                 - \dim_use:N \g_@@_x_initial_dim 
+               ) ^ 2
+                  +
+               (   \dim_use:N \g_@@_y_final_dim 
+                 - \dim_use:N \g_@@_y_initial_dim
+               ) ^ 2 
+             )
+          }
+      }
+%    \end{macrocode}
+% We draw only if the length is not equal to zero (in fact, in the first
+% compilation, the length may be equal to zero). 
+%    \begin{macrocode}
+    \dim_compare:nNnF \l_@@_l_dim = \c_zero_dim
+%    \end{macrocode}
+% The integer |\l_tmpa_int| is the number of dots of the dotted line.
+%    \begin{macrocode}
+      { 
+        \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.45 em } }
+              }
+              { 
+                \int_set:Nn \l_tmpa_int 
+                  { \dim_ratio:nn { \l_@@_l_dim - 0.3 em } { 0.45 em } }
+              }
+          }
+          { 
+            \bool_if:NTF \l_@@_final_open_bool
+              { 
+                \int_set:Nn \l_tmpa_int 
+                  { \dim_ratio:nn { \l_@@_l_dim - 0.3 em } { 0.45 em } }
+              }
+              { 
+                \int_set:Nn \l_tmpa_int 
+                  { \dim_ratio:nn { \l_@@_l_dim - 0.6 em } { 0.45 em }}
+              }
+          }
+%    \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_ratio:nn { 0.45 em } \l_@@_l_dim 
+          }
+        \dim_set:Nn \l_tmpb_dim 
+          { 
+            ( \g_@@_y_final_dim - \g_@@_y_initial_dim ) *
+            \dim_ratio:nn { 0.45 em } \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. 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 ) *
+            \dim_ratio:nn 
+              { \l_@@_l_dim - 0.45 em * \l_tmpa_int } { \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 ) * 
+            \dim_ratio:nn 
+              { \l_@@_l_dim - 0.45 em * \l_tmpa_int } 
+              { \l_@@_l_dim * 2 } * 
+            \l_tmpb_int
+          }
+        \begin { tikzpicture } [ overlay ]
+          \int_step_inline:nnnn 0 1 \l_tmpa_int
+            { 
+              \pgfpathcircle 
+                { \pgfpoint { \g_@@_x_initial_dim } { \g_@@_y_initial_dim } }
+                { 0.53 pt }
+              \pgfusepath { fill }
+              \dim_gadd:Nn \g_@@_x_initial_dim \l_tmpa_dim
+              \dim_gadd:Nn \g_@@_y_initial_dim \l_tmpb_dim 
+            }
+        \end { tikzpicture } 
+      }
+  }
+%    \end{macrocode}
+%
+% \subsection{User commands available in the new environments}
+%
+% We give new names for the commands |\ldots|, |\cdots|, |\vdots| and |\ddots|
+% because these commands will be redefined (if the option |renew-dots| is used).
+%    \begin{macrocode}
+\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
+%    \end{macrocode}
+%
+% \interitem
+% The command |\@@_add_to_empty_cells:| adds the current cell to
+% |\g_@@_empty_cells_seq| which is the list of the empty cells (the cells
+% explicitly declared ``empty'': there may be, of course, other empty cells in
+% the matrix). 
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_add_to_empty_cells:
+  { 
+    \seq_gput_right:Nx \g_@@_empty_cells_seq
+      { \int_use:N \g_@@_row_int - \int_use:N \g_@@_col_int }
+  }
+%    \end{macrocode}
+%
+% \interitem 
+% The commands |\@@_Ldots|, |\@@_Cdots|, |\@@_Vdots|, |\@@_Ddots| and
+% |\@@_Iddots| will be linked to |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots| and
+% |\Iddots| in the environments |{NiceArray}| (the other environments of
+% \pkg{nicematrix} rely upon |{NiceArray}|). 
+%    \begin{macrocode}
+\NewDocumentCommand \@@_Ldots { s }
+  { 
+    \bool_if:nF { #1 } { \@@_instruction_of_type:n { Ldots } }
+    \bool_if:NF \l_@@_nullify_dots_bool { \phantom \@@_ldots }
+    \@@_add_to_empty_cells:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentCommand \@@_Cdots { s }
+  { 
+    \bool_if:nF { #1 } { \@@_instruction_of_type:n { Cdots } }
+    \bool_if:NF \l_@@_nullify_dots_bool { \phantom \@@_cdots }
+    \@@_add_to_empty_cells:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentCommand \@@_Vdots { s }
+  {
+    \bool_if:nF { #1 } { \@@_instruction_of_type:n { Vdots } }
+    \bool_if:NF \l_@@_nullify_dots_bool { \phantom \@@_vdots }
+    \@@_add_to_empty_cells:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentCommand \@@_Ddots { s }
+  { 
+    \bool_if:nF { #1 } { \@@_instruction_of_type:n { Ddots } }
+    \bool_if:NF \l_@@_nullify_dots_bool { \phantom \@@_ddots }
+    \@@_add_to_empty_cells:
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentCommand \@@_Iddots { s }
+  { 
+    \bool_if:nF { #1 } { \@@_instruction_of_type:n { Iddots } }
+    \bool_if:NF \l_@@_nullify_dots_bool { \phantom \@@_iddots }
+    \@@_add_to_empty_cells:
+  }
+%    \end{macrocode}
+%
+%
+% \bigskip
+% The command |\@@_Hspace:| will be linked to |\hspace| in |{NiceArray}|.
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_Hspace:
+  { 
+   \@@_add_to_empty_cells:
+   \hspace
+  }
+%    \end{macrocode}
+%
+%
+% \bigskip
+% In the environment |{NiceArray}|, the command |\multicolumn| will be linked to
+% the following command |\@@_multicolumn:nnn|.
+%    \begin{macrocode}
+\cs_set_eq:NN \@@_old_multicolumn \multicolumn
+\cs_new:Npn \@@_multicolumn:nnn #1 #2 #3
+  { 
+    \@@_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_@@_col_int }
+        \seq_gput_left:Nn \g_@@_multicolumn_sizes_seq { #1 } 
+      }
+    \int_gadd:Nn \g_@@_col_int { #1 - 1 }
+  }
+%    \end{macrocode}
+%
+%
+% \bigskip
+% 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|. 
+%
+% \medskip
+% This command must not be protected since it begins with |\multicolumn|.
+%    \begin{macrocode}
+\cs_new:Npn \@@_Hdotsfor:
+  {
+    \multicolumn { 1 } { C } { }
+    \@@_Hdotsfor_i
+  }
+%    \end{macrocode}
+%
+% The command |\@@_Hdotsfor_i| is defined with the tools of \pkg{xparse} because
+% it has an optionnal argument. Note that such a command defined by
+% |\multicolumn| is protected and that's why we have put the |\multicolumn|
+% before (in the definition of |\@@_Hdotsfor:|).
+%    \begin{macrocode}
+\bool_if:NTF \c_@@_draft_bool
+  {
+    \NewDocumentCommand \@@_Hdotsfor_i { O { }  m }
+      {
+        \prg_replicate:nn { #2 - 1 } { & \multicolumn { 1 } { C } { } }
+      } 
+  }
+  {
+    \NewDocumentCommand \@@_Hdotsfor_i { O { }  m }
+      {
+        \tl_gput_right:Nx \g_@@_lines_to_draw_tl
+          {
+            \@@_draw_Hdotsfor:nnn
+              { \int_use:N \g_@@_row_int }
+              { \int_use:N \g_@@_col_int } 
+              { #2 }
+          }
+        \prg_replicate:nn { #2 - 1 } { & \multicolumn { 1 } { C } { } }
+      } 
+  }
+%    \end{macrocode}
+% 
+% \medskip
+%    \begin{macrocode}
+\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}
+% For the row, it's easy.
+%    \begin{macrocode}
+    \int_set:Nn \l_@@_initial_i_int { #1 }
+    \int_set:Nn \l_@@_final_i_int { #1 }
+%    \end{macrocode}
+% For the column, it's a bit more complicated.
+%    \begin{macrocode}
+    \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_@@_col_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}
+%
+% In the |code-after|, the command |\@@_line:nn| will be linked to |\line|. This
+% command takes two arguments which are the specification of two cells in the
+% array (in the format $i$-$j$) and draws a dotted line between these cells. 
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_line:nn
+  {
+    \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
+    \bool_set_false:N \l_@@_initial_open_bool
+    \bool_set_false:N \l_@@_final_open_bool
+    \begin { tikzpicture }
+       \path~(#1)~--~(#2)~node[at~start]~(i)~{}~node[at~end]~(f)~{} ;
+       \tikz@parse@node \pgfutil@firstofone ( i )
+       \dim_gset:Nn \g_@@_x_initial_dim \pgf@x
+       \dim_gset:Nn \g_@@_y_initial_dim \pgf@y
+       \tikz@parse@node \pgfutil@firstofone ( f )
+       \dim_gset:Nn \g_@@_x_final_dim \pgf@x
+       \dim_gset:Nn \g_@@_y_final_dim \pgf@y
+    \end { tikzpicture }  
+    \@@_draw_tikz_line:
+  }
+%    \end{macrocode}
+% 
+% The commands |\Ldots|, |\Cdots|, |\Vdots|, |\Ddots|, and |\Iddots| don't use
+% this command because they have to do other settings (for example, the diagonal 
+% lines must be parallelized). 
+%
+% \bigskip
+% \subsection{The commands to draw dotted lines to separate columns and rows}
+%
+% The command |\hdottedline| draws an horizontal dotted line to separate two
+% rows. Similarly, the letter ``:'' in the preamble draws a vertical dotted line
+% (the letter can be changed with the option |letter-for-dotted-lines|). Both
+% mechanisms write instructions in the |code-after|. The actual instructions in
+% the |code-after| use the commands |\@@_hdottedline:n| and |\@@_vdottedline:n|.
+% 
+% \bigskip
+% We want the horizontal lines at the same position\footnote{In fact, almost the
+% same position because of the width of the line: the width of a dotted line is
+% not the same as the width of a line created by |\hline|.} as the line created
+% by |\hline| (or |\hdashline| of \pkg{arydshln}). To this end, we construct a
+% ``false row'' and, in this row, we create a Tikz node (|\coordinate|) that
+% will be used to have the $y$-value of the line.
+% 
+%    \begin{macrocode}
+\cs_generate_variant:Nn \dim_set:Nn { N v }
+%    \end{macrocode}
+%
+% 
+% \medskip
+% Some extensions, like the extension \pkg{doc}, do a redefinition of the command
+% |\dotfill| of LaTeX. That's why we define a command |\@@_dotfill:| as we wish.
+% We test whether we are in draft mode because, in this case, we don't draw the
+% dotted lines.
+%    \begin{macrocode}
+\bool_if:NTF \c_@@_draft_bool
+  { \cs_set_eq:NN \@@_dotfill: \prg_do_nothing: }
+  {
+    \cs_set:Npn \@@_dotfill:
+      { 
+        \cleaders \hbox_to_wd:nn { .44 em } { \hss . \hss } \hfill 
+        \skip_horizontal:n \c_zero_dim
+      }
+  }
+%    \end{macrocode}
+%                                      
+% This command must \emph{not} be protected because it starts with |\noalign|.
+%    \begin{macrocode}
+\cs_new:Npn \@@_hdottedline:
+  {
+    \noalign 
+      { 
+        \bool_gset_true:N \g_@@_extra_nodes_bool
+        \cs_if_exist:cTF { @@_width_ \int_use:N \g_@@_env_int }
+          { \dim_set:Nv \l_tmpa_dim { @@_width_ \int_use:N \g_@@_env_int } }
+          { \dim_set:Nn \l_tmpa_dim { 5 mm } }
+        \hbox_overlap_right:n 
+          { 
+            \hbox_to_wd:nn 
+              { 
+                \l_tmpa_dim + 2 \arraycolsep 
+                - \l_@@_left_margin_dim - \g_@@_right_margin_dim 
+              } 
+            \@@_dotfill: 
+          }
+      } 
+  }
+%    \end{macrocode}
+%
+%
+%
+% \bigskip
+%    \begin{macrocode}
+\cs_new_protected:Nn \@@_vdottedline:n
+  {
+%    \end{macrocode}
+% We should allow the letter ``|:|'' in the first position of the preamble
+% but that would need a special programmation.
+%    \begin{macrocode}
+    \int_compare:nNnTF #1 = \c_zero_int
+      { \@@_error:n { Use~of~:~in~first~position } }
+      {   
+        \@@_create_extra_nodes:
+        \bool_if:NF \c_@@_draft_bool
+          {
+            \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
+            \bool_set_true:N \l_@@_initial_open_bool 
+            \bool_set_true:N \l_@@_final_open_bool 
+%    \end{macrocode}
+% In order to have the coordinates of the line to draw, we use the ``large nodes''.
+%    \begin{macrocode}
+            \begin { tikzpicture } [ remember~picture ]
+              \tikz@parse@node\pgfutil@firstofone
+                ( 1 - #1 - large .north~east )
+              \dim_gset:Nn \g_@@_x_initial_dim \pgf@x
+              \dim_gset:Nn \g_@@_y_initial_dim \pgf@y
+              \tikz@parse@node\pgfutil@firstofone
+                ( \int_use:N \g_@@_row_int - #1 - large .south~east )
+              \dim_gset:Nn \g_@@_x_final_dim \pgf@x
+              \dim_gset:Nn \g_@@_y_final_dim \pgf@y
+            \end { tikzpicture }
+%    \end{macrocode}
+% However, if the |w|-nodes are created in the previous column (that is if the
+% previous column was constructed explicitly or implicitly\footnote{A column is
+% constructed implicitly with the letter |w| if the option |columns-width| is
+% used or if the environment |{NiceMatrixBlock}| is used with the option
+% |auto-columns-width|.} with a letter |w|), we use the |w|-nodes to change the
+% $x$-value of the nodes in order to have the dotted lines perfectly aligned
+% when we use the environment |{NiceMatrixBlock}| with the option
+% |auto-columns-width|.
+%    \begin{macrocode}
+            \cs_if_exist:cT
+              { pgf@sh@ns@nm -\int_use:N \g_@@_env_int - 1 - #1 - w }
+              {
+                \begin { tikzpicture } [ remember~picture ]
+                  \tikz@parse@node\pgfutil@firstofone
+                    ( 1 - #1 - w .north~east )
+                  \dim_gset:Nn \g_@@_x_initial_dim \pgf@x
+                  \tikz@parse@node\pgfutil@firstofone
+                    ( \int_use:N \g_@@_row_int - #1 - w .south~east )
+                  \dim_gset:Nn \g_@@_x_final_dim \pgf@x
+                \end { tikzpicture }
+                \dim_gadd:Nn \g_@@_x_initial_dim \arraycolsep
+                \dim_gadd:Nn \g_@@_x_final_dim \arraycolsep
+              }
+            \@@_draw_tikz_line:
+          } 
+      }
+  }
+%    \end{macrocode}
+% 
+%
+%    \begin{macrocode}
+\@@_msg_new:nn { Use~of~:~in~first~position }
+  { 
+    You~can't~use~the~column~specifier~"\l_@@_letter_for_dotted_lines_str"~in~the~
+    first~position~of~the~preamble~of~the~environment~\{\@currenvir\}. \\
+    If~you~go~on,~this~dotted~line~will~be~ignored.
+  }
+%    \end{macrocode}
+%
+% \bigskip
+% \subsection{The vertical rules}
+%
+% We don't want that a vertical rule drawn by the specifier ``"|"'' extends
+% in the eventual ``first row'' and ``last row'' of the array.
+% 
+% The natural way to do that would be to redefine the specifier ``"|"''
+% with |\newcolumntype|:
+% \begin{Verbatim}[commandchars=\~\#\+]
+%    \newcolumntype { | }
+%      { ! { \int_compare:nNnF \g_@@_row_int = \c_zero_int \vline } } 
+% \end{Verbatim}
+% 
+% However, this code fails is the user uses "\DefineShortVerb{\|}" of
+% \pkg{fancyvrb}. Moreover, it would not be able to deal correctly with two
+% consecutive specifiers ``"|"'' (in a preambule like "ccc||ccc").
+%
+% That's why we will do a redefinition of the macro |\@arrayrule| of \pkg{array}
+% and this redefinition will add |\@@_vline:| instead of |\vline| to the
+% preamble.
+%
+% Here is the definition of |\@@_vline:|. This definition \emph{must} be
+% protected because you don't want that macro expanded during the construction of
+% the preamble (the tests must be effective in each row and not once when the
+% preamble is constructed).
+%    \begin{macrocode}
+\cs_new_protected:Npn \@@_vline:
+  { 
+    \int_compare:nNnTF \l_@@_first_col_int = \c_zero_int 
+      { 
+        \int_compare:nNnTF \g_@@_col_int = \c_zero_int
+          {
+            \int_compare:nNnTF \l_@@_first_row_int = \c_zero_int
+              {     
+                \int_compare:nNnF \g_@@_row_int = \c_zero_int 
+                  { 
+                    \int_compare:nNnF \g_@@_row_int = \l_@@_last_row_int \vline
+                  }  
+              }
+              {
+                \int_compare:nNnF \g_@@_row_int = \c_zero_int
+                  { 
+                    \int_compare:nNnF \g_@@_row_int = \l_@@_last_row_int \vline
+                  }   
+              }    
+           }
+           {     
+             \int_compare:nNnF \g_@@_row_int = \c_zero_int 
+               { \int_compare:nNnF \g_@@_row_int = \l_@@_last_row_int \vline } 
+           }
+      }
+      { 
+        \int_compare:nNnTF \g_@@_col_int = \c_zero_int
+          {
+            \int_compare:nNnF \g_@@_row_int = { -1 }
+              { 
+                \int_compare:nNnF \g_@@_row_int = { \l_@@_last_row_int - 1 }
+                  \vline
+              } 
+          }
+          {     
+            \int_compare:nNnF \g_@@_row_int = \c_zero_int 
+              { \int_compare:nNnF \g_@@_row_int = \l_@@_last_row_int \vline }  
+          }
+      }   
+  } 
+%    \end{macrocode}
+%
+%
+% 
+% \subsection{The environment \{NiceMatrixBlock\}}
+%
+% The following flag will be raised when all the columns of the environments of
+% the block must have the same width in ``auto'' mode.
+%    \begin{macrocode}
+\bool_new:N \l_@@_block_auto_columns_width_bool
+%    \end{macrocode}
+%
+% \bigskip
+% 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
+      }
+  }
+%    \end{macrocode}
+%
+% \bigskip
+%    \begin{macrocode}
+\NewDocumentEnvironment { NiceMatrixBlock } { ! O { } }
+  {
+    \keys_set:nn { NiceMatrix / NiceMatrixBlock } { #1 }
+    \int_zero_new:N \l_@@_first_env_block_int
+    \int_set:Nn \l_@@_first_env_block_int { \g_@@_env_int + 1 }
+  }
+%    \end{macrocode}
+%
+% \medskip
+% At the end of the environment |{NiceMatrixBlock}|, we write in the main |.aux|
+% file instructions for the column width of all the environments of the block
+% (that's why we have stored the number of the first environment of the block in
+% the counter |\l_@@_first_env_block_int|). 
+%    \begin{macrocode}
+  { 
+    \bool_if:NT \l_@@_block_auto_columns_width_bool
+      {
+        \iow_now:Nn \@mainaux \ExplSyntaxOn
+        \int_step_inline:nnnn \l_@@_first_env_block_int 1 \g_@@_env_int
+          { 
+            \iow_now:Nx \@mainaux         
+              { 
+                \cs_gset:cpn { @@ _ max _ cell _ width _ ##1 } 
+                  { \dim_use:N \g_@@_max_cell_width_dim }
+              }
+          }
+        \iow_now:Nn \@mainaux \ExplSyntaxOff
+      }
+  }
+%    \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 { v n }
+\cs_generate_variant:Nn \dim_max:nn { v n }
+%    \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:nnNn \g_@@_first_row_int \g_@@_row_total_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:nnNn \g_@@_first_col_int \g_@@_col_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:nnNn \g_@@_first_row_int \g_@@_row_total_int \@@_i:
+        { 
+          \int_step_variable:nnNn 
+            \g_@@_first_col_int \g_@@_col_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 exterior rows and columns 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_@@_col_int|$ (and not |\g_@@_col_total_int|). Idem for the rows.
+%     \begin{macrocode}
+      \int_set:Nn \g_@@_first_row_int 1
+      \int_set:Nn \g_@@_first_col_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:nNn { \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:nNn { \g_@@_col_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_@@_col_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:Npn \@@_create_extra_nodes: { }
+%    \end{macrocode}
+% 
+% \medskip
+% We can now compute the width of the array (used by |\hdottedline|).
+%    \begin{macrocode}
+      \begin { tikzpicture } [ remember~picture , overlay ]
+         \tikz@parse@node \pgfutil@firstofone 
+           ( nm - \int_use:N \g_@@_env_int - 1 - 1 - large .north~west )
+         \dim_gset:Nn \g_tmpa_dim \pgf@x 
+         \tikz@parse@node \pgfutil@firstofone 
+           ( nm - \int_use:N \g_@@_env_int - 1 - 
+                  \int_use:N \g_@@_col_int - large .north~east )
+         \dim_gset:Nn \g_tmpb_dim \pgf@x 
+      \end { tikzpicture }      
+      \iow_now:Nn \@mainaux \ExplSyntaxOn 
+      \iow_now:Nx \@mainaux 
+        { 
+          \cs_gset:cpn { @@_width_ \int_use:N \g_@@_env_int }
+            { \dim_eval:n { \g_tmpb_dim - \g_tmpa_dim } } 
+        }
+      \iow_now:Nn \@mainaux \ExplSyntaxOff
+  }
+%    \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:nnNn \g_@@_first_row_int \g_@@_row_total_int \@@_i:
+      { 
+        \int_step_variable:nnNn \g_@@_first_col_int \g_@@_col_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}
+            \node
+              [ 
+                node~contents = { } ,
+                fit = ( @@~south~west ) ( @@~north~east )  ,
+                inner~sep = \c_zero_dim ,
+                name = nm - \int_use:N \g_@@_env_int - \@@_i: - \@@_j: ,
+                alias = 
+                  \str_if_empty:NF \g_@@_name_str 
+                    { \g_@@_name_str - \@@_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_new_protected: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 } 
+      ) ; 
+    \node 
+      [ 
+        node~contents = { } ,
+        fit = ( @@~south~west ) ( @@~north~east ) ,
+        inner~sep = \c_zero_dim ,
+        name = nm - \int_use:N \g_@@_env_int - \@@_i: - \@@_j: ,
+        alias = 
+          \str_if_empty:NF \g_@@_name_str { \g_@@_name_str - \@@_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| executes 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 \textbackslash 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:nn { \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_protected:Npn \@@_renew_matrix:
+  { 
+    \RenewDocumentEnvironment { pmatrix } { }
+      { \pNiceMatrix } 
+      { \endpNiceMatrix }
+    \RenewDocumentEnvironment { vmatrix } { }
+      { \vNiceMatrix }
+      { \endvNiceMatrix }
+    \RenewDocumentEnvironment { Vmatrix } { }
+      { \VNiceMatrix }
+      { \endVNiceMatrix }
+    \RenewDocumentEnvironment { bmatrix } { }
+      { \bNiceMatrix }
+      { \endbNiceMatrix }
+    \RenewDocumentEnvironment { Bmatrix } { }
+      { \BNiceMatrix }
+      { \endBNiceMatrix }
+  }
+%    \end{macrocode}
+%
+%
+%
+% \subsection{Obsolete environments}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { pNiceArrayC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \pNiceArray
+  }
+  { \endpNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { bNiceArrayC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \bNiceArray
+  }
+  { \endbNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { BNiceArrayC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \BNiceArray
+  }
+  { \endBNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { vNiceArrayC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \vNiceArray
+  }
+  { \endvNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { VNiceArrayC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \VNiceArray
+  }
+  { \endVNiceArray }
+%    \end{macrocode}
+% 
+%    \begin{macrocode} 
+\NewDocumentEnvironment { pNiceArrayRC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \pNiceArray
+  }
+  { \endpNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { bNiceArrayRC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \bNiceArray
+  }
+  { \endbNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { BNiceArrayRC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \BNiceArray
+  }
+  { \endBNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { vNiceArrayRC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \vNiceArray
+  }
+  { \endvNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { VNiceArrayRC } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \VNiceArray
+  }
+  { \endVNiceArray }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { NiceArrayCwithDelims } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \NiceArrayWithDelims
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%
+%    \begin{macrocode} 
+\NewDocumentEnvironment { NiceArrayRCwithDelims } { }
+  {
+    \bool_set_true:N \l_@@_last_col_bool
+    \int_set:Nn \l_@@_first_row_int \c_zero_int
+    \NiceArrayWithDelims
+  }
+  { \endNiceArrayWithDelims }
+%    \end{macrocode}
+%
+% 
+% 
+% \section{History}
+%
+% \subsection*{Changes between versions 1.0 and 1.1}
+% 
+% 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.
+%
+% \subsection*{Changes between versions 1.1 and 1.2}
+%
+% New environment |{NiceArray}| with column types |L|, |C| and |R|.
+%
+% \subsection*{Changes between version 1.2 and 1.3}
+%
+% New environment |{pNiceArrayC}| and its variants.
+%
+% Correction of a bug in the definition of |{BNiceMatrix}|, |{vNiceMatrix}| and
+% |{VNiceMatrix}| (in fact, it was a typo).
+%
+% Options are now available locally in |{pNiceMatrix}| and its variants. 
+% 
+% The names of the options are changed. The old names were names in ``camel
+% style''. New names are in lowercase and hyphens (but backward compatibility is
+% kept). 
+% 
+%
+% \subsection*{Changes between version 1.3 and 1.4}
+% 
+% The column types |w| and |W| can now be used in the environments
+% |{NiceArray}|, |{pNiceArrayC}| and its variants with the same meaning as in
+% the package \pkg{array}. 
+% 
+% New option |columns-width| to fix the same width for all the columns of the
+% array. 
+% 
+%
+% \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 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''.
+%
+% \subsection*{Changes between version 2.1 and 2.1.1}
+%
+% Small corrections: for example, the option |code-for-first-row| is now
+% available in the command |\NiceMatrixOptions|. 
+%
+% Following a discussion on
+% TeX StackExchange\footnote{cf.
+% |tex.stackexchange.com/questions/450841/tikz-externalize-and-nicematrix-package|},  
+% Tikz externalization is now deactivated in the environments of the
+% extension \pkg{nicematrix}.\footnote{Before this version, there was an error
+% when using \pkg{nicematrix} with Tikz externalization. In any case, it's not
+% possible to externalize the Tikz elements constructed by \pkg{nicematrix}
+% because they use the options |overlay| and |remember picture|.} 
+% 
+% \subsection*{Changes between version 2.1 and 2.1.2}
+% Option |draft|: with this option, the dotted lines are not drawn (quicker).
+%
+% \subsection*{Changes between version 2.1.2 and 2.1.3}
+%
+% When searching the end of a dotted line from a command like |\Cdots| issued in
+% the ``main matrix'' (not in the column |C|), the cells in the column |C| are
+% considered as outside the matrix. That means that it's possible to do the
+% following matrix with only a |\Cdots| command (and a single |\Vdots|). 
+% \[\begin{pNiceArrayRC}{Wc{5mm}CWc{5mm}}
+% & C_j & \\
+% \mbox{\Large $0$} & \Vdots & \mbox{\Large $0$} \\
+%              & \strut a & \Cdots &  L_i \\
+% \mbox{\Large $0$} &  & \mbox{\Large $0$} \\
+% \end{pNiceArrayRC}\]
+%
+% \subsection*{Changes between version 2.1.3 and 2.1.4}
+%
+% Replacement of some options |O { }| in commands and environments defined with
+% \pkg{xparse} by |! O { }| (because a recent version of \pkg{xparse} introduced
+% the specifier |!| and modified the default behaviour of the last optional
+% arguments). 
+%
+% See |https://www.texdev.net/2018/04/21/xparse-optional-arguments-at-the-end|
+%
+% \subsection*{Changes between version 2.1.4 and 2.1.5}
+%
+% Compatibility with the classes \cls{revtex4-1} and \cls{revtex4-2}.
+% 
+% Option |allow-duplicate-names|.
+%
+% \subsection*{Changes between version 2.1.5 and 2.2}
+%
+% Possibility to draw horizontal dotted lines to separate rows with the command 
+% |\hdottedline| (similar to the classical command |\hline| and the command
+% |\hdashline| of \pkg{arydshln}). 
+%
+% Possibility to draw vertical dotted lines to separate columns with the
+% specifier ``|:|'' in the preamble (similar to the classical specifier
+% ``"|"'' and the specifier ``|:|'' of \pkg{arydshln}).
+%
+% \subsection*{Changes between version 2.2 and 2.2.1}
+%
+% Improvment of the vertical dotted lines drawn by the specifier ``:'' in the
+% preamble. 
+%
+% Modification of the position of the dotted lines drawn by |\hdottedline|.
+%
+% \subsection*{Changes between version 2.2.1 and 2.3}
+%
+% Compatibility with the column type |S| of \pkg{siunitx}.
+% 
+% Option |hlines|.
+% 
+% A warning is issued when the |draft| mode is used. In this case, the dotted
+% lines are not drawn.
+%
+% 
+% \subsection*{Changes between version 2.2.1 and 2.3}
+%
+% Modification of |\Hdotsfor|. Now |\Hdotsfor| erases the |\vlines| (of ``"|"'')
+% as |\hdotsfor| does.
+%
+% \subsection*{Changes between version 2.3 and 3.0}
+%
+% Composition of exterior rows and columns of the four sides of the matrix (and
+% not only on two sides) with the options |first-row|, |last-row|, |first-col|
+% and |last-col|.
+% 
+% \PrintIndex
+% 
+% \tableofcontents
+% \endinput
+% Local Variables:
+% TeX-fold-mode: nil
+% fill-column: 80
+% End:
-- 
cgit v1.2.3

