Blame specfunc/bessel_K1.c

Packit 67cb25
/* specfunc/bessel_K1.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
Packit 67cb25
 * Copyright (C) 2016 Pavel Holoborodko, Patrick Alken
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
/* Author:  G. Jungman */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_poly.h>
Packit 67cb25
#include <gsl/gsl_sf_exp.h>
Packit 67cb25
#include <gsl/gsl_sf_bessel.h>
Packit 67cb25
Packit 67cb25
#include "error.h"
Packit 67cb25
Packit 67cb25
#include "chebyshev.h"
Packit 67cb25
#include "cheb_eval.c"
Packit 67cb25
Packit 67cb25
/*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 Minimax rational approximation for [0,1), peak relative error = 1.83*GSL_DBL_EPSILON.
Packit 67cb25
 Source: http://www.advanpix.com/?p=3987
Packit 67cb25
*/
Packit 67cb25
static double k1_poly[9] = {
Packit 67cb25
  -3.0796575782920622440538935e-01,
Packit 67cb25
  -8.5370719728650778045782736e-02,
Packit 67cb25
  -4.6421827664715603298154971e-03,
Packit 67cb25
  -1.1253607036630425931072996e-04,
Packit 67cb25
  -1.5592887702110907110292728e-06,
Packit 67cb25
  -1.4030163679125934402498239e-08,
Packit 67cb25
  -8.8718998640336832196558868e-11,
Packit 67cb25
  -4.1614323580221539328960335e-13,
Packit 67cb25
  -1.5261293392975541707230366e-15
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static double i1_poly[7] = {
Packit 67cb25
  8.3333333333333325191635191e-02,
Packit 67cb25
  6.9444444444467956461838830e-03,
Packit 67cb25
  3.4722222211230452695165215e-04,
Packit 67cb25
  1.1574075952009842696580084e-05,
Packit 67cb25
  2.7555870002088181016676934e-07,
Packit 67cb25
  4.9724386164128529514040614e-09
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 Chebyshev expansion for [1,8], peak relative error = 1.28*GSL_DBL_EPSILON. 
Packit 67cb25
 Source: Pavel Holoborodko.
Packit 67cb25
*/
Packit 67cb25
static double ak1_data[25] = {
Packit 67cb25
  +2.07996868001418246e-01,
Packit 67cb25
  +1.62581565017881476e-01,
Packit 67cb25
  -5.87070423518863640e-03,
Packit 67cb25
  +4.95021520115789501e-04,
Packit 67cb25
  -5.78958347598556986e-05,
Packit 67cb25
  +8.18614610209334726e-06,
Packit 67cb25
  -1.31604832009487277e-06,
Packit 67cb25
  +2.32546031520101213e-07,
Packit 67cb25
  -4.42206518311557987e-08,
Packit 67cb25
  +8.92163994883100361e-09,
Packit 67cb25
  -1.89046270526983427e-09,
Packit 67cb25
  +4.17568808108504702e-10,
Packit 67cb25
  -9.55912361791375794e-11,
Packit 67cb25
  +2.25769353153867758e-11,
Packit 67cb25
  -5.48128000211158482e-12,
Packit 67cb25
  +1.36386122546441926e-12,
Packit 67cb25
  -3.46936690565986409e-13,
Packit 67cb25
  +9.00354564415705942e-14,
Packit 67cb25
  -2.37950577776254432e-14,
Packit 67cb25
  +6.39447503964025336e-15,
Packit 67cb25
  -1.74498363492322044e-15,
Packit 67cb25
  +4.82994547989290473e-16,
Packit 67cb25
  -1.35460927805445606e-16,
Packit 67cb25
  +3.84604274446777234e-17,
Packit 67cb25
  -1.10456856122581316e-17
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static cheb_series ak1_cs = {
Packit 67cb25
  ak1_data,
Packit 67cb25
  24,
Packit 67cb25
  -1, 1,
Packit 67cb25
  9
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/* 
Packit 67cb25
 Chebyshev expansion for [8,inf), peak relative error = 1.25*GSL_DBL_EPSILON.
Packit 67cb25
 Source: SLATEC/dbsk1e.f
Packit 67cb25
*/
Packit 67cb25
static double ak12_data[14] = {
Packit 67cb25
  +.637930834373900104E-1,
Packit 67cb25
  +.283288781304972094E-1,
Packit 67cb25
  -.247537067390525035E-3,
Packit 67cb25
  +.577197245160724882E-5,
Packit 67cb25
  -.206893921953654830E-6,
Packit 67cb25
  +.973998344138180418E-8,
Packit 67cb25
  -.558533614038062498E-9,
Packit 67cb25
  +.373299663404618524E-10,
Packit 67cb25
  -.282505196102322545E-11,
Packit 67cb25
  +.237201900248414417E-12,
Packit 67cb25
  -.217667738799175398E-13,
Packit 67cb25
  +.215791416161603245E-14,
Packit 67cb25
  -.229019693071826928E-15,
Packit 67cb25
  +.258288572982327496E-16
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static cheb_series ak12_cs = {
Packit 67cb25
  ak12_data,
Packit 67cb25
  13,
Packit 67cb25
  -1, 1,
Packit 67cb25
  7
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
Packit 67cb25
/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
Packit 67cb25
Packit 67cb25
int gsl_sf_bessel_K1_scaled_e(const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  /* CHECK_POINTER(result) */
Packit 67cb25
Packit 67cb25
  if(x <= 0.0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(x < 2.0*GSL_DBL_MIN) {
Packit 67cb25
    OVERFLOW_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(x < 1.0) {
Packit 67cb25
    const double lx = log(x);
Packit 67cb25
    const double ex = exp(x);
Packit 67cb25
    const double x2 = x*x;
Packit 67cb25
    const double t  = 0.25*x2;    
Packit 67cb25
    const double i1 = 0.5 * x * (1.0 + t * (0.5 + t * gsl_poly_eval(i1_poly,6,t)));
Packit 67cb25
    result->val  = ex * (x2 * gsl_poly_eval(k1_poly,9,x2) + x * lx * i1 + 1) / x;
Packit 67cb25
    result->err  = ex * (1.6+fabs(lx)*0.6) * GSL_DBL_EPSILON;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(x <= 8.0) {
Packit 67cb25
    const double sx = sqrt(x);
Packit 67cb25
    gsl_sf_result c;
Packit 67cb25
    cheb_eval_e(&ak1_cs, (16.0/x-9.0)/7.0, &c);
Packit 67cb25
    result->val  = (1.375 + c.val) / sx; /* 1.375 = 11/8 */
Packit 67cb25
    result->err  = c.err / sx;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    const double sx = sqrt(x);
Packit 67cb25
    gsl_sf_result c;
Packit 67cb25
    cheb_eval_e(&ak12_cs, 16.0/x-1.0, &c);
Packit 67cb25
    result->val  = (1.25 + c.val) / sx;
Packit 67cb25
    result->err  = c.err / sx;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_bessel_K1_e(const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  /* CHECK_POINTER(result) */
Packit 67cb25
Packit 67cb25
  if(x <= 0.0) {
Packit 67cb25
    DOMAIN_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(x < 2.0*GSL_DBL_MIN) {
Packit 67cb25
    OVERFLOW_ERROR(result);
Packit 67cb25
  }
Packit 67cb25
  else if(x < 1.0) {
Packit 67cb25
    const double lx = log(x);
Packit 67cb25
    const double x2 = x*x;
Packit 67cb25
    const double t  = 0.25*x2;    
Packit 67cb25
    const double i1 = 0.5 * x * (1.0 + t * (0.5 + t * gsl_poly_eval(i1_poly,6,t)));
Packit 67cb25
    result->val  = (x2 * gsl_poly_eval(k1_poly,9,x2) + x * lx * i1 + 1) / x;
Packit 67cb25
    result->err  = (1.6+fabs(lx)*0.6) * GSL_DBL_EPSILON;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;      
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    gsl_sf_result K1_scaled;
Packit 67cb25
    int stat_K1 = gsl_sf_bessel_K1_scaled_e(x, &K1_scaled);
Packit 67cb25
    int stat_e  = gsl_sf_exp_mult_err_e(-x, 0.0,
Packit 67cb25
                                           K1_scaled.val, K1_scaled.err,
Packit 67cb25
                                           result);
Packit 67cb25
    result->err = fabs(result->val) * (GSL_DBL_EPSILON*fabs(x) + K1_scaled.err/K1_scaled.val);
Packit 67cb25
    return GSL_ERROR_SELECT_2(stat_e, stat_K1);
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
Packit 67cb25
Packit 67cb25
#include "eval.h"
Packit 67cb25
Packit 67cb25
double gsl_sf_bessel_K1_scaled(const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_bessel_K1_scaled_e(x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double gsl_sf_bessel_K1(const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_bessel_K1_e(x, &result));
Packit 67cb25
}