MethodImplOptions.InternalCall
Це означає, що метод реально реалізований у CLR, написаному на C ++. Щойно вчасно компілятор звертається до таблиці з внутрішньо реалізованими методами та безпосередньо збирає виклик до функції 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()
цього не існує інструкції ФПУ. Але звичайно для інших простих операцій. Примітно те, що це може зробити математику з плаваючою комою в C # значно швидшою, ніж той самий код у C ++, перевірте цю відповідь з причини.
До речі, вихідний код для CRT також доступний, якщо у вас є повна версія каталогу Visual Studio vc / crt / src. Ти вдаришся об стіну, pow()
хоча Microsoft придбала цей код у Intel. Робити кращу роботу, ніж інженери Intel, навряд чи. Хоча особистість моєї середньої школи була вдвічі швидшою, коли я спробував її:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
Але це не справжній замінник, оскільки він накопичує помилку в 3 операціях з плаваючою точкою і не справляється з проблемами домену weirdo, які мають Pow (). Як 0 ^ 0 і -Безмежність піднята до будь-якої сили
InternalCall
зextern
модифікатором (оскільки вони здаються конфліктними), будь ласка, подивіться на питання (та отримані відповіді), яке я опублікував щодо цього самого.