개발관련/other

.NET Framework에서 Math.Pow ()를 구현하는 방법

Rateye 2022. 1. 17. 11:54
728x90
반응형
질문 : .NET Framework에서 Math.Pow ()는 어떻게 구현됩니까?

나는 b 를 계산하기위한 효율적인 접근법을 찾고있었습니다 (예 : a = 2b = 50 ). Math.Pow() 함수의 구현을 살펴보기로 결정했습니다. 그러나 .NET Reflector 에서 내가 찾은 것은 다음과 같습니다.

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern double Pow(double x, double y);

Math.Pow() 함수를 호출 할 때 내부에서 무슨 일이 일어나는지 확인할 수있는 리소스에는 어떤 것이 있습니까?

답변

MethodImplOptions.InternalCall

이는 메서드가 실제로 C ++로 작성된 CLR에서 구현됨을 의미합니다. Just-In-Time 컴파일러는 내부적으로 구현 된 메서드가있는 테이블을 참조하고 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로 이동합니다. 코드를 아끼지 말고 직접 살펴보세요. 기본적으로 코너 케이스를 pow() 를 호출합니다.

흥미로운 유일한 구현 세부 사항은 표의 FCIntrinsic 매크로입니다. 이는 지터가 함수를 내장 함수로 구현할 수 있다는 힌트입니다. 즉, 함수 호출을 부동 소수점 기계어 코드 명령어로 대체하십시오. Pow() 의 경우는 아니지만 이에 대한 FPU 명령이 없습니다. 그러나 다른 간단한 작업에 대해서는 확실히. 주목할만한 점은 이것이 C #의 부동 소수점 수학을 C ++의 동일한 코드보다 훨씬 빠르게 만들 수 있다는 것입니다. 이유에 대해이 답변을 확인하십시오.

그런데 Visual Studio vc / crt / src 디렉터리의 정식 버전이있는 경우 CRT의 소스 코드도 사용할 수 있습니다. 당신은에 벽에 충돌 것 pow() 마이크로 소프트는 인텔에서 해당 코드를 구입하지만. 인텔 엔지니어보다 더 나은 일을 할 가능성은 거의 없습니다. 고등학교 책의 정체성은 내가 시도했을 때 두 배나 빨랐지만 :

public static double FasterPow(double x, double y) {
    return Math.Exp(y * Math.Log(x));
}

그러나 3 개의 부동 소수점 연산에서 오류를 축적하고 Pow ()가 가진 이상한 도메인 문제를 처리하지 않기 때문에 진정한 대체물은 아닙니다. 0 ^ 0 및 -Infinity가 모든 거듭 제곱으로 올랐습니다.

출처 : https://stackoverflow.com/questions/8870442/how-is-math-pow-implemented-in-net-framework
728x90
반응형