Added MACS source
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / specfunc / bessel_Kn.c
1 /* specfunc/bessel_Kn.c
2  * 
3  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 /* Author:  G. Jungman */
21
22 #include <config.h>
23 #include <gsl/gsl_math.h>
24 #include <gsl/gsl_errno.h>
25 #include <gsl/gsl_sf_gamma.h>
26 #include <gsl/gsl_sf_psi.h>
27 #include <gsl/gsl_sf_bessel.h>
28
29 #include "error.h"
30
31 #include "bessel.h"
32
33 /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
34
35 /* [Abramowitz+Stegun, 9.6.11]
36  * assumes n >= 1
37  */
38 static
39 int
40 bessel_Kn_scaled_small_x(const int n, const double x, gsl_sf_result * result)
41 {
42   int k;
43   double y = 0.25 * x * x;
44   double ln_x_2 = log(0.5*x);
45   double ex = exp(x);
46   gsl_sf_result ln_nm1_fact;
47   double k_term;
48   double term1, sum1, ln_pre1;
49   double term2, sum2, pre2;
50
51   gsl_sf_lnfact_e((unsigned int)(n-1), &ln_nm1_fact);
52
53   ln_pre1 = -n*ln_x_2 + ln_nm1_fact.val;
54   if(ln_pre1 > GSL_LOG_DBL_MAX - 3.0) GSL_ERROR ("error", GSL_EOVRFLW);
55
56   sum1 = 1.0;
57   k_term = 1.0;
58   for(k=1; k<=n-1; k++) {
59     k_term *= -y/(k * (n-k));
60     sum1 += k_term;
61   }
62   term1 = 0.5 * exp(ln_pre1) * sum1;
63
64   pre2 = 0.5 * exp(n*ln_x_2);
65   if(pre2 > 0.0) {
66     const int KMAX = 20;
67     gsl_sf_result psi_n;
68     gsl_sf_result npk_fact;
69     double yk = 1.0;
70     double k_fact  = 1.0;
71     double psi_kp1 = -M_EULER;
72     double psi_npkp1;
73     gsl_sf_psi_int_e(n, &psi_n);
74     gsl_sf_fact_e((unsigned int)n, &npk_fact);
75     psi_npkp1 = psi_n.val + 1.0/n;
76     sum2 = (psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/npk_fact.val;
77     for(k=1; k<KMAX; k++) {
78       psi_kp1   += 1.0/k;
79       psi_npkp1 += 1.0/(n+k);
80       k_fact    *= k;
81       npk_fact.val *= n+k;
82       yk *= y;
83       k_term = yk*(psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/(k_fact*npk_fact.val);
84       sum2 += k_term;
85     }
86     term2 = ( GSL_IS_ODD(n) ? -1.0 : 1.0 ) * pre2 * sum2;
87   }
88   else {
89     term2 = 0.0;
90   }
91
92   result->val  = ex * (term1 + term2);
93   result->err  = ex * GSL_DBL_EPSILON * (fabs(ln_pre1)*fabs(term1) + fabs(term2));
94   result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
95
96   return GSL_SUCCESS;
97 }
98
99
100 /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
101
102 int gsl_sf_bessel_Kn_scaled_e(int n, const double x, gsl_sf_result * result)
103 {
104   n = abs(n); /* K(-n, z) = K(n, z) */
105
106   /* CHECK_POINTER(result) */
107
108   if(x <= 0.0) {
109     DOMAIN_ERROR(result);
110   }
111   else if(n == 0) {
112     return gsl_sf_bessel_K0_scaled_e(x, result);
113   }
114   else if(n == 1) {
115     return gsl_sf_bessel_K1_scaled_e(x, result);
116   }
117   else if(x <= 5.0) {
118     return bessel_Kn_scaled_small_x(n, x, result);
119   }
120   else if(GSL_ROOT3_DBL_EPSILON * x > 0.25 * (n*n + 1)) {
121     return gsl_sf_bessel_Knu_scaled_asympx_e((double)n, x, result);
122   }
123   else if(GSL_MIN(0.29/(n*n), 0.5/(n*n + x*x)) < GSL_ROOT3_DBL_EPSILON) {
124     return gsl_sf_bessel_Knu_scaled_asymp_unif_e((double)n, x, result);
125   }
126   else {
127     /* Upward recurrence. [Gradshteyn + Ryzhik, 8.471.1] */
128     double two_over_x = 2.0/x;
129     gsl_sf_result r_b_jm1;
130     gsl_sf_result r_b_j;
131     int stat_0 = gsl_sf_bessel_K0_scaled_e(x, &r_b_jm1);
132     int stat_1 = gsl_sf_bessel_K1_scaled_e(x, &r_b_j);
133     double b_jm1 = r_b_jm1.val;
134     double b_j   = r_b_j.val;
135     double b_jp1;
136     int j;
137
138     for(j=1; j<n; j++) {
139       b_jp1 = b_jm1 + j * two_over_x * b_j;
140       b_jm1 = b_j;
141       b_j   = b_jp1; 
142     } 
143     
144     result->val  = b_j;
145     result->err  = n * (fabs(b_j) * (fabs(r_b_jm1.err/r_b_jm1.val) + fabs(r_b_j.err/r_b_j.val)));
146     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
147
148     return GSL_ERROR_SELECT_2(stat_0, stat_1);
149   }
150 }
151
152
153 int gsl_sf_bessel_Kn_e(const int n, const double x, gsl_sf_result * result)
154 {
155   const int status = gsl_sf_bessel_Kn_scaled_e(n, x, result);
156   const double ex = exp(-x);
157   result->val *= ex;
158   result->err *= ex;
159   result->err += x * GSL_DBL_EPSILON * fabs(result->val);
160   return status;
161 }
162
163
164 int gsl_sf_bessel_Kn_scaled_array(const int nmin, const int nmax, const double x, double * result_array)
165 {
166   /* CHECK_POINTER(result_array) */
167
168   if(nmin < 0 || nmax < nmin || x <= 0.0) {
169     int j;
170     for(j=0; j<=nmax-nmin; j++) result_array[j] = 0.0;
171     GSL_ERROR ("domain error", GSL_EDOM);
172   }
173   else if(nmax == 0) {
174     gsl_sf_result b;
175     int stat = gsl_sf_bessel_K0_scaled_e(x, &b);
176     result_array[0] = b.val;
177     return stat;
178   }
179   else {
180     double two_over_x = 2.0/x;
181     gsl_sf_result r_Knm1;
182     gsl_sf_result r_Kn;
183     int stat_0 = gsl_sf_bessel_Kn_scaled_e(nmin,   x, &r_Knm1);
184     int stat_1 = gsl_sf_bessel_Kn_scaled_e(nmin+1, x, &r_Kn);
185     int stat = GSL_ERROR_SELECT_2(stat_0, stat_1);
186     double Knp1;
187     double Kn   = r_Kn.val;
188     double Knm1 = r_Knm1.val;
189     int n;
190
191     for(n=nmin+1; n<=nmax+1; n++) {
192       if(Knm1 < GSL_DBL_MAX) {
193         result_array[n-1-nmin] = Knm1;
194         Knp1 = Knm1 + n * two_over_x * Kn;
195         Knm1 = Kn;
196         Kn   = Knp1;
197       }
198       else {
199         /* Overflow. Set the rest of the elements to
200          * zero and bug out.
201          * FIXME: Note: this relies on the convention
202          * that the test x < DBL_MIN fails for x not
203          * a number. This may be only an IEEE convention,
204          * so the portability is unclear.
205          */
206         int j;
207         for(j=n; j<=nmax+1; j++) result_array[j-1-nmin] = 0.0;
208         GSL_ERROR ("overflow", GSL_EOVRFLW);
209       }
210     }
211
212     return stat;
213   }
214 }
215
216
217 int
218 gsl_sf_bessel_Kn_array(const int nmin, const int nmax, const double x, double * result_array)
219 {
220   int status = gsl_sf_bessel_Kn_scaled_array(nmin, nmax, x, result_array);
221   double ex = exp(-x);
222   int i;
223   for(i=0; i<=nmax-nmin; i++) result_array[i] *= ex;
224   return status;
225 }
226
227
228 /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
229
230 #include "eval.h"
231
232 double gsl_sf_bessel_Kn_scaled(const int n, const double x)
233 {
234   EVAL_RESULT(gsl_sf_bessel_Kn_scaled_e(n, x, &result));
235 }
236
237 double gsl_sf_bessel_Kn(const int n, const double x)
238 {
239   EVAL_RESULT(gsl_sf_bessel_Kn_e(n, x, &result));
240 }