Szybka i dokładna implementacja niepełnej funkcji gamma o podwójnej precyzji


10

Jaki jest najnowocześniejszy sposób wdrażania funkcji specjalnych podwójnej precyzji? Potrzebuję następującej całki:

Fm(t)=01u2metu2du=γ(m+12,t)2tm+12
dlam=0,1,2,...orazt>0, które można zapisać w kategoriach niższej niepełnej funkcji gamma. Oto moja implementacja Fortran i C.

https://gist.github.com/3764427

który korzysta z interpretacji szeregowej, sumuje warunki do danej dokładności, a następnie używa relacji rekurencyjnych w celu skutecznego uzyskania wartości dla niższego m . Testowałem to dobrze i uzyskuję dokładność 1e-15 dla wszystkich wartości parametrów, których potrzebuję, zobacz komentarze do wersji Fortran, aby uzyskać szczegółowe informacje.

Czy istnieje lepszy sposób na jego wdrożenie? Oto implementacja funkcji gamma w gfortran:

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

wykorzystuje przybliżenie funkcji racjonalnej zamiast sumowania niektórych nieskończonych szeregów, które robię. Myślę, że to lepsze podejście, ponieważ należy uzyskać jednolitą dokładność. Czy istnieje jakiś kanoniczny sposób podejścia do tych rzeczy, czy też trzeba opracować specjalny algorytm dla każdej funkcji specjalnej?

Aktualizacja 1 :

W oparciu o komentarze, oto implementacja wykorzystująca SLATEC:

https://gist.github.com/3767621

odtwarza wartości z mojej własnej funkcji, mniej więcej na poziomie dokładności 1e-15. Zauważyłem jednak problem, że dla t = 1e-6 im = 50, wyrażenie równa się 1e-303, a dla większego „m” zaczyna po prostu dawać nieprawidłowe odpowiedzi. Moja funkcja nie ma tego problemu, ponieważ używam relacji rozszerzania / powtarzania serii bezpośrednio dlaFm. Oto przykład poprawnej wartości:tm+12Fm

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

ale nie mogę tego uzyskać za pomocą SLATEC, ponieważ mianownik się wysadza. Jak widać, rzeczywista wartość jest ładna i mała.Fm

Aktualizacja 2 :

Aby uniknąć powyższego problemu, można użyć funkcji dgamit(niekompletna funkcja gamma Tricomi) F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2, więc nie ma już problemu z , ale niestety wysadza się dla m 172 . Może to jednak być wystarczająco wysoka m dla moich celów.tgamma(m+0.5_dp)m172m


2
Po co kodować własną funkcję? GSL, cephes i SLATEC to wszystko implementują.
Geoff Oxberry

Zaktualizowałem pytanie, dlaczego nie używam SLATEC.
Ondřej Čertík

@ OndřejČertík Chyba odkryłeś błąd! Głosowałem na twoje pytanie!
Ali

Ali --- to nie jest błąd w SLATEC, ale faktem, że faktycznie muszę podzielić przez t m + 1γ(z,x) w celu uzyskania wartościFm(t). Zatem metoda numeryczna, która działa dlaγ(z,x),może nie działać tak dobrze dlaFtm+12Fm(t)γ(z,x) . fam(t)
Ondřej Čertík

@ OndřejČertík OK, przepraszam, mój błąd, nie sprawdziłem kodu przed opublikowaniem komentarza.
Ali

Odpowiedzi:


9

Całka, o której mowa, znana jest również jako funkcja Boys, od brytyjskiego chemika Samuela Francisa Boysa, który wprowadził jej stosowanie na początku lat 50. XX wieku. Kilka lat temu musiałem obliczyć tę funkcję z podwójną precyzją, tak szybko, jak to możliwe, ale dokładnie. Udało mi się osiągnąć względny błąd rzędu w całej domenie wejściowej.10-15

Zasadniczo korzystne jest stosowanie różnych przybliżeń dla małych i dużych argumentów, przy czym optymalne przełączanie między „dużym” i „małym” najlepiej określa się eksperymentalnie i ogólnie jest funkcją . W moim kodzie zdefiniowałem „małe” argumenty jako spełniające warunek a m + 1 1m .zam+112)

W przypadku dużych argumentów obliczam

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

Ta kolejność operacji pozwala uniknąć przedwczesnego niedomiaru. Ponieważ potrzebujemy tutaj tylko niższej niepełnej funkcji gamma rzędów o wartościach całkowitych, a nie w pełni ogólnej niższej niepełnej funkcji gamma, z punktu widzenia wydajności korzystne jest obliczenie

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

przy użyciu tabelarycznych wartości i obliczeniaΓ(m+1Γ(m+12))zgodnie z tą odpowiedzią, przy jednoczesnym ostrożnym unikaniu problemu subtraktywnego anulowania poprzez zastosowanie połączonej operacji wielokrotnego dodawania. Potencjalną dalszą optymalizacją jest zaobserwowanie, że dla wystarczająco dużegoa,γ(m+1Γ(m+12),za)zaw ramach określonej precyzji zmiennoprzecinkowej.γ(m+12),za)=Γ(m+12))

W przypadku małych argumentów zacząłem od rozszerzenia serii dla niższej niepełnej funkcji gamma od

A. Erdelyi, W. Magnus, F. Oberhettinger i FG Tricomi, „Higher Transcendental Functions, Vol. 2”. Nowy Jork, NY: McGraw-Hill 1953

i zmodyfikowałem go, aby obliczyć funkcję Boys w następujący sposób (obcięcie serię gdy termin jest dostatecznie mała dla danej dokładności)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)) aby obliczyć wszystkie pozostałe wartości funkcji.


Dzięki @njuffa za świetną odpowiedź. Jeśli stworzysz kod dla tego open source, myślę, że byłby bardzo użyteczny dla wielu osób.
Ondřej Čertík

1
Obecnie implementacja CUDA opisanego algorytmu jest dostępna do bezpłatnego pobrania ze strony internetowej dewelopera NVIDIA (wymaga bezpłatnej rejestracji jako programista CUDA, zatwierdzenie zwykle w ciągu jednego dnia roboczego). Kod jest objęty licencją BSD, która powinna być kompatybilna z każdym projektem.
njuffa


4

Rzuciłbym okiem na książkę Abramowicza i Steguna lub na nowszą wersję, którą NIST opublikował kilka lat temu i wydaje mi się, że jest dostępna online. Dyskutują także o sposobach wdrażania rzeczy w stabilny sposób.


Korzystałem z tego: dlmf.nist.gov/8 , podczas jego wdrażania, ale to prawdopodobnie inny zasób. Rozdział 5 w Recepturach numerycznych również zawiera interesujące informacje, ale dotyczy tylko funkcji jednej zmiennej.
Ondřej Čertík

Nie sądzę, że znajdziesz coś znacznie nowszego niż ich wzmianka z 2001 roku; SLATEC będzie starszy.
Geoff Oxberry

1

Nie wydaje się to być najnowocześniejszym, ale SLATEC w Netlib oferuje „1400 ogólnych procedur matematycznych i statystycznych”. Niekompletna wartość gamma jest dostępna tutaj w ramach funkcji specjalnych .

Wdrożenie takich funkcji jest czasochłonne i podatne na błędy, więc nie zrobiłbym tego sam, chyba że absolutnie konieczne. SLATEC istnieje już od dłuższego czasu i jest szeroko stosowany, przynajmniej w oparciu o liczbę pobrań , więc oczekiwałbym, że implementacja będzie dojrzała.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.