Швидка та точна реалізація подвійної точності неповної гамма-функції


10

Який сучасний спосіб здійснення спеціальних функцій подвійної точності? Мені потрібен такий інтеграл: для і , які можна записати через нижню неповну гамма-функцію. Ось моя реалізація Fortran та C: м=0,1,2,. . . t>0

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

https://gist.github.com/3764427

який використовує розширення серій, підсумовує умови до заданої точності, а потім використовує рекурсійні відношення для ефективного отримання значень для нижчих . Я перевірив це добре і отримую точність 1e-15 для всіх значень параметрів, які мені потрібні, детальну інформацію див. У коментарях версії Fortran.m

Чи є кращий спосіб її реалізації? Ось реалізація гамма-функції в 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мtm+12Fm

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

але я не можу отримати це за допомогою SLATEC, оскільки знаменник вибухає. Як бачите, фактичне значення є приємним і малим.Fm

Оновлення 2 :

Щоб уникнути вищезазначеної проблеми, можна скористатися функцією dgamit(неповна Гамма-функція Tricomi), F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2тому більше немає з , але, на жаль, вибухає на . Це, однак, може бути досить високим для моїх цілей.м 172 мtgamma(m+0.5_dp)m172м


2
Навіщо кодувати власну функцію? GSL, cephes і SLATEC всі реалізують це.
Джефф Оксберрі

Я оновив питання, чому я не використовую SLATEC.
Ondřej Čertík

@ OndřejČertík Ви, очевидно, виявили помилку! Отримали ваше запитання!
Алі

Алі --- це не помилка в SLATEC, а в тому, що мені насправді потрібно розділити на , щоб отримати значення для . Тож числовий метод, який працює для може не працювати так добре для . t m + 1γ(z,x) Fm(t)γ(z,x)Fm(t)tm+12Fm(t)γ(z,x)Fm(t)
Ondřej Čertík

@ OndřejČertík Добре, вибачте, моя помилка, я не перевірив ваш код, перш ніж робити коментар.
Алі

Відповіді:


9

Інтеграл, про який йде мова, також відомий як функція Хлопчики, після британського хіміка Семюеля Френсіса Бойза, який ввів його використання на початку 1950-х. Кілька років тому мені потрібно було обчислити цю функцію в подвійній точності, якомога швидше, але точно. Мені вдалося досягти відносної помилки на порядку по всьому вхідному домену.10-15

Як правило, вигідно використовувати різні наближення для аргументів малого та великого розміру, де оптимальне переключення між "великим" та "малим" найкраще визначається експериментальним шляхом і, як правило, є функцією . Для свого коду я визначив "малі" аргументи як ті, що задовольняють умові .a m + 1 1мам+112

Для великих аргументів я обчислюю

Жм(а)=12γ(м+12,а)×p×p,  p=а-12(м+12)

Цей порядок операцій дозволяє уникнути передчасного переливу. Оскільки нам потрібна лише нижня неповна гамма-функція півзалікових порядків, а не повністю загальна нижча неповна гамма-функція, з точки зору продуктивності вигідно обчислити

γ(м+12,а)=Γ(м+12)-Γ(м+12,а)

використовуючи табличні значення та обчислюючи відповідно до цієї відповіді , обережно уникаючи проблеми віднімання віднімання шляхом використання злитої операції множення-додавання. Потенційна подальша оптимізація полягає в тому, щоб спостерігати, що для досить великого , в межах задана точність з плаваючою комою.Γ(m+1Γ(м+12)aγ(m+1Γ(м+12,а)аγ(м+12,а)=Γ(м+12)

Для невеликих аргументів я почав з розширення серії для нижньої неповної функції гами від

А. Ерделій, У. Магнус, Ф. Оберхеттінгер, Ф. Г. Трикомі, "Вищі трансцендентальні функції, т. 2". Нью-Йорк, Нью-Йорк: McGraw-Hill 1953

і змінив його для обчислення функції Boys наступним чином (обрізання рядів, коли термін достатньо малий для заданої точності):Жм(а)

Fm(a)=121m+12exp(a)(1+n=1an(1+m+12)× ... ×(n+m+12))

Існують також цікаві та потенційно важливі спеціальні випадки для низьких порядків функції хлопчиків, зокрема . По-перше, у нас є , де - функція помилок, надана у Fortran 2008 як елементарна функція, а в C / C ++ як стандартна функція бібліотеки та .м=0,1,2,3Ж0(а)=π4аеrf(а)еrfERFerferff

Для швидких обчислень, коли , я використовую спеціальні поліноміальні наближення minimax для малих аргументів, скажімо, та рекурсію вперед , для великих , де проблеми з відніманням відміни в останньому пом'якшуються за допомогою використання злитих операцій множення додавання.м=1,2,3а<212Жм(а)=12а((2м-1)Жм-1(а)-досвід(-а))

Якщо значення функції повинні бути обчислені для даного через кілька замовлень , один хотів би, щоб обчислити значення функції для найвищого значення безпосередньо, тобто , як описано вище, а потім використовувати чисельно стабільною зворотного рекурсії для обчислення всі інші значення функції.аммЖм-1=12м-1(2а Жм(а)+досвід(-а))


Дякую @njuffa за чудову відповідь. Якщо ви робите свій код для цього відкритого коду, я думаю, це було б дуже корисно для багатьох людей.
Ondřej Čertík

1
В даний час реалізація описаного алгоритму CUDA доступна для безкоштовного завантаження з веб-сайту розробників NVIDIA (потрібна безкоштовна реєстрація як розробник CUDA, затвердження зазвичай протягом одного робочого дня). Код під ліцензією BSD, який повинен бути сумісним практично з будь-яким проектом.
njuffa


4

Я б подивився на книгу Абрамовича та Стегуна, або на нову редакцію, яку NIST опублікував пару років тому і доступна в Інтернеті, я вважаю. Вони також обговорюють способи стабільного втілення речей.


Я використовував це: dlmf.nist.gov/8 при його реалізації, але це, мабуть, інший ресурс. У розділі 5 числових рецептів також є цікава інформація, але стосується лише функцій однієї змінної.
Ondřej Čertík

Я не думаю, що ви знайдете щось набагато пізніше, ніж їх посилання 2001 року; SLATEC буде старший за це.
Джефф Оксберрі

1

Це здається не найсучаснішим, але SLATEC в Netlib пропонує "1400 математичних та статистичних процедур загального призначення". Неповна Гамма доступна в рамках спеціальних функцій тут .

Реалізація таких функцій займає багато часу і схильна до помилок, тому я б не робив цього сам, якщо це абсолютно не потрібно. SLATEC існує вже досить давно і широко використовується, принаймні на основі кількості завантажень , тому я б очікував, що реалізація буде зрілою.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.