gsl_integration__qmomof.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. /* integration/qmomof.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. #include "gsl__config.h"
  20. #include <stdlib.h>
  21. #include "gsl_integration.h"
  22. #include "gsl_errno.h"
  23. static void
  24. compute_moments (double par, double * cheb);
  25. static int
  26. dgtsl (size_t n, double *c, double *d, double *e, double *b);
  27. gsl_integration_qawo_table *
  28. gsl_integration_qawo_table_alloc (double omega, double L,
  29. enum gsl_integration_qawo_enum sine,
  30. size_t n)
  31. {
  32. gsl_integration_qawo_table *t;
  33. double * chebmo;
  34. if (n == 0)
  35. {
  36. GSL_ERROR_VAL ("table length n must be positive integer",
  37. GSL_EDOM, 0);
  38. }
  39. t = (gsl_integration_qawo_table *)
  40. malloc (sizeof (gsl_integration_qawo_table));
  41. if (t == 0)
  42. {
  43. GSL_ERROR_VAL ("failed to allocate space for qawo_table struct",
  44. GSL_ENOMEM, 0);
  45. }
  46. chebmo = (double *) malloc (25 * n * sizeof (double));
  47. if (chebmo == 0)
  48. {
  49. free (t);
  50. GSL_ERROR_VAL ("failed to allocate space for chebmo block",
  51. GSL_ENOMEM, 0);
  52. }
  53. t->n = n;
  54. t->sine = sine;
  55. t->omega = omega;
  56. t->L = L;
  57. t->par = 0.5 * omega * L;
  58. t->chebmo = chebmo;
  59. /* precompute the moments */
  60. {
  61. size_t i;
  62. double scale = 1.0;
  63. for (i = 0 ; i < t->n; i++)
  64. {
  65. compute_moments (t->par * scale, t->chebmo + 25*i);
  66. scale *= 0.5;
  67. }
  68. }
  69. return t;
  70. }
  71. int
  72. gsl_integration_qawo_table_set (gsl_integration_qawo_table * t,
  73. double omega, double L,
  74. enum gsl_integration_qawo_enum sine)
  75. {
  76. t->omega = omega;
  77. t->sine = sine;
  78. t->L = L;
  79. t->par = 0.5 * omega * L;
  80. /* recompute the moments */
  81. {
  82. size_t i;
  83. double scale = 1.0;
  84. for (i = 0 ; i < t->n; i++)
  85. {
  86. compute_moments (t->par * scale, t->chebmo + 25*i);
  87. scale *= 0.5;
  88. }
  89. }
  90. return GSL_SUCCESS;
  91. }
  92. int
  93. gsl_integration_qawo_table_set_length (gsl_integration_qawo_table * t,
  94. double L)
  95. {
  96. /* return immediately if the length is the same as the old length */
  97. if (L == t->L)
  98. return GSL_SUCCESS;
  99. /* otherwise reset the table and compute the new parameters */
  100. t->L = L;
  101. t->par = 0.5 * t->omega * L;
  102. /* recompute the moments */
  103. {
  104. size_t i;
  105. double scale = 1.0;
  106. for (i = 0 ; i < t->n; i++)
  107. {
  108. compute_moments (t->par * scale, t->chebmo + 25*i);
  109. scale *= 0.5;
  110. }
  111. }
  112. return GSL_SUCCESS;
  113. }
  114. void
  115. gsl_integration_qawo_table_free (gsl_integration_qawo_table * t)
  116. {
  117. free (t->chebmo);
  118. free (t);
  119. }
  120. static void
  121. compute_moments (double par, double *chebmo)
  122. {
  123. double v[28], d[25], d1[25], d2[25];
  124. const size_t noeq = 25;
  125. const double par2 = par * par;
  126. const double par4 = par2 * par2;
  127. const double par22 = par2 + 2.0;
  128. const double sinpar = sin (par);
  129. const double cospar = cos (par);
  130. size_t i;
  131. /* compute the chebyschev moments with respect to cosine */
  132. double ac = 8 * cospar;
  133. double as = 24 * par * sinpar;
  134. v[0] = 2 * sinpar / par;
  135. v[1] = (8 * cospar + (2 * par2 - 8) * sinpar / par) / par2;
  136. v[2] = (32 * (par2 - 12) * cospar
  137. + (2 * ((par2 - 80) * par2 + 192) * sinpar) / par) / par4;
  138. if (fabs (par) <= 24)
  139. {
  140. /* compute the moments as the solution of a boundary value
  141. problem using the asyptotic expansion as an endpoint */
  142. double an2, ass, asap;
  143. double an = 6;
  144. size_t k;
  145. for (k = 0; k < noeq - 1; k++)
  146. {
  147. an2 = an * an;
  148. d[k] = -2 * (an2 - 4) * (par22 - 2 * an2);
  149. d2[k] = (an - 1) * (an - 2) * par2;
  150. d1[k + 1] = (an + 3) * (an + 4) * par2;
  151. v[k + 3] = as - (an2 - 4) * ac;
  152. an = an + 2.0;
  153. }
  154. an2 = an * an;
  155. d[noeq - 1] = -2 * (an2 - 4) * (par22 - 2 * an2);
  156. v[noeq + 2] = as - (an2 - 4) * ac;
  157. v[3] = v[3] - 56 * par2 * v[2];
  158. ass = par * sinpar;
  159. asap = (((((210 * par2 - 1) * cospar - (105 * par2 - 63) * ass) / an2
  160. - (1 - 15 * par2) * cospar + 15 * ass) / an2
  161. - cospar + 3 * ass) / an2
  162. - cospar) / an2;
  163. v[noeq + 2] = v[noeq + 2] - 2 * asap * par2 * (an - 1) * (an - 2);
  164. dgtsl (noeq, d1, d, d2, v + 3);
  165. }
  166. else
  167. {
  168. /* compute the moments by forward recursion */
  169. size_t k;
  170. double an = 4;
  171. for (k = 3; k < 13; k++)
  172. {
  173. double an2 = an * an;
  174. v[k] = ((an2 - 4) * (2 * (par22 - 2 * an2) * v[k - 1] - ac)
  175. + as - par2 * (an + 1) * (an + 2) * v[k - 2])
  176. / (par2 * (an - 1) * (an - 2));
  177. an = an + 2.0;
  178. }
  179. }
  180. for (i = 0; i < 13; i++)
  181. {
  182. chebmo[2 * i] = v[i];
  183. }
  184. /* compute the chebyschev moments with respect to sine */
  185. v[0] = 2 * (sinpar - par * cospar) / par2;
  186. v[1] = (18 - 48 / par2) * sinpar / par2 + (-2 + 48 / par2) * cospar / par;
  187. ac = -24 * par * cospar;
  188. as = -8 * sinpar;
  189. if (fabs (par) <= 24)
  190. {
  191. /* compute the moments as the solution of a boundary value
  192. problem using the asyptotic expansion as an endpoint */
  193. size_t k;
  194. double an2, ass, asap;
  195. double an = 5;
  196. for (k = 0; k < noeq - 1; k++)
  197. {
  198. an2 = an * an;
  199. d[k] = -2 * (an2 - 4) * (par22 - 2 * an2);
  200. d2[k] = (an - 1) * (an - 2) * par2;
  201. d1[k + 1] = (an + 3) * (an + 4) * par2;
  202. v[k + 2] = ac + (an2 - 4) * as;
  203. an = an + 2.0;
  204. }
  205. an2 = an * an;
  206. d[noeq - 1] = -2 * (an2 - 4) * (par22 - 2 * an2);
  207. v[noeq + 1] = ac + (an2 - 4) * as;
  208. v[2] = v[2] - 42 * par2 * v[1];
  209. ass = par * cospar;
  210. asap = (((((105 * par2 - 63) * ass - (210 * par2 - 1) * sinpar) / an2
  211. + (15 * par2 - 1) * sinpar
  212. - 15 * ass) / an2 - sinpar - 3 * ass) / an2 - sinpar) / an2;
  213. v[noeq + 1] = v[noeq + 1] - 2 * asap * par2 * (an - 1) * (an - 2);
  214. dgtsl (noeq, d1, d, d2, v + 2);
  215. }
  216. else
  217. {
  218. /* compute the moments by forward recursion */
  219. size_t k;
  220. double an = 3;
  221. for (k = 2; k < 12; k++)
  222. {
  223. double an2 = an * an;
  224. v[k] = ((an2 - 4) * (2 * (par22 - 2 * an2) * v[k - 1] + as)
  225. + ac - par2 * (an + 1) * (an + 2) * v[k - 2])
  226. / (par2 * (an - 1) * (an - 2));
  227. an = an + 2.0;
  228. }
  229. }
  230. for (i = 0; i < 12; i++)
  231. {
  232. chebmo[2 * i + 1] = v[i];
  233. }
  234. }
  235. static int
  236. dgtsl (size_t n, double *c, double *d, double *e, double *b)
  237. {
  238. /* solves a tridiagonal matrix A x = b
  239. c[1 .. n - 1] subdiagonal of the matrix A
  240. d[0 .. n - 1] diagonal of the matrix A
  241. e[0 .. n - 2] superdiagonal of the matrix A
  242. b[0 .. n - 1] right hand side, replaced by the solution vector x */
  243. size_t k;
  244. c[0] = d[0];
  245. if (n == 0)
  246. {
  247. return GSL_SUCCESS;
  248. }
  249. if (n == 1)
  250. {
  251. b[0] = b[0] / d[0] ;
  252. return GSL_SUCCESS;
  253. }
  254. d[0] = e[0];
  255. e[0] = 0;
  256. e[n - 1] = 0;
  257. for (k = 0; k < n - 1; k++)
  258. {
  259. size_t k1 = k + 1;
  260. if (fabs (c[k1]) >= fabs (c[k]))
  261. {
  262. {
  263. double t = c[k1];
  264. c[k1] = c[k];
  265. c[k] = t;
  266. };
  267. {
  268. double t = d[k1];
  269. d[k1] = d[k];
  270. d[k] = t;
  271. };
  272. {
  273. double t = e[k1];
  274. e[k1] = e[k];
  275. e[k] = t;
  276. };
  277. {
  278. double t = b[k1];
  279. b[k1] = b[k];
  280. b[k] = t;
  281. };
  282. }
  283. if (c[k] == 0)
  284. {
  285. return GSL_FAILURE ;
  286. }
  287. {
  288. double t = -c[k1] / c[k];
  289. c[k1] = d[k1] + t * d[k];
  290. d[k1] = e[k1] + t * e[k];
  291. e[k1] = 0;
  292. b[k1] = b[k1] + t * b[k];
  293. }
  294. }
  295. if (c[n - 1] == 0)
  296. {
  297. return GSL_FAILURE;
  298. }
  299. b[n - 1] = b[n - 1] / c[n - 1];
  300. b[n - 2] = (b[n - 2] - d[n - 2] * b[n - 1]) / c[n - 2];
  301. for (k = n ; k > 2; k--)
  302. {
  303. size_t kb = k - 3;
  304. b[kb] = (b[kb] - d[kb] * b[kb + 1] - e[kb] * b[kb + 2]) / c[kb];
  305. }
  306. return GSL_SUCCESS;
  307. }