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つの関数として定義したいのです。
[(1)について]
“メリット”はやっぱり「実装が単純」であることでしょう。逆にいうと、「引数を先に評価しない」ifthenelseを実装するのは結構大変だと思われます。というのも
pgfmathでは常に「評価しながら構文解析する」戦略であるため、現存のコードだけでは「評価しないで構文解析だけする」ことができないため
だからです。なお「構文解析しないで安直に引数を読み飛ばす」ことができないのは次のような例を見ればわかるでしょう。
ifthenelse(\y>0,mod(\x,\y),0)
※余談ですが、expl3言語について今年頭に、「ブール式において、論理演算子(&&
、||
)の短絡評価を廃止する」という仕様変化が行われました。この理由も、「式を読み飛ばすのが困難」(つまり従来の実装はバグっていた)ということのようです。
[(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}