home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include <stdio.h>
- #include <errno.h>
- /*@ Ensemble de fonctions pour calculer la fonction gamma
- Calcul du logarithme du valeur absolue de la fonction gamma pour \'eviter
- les d\'ebordements
- Les coefficients pour l'expansion au tour de z\'ero sont ceux de Hart and
- Cheney (\#5243) et pour l'expansion au tour de $\inf$ (\#5404)
-
- */
- #define M 6
- #define N 8
- static double p1[] = {
- 0.83333333333333101837e-1, /* 1 / 12 */
- -.277777777735865004e-2, /* 1 / 360 */
- 0.793650576493454e-3, /* 1 / 1260 */
- -.5951896861197e-3, /* 1 / 1680 */
- 0.83645878922e-3,
- -.1633436431e-2
- };
- static double p2[] = {
- -.42353689509744089647e5,
- -.20886861789269887364e5,
- -.87627102978521489560e4,
- -.20085274013072791214e4,
- -.43933044406002567613e3,
- -.50108693752970953015e2,
- -.67449507245925289918e1,
- 0.0
- };
- static double q2[] = {
- -.42353689509744090010e5,
- -.29803853309256649932e4,
- 0.99403074150827709015e4,
- -.15286072737795220248e4,
- -.49902852662143904834e3,
- 0.18949823415702801641e3,
- -.23081551524580124562e2,
- 0.10000000000000000000e1
- };
- static double factor = 0.9189385332046727417803297;
- int signgam = 0;
-
- static double asym(double arg);
- static double neg(double arg);
- static double pos(double arg);
- double lgamma(double arg)
- {
- signgam = 1;
- if(arg <= 0.0) return(neg(arg));
- if(arg > 8.0) return(asym(arg));
- return((double)signgam * log(pos(arg)));
- }
-
- static double asym(double arg)
- {
- double n, argsq;
- register int i;
-
- argsq = 1.0/(arg*arg);
- for(n = 0.0, i = M-1; i>=0; i--){
- n = n*argsq + p1[i];
- }
- return((arg - 0.5)*log(arg) - arg + factor + n/arg);
- }
-
- static double neg(double arg)
- {
- double temp;
-
- arg = -arg;
- temp = sin(M_PI*arg);
- if(temp == 0.0) {
- return(HUGE_VAL);
- }
- if(temp < 0.0) temp = -temp;
- else signgam = -1;
- return(-log(arg*pos(arg)*temp/M_PI));
- }
-
- static double pos(double arg)
- {
- double n, d, s;
- register int i;
-
- if(arg < 2.0) return(pos(arg+1.0)/arg);
- if(arg > 3.0) return((arg-1.0)*pos(arg-1.0));
-
- s = arg - 2.;
- for(n=0.0,d=0.0,i = N-1; i>=0; i--){
- n = n*s + p2[i];
- d = d*s + q2[i];
- }
- return(n/d);
- }
- #ifdef STANDALONE
- int main()
- {
- int i=1;
- double r;
-
- while (i < 10) {
- r= gamma((double)i);
- printf("[%3d] %10.15f\n",i,r);
- i++;
- }
- }
- #endif
-