12

I am trying to declare the sinc-function for usage in tikz. I tried two different ways:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
    \tikzmath{
        function sincm(\x) {
            if abs(\x) < 0.001 then {
                return 1.0;
            } else {
                return sin(\x r)/\x;
            };
        };
    }
    \pgfmathdeclarefunction{sinc}{1}{%
        \pgfmathparse{%
            abs(#1)<0.001 ? 1 : sin(#1 r)/#1%
            }%
        }

    \draw (-1,0) -- (1,0);
    \draw[domain=0:0.5, samples=1000] plot (\x, {sincm(\x*20)});
    \draw[domain=0:0.5, samples=1000, red, dotted] plot (\x,{sinc(\x*20)});

\end{tikzpicture}
\end{document}

Both ways yield the same result. I would like to use \pgfmathdeclarefunction variante, first of all to be able to declare this function globally, maybe even for several tikz-pictures. However, if I set the start of the plotting domain to zero:

\draw[domain=0:0.5, samples=1000, red, dotted] plot (\x,{sinc(\x*20)});

I get the Error Package PGF Math Error: You've asked me to divide '0,0' by '0.0'. Somehow, in this case, the ifthenelse-structure in my declaration of sinc does not seem to work?

Dux
  • 1,260

2 Answers2

13

Unfortunately, when encountered with an if-then syntax, PGF evaluates both branches and then chooses hence it will divide no matter what the value of #1 is. Instead you can use it to branch off

\begin{tikzpicture}
    \pgfmathdeclarefunction{sinc}{1}{%
        \pgfmathparse{abs(#1)<0.01 ? int(1) : int(0)}%
        \ifnum\pgfmathresult>0 \pgfmathparse{1}\else\pgfmathparse{sin(#1 r)/#1}\fi%
        }

    \draw (-1,0) -- (1,0);
    \draw[domain=0:0.5, samples=250] plot (\x,{sinc(20*\x)});

\end{tikzpicture}

enter image description here

percusse
  • 157,807
  • Works perfectly, thank you! This is a very counter-intuitive behavior, i would have thought such thing should be documented in the pgf-manual... – Dux Mar 25 '15 at 10:40
  • @Dux I'm guessing that it is more pragmatic this way due to TeX way of doing things. Note that you have to parse first and act later in TeX which brings in its own strangeness. – percusse Mar 25 '15 at 10:44
  • @percusse Where does exactly that “parse first and act later” behaviour come from? – Manuel Mar 25 '15 at 10:54
  • 1
    @Manuel Things like collecting expressions without evaluating them for possible macros inside it. Short circuiting is way more tedious than merely processing the expressions and choosing between #2 and #3. It is possible of course but it is what it is. And again I'm pretty much putting words in TikZ developers' mouths. – percusse Mar 25 '15 at 11:55
  • Does anyone know whether this function will find its way into the code of the fine pgf package? – Jürgen Jan 25 '17 at 12:58
1

I came across this question when I needed to plot a sinc function with pgfplots. It took me a while to figure out that the accepted answer for the original question here does not work in that case because of the way pgfplots handles numbers (see for example Plotting a function defined with \pgfmathdeclarefunction).

So in case anybody needs it, here is a solution that works both with TikZ \draw plot and \addplot:

\begin{tikzpicture}
    \pgfmathdeclarefunction{sinc}{1}{%
        \pgfmathparse{(#1==0 ? 1: sin(#1 r))/(#1==0 ? 1: #1)}%
        }
\begin{axis}
\addplot+[no markers] {sinc(x)};
\end{axis}

\end{tikzpicture}

EDIT: I improved my answer following @user202729's comment.

FlorianL
  • 1,659