[TikZ/PGF] ifthenelse の仕様について

[TikZ/PGF] ifthenelse の仕様について

- tat tsan の投稿
返信数: 3
TikZで ifthenelse を用いて関数を定義するとき、
if の判定が false の場合も then 側の式が展開されますね。
たとえば

\begin{tikzpicture}[
declare function={
foo(\x)=(\x)^(10);
hoge(\x)=ifthenelse(\x<1,foo(\x),1);
hogeSAFE(\x)=ifthenelse(\x<1,foo(min(\x,1)),1);
}
]
\draw[domain=0:3,samples=40] plot (\x,{hoge(\x)});
\end{tikzpicture}

において、hoge(\x) をプロットしようとすると \x>1 のときにも
foo(\x) が計算されてしまうために dimension too large error
となります。このため hogeSAFE(\x) のようにする必要があるの
ですが、これでも無駄な計算が生じるのが気に入りません。

そこで質問なのですが、

(1) ifthenelse のこの仕様のメリットは何でしょうか?
(2) 無駄な計算の生じない書き方はありませんか?

(2)はもちろん区間別にプロットすればよいのですが、そんなコードが
大量にあると見づらくなるので、1つの関数として定義したいのです。
tat tsan への返信

Re: [TikZ/PGF] ifthenelse の仕様について

- Z. R. の投稿

[(1)について]

“メリット”はやっぱり「実装が単純」であることでしょう。逆にいうと、「引数を先に評価しない」ifthenelseを実装するのは結構大変だと思われます。というのも

pgfmathでは常に「評価しながら構文解析する」戦略であるため、現存のコードだけでは「評価しないで構文解析だけする」ことができないため

だからです。なお「構文解析しないで安直に引数を読み飛ばす」ことができないのは次のような例を見ればわかるでしょう。

ifthenelse(\y>0,mod(\x,\y),0)

※余談ですが、expl3言語について今年頭に、「ブール式において、論理演算子(&&||)の短絡評価を廃止する」という仕様変化が行われました。この理由も、「式を読み飛ばすのが困難」(つまり従来の実装はバグっていた)ということのようです。

tat tsan への返信

Re: [TikZ/PGF] ifthenelse の仕様について

- Z. R. の投稿

[(2)について]

パッと思いつくのは、tikzmathを使うこと、ですね。

\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}[
    declare function = {
      foo(\x)=(\x)^(10);
    },
    evaluate = {
      function hoge(\x) {
        if \x < 1 then { return foo(\x); }
        else { return 1; };
      };
    },
    % pgfmathの関数(declare functionも含む)と
    % tikzmathの関数は同じ名前空間にあるらしい
  ]
  \draw[domain=0:3,samples=40] plot (\x,{hoge(\x)});
\end{tikzpicture}
\end{document}
Z. R. への返信

Re: [TikZ/PGF] ifthenelse の仕様について

- tat tsan の投稿
なるほど、 pgfmath の構文解析が評価を伴なうのですね。
また pgfmath と tikzmath の役割の違いを認識しておりませんでした。
tikzmath を積極的に使ってゆこうと思います。

詳しい御解説ありがとうございました。