gsl_integration__qc25f.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* integration/qc25f.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  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. struct fn_fourier_params
  20. {
  21. gsl_function *function;
  22. double omega;
  23. };
  24. static double fn_sin (double t, void *params);
  25. static double fn_cos (double t, void *params);
  26. static void
  27. qc25f (gsl_function * f, double a, double b,
  28. gsl_integration_qawo_table * wf, size_t level,
  29. double *result, double *abserr, double *resabs, double *resasc);
  30. static void
  31. qc25f (gsl_function * f, double a, double b,
  32. gsl_integration_qawo_table * wf, size_t level,
  33. double *result, double *abserr, double *resabs, double *resasc)
  34. {
  35. const double center = 0.5 * (a + b);
  36. const double half_length = 0.5 * (b - a);
  37. const double omega = wf->omega ;
  38. const double par = omega * half_length;
  39. if (fabs (par) < 2)
  40. {
  41. gsl_function weighted_function;
  42. struct fn_fourier_params fn_params;
  43. fn_params.function = f;
  44. fn_params.omega = omega;
  45. if (wf->sine == GSL_INTEG_SINE)
  46. {
  47. weighted_function.function = &fn_sin;
  48. }
  49. else
  50. {
  51. weighted_function.function = &fn_cos;
  52. }
  53. weighted_function.params = &fn_params;
  54. gsl_integration_qk15 (&weighted_function, a, b, result, abserr,
  55. resabs, resasc);
  56. return;
  57. }
  58. else
  59. {
  60. double *moment;
  61. double cheb12[13], cheb24[25];
  62. double result_abs, res12_cos, res12_sin, res24_cos, res24_sin;
  63. double est_cos, est_sin;
  64. double c, s;
  65. size_t i;
  66. gsl_integration_qcheb (f, a, b, cheb12, cheb24);
  67. if (level >= wf->n)
  68. {
  69. /* table overflow should not happen, check before calling */
  70. GSL_ERROR_VOID("table overflow in internal function", GSL_ESANITY);
  71. }
  72. /* obtain moments from the table */
  73. moment = wf->chebmo + 25 * level;
  74. res12_cos = cheb12[12] * moment[12];
  75. res12_sin = 0 ;
  76. for (i = 0; i < 6; i++)
  77. {
  78. size_t k = 10 - 2 * i;
  79. res12_cos += cheb12[k] * moment[k];
  80. res12_sin += cheb12[k + 1] * moment[k + 1];
  81. }
  82. res24_cos = cheb24[24] * moment[24];
  83. res24_sin = 0 ;
  84. result_abs = fabs(cheb24[24]) ;
  85. for (i = 0; i < 12; i++)
  86. {
  87. size_t k = 22 - 2 * i;
  88. res24_cos += cheb24[k] * moment[k];
  89. res24_sin += cheb24[k + 1] * moment[k + 1];
  90. result_abs += fabs(cheb24[k]) + fabs(cheb24[k+1]);
  91. }
  92. est_cos = fabs(res24_cos - res12_cos);
  93. est_sin = fabs(res24_sin - res12_sin);
  94. c = half_length * cos(center * omega);
  95. s = half_length * sin(center * omega);
  96. if (wf->sine == GSL_INTEG_SINE)
  97. {
  98. *result = c * res24_sin + s * res24_cos;
  99. *abserr = fabs(c * est_sin) + fabs(s * est_cos);
  100. }
  101. else
  102. {
  103. *result = c * res24_cos - s * res24_sin;
  104. *abserr = fabs(c * est_cos) + fabs(s * est_sin);
  105. }
  106. *resabs = result_abs * half_length;
  107. *resasc = GSL_DBL_MAX;
  108. return;
  109. }
  110. }
  111. static double
  112. fn_sin (double x, void *params)
  113. {
  114. struct fn_fourier_params *p = (struct fn_fourier_params *) params;
  115. gsl_function *f = p->function;
  116. double w = p->omega;
  117. double wx = w * x;
  118. double sinwx = sin(wx) ;
  119. return GSL_FN_EVAL (f, x) * sinwx;
  120. }
  121. static double
  122. fn_cos (double x, void *params)
  123. {
  124. struct fn_fourier_params *p = (struct fn_fourier_params *) params;
  125. gsl_function *f = p->function;
  126. double w = p->omega;
  127. double wx = w * x;
  128. double coswx = cos(wx) ;
  129. return GSL_FN_EVAL (f, x) * coswx ;
  130. }