# pgfmath / gnuplot: How to use gnuplot for complicated calculations?

Is there a way to use gnuplot for complicated calculations?

For
\pgfmathsetmacro{\x}{0.02} \pgfmathsetmacro{\y}{2*11000*(1 - 1.40576 - cos(\x) + sqrt(1.40576^2 - sin(\x)^2))}
for example I get 'Dimensions to large'.

% arara: pdflatex: {shell: yes}
\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{siunitx}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\pgfmathsetmacro{\x}{0.02}
%\pgfmathsetmacro{\y}{2*11000*(1 - 1.40576 - cos(\x) + sqrt(1.40576^2 - sin(\x)^2))}
Calculating works not: % \y

\begin{tikzpicture}[]
\newcommand\Curve[1]{2*11000*(1 - 1.40576 - cos(#1) + sqrt(1.40576^2 - sin(#1)^2))}
\begin{axis}[title=Graphing works:]
\addplot[blue,domain = {-0.07:0.07}] plot gnuplot[samples=500,id=curve]{\Curve{x}} node[anchor=east]{gnuplot: good};

\end{axis}
\end{tikzpicture}
\end{document}


gnuplot is more for plotting but you could use expl3's floating point instead:

\documentclass{article}
\usepackage{xfp}
\begin{document}
\newcommand{\x}{0.02}
\edef\y{\fpeval{2*11000*(1 - 1.40576 - cos(\x) + sqrt(1.40576^2 - sin(\x)^2))}}
\typeout{y=\y}
\edef\y{\fpeval{2*11000*(1 - 1.40576 - cos(\x deg) + sqrt(1.40576^2 - sin(\x deg)^2))}}
\typeout{y=\y}
\end{document}


produces

y=1.270132770126
y=0.000386870374


(Note PGF uses degrees by default in trig functions)

• Wouldn't we need \fpeval{2*11000*(1 - 1.40576 - cos(\x deg) + sqrt(1.40576^2 - sin(\x deg)^2))} to have the arguments of circular functions interpreted the same way as with pgfmath? (I get: 0.000386870374) – frougon Jun 22 '19 at 9:13
• @frougon oh you want mathematically correct results not just an error free tex run? So converntional:-) Yes thanks, I'll fix – David Carlisle Jun 22 '19 at 9:18
• Oh, no, rest assured: not me—but maybe cis? :-) – frougon Jun 22 '19 at 9:20
• @frougon better? – David Carlisle Jun 22 '19 at 9:22
• You now have the same result I got: so we are either both right or both wrong, that's all I can say. :-P (well, you gave two results, kind of cheating!) – frougon Jun 22 '19 at 9:24

If I do things as the manuals suggest me to do, then there is no problem. In particular, you may want to

1. switch on fpu to use it. Just loading pgfplots doesn't switch it on. In fact, you need to switch it off again before you start a tikzpicture.
2. Use lualatex -shell-escape for the compilation.

Then the results are fully consistent.

\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{siunitx}
\usepackage{pgfplots}
\pgfplotsset{compat=1.16}
\begin{document}
\pgfmathsetmacro{\x}{0.02}
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=sci}
\pgfmathsetmacro{\y}{2*11000*(1 - 1.40576 - cos(\x) + sqrt(1.40576^2 -
pow(sin(\x),2)))}
Calculating works:  \y
\pgfkeys{/pgf/fpu=false}

\begin{tikzpicture}[declare function={f(\x)=2*11000*(1 - 1.40576 - cos(\x) +
sqrt(1.40576^2 - sin(\x)^2));}]
\newcommand\Curve[1]{2*11000*(1 - 1.40576 - cos(#1) + sqrt(1.40576^2 - sin(#1)^2))}

\begin{axis}[title=Graphing works:]
gnuplot[samples=500,id=curve]{\Curve{x}} node[anchor=east]{gnuplot: good};

node[pos=0.5,anchor=north]{pgfplots: good};
\end{axis}
\end{tikzpicture}
\end{document}


Whether or not the result for \y is what you want or you need to add \pgfkeys{/pgf/trig format=rad} or something I don't know.

• Seems to be good with fpu. But the value should be f(x)=1.27013 for x=0.02 or f(x)=0.000386 for x=0.02° I thought fpu does not always work either. gnuplot creates an auxiliary file gnuplot01.curve.table You would have to somehow make him do that for the calculated value; and then read the table value. – cis Jun 22 '19 at 13:19
• @cis fpu does "work" but you are right in that it is not very accurate for trigonometric functions and small values. And yes, gnuplot generates a table which gets read. Similarly, when you use lualatex, the computations are not done by TeX, so they are more accurate. – user121799 Jun 22 '19 at 13:27

R have not problems with these calculations nor plotting the result with enough points:

\documentclass{article}
\begin{document}
<<echo=F,results='asis', fig.width=4,fig.height=4>>=
x = seq(-0.07,0.07,0.0001)
y=2*11000*(1 - 1.40576 - cos(x) + sqrt(1.40576^2 - sin(x)^2))
plot(x,y,type="l",lwd=3,col="blue")
@
\end{document}


OK, is the same parabola but not the same graph. Now with tikz look & feel:

\documentclass{article}
\begin{document}
<<echo=F,results='asis',dev="tikz",fig.width=4,fig.height=4>>=
x = seq(-0.07,0.07,0.0001)
y=2*11000*(1 - 1.40576 - cos(x) + sqrt(1.40576^2 - sin(x)^2))
plot(x*100,y,type="l",lwd=3,col="blue",
xlab="$x \\times10^{-2}$", ylab="$y$", xlim=c(-8.5,8.5),
xaxp  = c(-10,10,10), tck=0.02)
axis(side = 4, tck=0.02, labels = NA)
axis(side = 3, tck=0.02, at=seq(-8,8,2), labels = NA)
@
\end{document}


Something like that:

### Short:

% arara: pdflatex: {shell: yes}
\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{pgfplots, pgfplotstable}
\pgfplotsset{compat=1.16}
\newsavebox{\mycalc}
% See too: http://gnuplot.sourceforge.net/docs_4.2/node53.html
\begin{document}

\newcommand\Function[3][fixed,precision=6]{%%%%%%%%%
\sbox{\mycalc}{%%
\begin{tikzpicture}[]
\begin{axis}[]
\end{axis}
\end{tikzpicture}
}%%%
%\usebox{\mycalc}
%
%\pgfplotstabletypeset[string type]{\tempdata}
%
\pgfplotstablegetelem{0}{1}\of\tempdata
\pgfmathsetmacro\y{\pgfplotsretval}
\pgfmathprintnumber[#1]{\y}%
}%%%%%%%%%%%%%%%

\section{Easy}
$\sin(\frac\pi6) = \Function{sin(x)}{pi/6}$

\section{Difficult}
\newcommand\Curve[1]{2*11000*(1 - 1.40576 - cos(#1) + sqrt(1.40576^2 - sin(#1)^2))
}
\newcommand\curve[1]{2\cdot 11000\cdot \left(1 - 1.40576 - \cos(#1) + \sqrt{1.40576^2 - \sin(#1)^2}\right)}

Let $f(x) =\curve{x}$.
\pgfmathsetmacro\x{0.05}

$f(\x) = \Function{\Curve{x}}{\x}$
\end{document}


### Long:

% arara: pdflatex: {shell: yes}
\documentclass[margin=5mm, varwidth]{standalone}
\usepackage{pgfplots, pgfplotstable}
\pgfplotsset{compat=1.16}

\newcommand\Curve[1]{2*11000*(1 - 1.40576 - cos(#1) + sqrt(1.40576^2 - sin(#1)^2))
}
\newcommand\curve[1]{2\cdot 11000\cdot \left(1 - 1.40576 - \cos(#1) + \sqrt{1.40576^2 - \sin(#1)^2}\right)}

\begin{document}
Let $f(x) =\curve{x}$.

\pgfmathsetmacro\x{0.05}
We need $f(\x)$

\newsavebox{\mycalc}
\sbox{\mycalc}{%%%%%%%%%%%%%%%%%
\begin{tikzpicture}[]
\begin{axis}[]
\end{axis}
\end{tikzpicture}
}%%%%%%%%%%%%%%%%%%%%%%%
\section{Show graph - for Info}
\usebox{\mycalc}

\section{Show gnuplot-generated table - for Info}
\pgfplotstabletypeset[string type]{\tempdata}

$f(\x) = \pgfmathprintnumber[fixed,precision=6]{\y}$
$f(\x) = \pgfmathprintnumber[sci,precision=6]{\y}$