Blame specfunc/sinint.c

Packit 67cb25
/* specfunc/sinint.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
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_sf_trig.h>
Packit 67cb25
#include <gsl/gsl_sf_expint.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
/* based on SLATEC r9sifg.f, W. Fullerton */
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 series for f1   on the interval  2.00000e-02 to  6.25000e-02
Packit 67cb25
                                        with weighted error   2.82e-17
Packit 67cb25
                                         log weighted error  16.55
Packit 67cb25
                               significant figures required  15.36
Packit 67cb25
                                    decimal places required  17.20
Packit 67cb25
*/
Packit 67cb25
static double f1_data[20] = {
Packit 67cb25
   -0.1191081969051363610,
Packit 67cb25
   -0.0247823144996236248,
Packit 67cb25
    0.0011910281453357821,
Packit 67cb25
   -0.0000927027714388562,
Packit 67cb25
    0.0000093373141568271,
Packit 67cb25
   -0.0000011058287820557,
Packit 67cb25
    0.0000001464772071460,
Packit 67cb25
   -0.0000000210694496288,
Packit 67cb25
    0.0000000032293492367,
Packit 67cb25
   -0.0000000005206529618,
Packit 67cb25
    0.0000000000874878885,
Packit 67cb25
   -0.0000000000152176187,
Packit 67cb25
    0.0000000000027257192,
Packit 67cb25
   -0.0000000000005007053,
Packit 67cb25
    0.0000000000000940241,
Packit 67cb25
   -0.0000000000000180014,
Packit 67cb25
    0.0000000000000035063,
Packit 67cb25
   -0.0000000000000006935,
Packit 67cb25
    0.0000000000000001391,
Packit 67cb25
   -0.0000000000000000282
Packit 67cb25
};
Packit 67cb25
static cheb_series f1_cs = {
Packit 67cb25
  f1_data,
Packit 67cb25
  19,
Packit 67cb25
  -1, 1,
Packit 67cb25
  10
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
Packit 67cb25
 series for f2   on the interval  0.00000e+00 to  2.00000e-02
Packit 67cb25
                                        with weighted error   4.32e-17
Packit 67cb25
                                         log weighted error  16.36
Packit 67cb25
                               significant figures required  14.75
Packit 67cb25
                                    decimal places required  17.10
Packit 67cb25
*/
Packit 67cb25
static double f2_data[29] = {
Packit 67cb25
   -0.0348409253897013234,
Packit 67cb25
   -0.0166842205677959686,
Packit 67cb25
    0.0006752901241237738,
Packit 67cb25
   -0.0000535066622544701,
Packit 67cb25
    0.0000062693421779007,
Packit 67cb25
   -0.0000009526638801991,
Packit 67cb25
    0.0000001745629224251,
Packit 67cb25
   -0.0000000368795403065,
Packit 67cb25
    0.0000000087202677705,
Packit 67cb25
   -0.0000000022601970392,
Packit 67cb25
    0.0000000006324624977,
Packit 67cb25
   -0.0000000001888911889,
Packit 67cb25
    0.0000000000596774674,
Packit 67cb25
   -0.0000000000198044313,
Packit 67cb25
    0.0000000000068641396,
Packit 67cb25
   -0.0000000000024731020,
Packit 67cb25
    0.0000000000009226360,
Packit 67cb25
   -0.0000000000003552364,
Packit 67cb25
    0.0000000000001407606,
Packit 67cb25
   -0.0000000000000572623,
Packit 67cb25
    0.0000000000000238654,
Packit 67cb25
   -0.0000000000000101714,
Packit 67cb25
    0.0000000000000044259,
Packit 67cb25
   -0.0000000000000019634,
Packit 67cb25
    0.0000000000000008868,
Packit 67cb25
   -0.0000000000000004074,
Packit 67cb25
    0.0000000000000001901,
Packit 67cb25
   -0.0000000000000000900,
Packit 67cb25
    0.0000000000000000432
Packit 67cb25
};
Packit 67cb25
static cheb_series f2_cs = {
Packit 67cb25
  f2_data,
Packit 67cb25
  28,
Packit 67cb25
  -1, 1,
Packit 67cb25
  14
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
Packit 67cb25
 series for g1   on the interval  2.00000e-02 to  6.25000e-02
Packit 67cb25
                                        with weighted error   5.48e-17
Packit 67cb25
                                         log weighted error  16.26
Packit 67cb25
                               significant figures required  15.47
Packit 67cb25
                                    decimal places required  16.92
Packit 67cb25
*/
Packit 67cb25
static double g1_data[21] = {
Packit 67cb25
   -0.3040578798253495954,
Packit 67cb25
   -0.0566890984597120588,
Packit 67cb25
    0.0039046158173275644,
Packit 67cb25
   -0.0003746075959202261,
Packit 67cb25
    0.0000435431556559844,
Packit 67cb25
   -0.0000057417294453025,
Packit 67cb25
    0.0000008282552104503,
Packit 67cb25
   -0.0000001278245892595,
Packit 67cb25
    0.0000000207978352949,
Packit 67cb25
   -0.0000000035313205922,
Packit 67cb25
    0.0000000006210824236,
Packit 67cb25
   -0.0000000001125215474,
Packit 67cb25
    0.0000000000209088918,
Packit 67cb25
   -0.0000000000039715832,
Packit 67cb25
    0.0000000000007690431,
Packit 67cb25
   -0.0000000000001514697,
Packit 67cb25
    0.0000000000000302892,
Packit 67cb25
   -0.0000000000000061400,
Packit 67cb25
    0.0000000000000012601,
Packit 67cb25
   -0.0000000000000002615,
Packit 67cb25
    0.0000000000000000548
Packit 67cb25
};
Packit 67cb25
static cheb_series g1_cs = {
Packit 67cb25
  g1_data,
Packit 67cb25
  20,
Packit 67cb25
  -1, 1,
Packit 67cb25
  13
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
Packit 67cb25
 series for g2   on the interval  0.00000e+00 to  2.00000e-02
Packit 67cb25
                                        with weighted error   5.01e-17
Packit 67cb25
                                         log weighted error  16.30
Packit 67cb25
                               significant figures required  15.12
Packit 67cb25
                                    decimal places required  17.07
Packit 67cb25
*/
Packit 67cb25
static double g2_data[34] = {
Packit 67cb25
   -0.0967329367532432218,
Packit 67cb25
   -0.0452077907957459871,
Packit 67cb25
    0.0028190005352706523,
Packit 67cb25
   -0.0002899167740759160,
Packit 67cb25
    0.0000407444664601121,
Packit 67cb25
   -0.0000071056382192354,
Packit 67cb25
    0.0000014534723163019,
Packit 67cb25
   -0.0000003364116512503,
Packit 67cb25
    0.0000000859774367886,
Packit 67cb25
   -0.0000000238437656302,
Packit 67cb25
    0.0000000070831906340,
Packit 67cb25
   -0.0000000022318068154,
Packit 67cb25
    0.0000000007401087359,
Packit 67cb25
   -0.0000000002567171162,
Packit 67cb25
    0.0000000000926707021,
Packit 67cb25
   -0.0000000000346693311,
Packit 67cb25
    0.0000000000133950573,
Packit 67cb25
   -0.0000000000053290754,
Packit 67cb25
    0.0000000000021775312,
Packit 67cb25
   -0.0000000000009118621,
Packit 67cb25
    0.0000000000003905864,
Packit 67cb25
   -0.0000000000001708459,
Packit 67cb25
    0.0000000000000762015,
Packit 67cb25
   -0.0000000000000346151,
Packit 67cb25
    0.0000000000000159996,
Packit 67cb25
   -0.0000000000000075213,
Packit 67cb25
    0.0000000000000035970,
Packit 67cb25
   -0.0000000000000017530,
Packit 67cb25
    0.0000000000000008738,
Packit 67cb25
   -0.0000000000000004487,
Packit 67cb25
    0.0000000000000002397,
Packit 67cb25
   -0.0000000000000001347,
Packit 67cb25
    0.0000000000000000801,
Packit 67cb25
   -0.0000000000000000501
Packit 67cb25
};
Packit 67cb25
static cheb_series g2_cs = {
Packit 67cb25
  g2_data,
Packit 67cb25
  33,
Packit 67cb25
  -1, 1,
Packit 67cb25
  20
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* x >= 4.0 */
Packit 67cb25
static void fg_asymp(const double x, gsl_sf_result * f, gsl_sf_result * g)
Packit 67cb25
{
Packit 67cb25
  /*
Packit 67cb25
      xbig = sqrt (1.0/r1mach(3))
Packit 67cb25
      xmaxf = exp (amin1(-alog(r1mach(1)), alog(r1mach(2))) - 0.01)
Packit 67cb25
      xmaxg = 1.0/sqrt(r1mach(1))
Packit 67cb25
      xbnd = sqrt(50.0)
Packit 67cb25
  */
Packit 67cb25
  const double xbig  = 1.0/GSL_SQRT_DBL_EPSILON;
Packit 67cb25
  const double xmaxf = 1.0/GSL_DBL_MIN;
Packit 67cb25
  const double xmaxg = 1.0/GSL_SQRT_DBL_MIN;
Packit 67cb25
  const double xbnd  = 7.07106781187;
Packit 67cb25
Packit 67cb25
  const double x2 = x*x;
Packit 67cb25
Packit 67cb25
  if(x <= xbnd) {
Packit 67cb25
    gsl_sf_result result_c1;
Packit 67cb25
    gsl_sf_result result_c2;
Packit 67cb25
    cheb_eval_e(&f1_cs, (1.0/x2-0.04125)/0.02125, &result_c1);
Packit 67cb25
    cheb_eval_e(&g1_cs, (1.0/x2-0.04125)/0.02125, &result_c2);
Packit 67cb25
    f->val = (1.0 + result_c1.val)/x;
Packit 67cb25
    g->val = (1.0 + result_c2.val)/x2;
Packit 67cb25
    f->err = result_c1.err/x  + 2.0 * GSL_DBL_EPSILON * fabs(f->val);
Packit 67cb25
    g->err = result_c2.err/x2 + 2.0 * GSL_DBL_EPSILON * fabs(g->val);
Packit 67cb25
  }
Packit 67cb25
  else if(x <= xbig) {
Packit 67cb25
    gsl_sf_result result_c1;
Packit 67cb25
    gsl_sf_result result_c2;
Packit 67cb25
    cheb_eval_e(&f2_cs, 100.0/x2-1.0, &result_c1);
Packit 67cb25
    cheb_eval_e(&g2_cs, 100.0/x2-1.0, &result_c2);
Packit 67cb25
    f->val = (1.0 + result_c1.val)/x;
Packit 67cb25
    g->val = (1.0 + result_c2.val)/x2;
Packit 67cb25
    f->err = result_c1.err/x  + 2.0 * GSL_DBL_EPSILON * fabs(f->val);
Packit 67cb25
    g->err = result_c2.err/x2 + 2.0 * GSL_DBL_EPSILON * fabs(g->val);
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    f->val = (x < xmaxf ? 1.0/x  : 0.0);
Packit 67cb25
    g->val = (x < xmaxg ? 1.0/x2 : 0.0);
Packit 67cb25
    f->err = 2.0 * GSL_DBL_EPSILON * fabs(f->val);
Packit 67cb25
    g->err = 2.0 * GSL_DBL_EPSILON * fabs(g->val);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  return;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
/* based on SLATEC si.f, W. Fullerton
Packit 67cb25
Packit 67cb25
 series for si   on the interval  0.00000e+00 to  1.60000e+01
Packit 67cb25
                                        with weighted error   1.22e-17
Packit 67cb25
                                         log weighted error  16.91
Packit 67cb25
                               significant figures required  16.37
Packit 67cb25
                                    decimal places required  17.45
Packit 67cb25
*/
Packit 67cb25
Packit 67cb25
static double si_data[12] = {
Packit 67cb25
  -0.1315646598184841929,
Packit 67cb25
  -0.2776578526973601892,
Packit 67cb25
   0.0354414054866659180,
Packit 67cb25
  -0.0025631631447933978,
Packit 67cb25
   0.0001162365390497009,
Packit 67cb25
  -0.0000035904327241606,
Packit 67cb25
   0.0000000802342123706,
Packit 67cb25
  -0.0000000013562997693,
Packit 67cb25
   0.0000000000179440722,
Packit 67cb25
  -0.0000000000001908387,
Packit 67cb25
   0.0000000000000016670,
Packit 67cb25
  -0.0000000000000000122
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
static cheb_series si_cs = {
Packit 67cb25
  si_data,
Packit 67cb25
  11,
Packit 67cb25
  -1, 1,
Packit 67cb25
  9
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 series for ci   on the interval  0.00000e+00 to  1.60000e+01
Packit 67cb25
                                        with weighted error   1.94e-18
Packit 67cb25
                                         log weighted error  17.71
Packit 67cb25
                               significant figures required  17.74
Packit 67cb25
                                    decimal places required  18.27
Packit 67cb25
*/
Packit 67cb25
static double ci_data[13] = {
Packit 67cb25
   -0.34004281856055363156,
Packit 67cb25
   -1.03302166401177456807,
Packit 67cb25
    0.19388222659917082877,
Packit 67cb25
   -0.01918260436019865894,
Packit 67cb25
    0.00110789252584784967,
Packit 67cb25
   -0.00004157234558247209,
Packit 67cb25
    0.00000109278524300229,
Packit 67cb25
   -0.00000002123285954183,
Packit 67cb25
    0.00000000031733482164,
Packit 67cb25
   -0.00000000000376141548,
Packit 67cb25
    0.00000000000003622653,
Packit 67cb25
   -0.00000000000000028912,
Packit 67cb25
    0.00000000000000000194
Packit 67cb25
};
Packit 67cb25
static cheb_series ci_cs = {
Packit 67cb25
  ci_data,
Packit 67cb25
  12,
Packit 67cb25
  -1, 1,
Packit 67cb25
  9
Packit 67cb25
};
Packit 67cb25
Packit 67cb25
Packit 67cb25
/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
Packit 67cb25
Packit 67cb25
int gsl_sf_Si_e(const double x, gsl_sf_result * result)
Packit 67cb25
{
Packit 67cb25
  double ax = fabs(x);
Packit 67cb25
  
Packit 67cb25
  /* CHECK_POINTER(result) */
Packit 67cb25
Packit 67cb25
  if(ax < GSL_SQRT_DBL_EPSILON) {
Packit 67cb25
    result->val = x;
Packit 67cb25
    result->err = 0.0;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else if(ax <= 4.0) {
Packit 67cb25
    gsl_sf_result result_c;
Packit 67cb25
    cheb_eval_e(&si_cs, (x*x-8.0)*0.125, &result_c);
Packit 67cb25
    result->val  =  x * (0.75 + result_c.val);
Packit 67cb25
    result->err  = ax * result_c.err;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
  else {
Packit 67cb25
    /* Note there is no loss of precision
Packit 67cb25
     * here bcause of the leading constant.
Packit 67cb25
     */
Packit 67cb25
    gsl_sf_result f;
Packit 67cb25
    gsl_sf_result g;
Packit 67cb25
    fg_asymp(ax, &f, &g);
Packit 67cb25
    result->val  = 0.5 * M_PI - f.val*cos(ax) - g.val*sin(ax);
Packit 67cb25
    result->err  = f.err + g.err;
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    if(x < 0.0) result->val = -result->val;
Packit 67cb25
    return GSL_SUCCESS;
Packit 67cb25
  }
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
Packit 67cb25
int gsl_sf_Ci_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 <= 4.0) {
Packit 67cb25
    const double lx = log(x);
Packit 67cb25
    const double y  = (x*x-8.0)*0.125;
Packit 67cb25
    gsl_sf_result result_c;
Packit 67cb25
    cheb_eval_e(&ci_cs, y, &result_c);
Packit 67cb25
    result->val  = lx - 0.5 + result_c.val;
Packit 67cb25
    result->err  = 2.0 * GSL_DBL_EPSILON * (fabs(lx) + 0.5) + result_c.err;
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 sin_result;
Packit 67cb25
    gsl_sf_result cos_result;
Packit 67cb25
    int stat_sin = gsl_sf_sin_e(x, &sin_result);
Packit 67cb25
    int stat_cos = gsl_sf_cos_e(x, &cos_result);
Packit 67cb25
    gsl_sf_result f;
Packit 67cb25
    gsl_sf_result g;
Packit 67cb25
    fg_asymp(x, &f, &g);
Packit 67cb25
    result->val  = f.val*sin_result.val - g.val*cos_result.val;
Packit 67cb25
    result->err  = fabs(f.err*sin_result.val);
Packit 67cb25
    result->err += fabs(g.err*cos_result.val);
Packit 67cb25
    result->err += fabs(f.val*sin_result.err);
Packit 67cb25
    result->err += fabs(g.val*cos_result.err);
Packit 67cb25
    result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
Packit 67cb25
    return GSL_ERROR_SELECT_2(stat_sin, stat_cos);
Packit 67cb25
  }
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_Si(const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_Si_e(x, &result));
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double gsl_sf_Ci(const double x)
Packit 67cb25
{
Packit 67cb25
  EVAL_RESULT(gsl_sf_Ci_e(x, &result));
Packit 67cb25
}