Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

Following questions on constructing functions on the forum, I tried to build some myself. I can't seem to get the ifthenelse function in TikZ/PGF to work. Here is an example:

\documentclass[]{minimal}

\usepackage{tikz}
\usepackage{pgfplots}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}

\begin{document}

%this works
\pgfmathdeclarefunction{f}{0}{%
  \pgfmathparse{x^2}%
}

%this does not work
\pgfmathdeclarefunction{g}{0}{%
  \pgfmathparse{ifthenelse(x<0,-x^2,x^2)}%
}

\begin{tikzpicture}
\begin{axis}[every axis plot post/.append style={
  mark=none,domain=-2:2,smooth}, 
  axis x line*=bottom, axis y line*=left, enlargelimits=upper] 

  \addplot {f};
  \addplot {g};
\end{axis}
\end{tikzpicture}

\end{document}
share|improve this question
    
I don't think this code will compile. Doesn't the second argument of \pgfmathdeclarefunction require a number? –  Alan Munn Apr 10 '11 at 16:32
    
You are correct. I added a 0 and now it behaves as I described (f works, g does not). –  Frédéric Apr 10 '11 at 16:49
add comment

1 Answer 1

up vote 12 down vote accepted

This is a problem with the fpu library that is used by pgfplots: The ifthenelse command is not implemented in fpu, so it falls back to the normal pgfmath routine, which then stumbles over the floating point format of the arguments, because numbers are handled in the form 1Y1.0e0].

To circumvent this, the fpu library can be disabled in the newly defined math function using

\pgfkeys{/pgf/fpu=false}

However, the x-value handed over by pgfplots is still in the floating point format, so it has to be converted into a fixed point format:

\pgfmathfloattofixed{\x}
\let\x=\pgfmathresult

In case the fpu library is not active, this will fail because \pgfmathfloattofixed{\x} doesn't know what to do with a fixed point number. So we need to use \pgflibraryfpuifactive to test whether fpu is active, and convert the number only if it is.

Now x is a normal fixed point number, and all the common pgfmath functions should work.

However, the pgfmath engine is less precise than fpu, so it might not be desirable to fall back to it.

As ifthenelse is not a very complicated function, we can just define it ourselves:

\pgfmathdeclarefunction{ifthenelsefpu}{3}{ %}
  \pgfmathparse{#1*#2 + !#1*#3} %
}

Which can be used like the original function.

I've put both approaches into the example document below:

\documentclass{article}
\usepackage{pgfplots}

\pgfmathdeclarefunction{ifthenelsefpu}{3}{%
  \pgfmathparse{#1*#2 + !#1*#3}%
}
\pgfmathdeclarefunction{f}{1}{%
\pgfmathparse{ifthenelsefpu(#1<0,#1^2,#1)}%
}

\pgfmathdeclarefunction{g}{1}{%
  \pgflibraryfpuifactive{%
    \pgfkeys{/pgf/fpu=false}%
    \pgfmathfloattofixed{#1}%
    \let\x=\pgfmathresult%
  }%
  {%
    \pgfmathparse{#1}%
    \let\x=\pgfmathresult%
  }%
  \pgfmathparse{ifthenelse(\x<0,(\x)^2,\x)}%
}

\begin{document}
\begin{tikzpicture}
\begin{axis}[every axis plot post/.append style={
  mark=none,domain=-3:3,smooth}, 
  axis x line*=bottom, axis y line*=left, enlargelimits=upper]
  \addplot {f(x+0.5)};
  \addplot {g(x-1)};
\end{axis}
\end{tikzpicture}

%Code for showing that the functions work outside pgfplots
\pgfmathf{-3}\pgfmathresult

\pgfmathg{-3}\pgfmathresult
\end{document}

pgfplots and ifthenelse

share|improve this answer
    
@Jake : I understand the definition of f but not the definition of g –  Alain Matthes Apr 10 '11 at 21:07
    
@Jake : I understand the definition of f but not the definition of g. \pgfmathf{2} \pgfmathresult is fine but how do you use \pgfmathg ? Another question do you understand why with pgfplots there is a problem if we take the definition of ifthenelse as in pgf \pgfmathdeclarefunction{ifthenelsefpu}{3}{% \begingroup% \ifdim#1pt=0.0pt\relax% .... –  Alain Matthes Apr 10 '11 at 21:23
    
@Altermundus: As it was, the code for the g function only worked if the fpu library was active. I've fixed it now. The \ifdim approach doesn't work if the number is passed in floating point format (1Y1e0]), because there is a Y in the number, which \ifdim believes to be a strange unit. The number needs to be converted to a fixed point format (1.0) for that approach to work. –  Jake Apr 10 '11 at 21:53
    
@Jake Thanks! if I understand but it's not sure, pgfplots adapts all the pgfmath functions or it uses only the functions defined by the fpu library ? –  Alain Matthes Apr 10 '11 at 22:06
    
@Jake : Thank you very much. This answer my question completely. –  Frédéric Apr 11 '11 at 2:41
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.