MethodImplOptions.InternalCall
Eso significa que el método se implementa realmente en el CLR, escrito en C ++. El compilador justo a tiempo consulta una tabla con métodos implementados internamente y compila la llamada a la función C ++ directamente.
Echar un vistazo al código requiere el código fuente para el CLR. Puede obtener eso de la distribución SSCLI20 . Fue escrito alrededor del marco de tiempo de .NET 2.0, he encontrado que las implementaciones de bajo nivel Math.Pow()
siguen siendo muy precisas para versiones posteriores de CLR.
La tabla de búsqueda se encuentra en clr / src / vm / ecall.cpp. La sección relevante para se Math.Pow()
ve así:
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()
La búsqueda de "COMDouble" lo lleva a clr / src / classlibnative / float / comfloat.cpp. Te ahorraré el código, solo échale un vistazo. Básicamente verifica si hay casos de esquina, luego llama a la versión de CRT pow()
.
El único otro detalle de implementación que es interesante es la macro FCIntrinsic en la tabla. Esa es una pista de que el jitter puede implementar la función como intrínseca. En otras palabras, sustituya la llamada a la función con una instrucción de código de máquina de coma flotante. Lo cual no es el caso Pow()
, no hay instrucciones de FPU para ello. Pero ciertamente para las otras operaciones simples. Es notable que esto puede hacer que las matemáticas de coma flotante en C # sean sustancialmente más rápidas que el mismo código en C ++, verifique esta respuesta por la razón.
Por cierto, el código fuente para el CRT también está disponible si tiene la versión completa del directorio Visual Studio vc / crt / src. Sin pow()
embargo, te toparás con la pared , Microsoft compró ese código de Intel. Hacer un mejor trabajo que los ingenieros de Intel es poco probable. Aunque la identidad de mi libro de secundaria era el doble de rápido cuando lo probé:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
Pero no es un verdadero sustituto porque acumula el error de 3 operaciones de coma flotante y no se ocupa de los problemas de dominio raros que tiene Pow (). Como 0 ^ 0 y -Infinity elevado a cualquier poder.
InternalCall
con unextern
modificador (ya que parecen estar en conflicto), vea la pregunta (y las respuestas resultantes) que publiqué sobre esto mismo.