Implementação de precisão dupla rápida e precisa da função gama incompleta


10

Qual é a maneira mais avançada de implementar funções especiais de precisão dupla? Preciso da seguinte integral: para e , que pode ser escrita em termos da função gama incompleta inferior. Aqui está minha implementação de Fortran e C: m=0,1,2,. . . t>0

Fm(t)=0 01 1você2me-tvocê2dvocê=γ(m+1 12,t)2tm+1 12
m=0 0,1 1,2,...t>0 0

https://gist.github.com/3764427

que usa expansão em série, resume os termos até a precisão especificada e, em seguida, usa relações de recursão para obter com eficiência valores para inferiores . Testei bem e obtenho precisão 1e-15 para todos os valores de parâmetros necessários, consulte os comentários da versão Fortran para obter detalhes.m

Existe uma maneira melhor de implementá-lo? Aqui está uma implementação da função gama no gfortran:

https://github.com/mirrors/gcc/blob/master/libgfortran/intrinsics/c99_functions.c#L1781

está usando aproximação de função racional em vez de resumir algumas séries infinitas que estou fazendo. Eu acho que é uma abordagem melhor, porque é preciso obter precisão uniforme. Existe alguma maneira canônica de abordar essas coisas, ou é preciso descobrir um algoritmo especial para cada função especial?

Atualização 1 :

Com base nos comentários, aqui está a implementação usando o SLATEC:

https://gist.github.com/3767621

reproduz valores de minha própria função, aproximadamente no nível de precisão 1e-15. No entanto, notei um problema que, para t = 1e-6 em = 50, o termo fica igual a 1e-303 e, para "m" superior, ele simplesmente começa a dar respostas incorretas. Minha função não tem esse problema, porque eu uso uma série de relações de expansão / recorrência diretamente para . Aqui está um exemplo de um valor correto: Fmtm+1 12Fm

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

mas não consigo fazer isso usando SLATEC porque o denominador explode. Como você pode ver, o valor real de é bom e pequeno.Fm

Atualização 2 :

Para evitar o problema acima, pode-se usar a função dgamit( função Gamma incompleta do Tricomi) e F(m, t) = dgamit(m+0.5_dp, t) * gamma(m+0.5_dp) / 2, portanto, não há mais problema com , mas, infelizmente, a explosão ocorre por . Este, porém, pode ser alta o suficiente para os meus propósitos.m 172 mtgamma(m+0.5_dp)m172m


2
Por que codificar sua própria função? GSL, cephes e SLATEC todos os implementam.
Geoff Oxberry

Atualizei a pergunta por que não uso o SLATEC.
Ondřej Čertík

@ OndřejČertík Você descobriu um bug aparente! Votou com sua pergunta!
Ali

Ali --- não é um bug no SLATEC, mas, na verdade, eu preciso dividir por para obter um valor para . Portanto, o método numérico que funciona para pode não funcionar tão bem para . t m + 1γ(z,x) Fm(t)γ(z,x)Fm(t)tm+1 12Fm(t)γ(z,x)Fm(t)
Ondřej Čertík

@ OndřejČertík OK, desculpe, meu erro, eu não verifiquei seu código antes de fazer meu comentário.
Ali

Respostas:


9

A integral em questão também é conhecida como função de Boys, após o químico britânico Samuel Francis Boys, que introduziu seu uso no início dos anos 50. Alguns anos atrás, eu precisava calcular essa função em dupla precisão, o mais rápido possível, mas com precisão. Eu consegui alcançar um erro relativo da ordem de 10-15 em todo o domínio de entrada.

É geralmente vantajoso usar aproximações diferentes para argumentos pequenos e grandes, onde a melhor alternância entre "grande" e "pequeno" é melhor determinada experimentalmente e, em geral, é uma função de . Para o meu código, defini argumentos "pequenos" como aqueles que satisfazem a condição a m + 1 1m .umam+1 11 12

Para grandes argumentos, eu computo

Fm(a)=12γ(m+12,a)×p×p,  p=a12(m+12)

Essa ordem de operações evita o fluxo insuficiente prematuro. Como precisamos apenas da função gama incompleta mais baixa de ordens sem número inteiro aqui, em vez de uma função gama incompleta mais baixa totalmente geral, é vantajoso do ponto de vista do desempenho calcular

γ(m+1 12,uma)=Γ(m+1 12)-Γ(m+1 12,uma)

usando valores tabulados de e computaçãoΓ(m+1Γ(m+1 12)acordo com esta resposta, evitando cuidadosamente a questão do cancelamento subtrativo através do uso de uma operação de adição múltipla fundida. Uma possível otimização adicional é observar que paraa,γsuficientemente grande(m+1Γ(m+1 12,uma)umadentro de uma determinada precisão de ponto flutuante.γ(m+12,a)=Γ(m+12)

Para pequenos argumentos, comecei com uma expansão em série para a função gama incompleta mais baixa de

A. Erdelyi, W. Magnus, F. Oberhettinger e FG Tricomi, "Higher Transcendental Functions, Vol. 2". Nova York, NY: McGraw-Hill 1953

e modificou-o para calcular a função de meninos seguinte maneira (truncando a série quando o termo é suficientemente pequeno para uma determinada precisão):Fm(a)

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

m=0,1,2,3F0 0(uma)=π4umaerf(uma)erfERFerferff

m=1 1,2,3uma<21 12Fm(uma)=1 12uma((2m-1 1)Fm-1 1(uma)-exp(-uma))

umammFm-1 1=1 12m-1 1(2uma Fm(uma)+exp(-uma))


Obrigado @njuffa pela ótima resposta. Se você criar seu código para esse código-fonte aberto, acho que seria muito útil para muitas pessoas.
Ondřej Čertík

11
Atualmente, uma implementação CUDA do algoritmo descrito está disponível para download gratuito no site do desenvolvedor da NVIDIA (requer registro gratuito como desenvolvedor CUDA, aprovação geralmente dentro de um dia útil). O código está sob uma licença BSD, que deve ser compatível com praticamente qualquer tipo de projeto.
Njuffa


4

Eu daria uma olhada no livro de Abramowicz & Stegun, ou na revisão mais recente que o NIST publicou há alguns anos atrás e acredito que esteja disponível online. Eles também discutem maneiras de implementar as coisas de maneira estável.


Eu estava usando isso: dlmf.nist.gov/8 , ao implementá-lo, mas isso provavelmente é outro recurso. O capítulo 5 em Receitas numéricas também possui informações interessantes, mas aplicáveis ​​apenas às funções de uma variável.
Ondřej Čertík

Eu não acho que você encontrará algo muito mais recente do que a referência de 2001; O SLATEC será mais antigo que isso.
amigos estão dizendo sobre geoff

1

Não parece ser o estado da arte, mas o SLATEC da Netlib oferece "1400 rotinas matemáticas e estatísticas de uso geral". A gama incompleta está disponível sob as funções especiais aqui .

A implementação de tais funções é demorada e propensa a erros, então eu não faria isso a menos que fosse absolutamente necessário. O SLATEC já existe há algum tempo e é amplamente utilizado, pelo menos com base na contagem de downloads , portanto, espero que a implementação esteja madura.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.