Implementazione rapida e accurata della doppia precisione della funzione gamma incompleta


10

Qual è il modo più avanzato di implementare funzioni speciali a doppia precisione? Ho bisogno del seguente integrale: perm=0,1,2,. . . et>0, che può essere scritto in termini della funzione gamma incompleta inferiore. Ecco la mia implementazione Fortran e C:

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

https://gist.github.com/3764427

che utilizza l'espansione in serie, riassume i termini fino alla precisione data e quindi utilizza le relazioni di ricorsione per ottenere in modo efficiente valori per inferiori . L'ho testato bene e ottengo una precisione 1e-15 per tutti i valori dei parametri di cui ho bisogno, vedere i commenti della versione Fortran per i dettagli.m

C'è un modo migliore per implementarlo? Ecco un'implementazione della funzione gamma in gfortran:

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

sta usando l'approssimazione di funzioni razionali invece di riassumere alcune serie infinite che sto facendo. Penso che sia un approccio migliore, perché si dovrebbe ottenere una precisione uniforme. Esiste un modo canonico per avvicinarsi a queste cose o si deve capire un algoritmo speciale per ogni funzione speciale?

Aggiornamento 1 :

Sulla base dei commenti, ecco l'implementazione con SLATEC:

https://gist.github.com/3767621

riproduce i valori della mia stessa funzione, approssimativamente al livello di precisione 1e-15. Tuttavia, ho notato un problema che per t = 1e-6 e m = 50, la termine 2 diventa uguale a 1e-303 e per una "m" più alta inizia semplicemente a dare risposte errate. La mia funzione non ha questo problema, perché uso una serie di relazioni di espansione / ricorrenza direttamente perFm. Ecco un esempio di un valore corretto:tm+12Fm

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

ma non riesco a farlo usando SLATEC perché il denominatore esplode. Come puoi vedere, il valore reale di è bello e piccolo.Fm

Aggiornamento 2 :

Per evitare il problema di cui sopra, si può usare la funzione dgamit(la funzione Gamma incompleta di Tricomi), quindi F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2, quindi non ci sono più problemi con , ma sfortunatamente l' esplosione per m 172 . Questo però potrebbe essere abbastanza alto m per i miei scopi.tgamma(m+0.5_dp)m172m


2
Perché codificare la propria funzione? GSL, Cephes e SLATEC lo implementano tutti.
Geoff Oxberry,

Ho aggiornato la domanda sul perché non utilizzo SLATEC.
Ondřej Čertík,

@ OndřejČertík Hai scoperto apparentemente un bug! Hai valutato la tua domanda!
Ali,

Ali --- non è un bug in SLATEC, ma in realtà, ho davvero bisogno di dividere per t m + 1γ(z,X) per ottenere un valore perFm(t). Quindi il metodo numerico che funziona perγ(z,x)potrebbe non funzionare così bene perFm(t). tm+12Fm(t)γ(z,X)Fm(t)
Ondřej Čertík,

@ OndřejČertík OK, scusa, errore mio, non ho controllato il codice prima di esprimere il mio commento.
Ali,

Risposte:


9

L'integrale in questione è anche noto come funzione Boys, dopo il chimico britannico Samuel Francis Boys che ne introdusse l'uso nei primi anni '50. Alcuni anni fa, avevo bisogno di calcolare questa funzione in doppia precisione, il più velocemente possibile ma con precisione. Sono riuscito a ottenere un errore relativo dell'ordine di su tutto il dominio di ingresso.10-15

È generalmente vantaggioso usare approssimazioni diverse per argomenti piccoli e grandi, in cui il passaggio ottimale tra "grande" e "piccolo" è meglio determinato sperimentalmente ed è in generale una funzione di . Per il mio codice, ho definito argomenti "piccoli" come quelli che soddisfano la condizione a m + 1 1m .un'm+112

Per grandi argomenti, computo

Fm(un')=12γ(m+12,un')×p×p,  p=un'-12(m+12)

Questo ordine di operazioni evita il underflow prematuro. Dato che qui è necessaria solo la funzione gamma incompleta inferiore di ordini a mezzo numero intero anziché una funzione gamma incompleta inferiore completamente generale, è vantaggioso dal punto di vista delle prestazioni calcolare

γ(m+12,un')=Γ(m+12)-Γ(m+12,un')

usando valori tabulari di e calcoloΓ(m+1Γ(m+12)secondo questa risposta, evitando con attenzione il problema della cancellazione sottrattiva mediante l'uso di un'operazione di aggiunta multipla fusa. Una potenziale ulteriore ottimizzazione consiste nell'osservare che pera,γ(m+1)sufficientemente grandeΓ(m+12,un')un'entro una determinata precisione in virgola mobile.γ(m+12,un')=Γ(m+12)

Per piccoli argomenti, ho iniziato con un'espansione in serie per la funzione gamma incompleta inferiore di

A. Erdelyi, W. Magnus, F. Oberhettinger e FG Tricomi, "Funzioni trascendenti superiori, Vol. 2". New York, NY: McGraw-Hill 1953

e modificato per calcolare la funzione maschi come segue (troncando la serie quando il termine è sufficientemente piccolo per una data precisione):Fm(un')

Fm(un')=121m+12exp(-un')(1+Σn=1un'n(1+m+12)× ... ×(n+m+12))

m=0,1,2,3F0(un')=π4un'erf(un')erfERFerferff

m=1,2,3un'<212Fm(un')=12un'((2m-1)Fm-1(un')-exp(-un'))

un'mmFm-1=12m-1(2un' Fm(un')+exp(-un'))


Grazie @njuffa per l'ottima risposta. Se crei il tuo codice per questo open source, penso che sarebbe molto utile per molte persone.
Ondřej Čertík,

1
Attualmente, un'implementazione CUDA dell'algoritmo descritto è disponibile per il download gratuito dal sito Web degli sviluppatori di NVIDIA (richiede la registrazione gratuita come sviluppatore CUDA, l'approvazione di solito entro un giorno lavorativo). Il codice è sotto una licenza BSD, che dovrebbe essere compatibile con qualsiasi tipo di progetto.
njuffa,


4

Darei un'occhiata al libro di Abramowicz & Stegun o alla revisione più recente che NIST ha pubblicato un paio di anni fa ed è disponibile online credo. Discutono anche dei modi per implementare le cose in modo stabile.


Stavo usando questo: dlmf.nist.gov/8 , quando lo implementavo, ma probabilmente è un'altra risorsa. Anche il capitolo 5 in Ricette numeriche contiene informazioni interessanti, ma applicabili solo alle funzioni di una variabile.
Ondřej Čertík

Non credo che troverai qualcosa di molto più recente della loro referenza del 2001; SLATEC sarà più vecchio di così.
Geoff Oxberry,

1

Non sembra essere allo stato dell'arte, ma SLATEC di Netlib offre "1400 routine matematiche e statistiche generiche". La gamma incompleta è disponibile sotto le funzioni speciali qui .

L'implementazione di tali funzioni richiede tempo ed è soggetta a errori, quindi non lo farei da solo se non assolutamente necessario. SLATEC è in circolazione da un po 'di tempo ed è ampiamente utilizzato, almeno in base al numero di download , quindi mi aspetto che l'implementazione sia matura.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.