7

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.com Dec 26 '13 at 4:25

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

5

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 & }
     }
    % Add a 1
    \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}

enter image description here

5

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%
\addtocounter{#4}{#1}%
\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]
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.