6

I'm trying to create groups of 5 stacked xbars, using y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}. However, after some groups, the calculation seems to get thrown off and the third group actually consists of 6 bars:

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{pgfplotstable}
\begin{document}
\pgfplotstableread{%
x y
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
}\loadedtable

    \begin{figure}[h]
        \begin{tikzpicture}
            \begin{axis}[xbar stacked, ytick=data, y=0.9cm]
                \addplot table[x=x,y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}] \loadedtable ;
                \addplot table[x=x,y expr={\thisrow{y} - (mod(\thisrow{y},5)/2)}] \loadedtable ;
            \end{axis}
        \end{tikzpicture}
    \end{figure}
\end{document}

enter image description here

thpani
  • 493
  • 1
    @Jubobs Got it. That's precision problem it will repeat itself at 30,40,55 etc. because Mod is not in there yet and mod uses truncation – percusse Nov 19 '13 at 22:26
  • @percusse Glad you figured it out. I was worried I was simply missing something really obvious. Do you mind elaborating in a full-blow answer? – jub0bs Nov 19 '13 at 22:34
  • @percusse On second thought, I think the problem lies with \thisrow, not with mod. Try \pgfmathsetmacro\myresult{15-0.5*mod(15,5)} \draw node {\myresult}; inside a tikzpicture and you get 15, as expected. – jub0bs Nov 19 '13 at 23:15
  • @percusse \foreach[count=\xi] \x in {15,30,40,55} { \pgfmathsetmacro\myresult{\x-0.5*mod(\x,5)} \draw (\xi,0) node {\myresult}; } produces fine results. – jub0bs Nov 19 '13 at 23:39

1 Answers1

6

This happens because of numerical inaccuracies of the mod function when using the fpu library (which is the case for most calculations within an axis environment). Sometimes, the function incorrectly returns the divisor instead of zero (\pgfmathparse{mod(15,5)}, for instance).

You can fix this by defining a new version of the mod function that checks for this error:

\pgfmathdeclarefunction{fpumod}{2}{%
    \pgfmathfloatdivide{#1}{#2}%
    \pgfmathfloatint{\pgfmathresult}%
    \pgfmathfloatmultiply{\pgfmathresult}{#2}%
    \pgfmathfloatsubtract{#1}{\pgfmathresult}%
    \pgfmathfloatifapproxequalrel{\pgfmathresult}{#2}{\def\pgfmathresult{0}}{}%
}

\documentclass{article}
\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{pgfplotstable}

\pgfmathdeclarefunction{fpumod}{2}{%
    \pgfmathfloatdivide{#1}{#2}%
    \pgfmathfloatint{\pgfmathresult}%
    \pgfmathfloatmultiply{\pgfmathresult}{#2}%
    \pgfmathfloatsubtract{#1}{\pgfmathresult}%
    \pgfmathfloatifapproxequalrel{\pgfmathresult}{#2}{\def\pgfmathresult{0}}{}%
}

\begin{document}
\pgfplotstableread{%
x y
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
10 10
11 11
12 12
13 13
14 14
15 15
16 16
17 17
18 18
19 19
20 20
21 21
}\loadedtable

        \begin{tikzpicture}
            \begin{axis}[xbar stacked, ytick=data, y=0.9cm]
                \addplot table[x=x,y expr={\thisrow{y} - (fpumod(\thisrow{y},5)/2)}] \loadedtable ;
                \addplot table[x=x,y expr={\thisrow{y} - (fpumod(\thisrow{y},5)/2)}] \loadedtable ;
            \end{axis}
        \end{tikzpicture}
\end{document}
Jake
  • 232,450
  • 1
    Thanks for that, Sherlock Holmes :) But who is the culprit? fpu or the implementation of mod? Is the fpu not compliant with the IEEE-754 standard? – jub0bs Nov 20 '13 at 10:45