1 | /* hyperg.c |
---|
2 | * |
---|
3 | * Confluent hypergeometric function |
---|
4 | * |
---|
5 | * |
---|
6 | * |
---|
7 | * SYNOPSIS: |
---|
8 | * |
---|
9 | * double a, b, x, y, hyperg(); |
---|
10 | * |
---|
11 | * y = hyperg( a, b, x ); |
---|
12 | * |
---|
13 | * |
---|
14 | * |
---|
15 | * DESCRIPTION: |
---|
16 | * |
---|
17 | * Computes the confluent hypergeometric function |
---|
18 | * |
---|
19 | * 1 2 |
---|
20 | * a x a(a+1) x |
---|
21 | * F ( a,b;x ) = 1 + ---- + --------- + ... |
---|
22 | * 1 1 b 1! b(b+1) 2! |
---|
23 | * |
---|
24 | * Many higher transcendental functions are special cases of |
---|
25 | * this power series. |
---|
26 | * |
---|
27 | * As is evident from the formula, b must not be a negative |
---|
28 | * integer or zero unless a is an integer with 0 >= a > b. |
---|
29 | * |
---|
30 | * The routine attempts both a direct summation of the series |
---|
31 | * and an asymptotic expansion. In each case error due to |
---|
32 | * roundoff, cancellation, and nonconvergence is estimated. |
---|
33 | * The result with smaller estimated error is returned. |
---|
34 | * |
---|
35 | * |
---|
36 | * |
---|
37 | * ACCURACY: |
---|
38 | * |
---|
39 | * Tested at random points (a, b, x), all three variables |
---|
40 | * ranging from 0 to 30. |
---|
41 | * Relative error: |
---|
42 | * arithmetic domain # trials peak rms |
---|
43 | * DEC 0,30 2000 1.2e-15 1.3e-16 |
---|
44 | qtst1: |
---|
45 | 21800 max = 1.4200E-14 rms = 1.0841E-15 ave = -5.3640E-17 |
---|
46 | ltstd: |
---|
47 | 25500 max = 1.2759e-14 rms = 3.7155e-16 ave = 1.5384e-18 |
---|
48 | * IEEE 0,30 30000 1.8e-14 1.1e-15 |
---|
49 | * |
---|
50 | * Larger errors can be observed when b is near a negative |
---|
51 | * integer or zero. Certain combinations of arguments yield |
---|
52 | * serious cancellation error in the power series summation |
---|
53 | * and also are not in the region of near convergence of the |
---|
54 | * asymptotic series. An error message is printed if the |
---|
55 | * self-estimated relative error is greater than 1.0e-12. |
---|
56 | * |
---|
57 | */ |
---|
58 | |
---|
59 | /* hyperg.c */ |
---|
60 | |
---|
61 | |
---|
62 | /* |
---|
63 | Cephes Math Library Release 2.8: June, 2000 |
---|
64 | Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier |
---|
65 | */ |
---|
66 | |
---|
67 | #include "mconf.h" |
---|
68 | |
---|
69 | #ifdef ANSIPROT |
---|
70 | extern double exp ( double ); |
---|
71 | extern double log ( double ); |
---|
72 | extern double gamma ( double ); |
---|
73 | extern double lgam ( double ); |
---|
74 | extern double fabs ( double ); |
---|
75 | double hyp2f0 ( double, double, double, int, double * ); |
---|
76 | static double hy1f1p(double, double, double, double *); |
---|
77 | static double hy1f1a(double, double, double, double *); |
---|
78 | double hyperg (double, double, double); |
---|
79 | #else |
---|
80 | double exp(), log(), gamma(), lgam(), fabs(), hyp2f0(); |
---|
81 | static double hy1f1p(); |
---|
82 | static double hy1f1a(); |
---|
83 | double hyperg(); |
---|
84 | #endif |
---|
85 | extern double MAXNUM, MACHEP; |
---|
86 | |
---|
87 | double hyperg( a, b, x) |
---|
88 | double a, b, x; |
---|
89 | { |
---|
90 | double asum, psum, acanc, pcanc, temp; |
---|
91 | |
---|
92 | /* See if a Kummer transformation will help */ |
---|
93 | temp = b - a; |
---|
94 | if( fabs(temp) < 0.001 * fabs(a) ) |
---|
95 | return( exp(x) * hyperg( temp, b, -x ) ); |
---|
96 | |
---|
97 | |
---|
98 | psum = hy1f1p( a, b, x, &pcanc ); |
---|
99 | if( pcanc < 1.0e-15 ) |
---|
100 | goto done; |
---|
101 | |
---|
102 | |
---|
103 | /* try asymptotic series */ |
---|
104 | |
---|
105 | asum = hy1f1a( a, b, x, &acanc ); |
---|
106 | |
---|
107 | |
---|
108 | /* Pick the result with less estimated error */ |
---|
109 | |
---|
110 | if( acanc < pcanc ) |
---|
111 | { |
---|
112 | pcanc = acanc; |
---|
113 | psum = asum; |
---|
114 | } |
---|
115 | |
---|
116 | done: |
---|
117 | if( pcanc > 1.0e-12 ) |
---|
118 | mtherr( "hyperg", PLOSS ); |
---|
119 | |
---|
120 | return( psum ); |
---|
121 | } |
---|
122 | |
---|
123 | |
---|
124 | |
---|
125 | |
---|
126 | /* Power series summation for confluent hypergeometric function */ |
---|
127 | |
---|
128 | |
---|
129 | static double hy1f1p( a, b, x, err ) |
---|
130 | double a, b, x; |
---|
131 | double *err; |
---|
132 | { |
---|
133 | double n, a0, sum, t, u, temp; |
---|
134 | double an, bn, maxt, pcanc; |
---|
135 | |
---|
136 | |
---|
137 | /* set up for power series summation */ |
---|
138 | an = a; |
---|
139 | bn = b; |
---|
140 | a0 = 1.0; |
---|
141 | sum = 1.0; |
---|
142 | n = 1.0; |
---|
143 | t = 1.0; |
---|
144 | maxt = 0.0; |
---|
145 | |
---|
146 | |
---|
147 | while( t > MACHEP ) |
---|
148 | { |
---|
149 | if( bn == 0 ) /* check bn first since if both */ |
---|
150 | { |
---|
151 | mtherr( "hyperg", SING ); |
---|
152 | return( MAXNUM ); /* an and bn are zero it is */ |
---|
153 | } |
---|
154 | if( an == 0 ) /* a singularity */ |
---|
155 | return( sum ); |
---|
156 | if( n > 200 ) |
---|
157 | goto pdone; |
---|
158 | u = x * ( an / (bn * n) ); |
---|
159 | |
---|
160 | /* check for blowup */ |
---|
161 | temp = fabs(u); |
---|
162 | if( (temp > 1.0 ) && (maxt > (MAXNUM/temp)) ) |
---|
163 | { |
---|
164 | pcanc = 1.0; /* estimate 100% error */ |
---|
165 | goto blowup; |
---|
166 | } |
---|
167 | |
---|
168 | a0 *= u; |
---|
169 | sum += a0; |
---|
170 | t = fabs(a0); |
---|
171 | if( t > maxt ) |
---|
172 | maxt = t; |
---|
173 | /* |
---|
174 | if( (maxt/fabs(sum)) > 1.0e17 ) |
---|
175 | { |
---|
176 | pcanc = 1.0; |
---|
177 | goto blowup; |
---|
178 | } |
---|
179 | */ |
---|
180 | an += 1.0; |
---|
181 | bn += 1.0; |
---|
182 | n += 1.0; |
---|
183 | } |
---|
184 | |
---|
185 | pdone: |
---|
186 | |
---|
187 | /* estimate error due to roundoff and cancellation */ |
---|
188 | if( sum != 0.0 ) |
---|
189 | maxt /= fabs(sum); |
---|
190 | maxt *= MACHEP; /* this way avoids multiply overflow */ |
---|
191 | pcanc = fabs( MACHEP * n + maxt ); |
---|
192 | |
---|
193 | blowup: |
---|
194 | |
---|
195 | *err = pcanc; |
---|
196 | |
---|
197 | return( sum ); |
---|
198 | } |
---|
199 | |
---|
200 | |
---|
201 | /* hy1f1a() */ |
---|
202 | /* asymptotic formula for hypergeometric function: |
---|
203 | * |
---|
204 | * ( -a |
---|
205 | * -- ( |z| |
---|
206 | * | (b) ( -------- 2f0( a, 1+a-b, -1/x ) |
---|
207 | * ( -- |
---|
208 | * ( | (b-a) |
---|
209 | * |
---|
210 | * |
---|
211 | * x a-b ) |
---|
212 | * e |x| ) |
---|
213 | * + -------- 2f0( b-a, 1-a, 1/x ) ) |
---|
214 | * -- ) |
---|
215 | * | (a) ) |
---|
216 | */ |
---|
217 | |
---|
218 | static double hy1f1a( a, b, x, err ) |
---|
219 | double a, b, x; |
---|
220 | double *err; |
---|
221 | { |
---|
222 | double h1, h2, t, u, temp, acanc, asum, err1, err2; |
---|
223 | |
---|
224 | if( x == 0 ) |
---|
225 | { |
---|
226 | acanc = 1.0; |
---|
227 | asum = MAXNUM; |
---|
228 | goto adone; |
---|
229 | } |
---|
230 | temp = log( fabs(x) ); |
---|
231 | t = x + temp * (a-b); |
---|
232 | u = -temp * a; |
---|
233 | |
---|
234 | if( b > 0 ) |
---|
235 | { |
---|
236 | temp = lgam(b); |
---|
237 | t += temp; |
---|
238 | u += temp; |
---|
239 | } |
---|
240 | |
---|
241 | h1 = hyp2f0( a, a-b+1, -1.0/x, 1, &err1 ); |
---|
242 | |
---|
243 | temp = exp(u) / gamma(b-a); |
---|
244 | h1 *= temp; |
---|
245 | err1 *= temp; |
---|
246 | |
---|
247 | h2 = hyp2f0( b-a, 1.0-a, 1.0/x, 2, &err2 ); |
---|
248 | |
---|
249 | if( a < 0 ) |
---|
250 | temp = exp(t) / gamma(a); |
---|
251 | else |
---|
252 | temp = exp( t - lgam(a) ); |
---|
253 | |
---|
254 | h2 *= temp; |
---|
255 | err2 *= temp; |
---|
256 | |
---|
257 | if( x < 0.0 ) |
---|
258 | asum = h1; |
---|
259 | else |
---|
260 | asum = h2; |
---|
261 | |
---|
262 | acanc = fabs(err1) + fabs(err2); |
---|
263 | |
---|
264 | |
---|
265 | if( b < 0 ) |
---|
266 | { |
---|
267 | temp = gamma(b); |
---|
268 | asum *= temp; |
---|
269 | acanc *= fabs(temp); |
---|
270 | } |
---|
271 | |
---|
272 | |
---|
273 | if( asum != 0.0 ) |
---|
274 | acanc /= fabs(asum); |
---|
275 | |
---|
276 | acanc *= 30.0; /* fudge factor, since error of asymptotic formula |
---|
277 | * often seems this much larger than advertised */ |
---|
278 | |
---|
279 | adone: |
---|
280 | |
---|
281 | |
---|
282 | *err = acanc; |
---|
283 | return( asum ); |
---|
284 | } |
---|
285 | |
---|
286 | /* hyp2f0() */ |
---|
287 | |
---|
288 | double hyp2f0( a, b, x, type, err ) |
---|
289 | double a, b, x; |
---|
290 | int type; /* determines what converging factor to use */ |
---|
291 | double *err; |
---|
292 | { |
---|
293 | double a0, alast, t, tlast, maxt; |
---|
294 | double n, an, bn, u, sum, temp; |
---|
295 | |
---|
296 | an = a; |
---|
297 | bn = b; |
---|
298 | a0 = 1.0e0; |
---|
299 | alast = 1.0e0; |
---|
300 | sum = 0.0; |
---|
301 | n = 1.0e0; |
---|
302 | t = 1.0e0; |
---|
303 | tlast = 1.0e9; |
---|
304 | maxt = 0.0; |
---|
305 | |
---|
306 | do |
---|
307 | { |
---|
308 | if( an == 0 ) |
---|
309 | goto pdone; |
---|
310 | if( bn == 0 ) |
---|
311 | goto pdone; |
---|
312 | |
---|
313 | u = an * (bn * x / n); |
---|
314 | |
---|
315 | /* check for blowup */ |
---|
316 | temp = fabs(u); |
---|
317 | if( (temp > 1.0 ) && (maxt > (MAXNUM/temp)) ) |
---|
318 | goto error; |
---|
319 | |
---|
320 | a0 *= u; |
---|
321 | t = fabs(a0); |
---|
322 | |
---|
323 | /* terminating condition for asymptotic series */ |
---|
324 | if( t > tlast ) |
---|
325 | goto ndone; |
---|
326 | |
---|
327 | tlast = t; |
---|
328 | sum += alast; /* the sum is one term behind */ |
---|
329 | alast = a0; |
---|
330 | |
---|
331 | if( n > 200 ) |
---|
332 | goto ndone; |
---|
333 | |
---|
334 | an += 1.0e0; |
---|
335 | bn += 1.0e0; |
---|
336 | n += 1.0e0; |
---|
337 | if( t > maxt ) |
---|
338 | maxt = t; |
---|
339 | } |
---|
340 | while( t > MACHEP ); |
---|
341 | |
---|
342 | |
---|
343 | pdone: /* series converged! */ |
---|
344 | |
---|
345 | /* estimate error due to roundoff and cancellation */ |
---|
346 | *err = fabs( MACHEP * (n + maxt) ); |
---|
347 | |
---|
348 | alast = a0; |
---|
349 | goto done; |
---|
350 | |
---|
351 | ndone: /* series did not converge */ |
---|
352 | |
---|
353 | /* The following "Converging factors" are supposed to improve accuracy, |
---|
354 | * but do not actually seem to accomplish very much. */ |
---|
355 | |
---|
356 | n -= 1.0; |
---|
357 | x = 1.0/x; |
---|
358 | |
---|
359 | switch( type ) /* "type" given as subroutine argument */ |
---|
360 | { |
---|
361 | case 1: |
---|
362 | alast *= ( 0.5 + (0.125 + 0.25*b - 0.5*a + 0.25*x - 0.25*n)/x ); |
---|
363 | break; |
---|
364 | |
---|
365 | case 2: |
---|
366 | alast *= 2.0/3.0 - b + 2.0*a + x - n; |
---|
367 | break; |
---|
368 | |
---|
369 | default: |
---|
370 | ; |
---|
371 | } |
---|
372 | |
---|
373 | /* estimate error due to roundoff, cancellation, and nonconvergence */ |
---|
374 | *err = MACHEP * (n + maxt) + fabs ( a0 ); |
---|
375 | |
---|
376 | |
---|
377 | done: |
---|
378 | sum += alast; |
---|
379 | return( sum ); |
---|
380 | |
---|
381 | /* series blew up: */ |
---|
382 | error: |
---|
383 | *err = MAXNUM; |
---|
384 | mtherr( "hyperg", TLOSS ); |
---|
385 | return( sum ); |
---|
386 | } |
---|