gsl_specfunc__laguerre.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* specfunc/laguerre.c
  2. *
  3. * Copyright (C) 2007 Brian Gough
  4. * Copyright (C) 1996, 1997, 1998, 1999, 2000 Gerard Jungman
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. /* Author: G. Jungman */
  21. #include "gsl__config.h"
  22. #include "gsl_math.h"
  23. #include "gsl_errno.h"
  24. #include "gsl_sf_exp.h"
  25. #include "gsl_sf_gamma.h"
  26. #include "gsl_sf_laguerre.h"
  27. #include "gsl_specfunc__error.h"
  28. /*-*-*-*-*-*-*-*-*-*-*-* Private Section *-*-*-*-*-*-*-*-*-*-*-*/
  29. /* based on the large 2b-4a asymptotic for 1F1
  30. * [Abramowitz+Stegun, 13.5.21]
  31. * L^a_n(x) = (a+1)_n / n! 1F1(-n,a+1,x)
  32. *
  33. * The second term (ser_term2) is from Slater,"The Confluent
  34. * Hypergeometric Function" p.73. I think there may be an error in
  35. * the first term of the expression given there, comparing with AS
  36. * 13.5.21 (cf sin(a\pi+\Theta) vs sin(a\pi) + sin(\Theta)) - but the
  37. * second term appears correct.
  38. *
  39. */
  40. static
  41. int
  42. laguerre_large_n(const int n, const double alpha, const double x,
  43. gsl_sf_result * result)
  44. {
  45. const double a = -n;
  46. const double b = alpha + 1.0;
  47. const double eta = 2.0*b - 4.0*a;
  48. const double cos2th = x/eta;
  49. const double sin2th = 1.0 - cos2th;
  50. const double eps = asin(sqrt(cos2th)); /* theta = pi/2 - eps */
  51. const double pre_h = 0.25*M_PI*M_PI*eta*eta*cos2th*sin2th;
  52. gsl_sf_result lg_b;
  53. gsl_sf_result lnfact;
  54. int stat_lg = gsl_sf_lngamma_e(b+n, &lg_b);
  55. int stat_lf = gsl_sf_lnfact_e(n, &lnfact);
  56. double pre_term1 = 0.5*(1.0-b)*log(0.25*x*eta);
  57. double pre_term2 = 0.25*log(pre_h);
  58. double lnpre_val = lg_b.val - lnfact.val + 0.5*x + pre_term1 - pre_term2;
  59. double lnpre_err = lg_b.err + lnfact.err + GSL_DBL_EPSILON * (fabs(pre_term1)+fabs(pre_term2));
  60. double phi1 = 0.25*eta*(2*eps + sin(2.0*eps));
  61. double ser_term1 = -sin(phi1);
  62. double A1 = (1.0/12.0)*(5.0/(4.0*sin2th)+(3.0*b*b-6.0*b+2.0)*sin2th - 1.0);
  63. double ser_term2 = -A1 * cos(phi1)/(0.25*eta*sin(2.0*eps));
  64. double ser_val = ser_term1 + ser_term2;
  65. double ser_err = ser_term2*ser_term2 + GSL_DBL_EPSILON * (fabs(ser_term1) + fabs(ser_term2));
  66. int stat_e = gsl_sf_exp_mult_err_e(lnpre_val, lnpre_err, ser_val, ser_err, result);
  67. result->err += 2.0 * GSL_SQRT_DBL_EPSILON * fabs(result->val);
  68. return GSL_ERROR_SELECT_3(stat_e, stat_lf, stat_lg);
  69. }
  70. /* Evaluate polynomial based on confluent hypergeometric representation.
  71. *
  72. * L^a_n(x) = (a+1)_n / n! 1F1(-n,a+1,x)
  73. *
  74. * assumes n > 0 and a != negative integer greater than -n
  75. */
  76. static
  77. int
  78. laguerre_n_cp(const int n, const double a, const double x, gsl_sf_result * result)
  79. {
  80. gsl_sf_result lnfact;
  81. gsl_sf_result lg1;
  82. gsl_sf_result lg2;
  83. double s1, s2;
  84. int stat_f = gsl_sf_lnfact_e(n, &lnfact);
  85. int stat_g1 = gsl_sf_lngamma_sgn_e(a+1.0+n, &lg1, &s1);
  86. int stat_g2 = gsl_sf_lngamma_sgn_e(a+1.0, &lg2, &s2);
  87. double poly_1F1_val = 1.0;
  88. double poly_1F1_err = 0.0;
  89. int stat_e;
  90. int k;
  91. double lnpre_val = (lg1.val - lg2.val) - lnfact.val;
  92. double lnpre_err = lg1.err + lg2.err + lnfact.err + 2.0 * GSL_DBL_EPSILON * fabs(lnpre_val);
  93. for(k=n-1; k>=0; k--) {
  94. double t = (-n+k)/(a+1.0+k) * (x/(k+1));
  95. double r = t + 1.0/poly_1F1_val;
  96. if(r > 0.9*GSL_DBL_MAX/poly_1F1_val) {
  97. /* internal error only, don't call the error handler */
  98. INTERNAL_OVERFLOW_ERROR(result);
  99. }
  100. else {
  101. /* Collect the Horner terms. */
  102. poly_1F1_val = 1.0 + t * poly_1F1_val;
  103. poly_1F1_err += GSL_DBL_EPSILON + fabs(t) * poly_1F1_err;
  104. }
  105. }
  106. stat_e = gsl_sf_exp_mult_err_e(lnpre_val, lnpre_err,
  107. poly_1F1_val, poly_1F1_err,
  108. result);
  109. return GSL_ERROR_SELECT_4(stat_e, stat_f, stat_g1, stat_g2);
  110. }
  111. /* Evaluate the polynomial based on the confluent hypergeometric
  112. * function in a safe way, with no restriction on the arguments.
  113. *
  114. * assumes x != 0
  115. */
  116. static
  117. int
  118. laguerre_n_poly_safe(const int n, const double a, const double x, gsl_sf_result * result)
  119. {
  120. const double b = a + 1.0;
  121. const double mx = -x;
  122. const double tc_sgn = (x < 0.0 ? 1.0 : (GSL_IS_ODD(n) ? -1.0 : 1.0));
  123. gsl_sf_result tc;
  124. int stat_tc = gsl_sf_taylorcoeff_e(n, fabs(x), &tc);
  125. if(stat_tc == GSL_SUCCESS) {
  126. double term = tc.val * tc_sgn;
  127. double sum_val = term;
  128. double sum_err = tc.err;
  129. int k;
  130. for(k=n-1; k>=0; k--) {
  131. term *= ((b+k)/(n-k))*(k+1.0)/mx;
  132. sum_val += term;
  133. sum_err += 4.0 * GSL_DBL_EPSILON * fabs(term);
  134. }
  135. result->val = sum_val;
  136. result->err = sum_err + 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  137. return GSL_SUCCESS;
  138. }
  139. else if(stat_tc == GSL_EOVRFLW) {
  140. result->val = 0.0; /* FIXME: should be Inf */
  141. result->err = 0.0;
  142. return stat_tc;
  143. }
  144. else {
  145. result->val = 0.0;
  146. result->err = 0.0;
  147. return stat_tc;
  148. }
  149. }
  150. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*/
  151. int
  152. gsl_sf_laguerre_1_e(const double a, const double x, gsl_sf_result * result)
  153. {
  154. /* CHECK_POINTER(result) */
  155. {
  156. result->val = 1.0 + a - x;
  157. result->err = 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(a) + fabs(x));
  158. return GSL_SUCCESS;
  159. }
  160. }
  161. int
  162. gsl_sf_laguerre_2_e(const double a, const double x, gsl_sf_result * result)
  163. {
  164. /* CHECK_POINTER(result) */
  165. if(a == -2.0) {
  166. result->val = 0.5*x*x;
  167. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  168. return GSL_SUCCESS;
  169. }
  170. else {
  171. double c0 = 0.5 * (2.0+a)*(1.0+a);
  172. double c1 = -(2.0+a);
  173. double c2 = -0.5/(2.0+a);
  174. result->val = c0 + c1*x*(1.0 + c2*x);
  175. result->err = 2.0 * GSL_DBL_EPSILON * (fabs(c0) + 2.0 * fabs(c1*x) * (1.0 + 2.0 * fabs(c2*x)));
  176. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  177. return GSL_SUCCESS;
  178. }
  179. }
  180. int
  181. gsl_sf_laguerre_3_e(const double a, const double x, gsl_sf_result * result)
  182. {
  183. /* CHECK_POINTER(result) */
  184. if(a == -2.0) {
  185. double x2_6 = x*x/6.0;
  186. result->val = x2_6 * (3.0 - x);
  187. result->err = x2_6 * (3.0 + fabs(x)) * 2.0 * GSL_DBL_EPSILON;
  188. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  189. return GSL_SUCCESS;
  190. }
  191. else if(a == -3.0) {
  192. result->val = -x*x/6.0;
  193. result->err = 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  194. return GSL_SUCCESS;
  195. }
  196. else {
  197. double c0 = (3.0+a)*(2.0+a)*(1.0+a) / 6.0;
  198. double c1 = -c0 * 3.0 / (1.0+a);
  199. double c2 = -1.0/(2.0+a);
  200. double c3 = -1.0/(3.0*(3.0+a));
  201. result->val = c0 + c1*x*(1.0 + c2*x*(1.0 + c3*x));
  202. result->err = 1.0 + 2.0 * fabs(c3*x);
  203. result->err = 1.0 + 2.0 * fabs(c2*x) * result->err;
  204. result->err = 2.0 * GSL_DBL_EPSILON * (fabs(c0) + 2.0 * fabs(c1*x) * result->err);
  205. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  206. return GSL_SUCCESS;
  207. }
  208. }
  209. int gsl_sf_laguerre_n_e(const int n, const double a, const double x,
  210. gsl_sf_result * result)
  211. {
  212. /* CHECK_POINTER(result) */
  213. if(n < 0) {
  214. DOMAIN_ERROR(result);
  215. }
  216. else if(n == 0) {
  217. result->val = 1.0;
  218. result->err = 0.0;
  219. return GSL_SUCCESS;
  220. }
  221. else if(n == 1) {
  222. result->val = 1.0 + a - x;
  223. result->err = 2.0 * GSL_DBL_EPSILON * (1.0 + fabs(a) + fabs(x));
  224. return GSL_SUCCESS;
  225. }
  226. else if(x == 0.0) {
  227. double product = a + 1.0;
  228. int k;
  229. for(k=2; k<=n; k++) {
  230. product *= (a + k)/k;
  231. }
  232. result->val = product;
  233. result->err = 2.0 * (n + 1.0) * GSL_DBL_EPSILON * fabs(product) + GSL_DBL_EPSILON;
  234. return GSL_SUCCESS;
  235. }
  236. else if(x < 0.0 && a > -1.0) {
  237. /* In this case all the terms in the polynomial
  238. * are of the same sign. Note that this also
  239. * catches overflows correctly.
  240. */
  241. return laguerre_n_cp(n, a, x, result);
  242. }
  243. else if(n < 5 || (x > 0.0 && a < -n-1)) {
  244. /* Either the polynomial will not lose too much accuracy
  245. * or all the terms are negative. In any case,
  246. * the error estimate here is good. We try both
  247. * explicit summation methods, as they have different
  248. * characteristics. One may underflow/overflow while the
  249. * other does not.
  250. */
  251. if(laguerre_n_cp(n, a, x, result) == GSL_SUCCESS)
  252. return GSL_SUCCESS;
  253. else
  254. return laguerre_n_poly_safe(n, a, x, result);
  255. }
  256. else if(n > 1.0e+07 && x > 0.0 && a > -1.0 && x < 2.0*(a+1.0)+4.0*n) {
  257. return laguerre_large_n(n, a, x, result);
  258. }
  259. else if(a >= 0.0 || (x > 0.0 && a < -n-1)) {
  260. gsl_sf_result lg2;
  261. int stat_lg2 = gsl_sf_laguerre_2_e(a, x, &lg2);
  262. double Lkm1 = 1.0 + a - x;
  263. double Lk = lg2.val;
  264. double Lkp1;
  265. int k;
  266. for(k=2; k<n; k++) {
  267. Lkp1 = (-(k+a)*Lkm1 + (2.0*k+a+1.0-x)*Lk)/(k+1.0);
  268. Lkm1 = Lk;
  269. Lk = Lkp1;
  270. }
  271. result->val = Lk;
  272. result->err = (fabs(lg2.err/lg2.val) + GSL_DBL_EPSILON) * n * fabs(Lk);
  273. return stat_lg2;
  274. }
  275. else {
  276. /* Despair... or magic? */
  277. return laguerre_n_poly_safe(n, a, x, result);
  278. }
  279. }
  280. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  281. #include "gsl_specfunc__eval.h"
  282. double gsl_sf_laguerre_1(double a, double x)
  283. {
  284. EVAL_RESULT(gsl_sf_laguerre_1_e(a, x, &result));
  285. }
  286. double gsl_sf_laguerre_2(double a, double x)
  287. {
  288. EVAL_RESULT(gsl_sf_laguerre_2_e(a, x, &result));
  289. }
  290. double gsl_sf_laguerre_3(double a, double x)
  291. {
  292. EVAL_RESULT(gsl_sf_laguerre_3_e(a, x, &result));
  293. }
  294. double gsl_sf_laguerre_n(int n, double a, double x)
  295. {
  296. EVAL_RESULT(gsl_sf_laguerre_n_e(n, a, x, &result));
  297. }