Apa cara canggih menerapkan fungsi khusus presisi ganda? Saya membutuhkan integral berikut: untuk dan , yang dapat ditulis dalam bentuk fungsi gamma bawah yang tidak lengkap. Inilah implementasi Fortran dan C saya: m=0,1,2,. . . t>0
https://gist.github.com/3764427
yang menggunakan ekspansi seri, meringkas istilah sampai akurasi yang diberikan, dan kemudian menggunakan hubungan rekursi untuk secara efisien mendapatkan nilai untuk lebih rendah . Saya mengujinya dengan baik dan saya mendapatkan akurasi 1e-15 untuk semua nilai parameter yang saya butuhkan, lihat komentar versi Fortran untuk detailnya.
Apakah ada cara yang lebih baik untuk mengimplementasikannya? Berikut ini adalah implementasi fungsi gamma di gfortran:
https://github.com/mirrors/gcc/blob/master/libgfortran/intrinsics/c99_functions.c#L1781
itu menggunakan perkiraan fungsi rasional alih-alih menyimpulkan beberapa seri tak terbatas yang saya lakukan. Saya pikir itu pendekatan yang lebih baik, karena seseorang harus mendapatkan akurasi yang seragam. Apakah ada beberapa cara kanonik untuk mendekati hal-hal ini, atau apakah kita harus mencari algoritma khusus untuk setiap fungsi khusus?
Pembaruan 1 :
Berdasarkan komentar, berikut adalah implementasinya menggunakan SLATEC:
https://gist.github.com/3767621
itu mereproduksi nilai dari fungsi saya sendiri, kira-kira pada tingkat akurasi 1e-15. Namun, saya melihat masalah bahwa untuk t = 1e-6 dan m = 50, istilah sama dengan 1e-303 dan untuk "m" yang lebih tinggi, ia mulai memberikan jawaban yang salah. Fungsi saya tidak memiliki masalah ini, karena saya menggunakan hubungan ekspansi / perulangan rangkaian langsung untuk . Berikut ini contoh nilai yang benar: Fm
(1e-6)=4.97511945200351715E-003
,
tapi saya tidak bisa mendapatkan ini menggunakan SLATEC karena penyebutnya meledak. Seperti yang Anda lihat, nilai sebenarnya dari bagus dan kecil.
Pembaruan 2 :
Untuk menghindari masalah di atas, seseorang dapat menggunakan fungsi dgamit
( fungsi Gamma Tricomi yang tidak lengkap), maka F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2
, jadi tidak ada masalah dengan lagi, tapi sayangnya pukulan untuk . Namun ini mungkin cukup tinggi untuk tujuan saya.m ≈ 172 mgamma(m+0.5_dp)