asm背景C++では1.0とか書くとdoubleとして解釈され、floatにするには1.0fなどと書かねばならないことはご承知のとおりだ。doubleとfloatの演算の結果はdoubleになる。これはtemplateを使うときに若干面倒になる。以下のような関数fを実装したとする。y;}さて、浮動小数点数型を受け取るクラステンプレートがあり、中でfを呼ぶとしよう。0;}何が起きるだろうか。答:コンパイルエラーになる。xはdoubleとfloatの積なのでdoubleになり、するとtemplate型推論が上手く行かない。double);が与えられるのだ。Tはどちらとも取れない。~^~~~~~~~~~~~という感じになる。templateクラスの中で書かれてるリテラルはT型に勝手になってくれよ〜と思うかも知れないが、T型とリテラルが同じ型になるという関係はこのコードを書いた人間の脳みその中にしかないので、コンパイラはそんな勝手な解釈をすることができない。x);}};これなら通る。2は整数なので、演算結果は浮動小数点数になる。問題は整数では表現出来ないときで、これは難しい。倍にするのでなく2.5倍したいときはどうするか。ナイーブにやると以下のようになる。x);}};これだと2.0の時と同じ問題が発生する。それを避けるため、明示的にキャストするという手はある。x);}};単純に長い。一つならまだ良いが、複数個こんなものを書くとしんどい。static_castでなくT(2.5)と書いてもまあ良いのだが......template引数の推論に失敗するのだから、それを明示的に与えればよい。x);}};これはまあすっきりしている。他には、定数を集めたクラスを作っておいて、そこから持ってくるという戦略もあり得る。x);}};果たしてこれでどれほど簡単になるのかという話だが。長くなると面倒な感じになっていくし、非常に冗長だ。piとかroot_piみたいな特殊な値を持っておくなら、この戦略はありなのだが(boost::math::constantsなどは似たようなことをしている)。この例と同様のことは、例えば以下のような関数でも生じる。b);これをfloatで実体化しつつ、aに2.0、bにstd::complex<float>とかを入れた場合、こうなる。ハッハッエラーの内容は同じで、型推論の結果doubleかfloatかわからなかったよ、という話だ。速度の話と、さてここまでで大体めんどくさそうだなあということはわかっていただけたと思う。面倒くさいだけならまだ良いのだが。以下のリンク先を見て欲しい。godbolt.orgこのリンク先はwandboxと同じくオンラインコンパイラなのだが、アセンブリを見せてくれるところが違いだ。アセンブリとC++コードの対応する箇所をハイライトしてくれたり、色々便利だ。そこで、以下のようなコードをコンパイルした。cos3;}同じことをする関数を3つ書き、それぞれ、リテラルを4.0、4.0f、4と変えていって、double、floatで実体化した。-ffast-mathの結果だが、clang-6.0.0でも基本的に同じことが起きた。特筆すべきは、doubleリテラルを使ってfloatで実体化したときだ。コンパイラフラグは-ffast-mathと-O3を立てているので、リテラルはfloatに再解釈されることを期待していた。point"の略である。要するにfloatをdoubleに変換するもので(singleが2回書かれているのは、SIMDという複数個一気に計算する命令があるから、それとの区別のためである)、cvsd2ssはその逆だ。何が起きているかというと、こいつはfloatで来た引数を一度doubleにしてから計算して後でfloatに戻しているのである。断っておくが、これはよくある「C言語ではfloatは必ず一度doubleにされてから計算されるからdoubleの方が速い」系の話の亜種ではない。これは現代においては殆どの場合嘘だ。K&R時代とか私は生まれてないぞ。現代ではちゃんと単精度用の命令があるので、floatの計算はmulssやらsubssやらで行われ、実行速度に特に差はない。SIMDとかなら差は出るが、その場合floatの方が速かったりする。その辺りは詳しくは以下の記事などを参照していただきたい。リテラルを使った場合のアセンブリを見てみよう。ret変換命令はないし、subssやmulssが使われている。倍精度リテラルを使ったことで問題が生じたのだと考えるのが自然だろう。rootなるものをご存知だろうか。(7)はてなブログをはじめよう!tniinaさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。