|
|
1.1 root 1: /*
2: * Copyright (c) 1985 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)lgamma.c 5.2 (Berkeley) 4/29/88";
9: #endif /* not lint */
10:
11: /*
12: C program for floating point log Gamma function
13:
14: lgamma(x) computes the log of the absolute
15: value of the Gamma function.
16: The sign of the Gamma function is returned in the
17: external quantity signgam.
18:
19: The coefficients for expansion around zero
20: are #5243 from Hart & Cheney; for expansion
21: around infinity they are #5404.
22:
23: Calls log, floor and sin.
24: */
25:
26: #include <math.h>
27: #if defined(vax)||defined(tahoe)
28: #include <errno.h>
29: #endif /* defined(vax)||defined(tahoe) */
30: int signgam = 0;
31: static double goobie = 0.9189385332046727417803297; /* log(2*pi)/2 */
32: static double pi = 3.1415926535897932384626434;
33:
34: #define M 6
35: #define N 8
36: static double p1[] = {
37: 0.83333333333333101837e-1,
38: -.277777777735865004e-2,
39: 0.793650576493454e-3,
40: -.5951896861197e-3,
41: 0.83645878922e-3,
42: -.1633436431e-2,
43: };
44: static double p2[] = {
45: -.42353689509744089647e5,
46: -.20886861789269887364e5,
47: -.87627102978521489560e4,
48: -.20085274013072791214e4,
49: -.43933044406002567613e3,
50: -.50108693752970953015e2,
51: -.67449507245925289918e1,
52: 0.0,
53: };
54: static double q2[] = {
55: -.42353689509744090010e5,
56: -.29803853309256649932e4,
57: 0.99403074150827709015e4,
58: -.15286072737795220248e4,
59: -.49902852662143904834e3,
60: 0.18949823415702801641e3,
61: -.23081551524580124562e2,
62: 0.10000000000000000000e1,
63: };
64:
65: double
66: lgamma(arg)
67: double arg;
68: {
69: double log(), pos(), neg(), asym();
70:
71: signgam = 1.;
72: if(arg <= 0.) return(neg(arg));
73: if(arg > 8.) return(asym(arg));
74: return(log(pos(arg)));
75: }
76:
77: static double
78: asym(arg)
79: double arg;
80: {
81: double log();
82: double n, argsq;
83: int i;
84:
85: argsq = 1./(arg*arg);
86: for(n=0,i=M-1; i>=0; i--){
87: n = n*argsq + p1[i];
88: }
89: return((arg-.5)*log(arg) - arg + goobie + n/arg);
90: }
91:
92: static double
93: neg(arg)
94: double arg;
95: {
96: double t;
97: double log(), sin(), floor(), pos();
98:
99: arg = -arg;
100: /*
101: * to see if arg were a true integer, the old code used the
102: * mathematically correct observation:
103: * sin(n*pi) = 0 <=> n is an integer.
104: * but in finite precision arithmetic, sin(n*PI) will NEVER
105: * be zero simply because n*PI is a rational number. hence
106: * it failed to work with our newer, more accurate sin()
107: * which uses true pi to do the argument reduction...
108: * temp = sin(pi*arg);
109: */
110: t = floor(arg);
111: if (arg - t > 0.5e0)
112: t += 1.e0; /* t := integer nearest arg */
113: #if defined(vax)||defined(tahoe)
114: if (arg == t) {
115: extern double infnan();
116: return(infnan(ERANGE)); /* +INF */
117: }
118: #endif /* defined(vax)||defined(tahoe) */
119: signgam = (int) (t - 2*floor(t/2)); /* signgam = 1 if t was odd, */
120: /* 0 if t was even */
121: signgam = signgam - 1 + signgam; /* signgam = 1 if t was odd, */
122: /* -1 if t was even */
123: t = arg - t; /* -0.5 <= t <= 0.5 */
124: if (t < 0.e0) {
125: t = -t;
126: signgam = -signgam;
127: }
128: return(-log(arg*pos(arg)*sin(pi*t)/pi));
129: }
130:
131: static double
132: pos(arg)
133: double arg;
134: {
135: double n, d, s;
136: register i;
137:
138: if(arg < 2.) return(pos(arg+1.)/arg);
139: if(arg > 3.) return((arg-1.)*pos(arg-1.));
140:
141: s = arg - 2.;
142: for(n=0,d=0,i=N-1; i>=0; i--){
143: n = n*s + p2[i];
144: d = d*s + q2[i];
145: }
146: return(n/d);
147: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.