1*34120Sbostic /* 2*34120Sbostic * Copyright (c) 1985 Regents of the University of California. 3*34120Sbostic * All rights reserved. The Berkeley software License Agreement 4*34120Sbostic * specifies the terms and conditions for redistribution. 5*34120Sbostic */ 6*34120Sbostic 724600Szliu #ifndef lint 8*34120Sbostic static char sccsid[] = "@(#)lgamma.c 5.2 (Berkeley) 04/29/88"; 9*34120Sbostic #endif /* not lint */ 1024600Szliu 1124600Szliu /* 1224600Szliu C program for floating point log Gamma function 1324600Szliu 1424705Selefunt lgamma(x) computes the log of the absolute 1524600Szliu value of the Gamma function. 1624600Szliu The sign of the Gamma function is returned in the 1724600Szliu external quantity signgam. 1824600Szliu 1924600Szliu The coefficients for expansion around zero 2024600Szliu are #5243 from Hart & Cheney; for expansion 2124600Szliu around infinity they are #5404. 2224600Szliu 2324600Szliu Calls log, floor and sin. 2424600Szliu */ 2524600Szliu 2624600Szliu #include <math.h> 2731853Szliu #if defined(vax)||defined(tahoe) 2824600Szliu #include <errno.h> 2931853Szliu #endif /* defined(vax)||defined(tahoe) */ 3024600Szliu int signgam = 0; 3124600Szliu static double goobie = 0.9189385332046727417803297; /* log(2*pi)/2 */ 3224600Szliu static double pi = 3.1415926535897932384626434; 3324600Szliu 3424600Szliu #define M 6 3524600Szliu #define N 8 3624600Szliu static double p1[] = { 3724600Szliu 0.83333333333333101837e-1, 3824600Szliu -.277777777735865004e-2, 3924600Szliu 0.793650576493454e-3, 4024600Szliu -.5951896861197e-3, 4124600Szliu 0.83645878922e-3, 4224600Szliu -.1633436431e-2, 4324600Szliu }; 4424600Szliu static double p2[] = { 4524600Szliu -.42353689509744089647e5, 4624600Szliu -.20886861789269887364e5, 4724600Szliu -.87627102978521489560e4, 4824600Szliu -.20085274013072791214e4, 4924600Szliu -.43933044406002567613e3, 5024600Szliu -.50108693752970953015e2, 5124600Szliu -.67449507245925289918e1, 5224600Szliu 0.0, 5324600Szliu }; 5424600Szliu static double q2[] = { 5524600Szliu -.42353689509744090010e5, 5624600Szliu -.29803853309256649932e4, 5724600Szliu 0.99403074150827709015e4, 5824600Szliu -.15286072737795220248e4, 5924600Szliu -.49902852662143904834e3, 6024600Szliu 0.18949823415702801641e3, 6124600Szliu -.23081551524580124562e2, 6224600Szliu 0.10000000000000000000e1, 6324600Szliu }; 6424600Szliu 6524600Szliu double 6624705Selefunt lgamma(arg) 6724600Szliu double arg; 6824600Szliu { 6924600Szliu double log(), pos(), neg(), asym(); 7024600Szliu 7124600Szliu signgam = 1.; 7224600Szliu if(arg <= 0.) return(neg(arg)); 7324600Szliu if(arg > 8.) return(asym(arg)); 7424600Szliu return(log(pos(arg))); 7524600Szliu } 7624600Szliu 7724600Szliu static double 7824600Szliu asym(arg) 7924600Szliu double arg; 8024600Szliu { 8124600Szliu double log(); 8224600Szliu double n, argsq; 8324600Szliu int i; 8424600Szliu 8524600Szliu argsq = 1./(arg*arg); 8624600Szliu for(n=0,i=M-1; i>=0; i--){ 8724600Szliu n = n*argsq + p1[i]; 8824600Szliu } 8924600Szliu return((arg-.5)*log(arg) - arg + goobie + n/arg); 9024600Szliu } 9124600Szliu 9224600Szliu static double 9324600Szliu neg(arg) 9424600Szliu double arg; 9524600Szliu { 9624600Szliu double t; 9724600Szliu double log(), sin(), floor(), pos(); 9824600Szliu 9924600Szliu arg = -arg; 10024600Szliu /* 10124600Szliu * to see if arg were a true integer, the old code used the 10224600Szliu * mathematically correct observation: 10324600Szliu * sin(n*pi) = 0 <=> n is an integer. 10424600Szliu * but in finite precision arithmetic, sin(n*PI) will NEVER 10524600Szliu * be zero simply because n*PI is a rational number. hence 10624600Szliu * it failed to work with our newer, more accurate sin() 10724600Szliu * which uses true pi to do the argument reduction... 10824600Szliu * temp = sin(pi*arg); 10924600Szliu */ 11024600Szliu t = floor(arg); 11124600Szliu if (arg - t > 0.5e0) 11224600Szliu t += 1.e0; /* t := integer nearest arg */ 11331853Szliu #if defined(vax)||defined(tahoe) 11424600Szliu if (arg == t) { 11524600Szliu extern double infnan(); 11624600Szliu return(infnan(ERANGE)); /* +INF */ 11724600Szliu } 11831853Szliu #endif /* defined(vax)||defined(tahoe) */ 11924600Szliu signgam = (int) (t - 2*floor(t/2)); /* signgam = 1 if t was odd, */ 12024600Szliu /* 0 if t was even */ 12124600Szliu signgam = signgam - 1 + signgam; /* signgam = 1 if t was odd, */ 12224600Szliu /* -1 if t was even */ 12324600Szliu t = arg - t; /* -0.5 <= t <= 0.5 */ 12424600Szliu if (t < 0.e0) { 12524600Szliu t = -t; 12624600Szliu signgam = -signgam; 12724600Szliu } 12824600Szliu return(-log(arg*pos(arg)*sin(pi*t)/pi)); 12924600Szliu } 13024600Szliu 13124600Szliu static double 13224600Szliu pos(arg) 13324600Szliu double arg; 13424600Szliu { 13524600Szliu double n, d, s; 13624600Szliu register i; 13724600Szliu 13824600Szliu if(arg < 2.) return(pos(arg+1.)/arg); 13924600Szliu if(arg > 3.) return((arg-1.)*pos(arg-1.)); 14024600Szliu 14124600Szliu s = arg - 2.; 14224600Szliu for(n=0,d=0,i=N-1; i>=0; i--){ 14324600Szliu n = n*s + p2[i]; 14424600Szliu d = d*s + q2[i]; 14524600Szliu } 14624600Szliu return(n/d); 14724600Szliu } 148