sph_bessel.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. #include "sph_bessel.h"
  2. #include <limits>
  3. using namespace std;
  4. using namespace sph_bessel;
  5. #define DG 12
  6. Complex sph_bessel::besj(Complex z, int n) {
  7. if (n == 0) return besj0(z);
  8. else if (n == 1) return besj1(z);
  9. // else if (n < 0) return (n%2) ? besy(z,-n-1) : -besy(z,-n-1);
  10. if (abs(z) < 0.6) {
  11. int i, ip;
  12. Real tvv;
  13. Complex tc, tcc;
  14. tc = 1.; for (i=1; i<n+1; i++) tc *= z/Real(2*i+1); i = 1; tcc = tc;
  15. ip = int(0.4343*log(abs(tc))) - DG; tvv = (ip < -100) ? 1.e-100 : exp(2.3*ip);
  16. do {tcc += ( tc *= -Real(0.5)*z*z/Real(i*(2*(n+i)+1)) ); i++;} while (abs(tc) > tvv);
  17. return tcc;
  18. }
  19. else if (abs(z)/Real(n) < 1.) {
  20. int nn, i, pw;
  21. Real tv1, tv2, tv3, tx, tx1, tx2, ty1, ty2;
  22. Complex tc, tc1, tc2, tcc;
  23. if (n > int(abs(z))) pw = abs(int( (n*log(0.5*_e*abs(z)/n) - 0.5*log(n*abs(z)) - _ln2)/_ln10 )) + DG;
  24. else pw = DG;
  25. tv1 = abs(z); tv2 = 2./_e/tv1; tv3 = pw*_ln10 - _ln2;
  26. tx2 = (tx1 = n) + 2;
  27. ty1 = tx1*log(tv2*tx1) + 0.5*log(tv1*tx1) - tv3;
  28. ty2 = tx2*log(tv2*tx2) + 0.5*log(tv1*tx2) - tv3;
  29. do {
  30. tx = tx2 - ty2*(tx2-tx1)/(ty2-ty1); tx1 = tx2; tx2 = tx;
  31. ty1 = ty2; ty2 = tx2*log(tv2*tx2) + 0.5*log(tv1*tx2) - tv3;
  32. } while (fabs(tx2-tx1) > 0.5);
  33. nn = int(tx2);
  34. tc1 = 0.; tc2 = exp(-pw*_ln10);
  35. for (i=nn; i>0; i--) {
  36. tc = Real(2*i+1)/z*tc2 - tc1; tc1 = tc2; tc2 = tc;
  37. if (i == n+1) tcc = tc2;
  38. }
  39. return (abs(besj1(z)) > abs(besj0(z))) ? tcc*besj1(z)/tc1 : tcc*besj0(z)/tc2;
  40. }
  41. else {
  42. int i, tm;
  43. Real tvv;
  44. Complex tc, tp, tq, pp, qq;
  45. i = -int(0.4343*log(abs(z)/n)) - DG; tvv = (i < -100) ? 1.e-100 : exp(2.3*i);
  46. tp = pp = 1.; tm = (2*n+1)*(2*n+1); tq = qq = Real(tm-1)*(tc = Real(0.125)/z); tc *= tc; i = 1;
  47. do {
  48. pp += ( tp *= -tc*Real((tm - (4*i-1)*(4*i-1))*(tm - (4*i-3)*(4*i-3)))/Real(2*i*(2*i-1)) );
  49. qq += ( tq *= -tc*Real((tm - (4*i+1)*(4*i+1))*(tm - (4*i-1)*(4*i-1)))/Real(2*i*(2*i+1)) );
  50. i++;
  51. } while ((abs(tp) > tvv) && (abs(tq) > tvv));
  52. return (pp*cos(z-_pi_2*(n+1)) - qq*sin(z-_pi_2*(n+1)))/z;
  53. }
  54. }
  55. Complex sph_bessel::besjd(Complex z, int n) {
  56. if (n == 0) return besj0d(z);
  57. else if (n == 1) return besj1d(z);
  58. // else if (n < 0) return (n%2) ? besy(z,-n-1) : -besy(z,-n-1);
  59. if (abs(z) < 0.6) {
  60. int i, ip;
  61. Real tv, tvv;
  62. Complex tc, tcc;
  63. tc = 1/3.; for (i=2; i<n+1; i++) tc *= z/Real(2*i+1); i = 1; tcc = Real(n)*tc;
  64. ip = int(0.4343*log(abs(tc))) - DG; tvv = (ip < -100) ? 1.e-100 : exp(2.3*ip);
  65. do {tv = abs( tc *= -Real(0.5)*z*z/Real(i*(2*(n+i)+1)) ); tcc += Real(n+2*i)*tc; i++;} while (tv > tvv);
  66. return tcc;
  67. }
  68. else if (abs(z)/n < 1.) {
  69. int nn, i, pw;
  70. Real tv1, tv2, tv3, tx, tx1, tx2, ty1, ty2;
  71. Complex tc, tc1, tc2, tcc;
  72. if (n > int(abs(z))) pw = abs(int( (n*log(0.5*_e*abs(z)/n) - 0.5*log(n*abs(z)) - _ln2)/_ln10 )) + DG;
  73. else pw = DG;
  74. tv1 = abs(z); tv2 = 2./_e/tv1; tv3 = pw*_ln10 - _ln2;
  75. tx2 = (tx1 = n) + 2;
  76. ty1 = tx1*log(tv2*tx1) + 0.5*log(tv1*tx1) - tv3;
  77. ty2 = tx2*log(tv2*tx2) + 0.5*log(tv1*tx2) - tv3;
  78. do {
  79. tx = tx2 - ty2*(tx2-tx1)/(ty2-ty1); tx1 = tx2; tx2 = tx;
  80. ty1 = ty2; ty2 = tx2*log(tv2*tx2) + 0.5*log(tv1*tx2) - tv3;
  81. } while (fabs(tx2-tx1) > 0.5);
  82. nn = int(tx2);
  83. tc1 = 0.; tc2 = exp(-pw*_ln10);
  84. for (i=nn; i>0; i--) {
  85. tc = Real(2*i+1)/z*tc2 - tc1; tc1 = tc2; tc2 = tc;
  86. if (i == n+1) tcc = Real(n)/z*tc2 - tc1;
  87. }
  88. return (abs(besj1(z)) > abs(besj0(z))) ? tcc*besj1(z)/tc1 : tcc*besj0(z)/tc2;
  89. }
  90. else {
  91. return (Real(n)*besj(z,n-1) - Real(n+1)*besj(z,n+1))/Real(2*n+1);
  92. }
  93. }
  94. Complex sph_bessel::besy(Complex z, int n) {
  95. if (n == 0) return besy0(z);
  96. else if (n == 1) return besy1(z);
  97. // else if (n < 0) return (abs(n)%2) ? besj(z,n) : -besj(z,n);
  98. if (abs(z) < 0.6) {
  99. int i, ip;
  100. Real tv, tvv;
  101. Complex tc, tcc;
  102. tc = -Real(1)/z; for (i=1; i<n+1; i++) tc *= Real(2*i-1)/z; i = 1; tcc = tc;
  103. ip = int(0.4343*log(abs(tc))) - DG; tvv = (ip < -100) ? 1.e-100 : exp(2.3*ip);
  104. do {tv = abs( tc *= Real(0.5)*z*z/Real(2*(n-i+1)-1)/Real(i) ); tcc += tc; i++;} while (tv > tvv);
  105. return tcc;
  106. }
  107. else if (abs(z)/n < 1.) {
  108. Complex tc, tc1 = besy0(z), tc2 = besy1(z);
  109. for (int i=2; i<n+1; i++) {
  110. tc = Real(2*i-1)*tc2/z - tc1; tc1 = tc2; tc2 = tc;
  111. }
  112. return tc2;
  113. }
  114. else {
  115. int i, tm;
  116. Real tvv;
  117. Complex tc, tp, tq, pp, qq;
  118. i = -int(0.4343*log(abs(z))) - DG; tvv = (i < -100) ? 1.e-100 : exp(2.3*i);
  119. tp = pp = 1.; tm = (2*n+1)*(2*n+1); tq = qq = Real(tm-1)*(tc = Real(0.125)/z); tc *= tc; i = 1;
  120. do {
  121. pp += ( tp *= -tc*Real((tm - (4*i-1)*(4*i-1))*(tm - (4*i-3)*(4*i-3)))/Real(2*i*(2*i-1)) );
  122. qq += ( tq *= -tc*Real((tm - (4*i+1)*(4*i+1))*(tm - (4*i-1)*(4*i-1)))/Real(2*i*(2*i+1)) );
  123. i++;
  124. } while ((abs(tp) > tvv) && (abs(tq) > tvv));
  125. return (pp*sin(z-_pi_2*(n+1)) + qq*cos(z-_pi_2*(n+1)))/z;
  126. }
  127. }
  128. Complex sph_bessel::besyd(Complex z, int n) {
  129. if (n == 0) return besy0d(z);
  130. else if (n == 1) return besy1d(z);
  131. // else if (n < 0) return (abs(n)%2) ? besj(z,n) : -besj(z,n);
  132. if (abs(z) < 0.6) {
  133. int i, ip;
  134. Real tvv;
  135. Complex tc, tcc;
  136. tc = Real(1)/z/z; for (i=1; i<n+1; i++) tc *= Real(2*i-1)/z; i = 1; tcc = Real(n+1)*tc;
  137. ip = int(0.4343*log(abs(tc))) - DG; tvv = (ip < -100) ? 1.e-100 : exp(2.3*ip);
  138. do {tcc -= Real(2*i-n-1)*( tc *= Real(0.5)*z*z/Real(2*(n-i+1)-1)/Real(i) ); i++;} while (abs(tc) > tvv);
  139. return tcc;
  140. }
  141. else if (abs(z)/n < 1.) {
  142. Complex tc, tc1 = besy0(z), tc2 = besy1(z);
  143. for (int i=2; i<n+1; i++) {
  144. tc = Real(2*i-1)*tc2/z - tc1; tc1 = tc2; tc2 = tc;
  145. }
  146. return (tc1 - Real(n+1)/z*tc2);
  147. }
  148. else return (Real(n)*besy(z,n-1) - Real(n+1)*besy(z,n+1))/Real(2*n+1);
  149. }
  150. Complex sph_bessel::besh1(Complex z, int n) {
  151. if (n == 0) return besh10(z);
  152. else if (n == 1) return besh11(z);
  153. // return (besj(z,n) + j_*besy(z,n));
  154. if (z.imag() > -1.e-16*abs(z)) {
  155. Complex tc, tc1 = besh10(z), tc2 = besh11(z); int i = 1;
  156. do {tc = tc2*Real(2*i+1)/z-tc1; tc1 = tc2; tc2 = tc;} while (++i < n);
  157. return tc2;
  158. }
  159. else return (Real(2)*besj(z,n) - besh2(z,n));
  160. }
  161. Complex sph_bessel::besh2(Complex z, int n) {
  162. if (n == 0) return besh20(z);
  163. else if (n == 1) return besh21(z);
  164. // return (besj(z,n) - j_*besy(z,n));
  165. if (z.imag() < 1.e-16*abs(z)) {
  166. Complex tc, tc1 = besh20(z), tc2 = besh21(z); int i = 1;
  167. do {tc = tc2*Real(2*i+1)/z-tc1; tc1 = tc2; tc2 = tc;} while (++i < n);
  168. return tc2;
  169. }
  170. else return (Real(2)*besj(z,n) + besh1(z,n));
  171. }
  172. Complex sph_bessel::besh1d(Complex z, int n) {
  173. if (n == 0) return besh10d(z);
  174. else if (n == 1) return besh11d(z);
  175. // return (besjd(z,n) + j_*besyd(z,n));
  176. if (z.imag() > -1.e-16*abs(z)) {
  177. Complex tc, tc1 = besh10(z), tc2 = besh11(z); int i = 1;
  178. do {tc = tc2*Real(2*i+1)/z-tc1; tc1 = tc2; tc2 = tc;} while (++i < n);
  179. return (tc1 - Real(n+1)*tc2/z);
  180. }
  181. else return (Real(2)*besjd(z,n) - besh2d(z,n));
  182. }
  183. Complex sph_bessel::besh2d(Complex z, int n) {
  184. if (n == 0) return besh20d(z);
  185. else if (n == 1) return besh21d(z);
  186. // return (besjd(z,n) - j_*besyd(z,n));
  187. if (z.imag() < 1.e-16*abs(z)) {
  188. Complex tc, tc1 = besh20(z), tc2 = besh21(z); int i = 1;
  189. do {tc = tc2*Real(2*i+1)/z-tc1; tc1 = tc2; tc2 = tc;} while (++i < n);
  190. return (tc1 - Real(n+1)*tc2/z);
  191. }
  192. else return (Real(2)*besjd(z,n) + besh1d(z,n));
  193. }
  194. //###################################################
  195. void get_pitau_m01(Real x, Real *pi1, Real *tau0, Real *tau1, int deg_max) {
  196. if (fabs(x-1) < numeric_limits<Real>::epsilon()) {
  197. memset(tau0,0,(deg_max-1)*sizeof(Real));
  198. for (int n=0; n<deg_max; ++n) {
  199. pi1[n] = tau1[n] = 0.5*sqrt(0.5*(n+1)*(n+2)*(2*n+3));
  200. }
  201. }
  202. else if (fabs(x+1) < numeric_limits<Real>::epsilon()) {
  203. memset(tau0,0,(deg_max-1)*sizeof(Real));
  204. for (int n=0; n<deg_max; n+=2) {
  205. tau1[n] = -(pi1[n] = 0.5*sqrt(0.5*(n+1)*(n+2)*(2*n+3)));
  206. }
  207. for (int n=1; n<deg_max; n+=2) {
  208. pi1[n] = -(tau1[n] = 0.5*sqrt(0.5*(n+1)*(n+2)*(2*n+3)));
  209. }
  210. }
  211. else {
  212. Real pl1, pl2, tmp;
  213. Real tsin2 = Real(1)-x*x, tsin = sqrt(tsin2);
  214. pl1 = _1sq2;
  215. pl2 = sqrt(1.5)*x;
  216. pi1[0] = 0.5*sqrt(3);
  217. tau0[0] = -sqrt(1.5)*tsin;
  218. tau1[0] = 0.5*sqrt(3)*x;
  219. for (int n=1; n<deg_max; ++n) {
  220. tmp = sqrt(Real(2*n+3))/Real(n+1)*(x*pl2*sqrt(Real(2*n+1)) - Real(n)/sqrt(Real(2*n-1))*pl1);
  221. pl1 = pl2; pl2 = tmp;
  222. tmp = sqrt(Real(n+1)/Real(n+2))/tsin2;
  223. tau1[n] = sqrt(Real(2*n+3)/Real(2*n+1))*pl1;
  224. pi1[n] = -tmp*( tau0[n] = x*pl2 - tau1[n] );
  225. tau0[n] *= Real(n+1)/tsin;
  226. tau1[n] = tmp*( (Real(1)+(n+1)*tsin2)*pl2 - x*tau1[n] );
  227. }
  228. }
  229. }