¿Cuál es la forma más moderna de implementar funciones especiales de doble precisión? Necesito la siguiente integral:
https://gist.github.com/3764427
que usa la expansión en serie, resume los términos hasta la precisión dada y luego usa las relaciones de recursión para obtener de manera eficiente valores para menor . Lo probé bien y obtengo una precisión de 1e-15 para todos los valores de parámetros que necesito, vea los comentarios de la versión Fortran para más detalles.
¿Hay una mejor manera de implementarlo? Aquí hay una implementación de la función gamma en gfortran:
https://github.com/mirrors/gcc/blob/master/libgfortran/intrinsics/c99_functions.c#L1781
está usando la aproximación de funciones racionales en lugar de resumir algunas series infinitas que estoy haciendo. Creo que es un mejor enfoque, porque uno debería obtener una precisión uniforme. ¿Hay alguna forma canónica de abordar estas cosas, o hay que encontrar un algoritmo especial para cada función especial?
Actualización 1 :
Basado en los comentarios, aquí está la implementación usando SLATEC:
https://gist.github.com/3767621
reproduce valores de mi propia función, aproximadamente en el nivel de precisión 1e-15. Sin embargo, noté un problema que para t = 1e-6 ym = 50, el término 2 es igual a 1e-303 y para una "m" más alta simplemente comienza a dar respuestas incorrectas. Mi función no tiene este problema, porque utilizo una serie de relaciones de expansión / recurrencia directamente paraFm. Aquí hay un ejemplo de un valor correcto:
,(1e-6)=4.97511945200351715E-003
pero no puedo obtener esto usando SLATEC porque el denominador explota. Como puede ver, el valor real de es agradable y pequeño.
Actualización 2 :
Para evitar el problema anterior, se puede usar la función dgamit
( función Gamma incompleta de Tricomi), entonces F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2
, ya no hay problema con , pero desafortunadamente explota para m ≈ 172 . Sin embargo, esto podría ser lo suficientemente alta m para mis propósitos.gamma(m+0.5_dp)