LaTeX Loops in \newcommand

I have used LaTeX for about a year now and every time I write a paper I try to improve on my knowledge so recently I've been creating my own commands to help save time. I am interested if it is possible to use "for-loops" in LaTeX to create \newcommand in the following way:

\newcommand{idmatrix}[1]


where my parameter is the size say n and then it will print an n x n identity matrix. This would be useful for equations where I want to show the matrix calculations but don't have to do the mundane work of using \bmatrix etc and creating a 3x3 or a 2x2 matrix every single time.

migrated from stackoverflow.comDec 26 '13 at 4:25

This question came from our site for professional and enthusiast programmers.

Here's an implementation with LaTeX3 features. When \idmatrix{n} is called for the first time a new token list variable is set up containing the code for producing the matrix, so that it can be reused without being built each time.

Thus, \idmatrix{2} will build the token list variable \g_julian_idmatrix_1_tl and use it; subsequent calls of \idmatrix{2} will just use the variable.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\idmatrix}{ m }
{
\justin_idmatrix:n { #1 }
}

\cs_new_protected:Npn \justin_idmatrix:n #1
{
\tl_if_exist:cF { g_justin_idmatrix_#1_tl }
{
\justin_make_idmatrix:n { #1 }
}
\tl_use:c { g_justin_idmatrix_#1_tl }
}

\cs_new_protected:Npn \justin_make_idmatrix:n #1
{
\tl_new:c { g_justin_idmatrix_#1_tl }
\tl_gput_right:cn { g_justin_idmatrix_#1_tl }
{
\left[ % or the delimiter you like best
% there's a column more for accommodating the empty value after the last 0& (or 1&)
\begin{array}{ @{} *{#1}{c} @{} c @{} }
}
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
% At step k add k-1 zeroes
\prg_replicate:nn { ##1 - 1 }
{
\tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 0 & }
}
\tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 1 & }
% Add n - k zeroes
\prg_replicate:nn { #1 - ##1 }
{
\tl_gput_right:cn { g_justin_idmatrix_#1_tl } { 0 & }
}
% End the line
\tl_gput_right:cn { g_justin_idmatrix_#1_tl } { \\ }
}
\tl_gput_right:cn { g_justin_idmatrix_#1_tl }
{
\end{array}
\right] % or the delimiter you like best
}
}

\ExplSyntaxOff

\begin{document}
$\idmatrix{1}\quad \idmatrix{2}\quad \idmatrix{3}\quad \idmatrix{4}$
$\idmatrix{12}$
\end{document}


To answer your question all you need is just a slight modification of what is said here:

\documentclass{article}

\usepackage{amsmath,amssymb,mathtools}
\usepackage{ifthen}

\newcommand{\forLoop}[5][1]
{%
\setcounter{#4}{#2}%
\ifthenelse{ \value{#4} < #3 }%
{%
#5%
\forLoop[#1]{\value{#4}}{#3}{#4}{#5}%
}%
% Else
{%
\ifthenelse{\value{#4} = #3}%
{%
#5%
}%
% Else
{}%
}%
}

\newcounter{identRow}
\newcounter{identCol}
\newcommand{\idmatrixn}[1]
{
\begin{bmatrix}
\forLoop{1}{#1}{identRow}
{
\forLoop{1}{#1}{identCol}
{
\ifthenelse{\equal{\value{identRow}}{\value{identCol}}}{1}{0}
\ifthenelse{\equal{\value{identCol}}{#1}}{}{&}
}
\\
}
\end{bmatrix}
}

\begin{document}
\idmatrixn{10}
\end{document}


Be careful since I noticed that the bmatrix environment does not support matrices bigger than 10x m or m x 10 where 0<m<11. If you need bigger matrices you may use instead array in the following way:

\newcounter{identRow}
\newcounter{identCol}
\newcommand{\idmatrixn}[1]
{
\left[\begin{array}{*{#1}c}
\forLoop{1}{#1}{identRow}
{
\forLoop{1}{#1}{identCol}
{
\ifthenelse{\equal{\value{identRow}}{\value{identCol}}}{1}{0}
\ifthenelse{\equal{\value{identCol}}{#1}}{}{&}
}
\\
}
\end{array}\right]
}