pgf-tikz / pgf

A Portable Graphic Format for TeX
https://pgf-tikz.github.io/
1.12k stars 106 forks source link

Precision problems when not using the parser with luamath #699

Open hmenke opened 5 years ago

hmenke commented 5 years ago

Probably the PGF math parser evaluates subexpressions during parsing which leads to a massive loss of precision.

\documentclass[a5paper]{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{luamath}
\begin{document}
\pgfkeys{/pgf/trig format/rad}

\pgfkeys{/pgf/luamath=only computation}
\pgfmathparse{2*11000*(1 - 1.40576 - cos(0.02) + sqrt(1.40576^2 - sin(0.02)^2))}
only computation:\hfill\pgfmathresult

\pgfkeys{/pgf/luamath=parser and computation}
\pgfmathparse{2*11000*(1 - 1.40576 - cos(0.02) + sqrt(1.40576^2 - sin(0.02)^2))}
parser and computation:\hfill\pgfmathresult

Lua:\hfill\directlua{
    local print = tex.print
    local _ENV = math
    print(2*11000*(1 - 1.40576 - cos(0.02) + sqrt(1.40576^2 - sin(0.02)^2)))
}
\end{document}

Mo-Gul commented 4 years ago

@hmenke, in https://github.com/pgf-tikz/pgf/issues/861#issuecomment-633431073 you stated that LUA is broken. Could you elaborate on this? What do you think the "right" result is of the above expression?

(When I calculate it using Excel I get 1.270132770125 as well.)

hmenke commented 4 years ago

As you can see from the image in the first post, the only computation mode gives a completely wrong result.

Mo-Gul commented 4 years ago

Aah, now I see. I thought "only computation" was the result not using Lua (at all).

I had a closer look and it seems that the (large) difference in the output comes from 1.40576^2 and the rest is just a subsequent error. See the red marked entry in the following image. When I replace 1.40576^2 in the expression with the result of the computation from Lua, i.e. 1.9761611776, then the results are almost identical (the last line in the table marked in green).

When I am not mistaken the "large" difference comes from https://github.com/pgf-tikz/pgf/blob/e0b798ba19471877f80633a727c45e09439344b3/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex#L237-L242

All in all I wouldn't say that "Lua is broken". "Just" only computation is a bit inaccurate which seems to be explainable from the above comment in the code. 1.40576^2 gives the same result using LaTeX/pgf calculation (only) or using only computation.

Evaluating the whole expression not using Lua or xfp results in a Dimension too large error. And using fpu then gives a result that is even more off than the only computation result (which seems to be originated from the sqrt(a) computation result).

So when it is known that only computation is "inaccurate", why not (simply) use parser and computation instead?

image showing the result of the following code

Code to generate above result ```latex \documentclass{article} \usepackage[a4paper,margin=1in,landscape]{geometry} \usepackage{mathtools} \usepackage{xparse} \usepackage{xfp} \usepackage{tikz} \usetikzlibrary{ fpu, luamath, matrix, } % from \def\sqrtexplained#1{% \begingroup \sbox0{$#1$} \def\underbrace##1_##2{##1} \sbox2{$#1$} \dimen0=\wd0 \advance\dimen0-\wd2 \mathrlap{\sqrt{\phantom{\displaystyle#1}\kern\dimen0 }} \hphantom{\sqrt{\vphantom{\displaystyle#1}}} \endgroup #1% } \NewDocumentCommand{\mylua}{m}{ \directlua{ local print = tex.print; local _ENV = math; print(#1) } } \pgfkeys{ /pgf/trig format/rad, /pgf/number format/.cd, sci, precision=12, } \NewDocumentCommand{\myrow}{sm}{% % 2nd column \IfBooleanTF{#1}{ (error) }{ \pgfmathparse{#2}\pgfmathresult% % \pgfmathparse{#2}\pgfmathprintnumber{\pgfmathresult}% } \pgfmatrixnextcell % 3rd column \pgfkeys{ /pgf/fpu=true, % /pgf/fpu/output format=sci, } \pgfmathparse{#2}\pgfmathresult% % \pgfmathparse{#2}\pgfmathprintnumber{\pgfmathresult}% \pgfkeys{/pgf/fpu=false}% \pgfmatrixnextcell \pgfkeys{/pgf/luamath=only computation} \pgfmathparse{#2}\pgfmathresult% % \pgfmathparse{#2}\pgfmathprintnumber{\pgfmathresult}% \pgfmatrixnextcell \pgfkeys{/pgf/luamath=parser and computation} \pgfmathparse{#2}\pgfmathresult% % \pgfmathparse{#2}\pgfmathprintnumber{\pgfmathresult}% \pgfmatrixnextcell \mylua{#2} % \pgfmathprintnumber{\mylua{#2}} \pgfmatrixnextcell \fpeval{#2} % \pgfmathprintnumber{\fpeval{#2}} } \begin{document} \begin{equation*} 2 \cdot 11000 \cdot \bigg( \underbrace{1 - 1.40576 - \cos(0.02) + \sqrtexplained{\underbrace{1.40576^2 - \sin(0.02)^2}_{a}}}_{b} \bigg) \end{equation*} \begin{tikzpicture}[ row 2 column 4/.style=red, row 10/.style=green!50!black, ] \matrix (a) [ matrix of nodes, anchor=west, ] { expression & off & fpu & only computation & parser and computation & Lua & xfp \\ $1.40576^2$ & \myrow{1.40576^2} \\ $\sin(0.02)^2$ & \myrow{sin(0.02)^2} \\ $a$ & \myrow{1.40576^2 - sin(0.02)^2} \\ $\sqrt{a}$ & \myrow{sqrt(1.40576^2 - sin(0.02)^2)} \\ $\cos(0.02)$ & \myrow{cos(0.02)} \\ $1 - 1.40576 - \cos(0.02)$ & \myrow{1 - 1.40576 - cos(0.02)} \\ $b$ & \myrow*{1 - 1.40576 - cos(0.02) + sqrt(1.40576^2 - sin(0.02)^2)} \\ $2 \cdot 11000 \cdot b$ & \myrow*{2*11000*(1 - 1.40576 - cos(0.02) + sqrt(1.40576^2 - sin(0.02)^2))} \\ using $1.40576^2$ = Lua result & \myrow*{2*11000*(1 - 1.40576 - cos(0.02) + sqrt(1.9761611776 - sin(0.02)^2))} \\ }; \draw (a-1-1.south -| a.west) -- (a-1-7.south -| a.east); \end{tikzpicture} \end{document} ```
davidcarlisle commented 4 years ago

@Mo-Gul you confused me for a while as 1.460576^2 is 2.133 not 1.976 you intended 1.40576^2

Mo-Gul commented 4 years ago

@davidcarlisle, I am so sorry. Don't know how this typo could happen. I edited my previous post accordingly so that nobody else gets confused too.

hmenke commented 4 years ago

@Mo-Gul The comment you linked applies to the line below https://github.com/pgf-tikz/pgf/blob/e0b798ba19471877f80633a727c45e09439344b3/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex#L239-L243 Thanks for debugging this. I'll have a closer look.

hmenke commented 4 years ago

I have found part of the problem. pow is simply not implemented. https://github.com/pgf-tikz/pgf/blob/e0b798ba19471877f80633a727c45e09439344b3/tex/generic/pgf/libraries/luamath/pgflibraryluamath.code.tex#L307 However, the corresponding Lua code is there. Same for other functions. https://github.com/pgf-tikz/pgf/blob/e0b798ba19471877f80633a727c45e09439344b3/tex/generic/pgf/libraries/luamath/pgf/luamath/functions.lua#L105-L108 I have to email Christian anyway, so I will ask about that.