MethodImplOptions.InternalCall
Điều đó có nghĩa là phương thức này thực sự được thực hiện trong CLR, được viết bằng C ++. Trình biên dịch đúng lúc giới thiệu một bảng với các phương thức được triển khai bên trong và biên dịch lệnh gọi trực tiếp đến hàm C ++.
Có một cái nhìn vào mã yêu cầu mã nguồn cho CLR. Bạn có thể lấy nó từ bản phân phối SSCLI20 . Nó được viết xung quanh khung thời gian .NET 2.0, tôi đã tìm thấy các triển khai ở mức độ thấp, dường như Math.Pow()
vẫn chính xác phần lớn cho các phiên bản sau của CLR.
Bảng tra cứu được đặt trong clr / src / vm / ecall.cpp. Phần có liên quan đến Math.Pow()
như thế này:
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()
Tìm kiếm "COMDouble" sẽ đưa bạn đến clr / src / classlibnative / float / comfloat.cpp. Tôi sẽ cung cấp cho bạn mã, chỉ cần có một cái nhìn cho chính mình. Về cơ bản, nó kiểm tra các trường hợp góc, sau đó gọi phiên bản của CRT pow()
.
Chi tiết triển khai duy nhất khác thú vị là macro FCIntrinsic trong bảng. Đó là một gợi ý rằng jitter có thể thực hiện chức năng như một nội tại. Nói cách khác, thay thế lời gọi hàm bằng một lệnh mã máy dấu phẩy động. Đó không phải là trường hợp Pow()
, không có hướng dẫn của FPU cho nó. Nhưng chắc chắn cho các hoạt động đơn giản khác. Đáng chú ý là điều này có thể làm cho phép toán dấu phẩy động trong C # nhanh hơn đáng kể so với cùng mã trong C ++, kiểm tra câu trả lời này để biết lý do tại sao.
Nhân tiện, mã nguồn cho CRT cũng có sẵn nếu bạn có phiên bản đầy đủ của thư mục vc / crt / src của Visual Studio. pow()
Mặc dù vậy, bạn sẽ chạm tường , Microsoft đã mua mã đó từ Intel. Làm một công việc tốt hơn các kỹ sư Intel là không thể. Mặc dù danh tính cuốn sách cấp ba của tôi nhanh gấp đôi khi tôi thử nó:
public static double FasterPow(double x, double y) {
return Math.Exp(y * Math.Log(x));
}
Nhưng không phải là sự thay thế thực sự bởi vì nó tích lũy lỗi từ 3 hoạt động dấu phẩy động và không xử lý các vấn đề miền kỳ lạ mà Pow () gặp phải. Giống như 0 ^ 0 và -Tất cả được nâng lên thành bất kỳ sức mạnh nào.
InternalCall
với một công cụextern
sửa đổi (vì chúng có vẻ mâu thuẫn), vui lòng xem câu hỏi (và câu trả lời kết quả) mà tôi đã đăng về điều này rất giống nhau.