MethodImplOptions.InternalCall
つまり、メソッドは実際にはC++で記述されたCLRに実装されています。ジャストインタイムコンパイラは、内部で実装されたメソッドを使用してテーブルを参照し、C++関数の呼び出しを直接コンパイルします。
コードを確認するには、CLRのソースコードが必要です。SSCLI20ディストリビューションから入手できます。これは.NET2.0の時間枠を中心に書かれておりMath.Pow()
、CLRの新しいバージョンでもほぼ正確であるように、低レベルの実装を見つけました。
ルックアップテーブルはclr/src / vm/ecall.cppにあります。関連するセクションは次のMath.Pow()
ようになります。
FCFuncStart(gMathFuncs)
FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
FCFuncElement("Exp", COMDouble::Exp)
FCFuncElement("Pow", COMDouble::Pow)
// etc..
FCFuncEnd()
「COMDouble」を検索すると、clr / src / classlibnative / float/comfloat.cppに移動します。私はあなたにコードを惜しまないでしょう、ただあなた自身を見てください。基本的にコーナーケースをチェックしてから、CRTのバージョンのを呼び出しますpow()
。
興味深い他の実装の詳細は、テーブル内のFCIntrinsicマクロだけです。これは、ジッタが関数を組み込み関数として実装する可能性があることを示唆しています。つまり、関数呼び出しを浮動小数点マシンコード命令に置き換えます。これは当てはまりませんPow()
が、FPU命令はありません。しかし、確かに他の簡単な操作のために。これにより、C#の浮動小数点演算がC ++の同じコードよりも大幅に高速になる可能性があることに注意してください。理由については、この回答を確認してください。
ちなみに、フルバージョンのVisual Studio vc / crt / srcディレクトリがある場合は、CRTのソースコードも利用できます。しかし、壁にぶつかるでしょうpow()
、MicrosoftはIntelからそのコードを購入しました。インテルのエンジニアよりも優れた仕事をすることはまずありません。私の高校の本のアイデンティティは、私が試したときの2倍の速さでしたが:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
ただし、3つの浮動小数点演算からのエラーが蓄積され、Pow()が持つ変なドメインの問題を処理しないため、真の代替ではありません。0^0や-Infinityのように任意の累乗になります。