# PGF loop - how to use an array inside pgfmathdeclare function?

I'd like to pick a number from my array inside a loop. The first argument is a "starting" value which increments by 1 for each iteration based on the second and third argument (\qa). The maximum number of iterations can be determined by the second argument (\eval@limit). The other maximum value can be determined by the value of the third argument (\arbitraryarrayvalue).

I'm running into some issues using my array inside \pgfmathdeclarefunction. Specifically: The first case, the easy one, is to simply put:

\pgfmathparse{\myarray[\arbitraryarrayvalue]}
\pgfmath@smuggleone\pgfmathresult


Before closing the group. It turns out I can't look inside the array:

Paragraph ended before \pgfflt@readlowlevelfloat was complete.
<to be read again>
\par


So looking at the existing questsions I found one related question to \pgfflt@readlowlevelfloat, at How do I use pgfmathdeclarefunction to create define a new pgf function?.

I couldn't make the inference from that question to the solution of mine.

So second case: if I use the array inside my Expl3 solution for comparisons (this solution you will also find in the code below), I get an error like this one:

File ended while scanning use of \__fp_parse_after:ww.
Emergency stop.
==> Fatal error occurred, no output PDF file produced!


So judging from the fact they both refer to "file ended while doing something", I suspect these macro's keep reading further and expanding further until the document ends, which I usually solve with a well-placed \relax. I've tried adding that all over the place (inside the comparison, after it, about the array, etc.), but I can't seem to get rid of the error.

Possibly not so related but maybe a general solution outside expl3 would be the answer (?) regardless, I would like to see how a such general solution to break the loop would look like outside expl3. :-)

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fpu}

\usepackage{expl3}

\ExplSyntaxOn
\cs_new:Npn \breakloop #1 #2
{
\fp_compare:nNnT { #1 } > { #2 }
{ \breakforeach }
}
\ExplSyntaxOff

\global\def\myarray{{5,10,15,20,25,30,35,40,45,50,55,60}}

\makeatletter
\pgfmathdeclarefunction{blah}{3}{%
\begingroup
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}
\pgfmathparse{#1} % starting value
\edef\qa{\pgfmathresult}
\pgfmathparse{#2} % maximum amount of loops
\edef\eval@limit{\pgfmathresult}
\pgfmathparse{#3+1} % maximum value of array
\edef\arbitraryarrayvalue{\pgfmathresult}
\foreach \i in {0,...,\eval@limit}
{
\pgfmathparse{\qa+1} % \qa += 1
\global\edef\q@{\pgfmathresult} %
\pgfmathparse{\q@} %
\global\edef\qa{\pgfmathresult} %
\breakloop{\qa}{\myarray[\arbitraryarrayvalue]}
}
\pgfmathparse{\qa}
\pgfmath@smuggleone\pgfmathresult
\endgroup
}
\makeatother
\begin{document}
\pgfmathparse{blah(1,1000,9)}\pgfmathresult    %

\pgfmathparse{\myarray[2]}\pgfmathresult
\end{document}


This is solved by evaluating the array element first. Getting the element requires you pass an integer as an index, not a number in fixed point notation. I have moved the evaluation of the array element outside the loop as it does not vary with the iteration.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fpu}

\usepackage{expl3}

\ExplSyntaxOn
\cs_new:Npn \breakloop #1 #2
{
\fp_compare:nNnT { #1 } > { #2 }
{ \breakforeach }
}
\ExplSyntaxOff

\gdef\myarray{{5,10,15,20,25,30,35,40,45,50,55,60}}

\makeatletter
\pgfmathdeclarefunction{blah}{3}{%
\begingroup
\pgfmathparse{#1} % starting value
\edef\qa{\pgfmathresult}
\pgfmathparse{#2} % maximum amount of loops
\edef\eval@limit{\pgfmathresult}
\pgfmathparse{#3+1} % maximum value of array
\edef\arbitraryarrayvalue{\pgfmathresult}
\pgfmathparse{\myarray[\arbitraryarrayvalue]}
\edef\qb{\pgfmathresult}
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}
\foreach \i in {0,...,\eval@limit}
{
\pgfmathparse{\qa+1} % \qa += 1
\xdef\q@{\pgfmathresult} %
\pgfmathparse{\q@} %
\xdef\qa{\pgfmathresult} %
\breakloop{\qa}{\qb}
}
\pgfmathparse{\qa}
\pgfmath@smuggleone\pgfmathresult
\endgroup
}
\makeatother
\begin{document}
\pgfmathparse{blah(1,1000,9)}\pgfmathresult    %

\pgfmathparse{\myarray[4]}\pgfmathresult
\end{document}

• Nice addition of the shorthand notations \xdef and \gdef. I also noticed \gdef is unneeded for the array ? Which puzzles me a bit considering I just opened a new group, but hey, it works. – 1010011010 Jun 15 '14 at 19:36
• The array is defined at outer level so persists in lower level groups. The global there could be useful if you later package this up in something else. – Andrew Swann Jun 16 '14 at 9:12