Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Loops and variables in TeX/LaTeX

674 views
Skip to first unread message

Vitaly Repin

unread,
Oct 14, 2013, 12:25:41 PM10/14/13
to
Hello,

I need to generate a lot of floating point numbers according to the formula:

xx = 0
yy = 0

{loop begin}
x = yy - sin(x)
y = a - xx

plot (x, y)
xx = x ; yy = y;
{end loop}

I tried the following approach with latex:

First, defined the commands to calculate the new value (using pgf math library. \pgfmathresult contains the results of the calculation)

%% Calculates new X value.
%% Input 1: Y
%% Input 2: old X value
\newcommand{\calcX}[2]{\pgfmathparse{#1 - sin(#2)}\pgfmathresult}

%% Calculates new Y value.
%% Input 1: old X value
\newcommand{\calcY}[1]{\pgfmathparse{60 - #1)}\pgfmathresult}


Then I defined tokens:

\newtoks{\X}\X={0}
\newtoks{\Y}\Y={0}
\newtoks{\XX}\XX={0}
\newtoks{\YY}\YY={0}

And created the loop:

\newcounter{i}
\forloop{i}{0}{\value{i} < 5}{\the\X : \the\Y ; \X={\calcX{\the\YY}{\the\XX}}\Y={\calcY{\the\XX}}\XX=\X \YY=\Y}


Compilation failed with the weird error message:

! Undefined control sequence.
\pgfmath@parse@@number ...r \ifcat \pgfmath@token
\relax \expandafter \ifx \...
l.67 ...the\XX}}\Y={\calcY{\the\XX}}\XX=\X \YY=\Y}


Then I decided to make just one assignment instead of the loop:

%% Works:
\X={\calcX{\the\YY}{\the\XX}}\Y={\calcY{\the\XX}}
%% Works:
\the\Y\ : \the\X

%% Works
\XX=\X
\YY=\Y

% If I add this line then I receive the same weird error message as for the loop
\the\XX

Could you point me to the right direction? I want TeX to calculate the new value of \XX and \YY in each iteration. Looks like, it does not happen - the definition (not expanded?) is still in place instead.

Thanks in advance!
--
WBR & WBW, Vitaly

Dan Luecking

unread,
Oct 14, 2013, 2:23:01 PM10/14/13
to
On Mon, 14 Oct 2013 09:25:41 -0700 (PDT), Vitaly Repin
<vitaly...@gmail.com> wrote:

>Hello,
>
>I need to generate a lot of floating point numbers according to the formula:
>
>xx = 0
>yy = 0
>
>{loop begin}
>x = yy - sin(x)
>y = a - xx
>
>plot (x, y)
>xx = x ; yy = y;
>{end loop}
>
>I tried the following approach with latex:

Please pack this all up in a complete (but minimal) Latex document
so we can run it ourselves. I don't know what \usepackage commands
to include.

>
>First, defined the commands to calculate the new value (using pgf math library.
>\pgfmathresult contains the results of the calculation)
>
>%% Calculates new X value.
>%% Input 1: Y
>%% Input 2: old X value
>\newcommand{\calcX}[2]{\pgfmathparse{#1 - sin(#2)}\pgfmathresult}
>
>%% Calculates new Y value.
>%% Input 1: old X value
>\newcommand{\calcY}[1]{\pgfmathparse{60 - #1)}\pgfmathresult}
>
>
>Then I defined tokens:
>
>\newtoks{\X}\X={0}
>\newtoks{\Y}\Y={0}
>\newtoks{\XX}\XX={0}
>\newtoks{\YY}\YY={0}
>
>And created the loop:
>
>\newcounter{i}
>\forloop{i}{0}{\value{i} < 5}%
>{\the\X : \the\Y ;
>\X={\calcX{\the\YY}{\the\XX}}%
>\Y={\calcY{\the\XX}}%
>\XX=\X \YY=\Y}

Note that \X={\calcX{\the\YY}{\the\XX}} doesn't put the result
of the calculation in \X, only the tokens actually listed.
In the next iteration you will have:
\X={\calcX {\calcX{\the\YY}{\the\XX}}{\calcY{\the\XX}}}
You should arrange for the results of the calculation to be placed
in \X. Possibly something like (I can't test it as I don't have
the minimal document to play with):
\forloop{i}{0}{\value{i} < 5}%
{%
\the\X : \the\Y ;
\calcX{\the\YY}{\the\XX}%
\expandafter\X\expandafter{\pgfmathresult}%
\calcY{\the\XX}%
\expandafter\Y\expandafter{\pgfmathresult}%
\XX=\X \YY=\Y
}


Dan
To reply by email, change LookInSig to luecking

Martin Heller

unread,
Oct 15, 2013, 9:07:49 AM10/15/13
to
Vitaly Repin wrote, on 14-10-2013 18:25:
> Could you point me to the right direction? I want TeX to calculate the new value of \XX and \YY in each iteration. Looks like, it does not happen - the definition (not expanded?) is still in place instead.

Since you are already using pgf, you might as well use \foreach and do
the plotting with TikZ:

\documentclass{minimal}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[x=1mm,y=1mm]
\pgfmathsetmacro{\constA}{60}%
\foreach[%
remember=\x as \xx (initially 0),
remember=\y as \yy (initially 0),
evaluate=\x using \yy - sin(\xx),
evaluate=\y using \constA - \xx,
] \i in {0,...,50} {%
\fill(\x,\y) circle(1pt);
}%
\end{tikzpicture}

\end{document}

Vitaly Repin

unread,
Oct 16, 2013, 3:22:54 AM10/16/13
to
On Monday, October 14, 2013 9:23:01 PM UTC+3, Dan Luecking wrote:

Hello,

> Please pack this all up in a complete (but minimal) Latex document
> so we can run it ourselves.

This is the minimal document:

\documentclass{article}
\usepackage{ifthen}
\usepackage{forloop}
\usepackage{tikz}

\begin{document}

%% Calculates new X value.
%% Input 1: Y
%% Input 2: old X value
\newcommand{\calcX}[2]{\pgfmathparse{#1 - sin(#2)}\pgfmathresult}

%% Calculates new Y value.
%% Input 1: old X value
\newcommand{\calcY}[1]{\pgfmathparse{60 - #1)}\pgfmathresult}

\newtoks{\X}\X={0}
\newtoks{\Y}\Y={0}
\newtoks{\XX}\XX={0}
\newtoks{\YY}\YY={0}

\X={\calcX{\the\YY}{\the\XX}}\Y={\calcY{\the\XX}}

\the\Y\ : \the\X

\XX=\X
\YY=\Y

%% Error!
\the\XX

\newcounter{i}

%% Uncommenting results in an error
%\forloop{i}{0}{\value{i} < 5}{\the\X : \the\Y ; \X={\calcX{\the\YY}{\the\XX}}\Y={\calcY{\the\XX}}\XX=\X \YY=\Y}

\end{document}

> Note that \X={\calcX{\the\YY}{\the\XX}} doesn't put the result
> of the calculation in \X, only the tokens actually listed.
> In the next iteration you will have:
> \X={\calcX {\calcX{\the\YY}{\the\XX}}{\calcY{\the\XX}}}

Yep. I got the same understanding.

> You should arrange for the results of the calculation to be placed
> in \X. Possibly something like (I can't test it as I don't have
> the minimal document to play with):

> \forloop{i}{0}{\value{i} < 5}%
> {%
> \the\X : \the\Y ;
> \calcX{\the\YY}{\the\XX}%
> \expandafter\X\expandafter{\pgfmathresult}%
> \calcY{\the\XX}%
> \expandafter\Y\expandafter{\pgfmathresult}%
> \XX=\X \YY=\Y
> }

Your example works but it does not only prints "\the\X : \the\Y ;" but also values of \X and \Y if I understand it correctly:

0: 0; 0.060.00.0: 60.0; 60.060.060.0: 60.0; 59.133970.059.13397: 0.0; -0.858340.86603-0.85834: 0.86603; 0.88160.85834

Thanks! I got a keyword - \expandafter. Will study more about this command.

Vitaly Repin

unread,
Oct 18, 2013, 2:50:18 AM10/18/13
to
Hello,

On Tuesday, October 15, 2013 4:07:49 PM UTC+3, Martin Heller wrote:

> > Could you point me to the right direction? I want TeX to calculate the new value of \XX and \YY in each iteration. Looks like, it does not happen - the definition (not expanded?) is still in place instead.

> Since you are already using pgf, you might as well use \foreach

> \begin{tikzpicture}[x=1mm,y=1mm]
> \pgfmathsetmacro{\constA}{60}%
> \foreach[%
> remember=\x as \xx (initially 0),
> remember=\y as \yy (initially 0),
> evaluate=\x using \yy - sin(\xx),
> evaluate=\y using \constA - \xx,
> ] \i in {0,...,50} {%
> \fill(\x,\y) circle(1pt);
> }%
> \end{tikzpicture}

Thanks a lot! I managed to produce what I needed (using slightly different formula but it's OK for now).

But I faced one interesting problem - number of iterations seems to be limited.

This is my code:

\documentclass{minimal}
\usepackage{ifthen}
\usepackage{tikz}

\begin{document}

%% Calculates the #1 % 4
\newcount\dv\newcount\res
\newcommand{\calcmod}[1]{
\dv=#1
\res=\the\dv
\divide\dv by 4
\multiply\dv by -4
\advance\res by \the\dv
}

\begin{tikzpicture}[x=1mm,y=1mm,scale=.35]
\pgfmathsetmacro{\constA}{40}%
\pgfmathsetmacro{\constB}{20}%
\pgfmathsetmacro{\constC}{100}%
\foreach[%
remember=\x as \xx (initially 0),
remember=\y as \yy (initially 0),
evaluate=\x using (\xx>0) ? \yy - sqrt(abs(\constB*\xx-\constC)) : \yy + sqrt(abs(\constB*\xx-\constC)),
evaluate=\y using \constA - \xx,
] \i in {0,...,13000} {%
\calcmod{\i}
\ifnum\res=0 \fill[color=red](\x,\y) circle(1pt);
\fi
\ifnum\res=1 \fill[color=yellow](\x,\y) circle(1pt);
\fi
\ifnum\res=2 \fill[color=blue](\x,\y) circle(1pt);
\fi
\ifnum\res=3 \fill[color=black](\x,\y) circle(1pt);
\fi
}%
\end{tikzpicture}

\end{document}


It works fine up to ~12000 iterations but when I increase the number to 13000 then pdflatex fails with the error message:

! TeX capacity exceeded, sorry [main memory size=5000000].
\pgfsyssoftpath@thepath ...h@curvetosupportbtoken
{-100.15211pt}{-145.2793pt...
l.36 }
%
I

Is there any solution for this issue?

Thanks a lot for your help! I am new to tikz and was not aware of this foreach's nice feature.

Martin Heller

unread,
Oct 18, 2013, 5:20:13 AM10/18/13
to
Vitaly Repin wrote, on 18-10-2013 08:50:
> Is there any solution for this issue?

Your example compiles fine with LuaLaTeX. It does not have the same
memory restrictions as pdfLaTeX.

TikZ/pgfmath has a mod() function which you can use to simplify your
document:

\documentclass{minimal}
\usepackage{tikz}

\begin{document}

\colorlet{color0}{red}
\colorlet{color1}{yellow}
\colorlet{color2}{blue}
\colorlet{color3}{black}

\begin{tikzpicture}[x=1mm,y=1mm,scale=.35]
\pgfmathsetmacro{\constA}{40}%
\pgfmathsetmacro{\constB}{20}%
\pgfmathsetmacro{\constC}{100}%
\foreach[%
remember=\x as \xx (initially 0),
remember=\y as \yy (initially 0),
evaluate=\x using (\xx>0) ? \yy -
sqrt(abs(\constB*\xx-\constC)) : \yy + sqrt(abs(\constB*\xx-\constC)),
evaluate=\y using \constA - \xx,
] \i in {0,...,13000} {%
\pgfmathtruncatemacro{\c}{mod(\i,4)}%
\fill[color=color\c](\x,\y) circle(1pt);
}%
\end{tikzpicture}

\end{document}

Also, you should consider if TikZ and LaTeX are the right tool to do
this kind of numerical calculations.
0 new messages