4

First, I would like to apologize for the vague title of my question, somehow I didn't manage to come up with something more precise.

Based on an answer to this question, I wanted to create a function to draw the n-th roots of unity with tikz (this was done in the answer cited above) and outline the primitive ones in red (this is what I wanted to add). After some time of investigation I came across pgfmath and ended up with the following:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{ifthen}
\pgfmathdeclarefunction{GCD}{2}{
\ifnum#1>#2 \edef\no{#1}\edef\res{#2} \else \edef\no{#2}\edef\res{#1} \fi
\ifnum\res=0 \pgfmathtruncatemacro\temp{0}\pgfmathtruncatemacro\res{\no} \else \pgfmathtruncatemacro\temp{mod(\no,\res)}
    \whiledo{\temp>0}{
        \pgfmathtruncatemacro\no{\res}
        \pgfmathtruncatemacro\res{\temp}
        \pgfmathtruncatemacro\temp{mod(\no,\res)}
    }
\fi 
\pgfmathparse{\res}
}
\newcommand{\plotroots}[1]{
    \edef\n{#1}
    \begin{tikzpicture}[
    dot/.style={draw,fill,circle,inner sep=1pt}
    ]
        \draw[->] (-2.5,0) -- (2.5,0) node[right] {$\mathrm{Re}$};
        \draw[->] (0,-2.5) -- (0,2.5) node[above] {$\mathrm{Im}$};
        \draw[help lines] (0,0) circle (1.7);

        \node[dot,label={below right:$0$}] (H) at (0,0) {};
        \foreach \i in {1,...,\n} {
            \begin{scope}   
                \pgfmathparse{GCD(\i,\n)}
                \ifnum\pgfmathresult=1 \gdef\rootcolor{red} \else\gdef\rootcolor{black}\fi
            \end{scope}
            \node[\rootcolor,dot,label={\i*360/\n-(\i==\n)*45:\textcolor{\rootcolor}{\pgfmathparse{int(mod(\i,\n))}$\zeta_{\n}^{\pgfmathresult}$}}] (w\i) at (\i*360/\n:1.7) {};
    \draw[\rootcolor,->] (H) -- (w\i);
        }
        \draw[->] (0:.3) arc (0:360/\n:.3);
        \node at (360/\n/3:.75) {\footnotesize $2\pi/\n$};
    \end{tikzpicture}
}
\begin{document}
\centering\plotroots{12}
\end{document}

This works essentially fine, for example, the output is enter image description here
Still, there are some problems to it I would really like to understand:

  1. If the roots happen to be located on one of the coordinate axes, the label should be placed 45 degree off the respective axis as opposed to the usual placement. If I'm not completely mistaking the code taken from the answer cited above, this is done in label={\i*360/\n-(\i==\n)*45: But, in the example of \n=12 shown above, why would this apply for \i=3,6,9 (as it obviously does)?
    Also, for \n=8, the output is: enter image description here
    So, here, the condition applies for \i=4,6, but apparently not for \i=2. How can this be possible?

  2. Before I added the \begin{scope}...\end{scope} around the piece of new code inside the \foreach-loop which is checking if the root is primitive, the output looked like the following: enter image description here

EDIT: To be precise, the code that produced the image above was:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usepackage{ifthen}
\pgfmathdeclarefunction{GCD}{2}{
\ifnum#1>#2 \edef\no{#1}\edef\res{#2} \else \edef\no{#2}\edef\res{#1} \fi
\ifnum\res=0 \pgfmathtruncatemacro\temp{0}\pgfmathtruncatemacro\res{\no} \else \pgfmathtruncatemacro\temp{mod(\no,\res)}
    \whiledo{\temp>0}{
        \pgfmathtruncatemacro\no{\res}
        \pgfmathtruncatemacro\res{\temp}
        \pgfmathtruncatemacro\temp{mod(\no,\res)}
    }
\fi 
\pgfmathparse{\res}
}
\newcommand{\plotroots}[1]{
    \edef\n{#1}
    \begin{tikzpicture}[
    dot/.style={draw,fill,circle,inner sep=1pt}
    ]
        \draw[->] (-2.5,0) -- (2.5,0) node[right] {$\mathrm{Re}$};
        \draw[->] (0,-2.5) -- (0,2.5) node[above] {$\mathrm{Im}$};
        \draw[help lines] (0,0) circle (1.7);

        \node[dot,label={below right:$0$}] (H) at (0,0) {};
        \foreach \i in {1,...,\n} {     
            \pgfmathparse{GCD(\i,\n)}
            \ifnum\pgfmathresult=1 \gdef\rootcolor{red} \else\gdef\rootcolor{black}\fi
            \node[\rootcolor,dot,label={\i*360/\n-(\i==\n)*45:\textcolor{\rootcolor}{\pgfmathparse{int(mod(\i,\n))}$\zeta_{\n}^{\pgfmathresult}$}}] (w\i) at (\i*360/\n:1.7) {};
    \draw[\rootcolor,->] (H) -- (w\i);
        }
        \draw[->] (0:.3) arc (0:360/\n:.3);
        \node at (360/\n/3:.75) {\footnotesize $2\pi/\n$};
    \end{tikzpicture}
}
\begin{document}
\centering\plotroots{8}
\end{document}

So it appears that in this case, the origin is moving in every iteration. I would be really glad to know what causes this effect! What kind of mistakes have I made in writing the function GCD? And how can this affect the position of the drawing? And why is it that e.g. \bgroup ... \egroup doesn't have an effect, but \begin{scope} ... \end{scope} does? (Please excuse my lack of prior knowledge concerning this, but it is the first time I tried to write some kind of function in LaTeX)

Any help is highly appreciated, thanks in advance!

  • For your second question : you should read the doc about pgfmathdeclarefunction where we can see : "Furthermore, the function should have no other side effects, that is, it should not change any global values." – Kpym Mar 25 '18 at 7:59
  • @Kpym I found the doc you referred to, thank you for the hint! One thing is still unclear to me though: To my mind, the variables \no, \res and \temp in the GCD function should be local variables and I have no ideal how anything in there should have global side effects? Where do these occur, or, more precisely: How could I rewrite the above GCD function in a version without side effects? This would really help me understand the problem much better, I already tried to use the \begingroup ...\pgfmathreturn\res\endgroup construction I found in the docs, but unfortunately couldn't make it work – user103697 Mar 25 '18 at 10:22
  • Sorry I have no idea what exactly is wrong in your code. For some reason the spaces in \pgfmathdeclarefunction introduce some shift when used inside \foreach. – Kpym Mar 25 '18 at 16:05
  • Never mind! Actually, knowing that the effect is caused by the spaces already is quite an improvement for me and may be a good starting point for doing further investigation on my own... Thank you again for your answer! – user103697 Mar 25 '18 at 21:12
6
  1. The expression \i*360/\n-(\i==\n)*45 is not a legal pgf expression. So the result is "unpredictable" (actually it is the same as \i*360/\n-\i).
  2. If you want some answer to your question you should show the code that produce this problem.

By the way here is, I think, simpler and more "tikzedish" code:

\documentclass[tikz,border=7pt]{standalone}
\tikzset{
  color1/.style = {red},
  roots/.pic={
    \pgfmathtruncatemacro{\n}{#1}
    \pgfmathtruncatemacro{\m}{\n-1}
    \draw[-latex] (-90:3) -- (90:3) node[right]{Im};
    \draw[-latex] (180:3) -- (0:3) node[below]{Re};
    \draw (0,0) circle(2);
    \foreach[evaluate={\j=mod(4*\i,\n)==0;\k=gcd(\i,\n)}]\i in{0,...,\m}{
      \draw[color\k/.try]
        (0:0) -- (\i*360/\n:2) node[scale=3]{.}
        (\i*360/\n+\j*7:2.35) node{$\zeta_{\n}^{\i}$};
    }
  }
}
\begin{document}
  \begin{tikzpicture}
    \pic{roots=3*4};
  \end{tikzpicture}
\end{document}

enter image description here

  • Thanks a lot for your answer and the very nice code you provided! I added the code concerning the second question. It would be great if you could point out the mistake I made there! – user103697 Mar 24 '18 at 22:56

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.