# 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) Jun 22, 2019 at 9:13
• @frougon oh you want mathematically correct results not just an error free tex run? So converntional:-) Yes thanks, I'll fix Jun 22, 2019 at 9:18
• Oh, no, rest assured: not me—but maybe cis? :-) Jun 22, 2019 at 9:20
• @frougon better? Jun 22, 2019 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!) Jun 22, 2019 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:]
\addplot[blue,domain = {-0.07:0.07}] plot
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, 2019 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, 2019 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}[]
\addplot[blue,domain = {#3:#3+0.1}] plot gnuplot[id=mycalc]{#2};
%\addplot[blue,domain = {pi:2*pi}] plot gnuplot[id=mycalc]{5};
\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}[]
\addplot[blue,domain = {\x:\x+0.1}] plot gnuplot[id=mycalc]{\Curve{x}};
%\addplot[blue,domain = {pi:2*pi}] plot gnuplot[id=mycalc]{5};
\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}$