1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/* specfunc/bessel_Ynu.c
*
* Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman, 2017 Konrad Griessinger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* Author: G. Jungman */
#include <config.h>
#include <gsl/gsl_math.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_sf_bessel.h>
#include <gsl/gsl_sf_sincos_pi.h>
#include "error.h"
#include "bessel.h"
#include "bessel_olver.h"
#include "bessel_temme.h"
/* Perform forward recurrence for Y_nu(x) and Y'_nu(x)
*
* Y_{nu+1} = nu/x Y_nu - Y'_nu
* Y'_{nu+1} = -(nu+1)/x Y_{nu+1} + Y_nu
*/
#if 0
static
int
bessel_Y_recur(const double nu_min, const double x, const int kmax,
const double Y_start, const double Yp_start,
double * Y_end, double * Yp_end)
{
double x_inv = 1.0/x;
double nu = nu_min;
double Y_nu = Y_start;
double Yp_nu = Yp_start;
int k;
for(k=1; k<=kmax; k++) {
double nuox = nu*x_inv;
double Y_nu_save = Y_nu;
Y_nu = -Yp_nu + nuox * Y_nu;
Yp_nu = Y_nu_save - (nuox+x_inv) * Y_nu;
nu += 1.0;
}
*Y_end = Y_nu;
*Yp_end = Yp_nu;
return GSL_SUCCESS;
}
#endif
/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
int
gsl_sf_bessel_Ynupos_e(double nu, double x, gsl_sf_result * result)
{
/* CHECK_POINTER(result) */
if(nu > 50.0) {
return gsl_sf_bessel_Ynu_asymp_Olver_e(nu, x, result);
}
else {
/* -1/2 <= mu <= 1/2 */
int N = (int)(nu + 0.5);
double mu = nu - N;
gsl_sf_result Y_mu, Y_mup1;
int stat_mu;
double Ynm1;
double Yn;
double Ynp1;
int n;
if(x < 2.0) {
/* Determine Ymu, Ymup1 directly. This is really
* an optimization since this case could as well
* be handled by a call to gsl_sf_bessel_JY_mu_restricted(),
* as below.
*/
stat_mu = gsl_sf_bessel_Y_temme(mu, x, &Y_mu, &Y_mup1);
}
else {
/* Determine Ymu, Ymup1 and Jmu, Jmup1.
*/
gsl_sf_result J_mu, J_mup1;
stat_mu = gsl_sf_bessel_JY_mu_restricted(mu, x, &J_mu, &J_mup1, &Y_mu, &Y_mup1);
}
/* Forward recursion to get Ynu, Ynup1.
*/
Ynm1 = Y_mu.val;
Yn = Y_mup1.val;
for(n=1; n<=N; n++) {
Ynp1 = 2.0*(mu+n)/x * Yn - Ynm1;
Ynm1 = Yn;
Yn = Ynp1;
}
result->val = Ynm1; /* Y_nu */
result->err = (N + 1.0) * fabs(Ynm1) * (fabs(Y_mu.err/Y_mu.val) + fabs(Y_mup1.err/Y_mup1.val));
result->err += 2.0 * GSL_DBL_EPSILON * fabs(Ynm1);
return stat_mu;
}
}
int
gsl_sf_bessel_Ynu_e(double nu, double x, gsl_sf_result * result)
{
/* CHECK_POINTER(result) */
if(x <= 0.0) {
DOMAIN_ERROR(result);
}
else if (nu < 0.0) {
int Jstatus = gsl_sf_bessel_Jnupos_e(-nu, x, result);
double Jval = result->val;
double Jerr = result->err;
int Ystatus = gsl_sf_bessel_Ynupos_e(-nu, x, result);
double Yval = result->val;
double Yerr = result->err;
/* double s = sin(M_PI*nu), c = cos(M_PI*nu); */
int sinstatus = gsl_sf_sin_pi_e(nu, result);
double s = result->val;
double serr = result->err;
int cosstatus = gsl_sf_cos_pi_e(nu, result);
double c = result->val;
double cerr = result->err;
result->val = c*Yval - s*Jval;
result->err = fabs(c*Yerr) + fabs(s*Jerr) + fabs(cerr*Yval) + fabs(serr*Jval);
return GSL_ERROR_SELECT_4(Jstatus, Ystatus, sinstatus, cosstatus);
}
else return gsl_sf_bessel_Ynupos_e(nu, x, result);
}
/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
#include "eval.h"
double gsl_sf_bessel_Ynu(const double nu, const double x)
{
EVAL_RESULT(gsl_sf_bessel_Ynu_e(nu, x, &result));
}
|