6

The \zNonZero is equal to 0 if #1 is 0, but is equal to 1 if #1 is greater than 0. The problem is, the if check inside the loop is performed every iteration: I need it to be performed only once (for the first iteration). Is there a way to get rid of unneeded checks?

\begin{document}
\parindent0pt
\newcount\zNonZero
\def\zLoop#1%
  { \zNonZero1
    \ifnum#1<1 % HOW TO CHECK THIS ONLY ONCE?
      \zNonZero0
    \fi
    \ifnum#1<5
      #1...(\the\zNonZero)\newline
      \expandafter\zLoop\expandafter{\the\numexpr#1+1\relax}
    \fi
  }
\zLoop{0}
\end{document}

The "if" check is done 5 times here, but we need it to be done only once:

  • 1
    Is this your real code or is your actual test more expensive? I don't think this simple test will have any performance impact even for a larger number of iterations. – siracusa Jul 12 at 18:32
  • You could create two separate functions. One that processes the first iteration and does the "if" check, and something that processes subsequent iterations. – Werner Jul 12 at 18:33
6

Detach the first conditional.

\documentclass{article}

\newcount\zNonZero

\def\zLoop#1{%
  \zNonZero=1
  \zLoopStart{#1}%
  \zLoopLoop{#1}%
}
\def\zLoopStart#1{%
  \ifnum#1<1 % HOW TO CHECK THIS ONLY ONCE?
    \zNonZero=0
  \fi
}
\def\zLoopLoop#1{%
  \ifnum#1<5
    #1...(\the\zNonZero)\par
    \zNonZero=1
    \expandafter\zLoopLoop\expandafter{\the\numexpr#1+1\expandafter\relax\expandafter}%
  \fi
}

\setlength{\parindent}{0pt}

\begin{document}

\zLoop{0}

\end{document}

Note the two more \expandafter tokens so the entire conditional is removed before the loop is restarted.

This possibly doesn't qualify, but I'll mention it anyway.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\zLoop}{m}
 {
  \bp_zloop:n { #1 }
 }
\cs_new:Nn \bp_zloop:n
 {
  \int_compare:nT { #1 < 5 }
   {
    #1...(\int_eval:n { \int_min:nn { #1 } { 1 } })\par
    \bp_zloop:f { \int_eval:n { #1 + 1 } }
   }
 }
\cs_generate_variant:Nn \bp_zloop:n { f }

\ExplSyntaxOff

\begin{document}

\zLoop{0}

\end{document}
2
\documentclass{article}    
\begin{document}
    \parindent0pt
    \newcount\zNonZero
    \newif\ifCheck \Checktrue
    \def\zLoop#1{%
        \zNonZero1
        \ifCheck\ifnum#1<1 \zNonZero0 \fi\Checkfalse\fi
        \ifnum#1<5
        #1...(\the\zNonZero)\newline
        \expandafter\zLoop\expandafter{\the\numexpr#1+1\relax}
        \fi
      \Checktrue
    }
    \zLoop{0}
\end{document}
  • 1
    ...this still performs a conditional check \ifCheck with every call of \zLoop. – Werner Jul 12 at 19:17
  • @Werner in case the \ifnum#1<1 is a placeholder for a test that is actually more expensive then this could actually be faster - maybe in practise it does not make a difference but at least in theory it is a good idea. – Marijn Jul 13 at 10:32

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.