Added script front-end for primer-design code
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / specfunc / bessel_k.c
1 /* specfunc/bessel_k.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_pow_int.h>
26 #include <gsl/gsl_sf_gamma.h>
27 #include <gsl/gsl_sf_bessel.h>
28
29 #include "error.h"
30 #include "check.h"
31
32 #include "bessel.h"
33
34 /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
35
36 /* [Abramowitz+Stegun, 10.2.4 + 10.2.6]
37  * with lmax=15, precision ~ 15D for x < 3
38  *
39  * assumes l >= 1
40  */
41 static int bessel_kl_scaled_small_x(int l, const double x, gsl_sf_result * result)
42 {
43   gsl_sf_result num_fact;
44   double den  = gsl_sf_pow_int(x, l+1);
45   int stat_df = gsl_sf_doublefact_e((unsigned int) (2*l-1), &num_fact);
46
47   if(stat_df != GSL_SUCCESS || den == 0.0) {
48     OVERFLOW_ERROR(result);
49   }
50   else {
51     const int lmax = 50;
52     gsl_sf_result ipos_term;
53     double ineg_term;
54     double sgn = (GSL_IS_ODD(l) ? -1.0 : 1.0);
55     double ex  = exp(x);
56     double t = 0.5*x*x;
57     double sum = 1.0;
58     double t_coeff = 1.0;
59     double t_power = 1.0;
60     double delta;
61     int stat_il;
62     int i;
63
64     for(i=1; i<lmax; i++) {
65       t_coeff /= i*(2*(i-l) - 1);
66       t_power *= t;
67       delta = t_power*t_coeff;
68       sum += delta;
69       if(fabs(delta/sum) < GSL_DBL_EPSILON) break;
70     }
71
72     stat_il = gsl_sf_bessel_il_scaled_e(l, x, &ipos_term);
73     ineg_term =  sgn * num_fact.val/den * sum;
74     result->val = -sgn * 0.5*M_PI * (ex*ipos_term.val - ineg_term);
75     result->val *= ex;
76     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
77     return stat_il;
78   }
79 }
80
81
82 /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
83
84 int gsl_sf_bessel_k0_scaled_e(const double x, gsl_sf_result * result)
85 {
86   /* CHECK_POINTER(result) */
87
88   if(x <= 0.0) {
89     DOMAIN_ERROR(result);
90   }
91   else {
92     result->val = M_PI/(2.0*x);
93     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
94     CHECK_UNDERFLOW(result);
95     return GSL_SUCCESS;
96   }
97 }
98
99
100 int gsl_sf_bessel_k1_scaled_e(const double x, gsl_sf_result * result)
101 {
102   /* CHECK_POINTER(result) */
103
104   if(x <= 0.0) {
105     DOMAIN_ERROR(result);
106   }
107   else if(x < (M_SQRTPI+1.0)/(M_SQRT2*GSL_SQRT_DBL_MAX)) {
108     OVERFLOW_ERROR(result);
109   }
110   else {
111     result->val = M_PI/(2.0*x) * (1.0 + 1.0/x);
112     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
113     CHECK_UNDERFLOW(result);
114     return GSL_SUCCESS;
115   }
116 }
117
118
119 int gsl_sf_bessel_k2_scaled_e(const double x, gsl_sf_result * result)
120 {
121   /* CHECK_POINTER(result) */
122
123   if(x <= 0.0) {
124     DOMAIN_ERROR(result);
125   }
126   else if(x < 2.0/GSL_ROOT3_DBL_MAX) {
127     OVERFLOW_ERROR(result);
128   }
129   else {
130     result->val = M_PI/(2.0*x) * (1.0 + 3.0/x * (1.0 + 1.0/x));
131     result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
132     CHECK_UNDERFLOW(result);
133     return GSL_SUCCESS;
134   }
135 }
136
137
138 int gsl_sf_bessel_kl_scaled_e(int l, const double x, gsl_sf_result * result)
139 {
140   if(l < 0 || x <= 0.0) {
141     DOMAIN_ERROR(result);
142   }
143   else if(l == 0) {
144     return gsl_sf_bessel_k0_scaled_e(x, result);
145   }
146   else if(l == 1) {
147     return gsl_sf_bessel_k1_scaled_e(x, result);
148   }
149   else if(l == 2) {
150     return gsl_sf_bessel_k2_scaled_e(x, result);
151   }
152   else if(x < 3.0) {
153     return bessel_kl_scaled_small_x(l, x, result);
154   }
155   else if(GSL_ROOT3_DBL_EPSILON * x > (l*l + l + 1)) {
156     int status = gsl_sf_bessel_Knu_scaled_asympx_e(l + 0.5, x, result);
157     double pre = sqrt((0.5*M_PI)/x);
158     result->val *= pre;
159     result->err *= pre;
160     return status;
161   }
162   else if(GSL_MIN(0.29/(l*l+1.0), 0.5/(l*l+1.0+x*x)) < GSL_ROOT3_DBL_EPSILON) {
163     int status = gsl_sf_bessel_Knu_scaled_asymp_unif_e(l + 0.5, x, result);
164     double pre = sqrt((0.5*M_PI)/x);
165     result->val *= pre;
166     result->err *= pre;
167     return status;
168   }
169   else {
170     /* recurse upward */
171     gsl_sf_result r_bk;
172     gsl_sf_result r_bkm;
173     int stat_1 = gsl_sf_bessel_k1_scaled_e(x, &r_bk);
174     int stat_0 = gsl_sf_bessel_k0_scaled_e(x, &r_bkm);
175     double bkp;
176     double bk  = r_bk.val;
177     double bkm = r_bkm.val;
178     int j;
179     for(j=1; j<l; j++) { 
180       bkp = (2*j+1)/x*bk + bkm;
181       bkm = bk;
182       bk  = bkp;
183     }
184     result->val  = bk;
185     result->err  = fabs(bk) * (fabs(r_bk.err/r_bk.val) + fabs(r_bkm.err/r_bkm.val));
186     result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
187
188     return GSL_ERROR_SELECT_2(stat_1, stat_0);
189   }
190 }
191
192 int 
193 gsl_sf_bessel_kl_scaled_array(const int lmax, const double x, double * result_array)
194 {
195   if(lmax < 0 || x <= 0.0) {
196     GSL_ERROR("domain error", GSL_EDOM);
197   } else if (lmax == 0) {
198     gsl_sf_result result;
199     int stat = gsl_sf_bessel_k0_scaled_e(x, &result);
200     result_array[0] = result.val;
201     return stat;
202   } else {
203     int ell;
204     double kellp1, kell, kellm1;
205     gsl_sf_result r_kell;
206     gsl_sf_result r_kellm1;
207     gsl_sf_bessel_k1_scaled_e(x, &r_kell);
208     gsl_sf_bessel_k0_scaled_e(x, &r_kellm1);
209     kell   = r_kell.val;
210     kellm1 = r_kellm1.val;
211     result_array[0] = kellm1;
212     result_array[1] = kell;
213     for(ell = 1; ell < lmax; ell++) {
214       kellp1 = (2*ell+1)/x * kell + kellm1;
215       result_array[ell+1] = kellp1;
216       kellm1 = kell;
217       kell   = kellp1;
218     }
219     return GSL_SUCCESS;
220   }
221 }
222
223
224 /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
225
226 #include "eval.h"
227
228 double gsl_sf_bessel_k0_scaled(const double x)
229 {
230   EVAL_RESULT(gsl_sf_bessel_k0_scaled_e(x, &result));
231 }
232
233 double gsl_sf_bessel_k1_scaled(const double x)
234 {
235   EVAL_RESULT(gsl_sf_bessel_k1_scaled_e(x, &result));
236 }
237
238 double gsl_sf_bessel_k2_scaled(const double x)
239 {
240   EVAL_RESULT(gsl_sf_bessel_k2_scaled_e(x, &result));
241 }
242
243 double gsl_sf_bessel_kl_scaled(const int l, const double x)
244 {
245   EVAL_RESULT(gsl_sf_bessel_kl_scaled_e(l, x, &result));
246 }
247
248