gsl_dht__dht.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. /* dht/dht.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  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. /* Author: G. Jungman
  20. */
  21. #include "gsl__config.h"
  22. #include <stdlib.h>
  23. #include "gsl_errno.h"
  24. #include "gsl_math.h"
  25. #include "gsl_sf_bessel.h"
  26. #include "gsl_dht.h"
  27. gsl_dht *
  28. gsl_dht_alloc (size_t size)
  29. {
  30. gsl_dht * t;
  31. if(size == 0) {
  32. GSL_ERROR_VAL("size == 0", GSL_EDOM, 0);
  33. }
  34. t = (gsl_dht *)malloc(sizeof(gsl_dht));
  35. if(t == 0) {
  36. GSL_ERROR_VAL("out of memory", GSL_ENOMEM, 0);
  37. }
  38. t->size = size;
  39. t->xmax = -1.0; /* Make it clear that this needs to be calculated. */
  40. t->nu = -1.0;
  41. t->j = (double *)malloc((size+2)*sizeof(double));
  42. if(t->j == 0) {
  43. free(t);
  44. GSL_ERROR_VAL("could not allocate memory for j", GSL_ENOMEM, 0);
  45. }
  46. t->Jjj = (double *)malloc(size*(size+1)/2 * sizeof(double));
  47. if(t->Jjj == 0) {
  48. free(t->j);
  49. free(t);
  50. GSL_ERROR_VAL("could not allocate memory for Jjj", GSL_ENOMEM, 0);
  51. }
  52. t->J2 = (double *)malloc((size+1)*sizeof(double));
  53. if(t->J2 == 0) {
  54. free(t->Jjj);
  55. free(t->j);
  56. free(t);
  57. GSL_ERROR_VAL("could not allocate memory for J2", GSL_ENOMEM, 0);
  58. }
  59. return t;
  60. }
  61. /* Handle internal calculation of Bessel zeros. */
  62. static int
  63. dht_bessel_zeros(gsl_dht * t)
  64. {
  65. unsigned int s;
  66. gsl_sf_result z;
  67. int stat_z = 0;
  68. t->j[0] = 0.0;
  69. for(s=1; s < t->size + 2; s++) {
  70. stat_z += gsl_sf_bessel_zero_Jnu_e(t->nu, s, &z);
  71. t->j[s] = z.val;
  72. }
  73. if(stat_z != 0) {
  74. GSL_ERROR("could not compute bessel zeroes", GSL_EFAILED);
  75. }
  76. else {
  77. return GSL_SUCCESS;
  78. }
  79. }
  80. gsl_dht *
  81. gsl_dht_new (size_t size, double nu, double xmax)
  82. {
  83. int status;
  84. gsl_dht * dht = gsl_dht_alloc (size);
  85. if (dht == 0)
  86. return 0;
  87. status = gsl_dht_init(dht, nu, xmax);
  88. if (status)
  89. return 0;
  90. return dht;
  91. }
  92. int
  93. gsl_dht_init(gsl_dht * t, double nu, double xmax)
  94. {
  95. if(xmax <= 0.0) {
  96. GSL_ERROR ("xmax is not positive", GSL_EDOM);
  97. } else if(nu < 0.0) {
  98. GSL_ERROR ("nu is negative", GSL_EDOM);
  99. }
  100. else {
  101. size_t n, m;
  102. int stat_bz = GSL_SUCCESS;
  103. int stat_J = 0;
  104. double jN;
  105. if(nu != t->nu) {
  106. /* Recalculate Bessel zeros if necessary. */
  107. t->nu = nu;
  108. stat_bz = dht_bessel_zeros(t);
  109. }
  110. jN = t->j[t->size+1];
  111. t->xmax = xmax;
  112. t->kmax = jN / xmax;
  113. t->J2[0] = 0.0;
  114. for(m=1; m<t->size+1; m++) {
  115. gsl_sf_result J;
  116. stat_J += gsl_sf_bessel_Jnu_e(nu + 1.0, t->j[m], &J);
  117. t->J2[m] = J.val * J.val;
  118. }
  119. /* J_nu(j[n] j[m] / j[N]) = Jjj[n(n-1)/2 + m - 1], 1 <= n,m <= size
  120. */
  121. for(n=1; n<t->size+1; n++) {
  122. for(m=1; m<=n; m++) {
  123. double arg = t->j[n] * t->j[m] / jN;
  124. gsl_sf_result J;
  125. stat_J += gsl_sf_bessel_Jnu_e(nu, arg, &J);
  126. t->Jjj[n*(n-1)/2 + m - 1] = J.val;
  127. }
  128. }
  129. if(stat_J != 0) {
  130. GSL_ERROR("error computing bessel function", GSL_EFAILED);
  131. }
  132. else {
  133. return stat_bz;
  134. }
  135. }
  136. }
  137. double gsl_dht_x_sample(const gsl_dht * t, int n)
  138. {
  139. return t->j[n+1]/t->j[t->size+1] * t->xmax;
  140. }
  141. double gsl_dht_k_sample(const gsl_dht * t, int n)
  142. {
  143. return t->j[n+1] / t->xmax;
  144. }
  145. void gsl_dht_free(gsl_dht * t)
  146. {
  147. free(t->J2);
  148. free(t->Jjj);
  149. free(t->j);
  150. free(t);
  151. }
  152. int
  153. gsl_dht_apply(const gsl_dht * t, double * f_in, double * f_out)
  154. {
  155. const double jN = t->j[t->size + 1];
  156. const double r = t->xmax / jN;
  157. size_t m;
  158. size_t i;
  159. for(m=0; m<t->size; m++) {
  160. double sum = 0.0;
  161. double Y;
  162. for(i=0; i<t->size; i++) {
  163. /* Need to find max and min so that we
  164. * address the symmetric Jjj matrix properly.
  165. * FIXME: we can presumably optimize this
  166. * by just running over the elements of Jjj
  167. * in a deterministic manner.
  168. */
  169. size_t m_local;
  170. size_t n_local;
  171. if(i < m) {
  172. m_local = i;
  173. n_local = m;
  174. }
  175. else {
  176. m_local = m;
  177. n_local = i;
  178. }
  179. Y = t->Jjj[n_local*(n_local+1)/2 + m_local] / t->J2[i+1];
  180. sum += Y * f_in[i];
  181. }
  182. f_out[m] = sum * 2.0 * r*r;
  183. }
  184. return GSL_SUCCESS;
  185. }