gsl_specfunc__poch.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. /* specfunc/poch.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. #include "gsl__config.h"
  21. #include "gsl_math.h"
  22. #include "gsl_errno.h"
  23. #include "gsl_sf_exp.h"
  24. #include "gsl_sf_log.h"
  25. #include "gsl_sf_pow_int.h"
  26. #include "gsl_sf_psi.h"
  27. #include "gsl_sf_gamma.h"
  28. #include "gsl_specfunc__error.h"
  29. static const double bern[21] = {
  30. 0.0 /* no element 0 */,
  31. +0.833333333333333333333333333333333e-01,
  32. -0.138888888888888888888888888888888e-02,
  33. +0.330687830687830687830687830687830e-04,
  34. -0.826719576719576719576719576719576e-06,
  35. +0.208767569878680989792100903212014e-07,
  36. -0.528419013868749318484768220217955e-09,
  37. +0.133825365306846788328269809751291e-10,
  38. -0.338968029632258286683019539124944e-12,
  39. +0.858606205627784456413590545042562e-14,
  40. -0.217486869855806187304151642386591e-15,
  41. +0.550900282836022951520265260890225e-17,
  42. -0.139544646858125233407076862640635e-18,
  43. +0.353470703962946747169322997780379e-20,
  44. -0.895351742703754685040261131811274e-22,
  45. +0.226795245233768306031095073886816e-23,
  46. -0.574472439520264523834847971943400e-24,
  47. +0.145517247561486490186626486727132e-26,
  48. -0.368599494066531017818178247990866e-28,
  49. +0.933673425709504467203255515278562e-30,
  50. -0.236502241570062993455963519636983e-31
  51. };
  52. /* ((a)_x - 1)/x in the "small x" region where
  53. * cancellation must be controlled.
  54. *
  55. * Based on SLATEC DPOCH1().
  56. */
  57. /*
  58. C When ABS(X) is so small that substantial cancellation will occur if
  59. C the straightforward formula is used, we use an expansion due
  60. C to Fields and discussed by Y. L. Luke, The Special Functions and Their
  61. C Approximations, Vol. 1, Academic Press, 1969, page 34.
  62. C
  63. C The ratio POCH(A,X) = GAMMA(A+X)/GAMMA(A) is written by Luke as
  64. C (A+(X-1)/2)**X * polynomial in (A+(X-1)/2)**(-2) .
  65. C In order to maintain significance in POCH1, we write for positive a
  66. C (A+(X-1)/2)**X = EXP(X*LOG(A+(X-1)/2)) = EXP(Q)
  67. C = 1.0 + Q*EXPREL(Q) .
  68. C Likewise the polynomial is written
  69. C POLY = 1.0 + X*POLY1(A,X) .
  70. C Thus,
  71. C POCH1(A,X) = (POCH(A,X) - 1) / X
  72. C = EXPREL(Q)*(Q/X + Q*POLY1(A,X)) + POLY1(A,X)
  73. C
  74. */
  75. static
  76. int
  77. pochrel_smallx(const double a, const double x, gsl_sf_result * result)
  78. {
  79. /*
  80. SQTBIG = 1.0D0/SQRT(24.0D0*D1MACH(1))
  81. ALNEPS = LOG(D1MACH(3))
  82. */
  83. const double SQTBIG = 1.0/(2.0*M_SQRT2*M_SQRT3*GSL_SQRT_DBL_MIN);
  84. const double ALNEPS = GSL_LOG_DBL_EPSILON - M_LN2;
  85. if(x == 0.0) {
  86. return gsl_sf_psi_e(a, result);
  87. }
  88. else {
  89. const double bp = ( (a < -0.5) ? 1.0-a-x : a );
  90. const int incr = ( (bp < 10.0) ? 11.0-bp : 0 );
  91. const double b = bp + incr;
  92. double dpoch1;
  93. gsl_sf_result dexprl;
  94. int stat_dexprl;
  95. int i;
  96. double var = b + 0.5*(x-1.0);
  97. double alnvar = log(var);
  98. double q = x*alnvar;
  99. double poly1 = 0.0;
  100. if(var < SQTBIG) {
  101. const int nterms = (int)(-0.5*ALNEPS/alnvar + 1.0);
  102. const double var2 = (1.0/var)/var;
  103. const double rho = 0.5 * (x + 1.0);
  104. double term = var2;
  105. double gbern[24];
  106. int k, j;
  107. gbern[1] = 1.0;
  108. gbern[2] = -rho/12.0;
  109. poly1 = gbern[2] * term;
  110. if(nterms > 20) {
  111. /* NTERMS IS TOO BIG, MAYBE D1MACH(3) IS BAD */
  112. /* nterms = 20; */
  113. result->val = 0.0;
  114. result->err = 0.0;
  115. GSL_ERROR ("error", GSL_ESANITY);
  116. }
  117. for(k=2; k<=nterms; k++) {
  118. double gbk = 0.0;
  119. for(j=1; j<=k; j++) {
  120. gbk += bern[k-j+1]*gbern[j];
  121. }
  122. gbern[k+1] = -rho*gbk/k;
  123. term *= (2*k-2-x)*(2*k-1-x)*var2;
  124. poly1 += gbern[k+1]*term;
  125. }
  126. }
  127. stat_dexprl = gsl_sf_expm1_e(q, &dexprl);
  128. if(stat_dexprl != GSL_SUCCESS) {
  129. result->val = 0.0;
  130. result->err = 0.0;
  131. return stat_dexprl;
  132. }
  133. dexprl.val = dexprl.val/q;
  134. poly1 *= (x - 1.0);
  135. dpoch1 = dexprl.val * (alnvar + q * poly1) + poly1;
  136. for(i=incr-1; i >= 0; i--) {
  137. /*
  138. C WE HAVE DPOCH1(B,X), BUT BP IS SMALL, SO WE USE BACKWARDS RECURSION
  139. C TO OBTAIN DPOCH1(BP,X).
  140. */
  141. double binv = 1.0/(bp+i);
  142. dpoch1 = (dpoch1 - binv) / (1.0 + x*binv);
  143. }
  144. if(bp == a) {
  145. result->val = dpoch1;
  146. result->err = 2.0 * GSL_DBL_EPSILON * (fabs(incr) + 1.0) * fabs(result->val);
  147. return GSL_SUCCESS;
  148. }
  149. else {
  150. /*
  151. C WE HAVE DPOCH1(BP,X), BUT A IS LT -0.5. WE THEREFORE USE A
  152. C REFLECTION FORMULA TO OBTAIN DPOCH1(A,X).
  153. */
  154. double sinpxx = sin(M_PI*x)/x;
  155. double sinpx2 = sin(0.5*M_PI*x);
  156. double t1 = sinpxx/tan(M_PI*b);
  157. double t2 = 2.0*sinpx2*(sinpx2/x);
  158. double trig = t1 - t2;
  159. result->val = dpoch1 * (1.0 + x*trig) + trig;
  160. result->err = (fabs(dpoch1*x) + 1.0) * GSL_DBL_EPSILON * (fabs(t1) + fabs(t2));
  161. result->err += 2.0 * GSL_DBL_EPSILON * (fabs(incr) + 1.0) * fabs(result->val);
  162. return GSL_SUCCESS;
  163. }
  164. }
  165. }
  166. /* Assumes a>0 and a+x>0.
  167. */
  168. static
  169. int
  170. lnpoch_pos(const double a, const double x, gsl_sf_result * result)
  171. {
  172. double absx = fabs(x);
  173. if(absx > 0.1*a || absx*log(GSL_MAX_DBL(a,2.0)) > 0.1) {
  174. if(a < GSL_SF_GAMMA_XMAX && a+x < GSL_SF_GAMMA_XMAX) {
  175. /* If we can do it by calculating the gamma functions
  176. * directly, then that will be more accurate than
  177. * doing the subtraction of the logs.
  178. */
  179. gsl_sf_result g1;
  180. gsl_sf_result g2;
  181. gsl_sf_gammainv_e(a, &g1);
  182. gsl_sf_gammainv_e(a+x, &g2);
  183. result->val = -log(g2.val/g1.val);
  184. result->err = g1.err/fabs(g1.val) + g2.err/fabs(g2.val);
  185. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  186. return GSL_SUCCESS;
  187. }
  188. else {
  189. /* Otherwise we must do the subtraction.
  190. */
  191. gsl_sf_result lg1;
  192. gsl_sf_result lg2;
  193. int stat_1 = gsl_sf_lngamma_e(a, &lg1);
  194. int stat_2 = gsl_sf_lngamma_e(a+x, &lg2);
  195. result->val = lg2.val - lg1.val;
  196. result->err = lg2.err + lg1.err;
  197. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  198. return GSL_ERROR_SELECT_2(stat_1, stat_2);
  199. }
  200. }
  201. else if(absx < 0.1*a && a > 15.0) {
  202. /* Be careful about the implied subtraction.
  203. * Note that both a+x and and a must be
  204. * large here since a is not small
  205. * and x is not relatively large.
  206. * So we calculate using Stirling for Log[Gamma(z)].
  207. *
  208. * Log[Gamma(a+x)/Gamma(a)] = x(Log[a]-1) + (x+a-1/2)Log[1+x/a]
  209. * + (1/(1+eps) - 1) / (12 a)
  210. * - (1/(1+eps)^3 - 1) / (360 a^3)
  211. * + (1/(1+eps)^5 - 1) / (1260 a^5)
  212. * - (1/(1+eps)^7 - 1) / (1680 a^7)
  213. * + ...
  214. */
  215. const double eps = x/a;
  216. const double den = 1.0 + eps;
  217. const double d3 = den*den*den;
  218. const double d5 = d3*den*den;
  219. const double d7 = d5*den*den;
  220. const double c1 = -eps/den;
  221. const double c3 = -eps*(3.0+eps*(3.0+eps))/d3;
  222. const double c5 = -eps*(5.0+eps*(10.0+eps*(10.0+eps*(5.0+eps))))/d5;
  223. const double c7 = -eps*(7.0+eps*(21.0+eps*(35.0+eps*(35.0+eps*(21.0+eps*(7.0+eps))))))/d7;
  224. const double p8 = gsl_sf_pow_int(1.0+eps,8);
  225. const double c8 = 1.0/p8 - 1.0; /* these need not */
  226. const double c9 = 1.0/(p8*(1.0+eps)) - 1.0; /* be very accurate */
  227. const double a4 = a*a*a*a;
  228. const double a6 = a4*a*a;
  229. const double ser_1 = c1 + c3/(30.0*a*a) + c5/(105.0*a4) + c7/(140.0*a6);
  230. const double ser_2 = c8/(99.0*a6*a*a) - 691.0/360360.0 * c9/(a6*a4);
  231. const double ser = (ser_1 + ser_2)/ (12.0*a);
  232. double term1 = x * log(a/M_E);
  233. double term2;
  234. gsl_sf_result ln_1peps;
  235. gsl_sf_log_1plusx_e(eps, &ln_1peps); /* log(1 + x/a) */
  236. term2 = (x + a - 0.5) * ln_1peps.val;
  237. result->val = term1 + term2 + ser;
  238. result->err = GSL_DBL_EPSILON*fabs(term1);
  239. result->err += fabs((x + a - 0.5)*ln_1peps.err);
  240. result->err += fabs(ln_1peps.val) * GSL_DBL_EPSILON * (fabs(x) + fabs(a) + 0.5);
  241. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  242. return GSL_SUCCESS;
  243. }
  244. else {
  245. gsl_sf_result poch_rel;
  246. int stat_p = pochrel_smallx(a, x, &poch_rel);
  247. double eps = x*poch_rel.val;
  248. int stat_e = gsl_sf_log_1plusx_e(eps, result);
  249. result->err = 2.0 * fabs(x * poch_rel.err / (1.0 + eps));
  250. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  251. return GSL_ERROR_SELECT_2(stat_e, stat_p);
  252. }
  253. }
  254. /*-*-*-*-*-*-*-*-*-*-*-* Functions with Error Codes *-*-*-*-*-*-*-*-*-*-*-*/
  255. int
  256. gsl_sf_lnpoch_e(const double a, const double x, gsl_sf_result * result)
  257. {
  258. /* CHECK_POINTER(result) */
  259. if(a <= 0.0 || a+x <= 0.0) {
  260. DOMAIN_ERROR(result);
  261. }
  262. else if(x == 0.0) {
  263. result->val = 0.0;
  264. result->err = 0.0;
  265. return GSL_SUCCESS;
  266. }
  267. else {
  268. return lnpoch_pos(a, x, result);
  269. }
  270. }
  271. int
  272. gsl_sf_lnpoch_sgn_e(const double a, const double x,
  273. gsl_sf_result * result, double * sgn)
  274. {
  275. if(a == 0.0 || a+x == 0.0) {
  276. *sgn = 0.0;
  277. DOMAIN_ERROR(result);
  278. }
  279. else if(x == 0.0) {
  280. *sgn = 1.0;
  281. result->val = 0.0;
  282. result->err = 0.0;
  283. return GSL_SUCCESS;
  284. }
  285. else if(a > 0.0 && a+x > 0.0) {
  286. *sgn = 1.0;
  287. return lnpoch_pos(a, x, result);
  288. }
  289. else if(a < 0.0 && a+x < 0.0) {
  290. /* Reduce to positive case using reflection.
  291. */
  292. double sin_1 = sin(M_PI * (1.0 - a));
  293. double sin_2 = sin(M_PI * (1.0 - a - x));
  294. if(sin_1 == 0.0 || sin_2 == 0.0) {
  295. *sgn = 0.0;
  296. DOMAIN_ERROR(result);
  297. }
  298. else {
  299. gsl_sf_result lnp_pos;
  300. int stat_pp = lnpoch_pos(1.0-a, -x, &lnp_pos);
  301. double lnterm = log(fabs(sin_1/sin_2));
  302. result->val = lnterm - lnp_pos.val;
  303. result->err = lnp_pos.err;
  304. result->err += 2.0 * GSL_DBL_EPSILON * (fabs(1.0-a) + fabs(1.0-a-x)) * fabs(lnterm);
  305. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  306. *sgn = GSL_SIGN(sin_1*sin_2);
  307. return stat_pp;
  308. }
  309. }
  310. else {
  311. /* Evaluate gamma ratio directly.
  312. */
  313. gsl_sf_result lg_apn;
  314. gsl_sf_result lg_a;
  315. double s_apn, s_a;
  316. int stat_apn = gsl_sf_lngamma_sgn_e(a+x, &lg_apn, &s_apn);
  317. int stat_a = gsl_sf_lngamma_sgn_e(a, &lg_a, &s_a);
  318. if(stat_apn == GSL_SUCCESS && stat_a == GSL_SUCCESS) {
  319. result->val = lg_apn.val - lg_a.val;
  320. result->err = lg_apn.err + lg_a.err;
  321. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  322. *sgn = s_a * s_apn;
  323. return GSL_SUCCESS;
  324. }
  325. else if(stat_apn == GSL_EDOM || stat_a == GSL_EDOM){
  326. *sgn = 0.0;
  327. DOMAIN_ERROR(result);
  328. }
  329. else {
  330. result->val = 0.0;
  331. result->err = 0.0;
  332. *sgn = 0.0;
  333. return GSL_FAILURE;
  334. }
  335. }
  336. }
  337. int
  338. gsl_sf_poch_e(const double a, const double x, gsl_sf_result * result)
  339. {
  340. /* CHECK_POINTER(result) */
  341. if(x == 0.0) {
  342. result->val = 1.0;
  343. result->err = 0.0;
  344. return GSL_SUCCESS;
  345. }
  346. else {
  347. gsl_sf_result lnpoch;
  348. double sgn;
  349. int stat_lnpoch = gsl_sf_lnpoch_sgn_e(a, x, &lnpoch, &sgn);
  350. int stat_exp = gsl_sf_exp_err_e(lnpoch.val, lnpoch.err, result);
  351. result->val *= sgn;
  352. result->err += 2.0 * GSL_DBL_EPSILON * fabs(result->val);
  353. return GSL_ERROR_SELECT_2(stat_exp, stat_lnpoch);
  354. }
  355. }
  356. int
  357. gsl_sf_pochrel_e(const double a, const double x, gsl_sf_result * result)
  358. {
  359. const double absx = fabs(x);
  360. const double absa = fabs(a);
  361. /* CHECK_POINTER(result) */
  362. if(absx > 0.1*absa || absx*log(GSL_MAX(absa,2.0)) > 0.1) {
  363. gsl_sf_result lnpoch;
  364. double sgn;
  365. int stat_poch = gsl_sf_lnpoch_sgn_e(a, x, &lnpoch, &sgn);
  366. if(lnpoch.val > GSL_LOG_DBL_MAX) {
  367. OVERFLOW_ERROR(result);
  368. }
  369. else {
  370. const double el = exp(lnpoch.val);
  371. result->val = (sgn*el - 1.0)/x;
  372. result->err = fabs(result->val) * (lnpoch.err + 2.0 * GSL_DBL_EPSILON);
  373. result->err += 2.0 * GSL_DBL_EPSILON * (fabs(sgn*el) + 1.0) / fabs(x);
  374. return stat_poch;
  375. }
  376. }
  377. else {
  378. return pochrel_smallx(a, x, result);
  379. }
  380. }
  381. /*-*-*-*-*-*-*-*-*-* Functions w/ Natural Prototypes *-*-*-*-*-*-*-*-*-*-*/
  382. #include "gsl_specfunc__eval.h"
  383. double gsl_sf_lnpoch(const double a, const double x)
  384. {
  385. EVAL_RESULT(gsl_sf_lnpoch_e(a, x, &result));
  386. }
  387. double gsl_sf_poch(const double a, const double x)
  388. {
  389. EVAL_RESULT(gsl_sf_poch_e(a, x, &result));
  390. }
  391. double gsl_sf_pochrel(const double a, const double x)
  392. {
  393. EVAL_RESULT(gsl_sf_pochrel_e(a, x, &result));
  394. }