Added MACS source
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / specfunc / bessel_Yn.c
1 /* specfunc/bessel_Yn.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 #include "bessel_amp_phase.h"
33 #include "bessel_olver.h"
34
35 /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
36
37 /* assumes n >= 1 */
38 static int bessel_Yn_small_x(const int n, const double x, gsl_sf_result * result)
39 {
40   int k;
41   double y = 0.25 * x * x;
42   double ln_x_2 = log(0.5*x);
43   gsl_sf_result ln_nm1_fact;
44   double k_term;
45   double term1, sum1, ln_pre1;
46   double term2, sum2, pre2;
47
48   gsl_sf_lnfact_e((unsigned int)(n-1), &ln_nm1_fact);
49
50   ln_pre1 = -n*ln_x_2 + ln_nm1_fact.val;
51   if(ln_pre1 > GSL_LOG_DBL_MAX - 3.0) GSL_ERROR ("error", GSL_EOVRFLW);
52
53   sum1 = 1.0;
54   k_term = 1.0;
55   for(k=1; k<=n-1; k++) {
56     k_term *= y/(k * (n-k));
57     sum1 += k_term;
58   }
59   term1 = -exp(ln_pre1) * sum1 / M_PI;
60   
61   pre2 = -exp(n*ln_x_2) / M_PI;
62   if(fabs(pre2) > 0.0) {
63     const int KMAX = 20;
64     gsl_sf_result psi_n;
65     gsl_sf_result npk_fact;
66     double yk = 1.0;
67     double k_fact  = 1.0;
68     double psi_kp1 = -M_EULER;
69     double psi_npkp1;
70     gsl_sf_psi_int_e(n, &psi_n);
71     gsl_sf_fact_e((unsigned int)n, &npk_fact);
72     psi_npkp1 = psi_n.val + 1.0/n;
73     sum2 = (psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/npk_fact.val;
74     for(k=1; k<KMAX; k++) {
75       psi_kp1   += 1./k;
76       psi_npkp1 += 1./(n+k);
77       k_fact   *= k;
78       npk_fact.val *= n+k;
79       yk *= -y;
80       k_term = yk*(psi_kp1 + psi_npkp1 - 2.0*ln_x_2)/(k_fact*npk_fact.val);
81       sum2 += k_term;
82     }
83     term2 = pre2 * sum2;
84   }
85   else {
86     term2 = 0.0;
87   }
88
89   result->val  = term1 + term2;
90   result->err  = GSL_DBL_EPSILON * (fabs(ln_pre1)*fabs(term1) + fabs(term2));
91   result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
92
93   return GSL_SUCCESS;
94 }
95
96
97 /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
98
99
100 int
101 gsl_sf_bessel_Yn_e(int n, const double x, gsl_sf_result * result)
102 {
103   int sign = 1;
104
105   if(n < 0) {
106     /* reduce to case n >= 0 */
107     n = -n;
108     if(GSL_IS_ODD(n)) sign = -1;
109   }
110
111   /* CHECK_POINTER(result) */
112
113   if(n == 0) {
114     int status = gsl_sf_bessel_Y0_e(x, result);
115     result->val *= sign;
116     return status;
117   }
118   else if(n == 1) {
119     int status = gsl_sf_bessel_Y1_e(x, result);
120     result->val *= sign;
121     return status;
122   }
123   else {
124     if(x <= 0.0) {
125       DOMAIN_ERROR(result);
126     }
127     if(x < 5.0) {
128       int status = bessel_Yn_small_x(n, x, result);
129       result->val *= sign;
130       return status;
131     }
132     else if(GSL_ROOT3_DBL_EPSILON * x > (n*n + 1.0)) {
133       int status = gsl_sf_bessel_Ynu_asympx_e((double)n, x, result);
134       result->val *= sign;
135       return status;
136     }
137     else if(n > 50) {
138       int status = gsl_sf_bessel_Ynu_asymp_Olver_e((double)n, x, result);
139       result->val *= sign;
140       return status;
141     }
142     else {
143       double two_over_x = 2.0/x;
144       gsl_sf_result r_by;
145       gsl_sf_result r_bym;
146       int stat_1 = gsl_sf_bessel_Y1_e(x, &r_by);
147       int stat_0 = gsl_sf_bessel_Y0_e(x, &r_bym);
148       double bym = r_bym.val;
149       double by  = r_by.val;
150       double byp;
151       int j;
152
153       for(j=1; j<n; j++) { 
154         byp = j*two_over_x*by - bym;
155         bym = by;
156         by  = byp;
157       }
158       result->val  = sign * by;
159       result->err  = fabs(result->val) * (fabs(r_by.err/r_by.val) + fabs(r_bym.err/r_bym.val));
160       result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
161
162       return GSL_ERROR_SELECT_2(stat_1, stat_0);
163     }
164   }
165 }
166
167
168 int
169 gsl_sf_bessel_Yn_array(const int nmin, const int nmax, const double x, double * result_array)
170 {
171   /* CHECK_POINTER(result_array) */
172
173   if(nmin < 0 || nmax < nmin || x <= 0.0) {
174     int j;
175     for(j=0; j<=nmax-nmin; j++) result_array[j] = 0.0;
176     GSL_ERROR ("error", GSL_EDOM);
177   }
178   else {
179     gsl_sf_result r_Ynm1;
180     gsl_sf_result r_Yn;
181     int stat_nm1 = gsl_sf_bessel_Yn_e(nmin,   x, &r_Ynm1);
182     int stat_n   = gsl_sf_bessel_Yn_e(nmin+1, x, &r_Yn);
183     double Ynp1;
184     double Yn   = r_Yn.val;
185     double Ynm1 = r_Ynm1.val;
186     int n;
187
188     int stat = GSL_ERROR_SELECT_2(stat_nm1, stat_n);
189
190     if(stat == GSL_SUCCESS) {
191       for(n=nmin+1; n<=nmax+1; n++) {
192         result_array[n-nmin-1] = Ynm1;
193         Ynp1 = -Ynm1 + 2.0*n/x * Yn;
194         Ynm1 = Yn;
195         Yn   = Ynp1;
196       }
197     }
198     else {
199       for(n=nmin; n<=nmax; n++) {
200         result_array[n-nmin] = 0.0;
201       }
202     }
203
204     return stat;
205   }
206 }
207
208
209 /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
210
211 #include "eval.h"
212
213 double gsl_sf_bessel_Yn(const int n, const double x)
214 {
215   EVAL_RESULT(gsl_sf_bessel_Yn_e(n, x, &result));
216 }
217