Каков современный способ реализации специальных функций двойной точности? Мне нужен следующий интеграл: для и , что можно записать в терминах нижней неполной гамма-функции. Вот моя реализация на Фортране и Си: м=0,1,2,. , , t>0
https://gist.github.com/3764427
который использует последовательное расширение, суммирует термины до заданной точности, а затем использует рекурсивные соотношения для эффективного получения значений для меньшего . Я хорошо это проверил, и я получаю точность 1e-15 для всех значений параметров, которые мне нужны, подробности см. В комментариях к версии на Fortran.
Есть ли лучший способ реализовать это? Вот реализация гамма-функции в 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 член становится равным 1e-303, а для более высоких «m» он просто начинает давать неправильные ответы. У моей функции нет этой проблемы, потому что я использую отношения расширения / повторения ряда непосредственно для . Вот пример правильного значения: Fм
(1e-6)=4.97511945200351715E-003
,
но я не могу получить это, используя SLATEC, потому что знаменатель взрывается. Как видите, фактическое значение хорошее и маленькое.
Обновление 2 :
Чтобы избежать вышеупомянутой проблемы, можно использовать функцию dgamit
(неполная гамма-функция Трикоми), то F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2
есть проблем с больше нет, но, к сожалению, взрывы для . Это , однако , может быть достаточно высокими для моих целей.м ≈ 172 мgamma(m+0.5_dp)