불완전한 감마 기능의 빠르고 정확한 배정도 구현


10

배정도 특수 기능을 구현하는 최첨단 방법은 무엇입니까? 다음 적분이 필요합니다. m=0,1,2,. . . t>0, 이는 불완전한 감마 함수의 하에서 작성 될 수있다. 다음은 Fortran 및 C 구현입니다.

Fm(t)=01u2metu2du=γ(m+12,t)2tm+12
m=0,1,2,...t>0

https://gist.github.com/3764427

시리즈 확장을 사용하고 주어진 정확도까지 항을 합한 다음 재귀 관계를 사용하여 더 낮은 값을 효율적으로 얻습니다 . 나는 그것을 잘 테스트했고 필요한 모든 매개 변수 값에 대해 1e-15의 정확도를 얻었습니다. 자세한 내용은 Fortran 버전의 주석을 참조하십시오.m

그것을 구현하는 더 좋은 방법이 있습니까? gfortran의 감마 함수 구현은 다음과 같습니다.

https://github.com/mirrors/gcc/blob/master/libgfortran/intrinsics/c99_functions.c#L1781

내가하고있는 무한 시리즈를 합산하는 대신 합리적인 함수 근사법을 사용하고 있습니다. 나는 그것이 더 나은 접근 방법이라고 생각합니다. 왜냐하면 균일 한 정확도를 얻어야하기 때문입니다. 이러한 것들에 접근하는 정식적인 방법이 있습니까, 아니면 각 특수 기능에 대한 특수 알고리즘을 찾아야합니까?

업데이트 1 :

주석을 기반으로 SLATEC을 사용한 구현은 다음과 같습니다.

https://gist.github.com/3767621

그것은 대략 1e-15 정확도 수준에서 내 자신의 기능에서 값을 재현합니다. 그러나 t = 1e-6 및 m = 50의 경우 t m + 1 이라는 문제를 발견했습니다. 항은 1e-303과 같고 "m"이 높을수록 오답을주기 시작합니다. Fm에대해 직접 직렬 확장 / 재귀 관계를 사용하기 때문에 함수에이 문제가 없습니다. 올바른 값의 예는 다음과 같습니다.tm+12Fm

,F100(1e-6)=4.97511945200351715E-003

하지만 분모가 터지기 때문에 SLATEC를 사용하여 이것을 얻을 수 없습니다. 보다시피 의 실제 값 은 훌륭하고 작습니다.Fm

업데이트 2 :

위의 문제를 피하기 위해 함수 dgamit(Tricomi의 불완전한 감마 함수)를 사용하면 더 이상 t에F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2 아무런 문제가 없지만 불행히도 m 172 의 타격이 발생합니다 . 그러나 이것은 충분히 높은 수 있습니다 m 내 목적을 위해.tgamma(m+0.5_dp)m172m


2
왜 자신 만의 함수를 코딩해야합니까? GSL, cephes 및 SLATEC이 모두 구현합니다.
Geoff Oxberry

SLATEC를 사용하지 않는 이유를 질문했습니다.
Ondřej Čertík

@ OndřejČertík 버그를 적절하게 발견했습니다! 귀하의 질문을 공언했습니다!
알리

Ali --- SLATEC의 버그는 아니지만 실제로 로 나눌 필요가 있다는 사실γ(z,x)tm+12Fm(t)γ(z,x)Fm(t)

@ OndřejČertík 알겠습니다. 죄송합니다. 제 코멘트를 작성하기 전에 코드를 확인하지 않았습니다.
알리

답변:


9

1015

mam+112

큰 논쟁의 경우, 나는 계산한다

Fm(a)=12γ(m+12,a)×p×p,  p=a12(m+12)

이 순서는 조기 언더 플로를 방지합니다. 완전 일반 불완전한 감마 함수보다는 반정 수 차수의 불완전한 감마 함수 만 있으면되므로 성능 관점에서 계산하는 것이 유리합니다.

γ(m+12,a)=Γ(m+12)Γ(m+12,a)

의 테이블 값 사용Γ(m+12)Γ(m+12,a)aγ(m+12,a)=Γ(m+12)

작은 인수의 경우, 불완전한 감마 함수를 낮추기 위해 시리즈 확장으로 시작했습니다.

A. Erdelyi, W. Magnus, F. Oberhettinger 및 FG Tricomi, "높은 초월 적 기능, Vol. 2". 뉴욕, 뉴욕 : McGraw-Hill 1953

Fm(a)

Fm(a)=121m+12exp(a)(1+n=1an(1+m+12)× ... ×(n+m+12))

m=0,1,2,3F0(a)=π4aerf(a)erfERFerferff

m=1,2,3a<212Fm(a)=12a((2m1)Fm1(a)exp(a))

ammFm1=12m1(2a Fm(a)+exp(a))


훌륭한 답변을 위해 @njuffa에게 감사드립니다. 이 오픈 소스에 대한 코드를 작성하면 많은 사람들에게 매우 유용하다고 생각합니다.
Ondřej Čertík

1
현재 설명 된 알고리즘의 CUDA 구현은 NVIDIA 개발자 웹 사이트 에서 무료로 다운로드 할 수 있습니다 (CUDA 개발자로 무료 등록 필요, 일반적으로 영업일 기준 1 일 이내 승인). 이 코드는 BSD 라이센스하에 있으며 거의 ​​모든 종류의 프로젝트와 호환되어야합니다.
njuffa 2016 년


4

나는 Abramowicz & Stegun의 책, 또는 NIST가 몇 년 전에 출판 한 최신 개정판을보고 온라인에서 구할 수 있다고 생각합니다. 또한 안정적인 방식으로 구현하는 방법에 대해서도 설명합니다.


나는 이것을 구현할 때 dlmf.nist.gov/8 을 사용 했지만 아마도 다른 리소스 일 것입니다. Numerical Recipes의 5 장에도 흥미로운 정보가 있지만 한 변수의 함수에만 적용 할 수 있습니다.
Ondřej Čertík

나는 당신이 그들의 2001 년 참조보다 훨씬 더 최근의 것을 찾을 것이라고 생각하지 않습니다. SLATEC는 그것보다 오래 될 것입니다.
Geoff Oxberry

1

될 것 같지 않습니다 최첨단 하지만 SLATEC NETLIB의 이벤트에서 "1400 범용 수학 및 통계 루틴을." 불완전한 감마는 여기특수 기능에서 사용할 수 있습니다 .

이러한 기능을 구현하면 시간이 많이 걸리고 오류가 발생하기 쉽기 때문에 꼭 필요한 경우가 아니라면 직접하지 않겠습니다. SLATEC은 꽤 오랫동안 사용되어 왔으며 적어도 다운로드 횟수 에 따라 널리 사용 되므로 구현이 성숙 할 것으로 기대합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.