Який сучасний спосіб здійснення спеціальних функцій подвійної точності? Мені потрібен такий інтеграл: для і , які можна записати через нижню неповну гамма-функцію. Ось моя реалізація Fortran та C: м=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
(неповна Гамма-функція Tricomi), F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2
тому більше немає з , але, на жаль, вибухає на . Це, однак, може бути досить високим для моїх цілей.м ≈ 172 мgamma(m+0.5_dp)