Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1906 | serge | 1 | /* gammaf.c |
2 | * |
||
3 | * Gamma function |
||
4 | * |
||
5 | * |
||
6 | * |
||
7 | * SYNOPSIS: |
||
8 | * |
||
9 | * float x, y, __tgammaf_r(); |
||
10 | * int* sgngamf; |
||
11 | * y = __tgammaf_r( x, sgngamf ); |
||
12 | * |
||
13 | * float x, y, tgammaf(); |
||
14 | * y = tgammaf( x); |
||
15 | * |
||
16 | * |
||
17 | * DESCRIPTION: |
||
18 | * |
||
19 | * Returns gamma function of the argument. The result is |
||
20 | * correctly signed. In the reentrant version the sign (+1 or -1) |
||
21 | * is returned in the variable referenced by sgngamf. |
||
22 | * |
||
23 | * Arguments between 0 and 10 are reduced by recurrence and the |
||
24 | * function is approximated by a polynomial function covering |
||
25 | * the interval (2,3). Large arguments are handled by Stirling's |
||
26 | * formula. Negative arguments are made positive using |
||
27 | * a reflection formula. |
||
28 | * |
||
29 | * |
||
30 | * ACCURACY: |
||
31 | * |
||
32 | * Relative error: |
||
33 | * arithmetic domain # trials peak rms |
||
34 | * IEEE 0,-33 100,000 5.7e-7 1.0e-7 |
||
35 | * IEEE -33,0 100,000 6.1e-7 1.2e-7 |
||
36 | * |
||
37 | * |
||
38 | */ |
||
39 | |||
40 | /* |
||
41 | Cephes Math Library Release 2.7: July, 1998 |
||
42 | Copyright 1984, 1987, 1989, 1992, 1998 by Stephen L. Moshier |
||
43 | */ |
||
44 | |||
45 | |||
46 | /* |
||
47 | * 26-11-2002 Modified for mingw. |
||
48 | * Danny Smith |
||
49 | */ |
||
50 | |||
51 | |||
52 | #ifndef __MINGW32__ |
||
53 | #include "mconf.h" |
||
54 | #else |
||
55 | #include "cephes_mconf.h" |
||
56 | #endif |
||
57 | |||
58 | /* define MAXGAM 34.84425627277176174 */ |
||
59 | |||
60 | /* Stirling's formula for the gamma function |
||
61 | * gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) ) |
||
62 | * .028 < 1/x < .1 |
||
63 | * relative error < 1.9e-11 |
||
64 | */ |
||
65 | static const float STIR[] = { |
||
66 | -2.705194986674176E-003, |
||
67 | 3.473255786154910E-003, |
||
68 | 8.333331788340907E-002, |
||
69 | }; |
||
70 | static const float MAXSTIR = 26.77; |
||
71 | static const float SQTPIF = 2.50662827463100050242; /* sqrt( 2 pi ) */ |
||
72 | |||
73 | #ifndef __MINGW32__ |
||
74 | |||
75 | extern float MAXLOGF, MAXNUMF, PIF; |
||
76 | |||
77 | #ifdef ANSIC |
||
78 | float expf(float); |
||
79 | float logf(float); |
||
80 | float powf( float, float ); |
||
81 | float sinf(float); |
||
82 | float gammaf(float); |
||
83 | float floorf(float); |
||
84 | static float stirf(float); |
||
85 | float polevlf( float, float *, int ); |
||
86 | float p1evlf( float, float *, int ); |
||
87 | #else |
||
88 | float expf(), logf(), powf(), sinf(), floorf(); |
||
89 | float polevlf(), p1evlf(); |
||
90 | static float stirf(); |
||
91 | #endif |
||
92 | |||
93 | #else /* __MINGW32__ */ |
||
94 | static float stirf(float); |
||
95 | #endif |
||
96 | |||
97 | /* Gamma function computed by Stirling's formula, |
||
98 | * sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x)) |
||
99 | * The polynomial STIR is valid for 33 <= x <= 172. |
||
100 | */ |
||
101 | static float stirf( float x ) |
||
102 | { |
||
103 | float y, w, v; |
||
104 | |||
105 | w = 1.0/x; |
||
106 | w = 1.0 + w * polevlf( w, STIR, 2 ); |
||
107 | y = expf( -x ); |
||
108 | if( x > MAXSTIR ) |
||
109 | { /* Avoid overflow in pow() */ |
||
110 | v = powf( x, 0.5 * x - 0.25 ); |
||
111 | y *= v; |
||
112 | y *= v; |
||
113 | } |
||
114 | else |
||
115 | { |
||
116 | y = powf( x, x - 0.5 ) * y; |
||
117 | } |
||
118 | y = SQTPIF * y * w; |
||
119 | return( y ); |
||
120 | } |
||
121 | |||
122 | |||
123 | /* gamma(x+2), 0 < x < 1 */ |
||
124 | static const float P[] = { |
||
125 | 1.536830450601906E-003, |
||
126 | 5.397581592950993E-003, |
||
127 | 4.130370201859976E-003, |
||
128 | 7.232307985516519E-002, |
||
129 | 8.203960091619193E-002, |
||
130 | 4.117857447645796E-001, |
||
131 | 4.227867745131584E-001, |
||
132 | 9.999999822945073E-001, |
||
133 | }; |
||
134 | |||
135 | float __tgammaf_r( float x, int* sgngamf) |
||
136 | { |
||
137 | float p, q, z, nz; |
||
138 | int i, direction, negative; |
||
139 | |||
140 | #ifdef NANS |
||
141 | if( isnan(x) ) |
||
142 | return(x); |
||
143 | #endif |
||
144 | #ifdef INFINITIES |
||
145 | #ifdef NANS |
||
146 | if( x == INFINITYF ) |
||
147 | return(x); |
||
148 | if( x == -INFINITYF ) |
||
149 | return(NANF); |
||
150 | #else |
||
151 | if( !isfinite(x) ) |
||
152 | return(x); |
||
153 | #endif |
||
154 | #endif |
||
155 | |||
156 | *sgngamf = 1; |
||
157 | negative = 0; |
||
158 | nz = 0.0; |
||
159 | if( x < 0.0 ) |
||
160 | { |
||
161 | negative = 1; |
||
162 | q = -x; |
||
163 | p = floorf(q); |
||
164 | if( p == q ) |
||
165 | { |
||
166 | gsing: |
||
167 | _SET_ERRNO(EDOM); |
||
168 | mtherr( "tgammaf", SING ); |
||
169 | #ifdef INFINITIES |
||
170 | return (INFINITYF); |
||
171 | #else |
||
172 | return (MAXNUMF); |
||
173 | #endif |
||
174 | } |
||
175 | i = p; |
||
176 | if( (i & 1) == 0 ) |
||
177 | *sgngamf = -1; |
||
178 | nz = q - p; |
||
179 | if( nz > 0.5 ) |
||
180 | { |
||
181 | p += 1.0; |
||
182 | nz = q - p; |
||
183 | } |
||
184 | nz = q * sinf( PIF * nz ); |
||
185 | if( nz == 0.0 ) |
||
186 | { |
||
187 | _SET_ERRNO(ERANGE); |
||
188 | mtherr( "tgamma", OVERFLOW ); |
||
189 | #ifdef INFINITIES |
||
190 | return( *sgngamf * INFINITYF); |
||
191 | #else |
||
192 | return( *sgngamf * MAXNUMF); |
||
193 | #endif |
||
194 | } |
||
195 | if( nz < 0 ) |
||
196 | nz = -nz; |
||
197 | x = q; |
||
198 | } |
||
199 | if( x >= 10.0 ) |
||
200 | { |
||
201 | z = stirf(x); |
||
202 | } |
||
203 | if( x < 2.0 ) |
||
204 | direction = 1; |
||
205 | else |
||
206 | direction = 0; |
||
207 | z = 1.0; |
||
208 | while( x >= 3.0 ) |
||
209 | { |
||
210 | x -= 1.0; |
||
211 | z *= x; |
||
212 | } |
||
213 | /* |
||
214 | while( x < 0.0 ) |
||
215 | { |
||
216 | if( x > -1.E-4 ) |
||
217 | goto Small; |
||
218 | z *=x; |
||
219 | x += 1.0; |
||
220 | } |
||
221 | */ |
||
222 | while( x < 2.0 ) |
||
223 | { |
||
224 | if( x < 1.e-4 ) |
||
225 | goto Small; |
||
226 | z *=x; |
||
227 | x += 1.0; |
||
228 | } |
||
229 | |||
230 | if( direction ) |
||
231 | z = 1.0/z; |
||
232 | |||
233 | if( x == 2.0 ) |
||
234 | return(z); |
||
235 | |||
236 | x -= 2.0; |
||
237 | p = z * polevlf( x, P, 7 ); |
||
238 | |||
239 | gdone: |
||
240 | |||
241 | if( negative ) |
||
242 | { |
||
243 | p = *sgngamf * PIF/(nz * p ); |
||
244 | } |
||
245 | return(p); |
||
246 | |||
247 | Small: |
||
248 | if( x == 0.0 ) |
||
249 | { |
||
250 | goto gsing; |
||
251 | } |
||
252 | else |
||
253 | { |
||
254 | p = z / ((1.0 + 0.5772156649015329 * x) * x); |
||
255 | goto gdone; |
||
256 | } |
||
257 | } |
||
258 | |||
259 | /* This is the C99 version */ |
||
260 | |||
261 | float tgammaf(float x) |
||
262 | { |
||
263 | int local_sgngamf=0; |
||
264 | return (__tgammaf_r(x, &local_sgngamf)); |
||
265 | }>>>>>>>>=>=>>>> |