MethodImplOptions.InternalCall
つまり、メソッドは実際にはC ++で記述されたCLRで実装されます。ジャストインタイムコンパイラは、内部的に実装されたメソッドを含むテーブルを参照し、C ++関数の呼び出しを直接コンパイルします。
コードを見るには、CLRのソースコードが必要です。SSCLI20ディストリビューションから取得できます。それは.NET 2.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を任意のパワーに引き上げたようなものです。
InternalCall
と混同している場合extern
(競合しているように思われる場合)、これと同じことについて私が投稿した質問(および結果の回答)を参照してください。