5
\$\begingroup\$

I need to go and rework a bunch of notation in a large body of work. But I might change my mind later, so I want to move to defining the notation a bit more semantically (e.g. writing \v x to represent a vector, so I can later decide to format vectors in different ways).

On thing that is currently wrong with it is that I write A_i to represent that \$i^{\text {th}}\$ column vector. After looking at other similar works, I have concluded that A_{:,i} would be clearer. So I have defined a macro to smartly determine if a : should be added.

I called it \i to be concise since I will be writing it often.

\documentclass{article}

\usepackage{xparse,xstring,etoolbox}

\renewcommand{\v}[1]{\tilde{#1}} % a vector 

\newcommand{\ind}[2]{#1_{#2}} % indexed

%% Smart indexing and naming code

\newcommand{\ifupper}[3]{
    \normalexpandarg
    \exploregroups
    \StrCount{ABCDEFGHIJKLMNOPQRSTUVWXYZ}{#1}[\uppercount]
    \ifnumgreater{\uppercount}{0}{#2}{#3}
}

%smart index
\DeclareDocumentCommand{\i}{u{_} m}{
    \ifupper{#1}%
    {% just a single uppercase character, i.e. a matrix
        %make sure the index is the right length
        \StrCount{#2}{,}[\indcount]
        \ifnumgreater{\indcount}{0}
        { % Got multiple indexes so all good
            \ind{#1}{#2}
        }
        { % Only 1 index so grab the column
            \ind{#1}{{:,#2}}
        }
    }%
    {% Not just a single upper case character
        \ind{#1}{#2}
    }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Example document
\begin{document}

        \begin{tabular}{r l}
		$\i {\v x}_i$ & the $i$th element of the vector $\v x$\\
		$\i{X}_{i,j}$ & the row $i$ and column $j$ element of the matrix $X$\\
		$\i{X}_i$ & the $i$th column vector of the matrix $X$\\
		$\i{X}_{i,:}$ & the $i$th row vector of the matrix $X$\\
	\end{tabular}

\end{document}

Example document output

example output

Crossref

\$\endgroup\$
1
\$\begingroup\$

Redefining \v and \i is a bad thing. Don't, you'll regret it as soon as you want to need to cite a paper by Eduard Čech or by Erdal Arıkan.

You also have quite an inefficient usage of xstring and no error checking if a _ is forgotten.

Here's a complete implementation with xparse:

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\ind}{me{_}}{%
  \IfNoValueTF{#2}{\doind{#1}{???}}{\doind{#1}{#2}}
}

\ExplSyntaxOn
\NewDocumentCommand{\doind}{mm}
 {
  \tl_if_single:nTF { #1 }
   {% a single character
    \str_if_eq_x:nnTF { #1 } { \str_upper_case:n { #1 } }
     {% upper case, assume matrix
      \lyndon_index_matrix:nn { #1 } { #2 }
     }
     {
      \lyndon_index_do:nn { #1 } { #2 }
     }
   }
   {% not a single character
    \lyndon_index_do:nn { #1 } { #2 }
   }
 }

\cs_new_protected:Nn \lyndon_index_matrix:nn
 {
  \int_compare:nTF { \clist_count:n { #2 } > 1 }
   {% Got multiple indexes so all good
    \lyndon_index_do:nn { #1 } { #2 }
   }
   {% Only one index so grab the column
    \lyndon_index_do:nn { #1 } { {:},#2 }
   }
 }
\cs_new_protected:Nn \lyndon_index_do:nn
 {
  #1\sb{#2}
 }
\ExplSyntaxOff

% Example document
\begin{document}

\begin{tabular}{r l}
$\ind{A}$           & missing subscript\\
$\ind{\tilde{x}}_i$ & the $i$th element of the vector $\tilde{x}$\\
$\ind{X}_{i,j}$     & the row $i$ and column $j$ element of the matrix $X$\\
$\ind{X}_i$         & the $i$th column vector of the matrix $X$\\
$\ind{X}_{i,:}$     & the $i$th row vector of the matrix $X$\\
\end{tabular}

\end{document}

enter image description here

On the other hand, I see no much gain in using _ and also in doing checks for uppercase letters, which is quite limiting. I'd prefer a * version for vectors.

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn

\NewDocumentCommand{\ind}{smm}
 {
  \IfBooleanTF{#1}
   {% *, a vector
    \lyndon_index_do:nn { #2 } { #3 }
   }
   {% normal, a matrix
    \lyndon_index_matrix:nn { #2 } { #3 }
   }
 }
\cs_new_protected:Nn \lyndon_index_matrix:nn
 {
  \int_compare:nTF { \clist_count:n { #2 } > 1 }
   {% Got multiple indexes so all good
    \lyndon_index_do:nn { #1 } { #2 }
   }
   {% Only one index so grab the column
    \lyndon_index_do:nn { #1 } { {:},#2 }
   }
 }
\cs_new_protected:Nn \lyndon_index_do:nn
 {
  #1\sb{#2}
 }

\ExplSyntaxOff

% Example document
\begin{document}

\begin{tabular}{r l}
$\ind*{\tilde{x}}{i}$ & the $i$th element of the vector $\tilde{x}$\\
$\ind{X}{i,j}$        & the row $i$ and column $j$ element of the matrix $X$\\
$\ind{X}{i}$          & the $i$th column vector of the matrix $X$\\
$\ind{X}{i,:}$        & the $i$th row vector of the matrix $X$\\
$\ind{\Gamma}{j}$     & Greek matrix
\end{tabular}

\end{document}

enter image description here

\$\endgroup\$

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.