3

I was trying to draw a Pierson-Moskowitz wave spectrum in TikZ and had to load the PGF's fpu library to do some of the calculations.

Lots of errors!

What surprised me is that one of them doesn't have to do with my wave spectrum, but with the tape shape from the shapes.symbols library:

\documentclass[tikz]{standalone}

\usetikzlibrary{shapes.symbols}
\usetikzlibrary{fpu}

\begin{document}

\pgfkeys{/pgf/fpu=true,/pgf/fpu/output format=fixed}
\begin{tikzpicture}
  \node [tape] (model) {Do stuff};
\end{tikzpicture}

\end{document}

this raises the ill-formatted floating point number.

Why is the FPU incompatible with this (apparently simple) library?

  • My experience has been that if TikZ can use the FPU, it will, and not to mess around with the pgfkeys. – John Kormylo Aug 26 '18 at 14:47
  • @JohnKormylo First I tried without explicitly setting the FPU. The thing is that if I don't use the FPU then I can't draw the function I want because of "dimension too large". I already managed to work around the issue, but I asked because I don't think that the FPU should break one of TikZ's standard libraries. – Phelype Oleinik Aug 26 '18 at 14:58
  • Do you have to set the pgfkeys globally or is it sufficient to set it just locally where you need it? –  Aug 26 '18 at 15:08
  • @JohnKormylo Indeed, it can, bot for my purposes it works. As I said my question is about the incompatibility of the FPU and a simple library. – Phelype Oleinik Aug 26 '18 at 15:09
  • @marmot That's what I did to have my picture working. I'm curious about the incompatibility :) – Phelype Oleinik Aug 26 '18 at 15:10
  • I am also curious and already upvoted that question. And I am also always confused about that library, sometimes people also load \uspackage{fp}, sometimes not, and I don't know when to do what. –  Aug 26 '18 at 15:13
  • @marmot I think that's another choice of floating point library. As far as I know there's the one you mentioned, PGF's, and expl3's for one to choose from. I'm using PGF's right now because it works quite well in pictures. I think that the others are for more general stuff... – Phelype Oleinik Aug 26 '18 at 15:17
  • @PhelypeOleinik Actually some packages like pgfplots even rely on Lua (in LuaLaTeX) to do calculations. – TeXnician Aug 26 '18 at 15:21
  • @TeXnician That I didn't know :) – Phelype Oleinik Aug 26 '18 at 15:28
  • @Schrödinger'scat Thanks for your comment! A couple of thesis pages after asking this question I stumbled across a similar issue which I reported (https://github.com/pgf-tikz/pgf/issues/678) and Henri said that "drawing with FPU enabled will not work". Some more discussion in the chat room (which I couldn't find now) convinced me enabling the FPU for drawing is not a good idea. It's just that I naively thought that the FPU was supposed to work out-of-the-box to extend the range of numbers when drawing. If you'd like to write down an answer, I'd be happy to accept it (tomorrow, bed time now :-) – Phelype Oleinik Sep 11 '19 at 01:31
  • I think it would be better if Henri wrote an answer. (Personally I do not think it is absolutely hopeless since pgfplots does manage to cooperate with shapes while fpu is switched on. I have played with this a tiny bit and am currently debating whether or not it will be used by the 3D parser https://github.com/tallmarmot/pgf/blob/master/experiments/Marmot/3dtools/tikzlibrary3dtools.code.tex. As long it is used locally, it will slow down the compilation a bit, but is AFAIK safe.) –  Sep 11 '19 at 02:17
  • @Schrödinger'scat I don't have the knowledge to tell if you should use the FPU or not, but I think you should make these libraries public :D The 3D parser is an amazing piece of work, and the one I am sure I would use (because I had already needed something like that) is the bbox thingy. Fun fact: one of my first answers in this site (here) was due to this bounding box issue (of course at the time I had absolutely no idea what a bounding box was). – Phelype Oleinik Sep 11 '19 at 11:23
  • @PhelypeOleinik The tikz-cd example is precisely of the type that prevents one from really "publishing" such a library. tikz-cd does some black magic, and it is hard to write something that deals with all these things appropriately. It however does work with fpu, see the last version here. Which is why I think one could fpuify many things without problems. (I am not saying this will work with plain TeX and/or ConTeXt.) –  Sep 11 '19 at 14:47
  • @Schrödinger'scat Hm... Indeed, I tried it and it didn't work :/ About Plain and ConTeXt: I doubt that it won't work. All of PGF and TikZ are self-contained and don't rely on the format being used (of course you already know that :-), so unless you use some LaTeX-specific macro (which you don't, from what I saw), it should (!) work the same on either format. – Phelype Oleinik Sep 11 '19 at 15:09

1 Answers1

2

It is not possible to use fpu "just so" when you use some basic pgf routines such as the ones employed in the tape shape. However, it is possible to use it locally where it matters. That is, you can switch it on locally in a group and the use \pgfmathsmuggle, which was added to pgf long after this question was written (internal versions were available before), to smuggle the result of a computation out of the group. This allows you to define functions which yield reasonably small values but go over large values when parsing the expression. The function under your link is a good example since it involves high powers of the argument, omega, but the result is not too extreme because these large values cancel.

\documentclass[tikz]{standalone}
\usetikzlibrary{shapes.symbols}
\usetikzlibrary{fpu}
\newcommand{\pgfmathparseFPU}[1]{\begingroup%
\pgfkeys{/pgf/fpu,/pgf/fpu/output format=fixed}%
\pgfmathparse{#1}%
\pgfmathsmuggle\pgfmathresult\endgroup}
\pgfmathdeclarefunction{SPM}{4}{\begingroup% #1=omega,#2=omega_p,#3=alpha,#4=beta
\pgfmathparseFPU{(#2/pow(#1,5))*exp(-#4*pow(#2/#1,4))}%
\pgfmathsmuggle\pgfmathresult\endgroup} 

\begin{document}
\pgfmathsetmacro{\xtest}{SPM(1,1,1,1)}
\begin{tikzpicture}
  \draw[stealth-stealth] (0,4) node[below left] {$S_\mathrm{PM}(\omega) $ }|- (5,0) node[below left] {$\omega$ };
  \draw[blue,thick] plot[variable=\x,domain=0.2:5,smooth,samples=71] (\x,{4*SPM(\x,1,1,1)});
  \node [tape,below right,draw] at (0.1,4){$\displaystyle S_\mathrm{PM}(\omega) 
  = \frac{\alpha g^2}{\omega^5} \exp \left [-\beta \left (\frac{\omega_p}{\omega} \right )^4 \right ]$};
\end{tikzpicture}
\end{document}

enter image description here

Needless to say that the canonical way to produce this plot is using pgfplots, which also switches on fpu only where it is needed.

\documentclass[tikz]{standalone}
\usepackage{pgfplots}
\usetikzlibrary{shapes.symbols}
\pgfplotsset{compat=1.16}
\begin{document}
\begin{tikzpicture}[declare function={SPM(\omega,\omegap,\alpha,\beta)=%
 (\omegap/pow(\omega,5))*exp(-\beta*pow(\omegap/\omega,4));}]
 \begin{axis}[xlabel=$\omega$,ylabel=$S_\mathrm{PM}(\omega)$,ymax=0.8]
  \addplot[domain=0.2:5,smooth,samples=71,blue,thick] {SPM(x,1,1,1)};
  \node[below right,draw,tape] at (0.2,0.75) {$\displaystyle S_\mathrm{PM}(\omega) 
  = \frac{\alpha g^2}{\omega^5} \exp \left [-\beta \left
  (\frac{\omega_p}{\omega} \right )^4 \right ]$};
 \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

Yet there are definitely applications where locally switching on fpu makes sense, such as this one from the answer of which I copied (more or less) the code for this answer.