Wie werden Spezialfunktionen mit doppelter Genauigkeit auf dem neuesten Stand der Technik implementiert? Ich brauche die folgende Integral: fürm=0,1,2,. . . undt>0, was als niedrigere unvollständige Gammafunktion geschrieben werden kann. Hier ist meine Fortran- und C-Implementierung:
https://gist.github.com/3764427
Bei Verwendung der Reihenerweiterung werden die Terme bis zur angegebenen Genauigkeit zusammengefasst und anschließend Rekursionsrelationen verwendet, um effizient Werte für niedrigeres . Ich habe es gut getestet und erhalte eine 1e-15-Genauigkeit für alle Parameterwerte, die ich benötige. Weitere Informationen finden Sie in den Kommentaren der Fortran-Version.
Gibt es einen besseren Weg, um es umzusetzen? Hier ist eine Implementierung der Gammafunktion in Gfortran:
https://github.com/mirrors/gcc/blob/master/libgfortran/intrinsics/c99_functions.c#L1781
Es verwendet die rationale Funktionsnäherung, anstatt einige unendliche Reihen zusammenzufassen, die ich mache. Ich denke, das ist ein besserer Ansatz, weil man eine einheitliche Genauigkeit erhalten sollte. Gibt es eine kanonische Möglichkeit, sich diesen Dingen zu nähern, oder muss man für jede spezielle Funktion einen speziellen Algorithmus finden?
Update 1 :
Basierend auf den Kommentaren ist hier die Implementierung mit SLATEC:
https://gist.github.com/3767621
Es gibt Werte aus meiner eigenen Funktion wieder, ungefähr auf der Ebene der Genauigkeit 1e-15. Ich bemerkte jedoch ein Problem, dass für t = 1e-6 und m = 50 Term wird gleich 1e-303 und für höheres "m" gibt es einfach falsche Antworten. Meine Funktion hat dieses Problem nicht, da ich eine Reihenexpansions- / Wiederholungsrelation direkt fürFm verwende. Hier ist ein Beispiel für einen korrekten Wert:
,(1e-6)=4.97511945200351715E-003
aber ich kann das nicht mit SLATEC bekommen, weil der Nenner explodiert. Wie Sie sehen können, ist der tatsächliche Wert von schön klein.
Update 2 :
Um das obige Problem zu vermeiden, kann man die Funktion dgamit
(Tricomis unvollständige Gammafunktion) verwenden, F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2
so dass es kein Problem mehr mit , aber leider explodiert das für m ≈ 172 . Dies könnte jedoch hoch genug sein , m für meine Zwecke.gamma(m+0.5_dp)
quelle
Antworten:
Für große Argumente berechne ich
Diese Betriebsreihenfolge vermeidet vorzeitiges Unterlaufen. Da wir hier nur die niedrigere unvollständige Gammafunktion von halbzahligen Ordnungen anstelle einer vollständig allgemeinen unteren unvollständigen Gammafunktion benötigen, ist die Berechnung aus Sicht der Leistung vorteilhaft
Für kleine Argumente habe ich mit einer Reihenerweiterung für die untere unvollständige Gammafunktion von begonnen
A. Erdelyi, W. Magnus, F. Oberhettinger und FG Tricomi, "Higher Transcendental Functions, Vol. 2". New York, NY: McGraw-Hill 1953
ERF
erf
erff
quelle
Sie können sich numerische Methoden für spezielle Funktionen von Amparo Gil, Javier Segura und Nico M. Temme ansehen .
quelle
Ich würde mir Abramowicz & Steguns Buch oder die neuere Version ansehen, die NIST vor ein paar Jahren veröffentlicht hat und die meiner Meinung nach online verfügbar ist. Sie diskutieren auch Möglichkeiten, Dinge stabil zu implementieren.
quelle
Es scheint nicht auf dem neuesten Stand der Technik zu sein, aber SLATEC bei Netlib bietet "1400 allgemeine mathematische und statistische Routinen". Das unvollständige Gamma steht hier unter den Sonderfunktionen zur Verfügung .
Die Implementierung solcher Funktionen ist zeitaufwändig und fehleranfällig, sodass ich sie nur dann selbst ausführen würde, wenn dies unbedingt erforderlich ist. SLATEC gibt es schon seit einiger Zeit und ist weit verbreitet, zumindest basierend auf der Anzahl der Downloads. Daher würde ich erwarten, dass die Implementierung ausgereift ist.
quelle