⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trig.c

📁 多个常用的特殊函数的例子
💻 C
📖 第 1 页 / 共 2 页
字号:
/* specfunc/trig.c *  * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman *  * 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA. *//* Author:  G. Jungman */#include <config.h>#include <gsl/gsl_math.h>#include <gsl/gsl_errno.h>#include <gsl/gsl_sf_log.h>#include <gsl/gsl_sf_trig.h>#include "error.h"#include "chebyshev.h"#include "cheb_eval.c"/* sinh(x) series * double-precision for |x| < 1.0 */inlinestaticintsinh_series(const double x, double * result){  const double y = x*x;  const double c0 = 1.0/6.0;  const double c1 = 1.0/120.0;  const double c2 = 1.0/5040.0;  const double c3 = 1.0/362880.0;  const double c4 = 1.0/39916800.0;  const double c5 = 1.0/6227020800.0;  const double c6 = 1.0/1307674368000.0;  const double c7 = 1.0/355687428096000.0;  *result = x*(1.0 + y*(c0+y*(c1+y*(c2+y*(c3+y*(c4+y*(c5+y*(c6+y*c7))))))));  return GSL_SUCCESS;}/* cosh(x)-1 series * double-precision for |x| < 1.0 */inlinestaticintcosh_m1_series(const double x, double * result){  const double y = x*x;  const double c0 = 0.5;  const double c1 = 1.0/24.0;  const double c2 = 1.0/720.0;  const double c3 = 1.0/40320.0;  const double c4 = 1.0/3628800.0;  const double c5 = 1.0/479001600.0;  const double c6 = 1.0/87178291200.0;  const double c7 = 1.0/20922789888000.0;  const double c8 = 1.0/6402373705728000.0;  *result = y*(c0+y*(c1+y*(c2+y*(c3+y*(c4+y*(c5+y*(c6+y*(c7+y*c8))))))));  return GSL_SUCCESS;}/* Chebyshev expansion for f(t) = sinc((t+1)/2), -1 < t < 1 */static double sinc_data[17] = {  1.133648177811747875422, -0.532677564732557348781, -0.068293048346633177859,  0.033403684226353715020,  0.001485679893925747818, -0.000734421305768455295, -0.000016837282388837229,  0.000008359950146618018,  0.000000117382095601192, -0.000000058413665922724, -0.000000000554763755743,  0.000000000276434190426,  0.000000000001895374892, -0.000000000000945237101, -0.000000000000004900690,  0.000000000000002445383,  0.000000000000000009925};static cheb_series sinc_cs = {  sinc_data,  16,  -1, 1,  10};/* Chebyshev expansion for f(t) = g((t+1)Pi/8), -1<t<1 * g(x) = (sin(x)/x - 1)/(x*x) */static double sin_data[12] = {  -0.3295190160663511504173,   0.0025374284671667991990,   0.0006261928782647355874,  -4.6495547521854042157541e-06,  -5.6917531549379706526677e-07,   3.7283335140973803627866e-09,   3.0267376484747473727186e-10,  -1.7400875016436622322022e-12,  -1.0554678305790849834462e-13,   5.3701981409132410797062e-16,   2.5984137983099020336115e-17,  -1.1821555255364833468288e-19};static cheb_series sin_cs = {  sin_data,  11,  -1, 1,  11};/* Chebyshev expansion for f(t) = g((t+1)Pi/8), -1<t<1 * g(x) = (2(cos(x) - 1)/(x^2) + 1) / x^2 */static double cos_data[11] = {  0.165391825637921473505668118136, -0.00084852883845000173671196530195, -0.000210086507222940730213625768083,  1.16582269619760204299639757584e-6,  1.43319375856259870334412701165e-7, -7.4770883429007141617951330184e-10, -6.0969994944584252706997438007e-11,  2.90748249201909353949854872638e-13,  1.77126739876261435667156490461e-14, -7.6896421502815579078577263149e-17, -3.7363121133079412079201377318e-18};static cheb_series cos_cs = {  cos_data,  10,  -1, 1,  10};/*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*//* I would have prefered just using the library sin() function. * But after some experimentation I decided that there was * no good way to understand the error; library sin() is just a black box. * So we have to roll our own. */intgsl_sf_sin_e(double x, gsl_sf_result * result){  /* CHECK_POINTER(result) */  {    const double P1 = 7.85398125648498535156e-1;    const double P2 = 3.77489470793079817668e-8;    const double P3 = 2.69515142907905952645e-15;    const double sgn_x = GSL_SIGN(x);    const double abs_x = fabs(x);    if(abs_x < GSL_ROOT4_DBL_EPSILON) {      const double x2 = x*x;      result->val = x * (1.0 - x2/6.0);      result->err = fabs(x*x2*x2 / 100.0);      return GSL_SUCCESS;    }    else {      double sgn_result = sgn_x;      double y = floor(abs_x/(0.25*M_PI));      int octant = y - ldexp(floor(ldexp(y,-3)),3);      int stat_cs;      double z;      if(GSL_IS_ODD(octant)) {        octant += 1;	octant &= 07;	y += 1.0;      }      if(octant > 3) {        octant -= 4;	sgn_result = -sgn_result;      }            z = ((abs_x - y * P1) - y * P2) - y * P3;      if(octant == 0) {        gsl_sf_result sin_cs_result;	const double t = 8.0*fabs(z)/M_PI - 1.0;	stat_cs = cheb_eval_e(&sin_cs, t, &sin_cs_result);        result->val = z * (1.0 + z*z * sin_cs_result.val);      }      else { /* octant == 2 */        gsl_sf_result cos_cs_result;	const double t = 8.0*fabs(z)/M_PI - 1.0;	stat_cs = cheb_eval_e(&cos_cs, t, &cos_cs_result);        result->val = 1.0 - 0.5*z*z * (1.0 - z*z * cos_cs_result.val);      }      result->val *= sgn_result;      if(abs_x > 1.0/GSL_DBL_EPSILON) {        result->err = fabs(result->val);      }      else if(abs_x > 100.0/GSL_SQRT_DBL_EPSILON) {        result->err = 2.0 * abs_x * GSL_DBL_EPSILON * fabs(result->val);      }      else if(abs_x > 0.1/GSL_SQRT_DBL_EPSILON) {        result->err = 2.0 * GSL_SQRT_DBL_EPSILON * fabs(result->val);      }      else {        result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);      }      return stat_cs;    }  }}intgsl_sf_cos_e(double x, gsl_sf_result * result){  /* CHECK_POINTER(result) */  {    const double P1 = 7.85398125648498535156e-1;    const double P2 = 3.77489470793079817668e-8;    const double P3 = 2.69515142907905952645e-15;    const double abs_x = fabs(x);    if(abs_x < GSL_ROOT4_DBL_EPSILON) {      const double x2 = x*x;      result->val = 1.0 - 0.5*x2;      result->err = fabs(x2*x2/12.0);      return GSL_SUCCESS;    }    else {      double sgn_result = 1.0;      double y = floor(abs_x/(0.25*M_PI));      int octant = y - ldexp(floor(ldexp(y,-3)),3);      int stat_cs;      double z;      if(GSL_IS_ODD(octant)) {        octant += 1;	octant &= 07;	y += 1.0;      }      if(octant > 3) {        octant -= 4;	sgn_result = -sgn_result;      }      if(octant > 1) {        sgn_result = -sgn_result;      }      z = ((abs_x - y * P1) - y * P2) - y * P3;      if(octant == 0) {        gsl_sf_result cos_cs_result;        const double t = 8.0*fabs(z)/M_PI - 1.0;        stat_cs = cheb_eval_e(&cos_cs, t, &cos_cs_result);        result->val = 1.0 - 0.5*z*z * (1.0 - z*z * cos_cs_result.val);      }      else { /* octant == 2 */        gsl_sf_result sin_cs_result;        const double t = 8.0*fabs(z)/M_PI - 1.0;        stat_cs = cheb_eval_e(&sin_cs, t, &sin_cs_result);        result->val = z * (1.0 + z*z * sin_cs_result.val);      }      result->val *= sgn_result;      if(abs_x > 1.0/GSL_DBL_EPSILON) {        result->err = fabs(result->val);      }      else if(abs_x > 100.0/GSL_SQRT_DBL_EPSILON) {        result->err = 2.0 * abs_x * GSL_DBL_EPSILON * fabs(result->val);      }      else if(abs_x > 0.1/GSL_SQRT_DBL_EPSILON) {        result->err = 2.0 * GSL_SQRT_DBL_EPSILON * fabs(result->val);      }      else {        result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);      }      return stat_cs;    }  }}intgsl_sf_hypot_e(const double x, const double y, gsl_sf_result * result){  /* CHECK_POINTER(result) */  if(x == 0.0 && y == 0.0) {    result->val = 0.0;    result->err = 0.0;    return GSL_SUCCESS;  }  else {    const double a = fabs(x);    const double b = fabs(y);    const double min = GSL_MIN_DBL(a,b);    const double max = GSL_MAX_DBL(a,b);    const double rat = min/max;    const double root_term = sqrt(1.0 + rat*rat);    if(max < GSL_DBL_MAX/root_term) {      result->val = max * root_term;      result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);      return GSL_SUCCESS;    }    else {      OVERFLOW_ERROR(result);    }  }}intgsl_sf_complex_sin_e(const double zr, const double zi,                        gsl_sf_result * szr, gsl_sf_result * szi){  /* CHECK_POINTER(szr) */  /* CHECK_POINTER(szi) */  if(fabs(zi) < 1.0) {    double ch_m1, sh;    sinh_series(zi, &sh);    cosh_m1_series(zi, &ch_m1);    szr->val = sin(zr)*(ch_m1 + 1.0);    szi->val = cos(zr)*sh;    szr->err = 2.0 * GSL_DBL_EPSILON * fabs(szr->val);    szi->err = 2.0 * GSL_DBL_EPSILON * fabs(szi->val);    return GSL_SUCCESS;  }  else if(fabs(zi) < GSL_LOG_DBL_MAX) {    double ex = exp(zi);    double ch = 0.5*(ex+1.0/ex);    double sh = 0.5*(ex-1.0/ex);    szr->val = sin(zr)*ch;    szi->val = cos(zr)*sh;    szr->err = 2.0 * GSL_DBL_EPSILON * fabs(szr->val);    szi->err = 2.0 * GSL_DBL_EPSILON * fabs(szi->val);    return GSL_SUCCESS;  }  else {    OVERFLOW_ERROR_2(szr, szi);  }}intgsl_sf_complex_cos_e(const double zr, const double zi,                        gsl_sf_result * czr, gsl_sf_result * czi){  /* CHECK_POINTER(czr) */  /* CHECK_POINTER(czi) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -