1 #include <gnumeric-config.h>
6 #define ML_ERR_return_NAN { return gnm_nan; }
7 #define ML_UNDERFLOW (GNM_EPSILON * GNM_EPSILON)
8 #define ML_ERROR(cause) do { } while(0)
10 static int qgammaf (gnm_float x
, GnmQuad
*mant
, int *exp2
);
11 static void pochhammer_small_n (gnm_float x
, gnm_float n
, GnmQuad
*res
);
14 /* Compute gnm_log(gamma(a+1)) accurately also for small a (0 < a < 0.5). */
15 gnm_float
lgamma1p (gnm_float a
)
17 const gnm_float eulers_const
= GNM_const(0.5772156649015328606065120900824024);
19 /* coeffs[i] holds (zeta(i+2)-1)/(i+2) , i = 1:N, N = 40 : */
21 static const gnm_float coeffs
[40] = {
22 GNM_const(0.3224670334241132182362075833230126e-0),
23 GNM_const(0.6735230105319809513324605383715000e-1),
24 GNM_const(0.2058080842778454787900092413529198e-1),
25 GNM_const(0.7385551028673985266273097291406834e-2),
26 GNM_const(0.2890510330741523285752988298486755e-2),
27 GNM_const(0.1192753911703260977113935692828109e-2),
28 GNM_const(0.5096695247430424223356548135815582e-3),
29 GNM_const(0.2231547584535793797614188036013401e-3),
30 GNM_const(0.9945751278180853371459589003190170e-4),
31 GNM_const(0.4492623673813314170020750240635786e-4),
32 GNM_const(0.2050721277567069155316650397830591e-4),
33 GNM_const(0.9439488275268395903987425104415055e-5),
34 GNM_const(0.4374866789907487804181793223952411e-5),
35 GNM_const(0.2039215753801366236781900709670839e-5),
36 GNM_const(0.9551412130407419832857179772951265e-6),
37 GNM_const(0.4492469198764566043294290331193655e-6),
38 GNM_const(0.2120718480555466586923135901077628e-6),
39 GNM_const(0.1004322482396809960872083050053344e-6),
40 GNM_const(0.4769810169363980565760193417246730e-7),
41 GNM_const(0.2271109460894316491031998116062124e-7),
42 GNM_const(0.1083865921489695409107491757968159e-7),
43 GNM_const(0.5183475041970046655121248647057669e-8),
44 GNM_const(0.2483674543802478317185008663991718e-8),
45 GNM_const(0.1192140140586091207442548202774640e-8),
46 GNM_const(0.5731367241678862013330194857961011e-9),
47 GNM_const(0.2759522885124233145178149692816341e-9),
48 GNM_const(0.1330476437424448948149715720858008e-9),
49 GNM_const(0.6422964563838100022082448087644648e-10),
50 GNM_const(0.3104424774732227276239215783404066e-10),
51 GNM_const(0.1502138408075414217093301048780668e-10),
52 GNM_const(0.7275974480239079662504549924814047e-11),
53 GNM_const(0.3527742476575915083615072228655483e-11),
54 GNM_const(0.1711991790559617908601084114443031e-11),
55 GNM_const(0.8315385841420284819798357793954418e-12),
56 GNM_const(0.4042200525289440065536008957032895e-12),
57 GNM_const(0.1966475631096616490411045679010286e-12),
58 GNM_const(0.9573630387838555763782200936508615e-13),
59 GNM_const(0.4664076026428374224576492565974577e-13),
60 GNM_const(0.2273736960065972320633279596737272e-13),
61 GNM_const(0.1109139947083452201658320007192334e-13)
64 const gnm_float c
= GNM_const(0.2273736845824652515226821577978691e-12);/* zeta(N+2)-1 */
68 if (gnm_abs (a
) >= 0.5)
69 return gnm_lgamma (a
+ 1);
71 /* Abramowitz & Stegun 6.1.33,
72 * also http://functions.wolfram.com/06.11.06.0008.01 */
73 lgam
= c
* gnm_logcf (-a
/ 2, N
+ 2, 1);
74 for (i
= N
- 1; i
>= 0; i
--)
75 lgam
= coeffs
[i
] - a
* lgam
;
77 return (a
* lgam
- eulers_const
) * a
- log1pmx (a
);
80 /* ------------------------------------------------------------------------ */
82 /* Imported src/nmath/stirlerr.c from R. */
85 * Catherine Loader, catherine@research.bell-labs.com.
89 * Copyright (C) 2000, The R Core Development Team
91 * This program is free software; you can redistribute it and/or modify
92 * it under the terms of the GNU General Public License as published by
93 * the Free Software Foundation; either version 2 of the License, or
94 * (at your option) any later version.
96 * This program is distributed in the hope that it will be useful,
97 * but WITHOUT ANY WARRANTY; without even the implied warranty of
98 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
99 * GNU General Public License for more details.
101 * You should have received a copy of the GNU General Public License
102 * along with this program; if not, write to the Free Software
103 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
109 * Computes the log of the error term in Stirling's formula.
110 * For n > 15, uses the series 1/12n - 1/360n^3 + ...
111 * For n <=15, integers or half-integers, uses stored values.
112 * For other n < 15, uses lgamma directly (don't use this to
116 * Copyright (C) 2000, The R Core Development Team
117 * R has lgammafn, and lgamma is not part of ISO C
121 /* stirlerr(n) = gnm_log(n!) - gnm_log( gnm_sqrt(2*pi*n)*(n/e)^n )
122 * = gnm_log Gamma(n+1) - 1/2 * [gnm_log(2*pi) + gnm_log(n)] - n*[gnm_log(n) - 1]
123 * = gnm_log Gamma(n+1) - (n + 1/2) * gnm_log(n) + n - gnm_log(2*pi)/2
125 * see also lgammacor() in ./lgammacor.c which computes almost the same!
128 gnm_float
stirlerr(gnm_float n
)
131 #define S0 GNM_const(0.083333333333333333333) /* 1/12 */
132 #define S1 GNM_const(0.00277777777777777777778) /* 1/360 */
133 #define S2 GNM_const(0.00079365079365079365079365) /* 1/1260 */
134 #define S3 GNM_const(0.000595238095238095238095238) /* 1/1680 */
135 #define S4 GNM_const(0.0008417508417508417508417508)/* 1/1188 */
138 error for 0, 0.5, 1.0, 1.5, ..., 14.5, 15.0.
140 static const gnm_float sferr_halves
[31] = {
141 0.0, /* n=0 - wrong, place holder only */
142 GNM_const(0.1534264097200273452913848), /* 0.5 */
143 GNM_const(0.0810614667953272582196702), /* 1.0 */
144 GNM_const(0.0548141210519176538961390), /* 1.5 */
145 GNM_const(0.0413406959554092940938221), /* 2.0 */
146 GNM_const(0.03316287351993628748511048), /* 2.5 */
147 GNM_const(0.02767792568499833914878929), /* 3.0 */
148 GNM_const(0.02374616365629749597132920), /* 3.5 */
149 GNM_const(0.02079067210376509311152277), /* 4.0 */
150 GNM_const(0.01848845053267318523077934), /* 4.5 */
151 GNM_const(0.01664469118982119216319487), /* 5.0 */
152 GNM_const(0.01513497322191737887351255), /* 5.5 */
153 GNM_const(0.01387612882307074799874573), /* 6.0 */
154 GNM_const(0.01281046524292022692424986), /* 6.5 */
155 GNM_const(0.01189670994589177009505572), /* 7.0 */
156 GNM_const(0.01110455975820691732662991), /* 7.5 */
157 GNM_const(0.010411265261972096497478567), /* 8.0 */
158 GNM_const(0.009799416126158803298389475), /* 8.5 */
159 GNM_const(0.009255462182712732917728637), /* 9.0 */
160 GNM_const(0.008768700134139385462952823), /* 9.5 */
161 GNM_const(0.008330563433362871256469318), /* 10.0 */
162 GNM_const(0.007934114564314020547248100), /* 10.5 */
163 GNM_const(0.007573675487951840794972024), /* 11.0 */
164 GNM_const(0.007244554301320383179543912), /* 11.5 */
165 GNM_const(0.006942840107209529865664152), /* 12.0 */
166 GNM_const(0.006665247032707682442354394), /* 12.5 */
167 GNM_const(0.006408994188004207068439631), /* 13.0 */
168 GNM_const(0.006171712263039457647532867), /* 13.5 */
169 GNM_const(0.005951370112758847735624416), /* 14.0 */
170 GNM_const(0.005746216513010115682023589), /* 14.5 */
171 GNM_const(0.005554733551962801371038690) /* 15.0 */
177 if (nn
== (int)nn
) return(sferr_halves
[(int)nn
]);
178 return(lgamma1p (n
) - (n
+ 0.5)*gnm_log(n
) + n
- M_LN_SQRT_2PI
);
182 if (n
>500) return((S0
-S1
/nn
)/n
);
183 if (n
> 80) return((S0
-(S1
-S2
/nn
)/nn
)/n
);
184 if (n
> 35) return((S0
-(S1
-(S2
-S3
/nn
)/nn
)/nn
)/n
);
186 return((S0
-(S1
-(S2
-(S3
-S4
/nn
)/nn
)/nn
)/nn
)/n
);
188 /* Cleaning up done by tools/import-R: */
195 /* ------------------------------------------------------------------------ */
196 /* Imported src/nmath/chebyshev.c from R. */
198 * Mathlib : A C Library of Special Functions
199 * Copyright (C) 1998 Ross Ihaka
201 * This program is free software; you can redistribute it and/or modify
202 * it under the terms of the GNU General Public License as published by
203 * the Free Software Foundation; either version 2 of the License, or
204 * (at your option) any later version.
206 * This program is distributed in the hope that it will be useful,
207 * but WITHOUT ANY WARRANTY; without even the implied warranty of
208 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
209 * GNU General Public License for more details.
211 * You should have received a copy of the GNU General Public License
212 * along with this program; if not, write to the Free Software
213 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
218 * int chebyshev_init(double *dos, int nos, double eta)
219 * double chebyshev_eval(double x, double *a, int n)
223 * "chebyshev_init" determines the number of terms for the
224 * double precision orthogonal series "dos" needed to insure
225 * the error is no larger than "eta". Ordinarily eta will be
226 * chosen to be one-tenth machine precision.
228 * "chebyshev_eval" evaluates the n-term Chebyshev series
233 * These routines are translations into C of Fortran routines
234 * by W. Fullerton of Los Alamos Scientific Laboratory.
236 * Based on the Fortran routine dcsevl by W. Fullerton.
237 * Adapted from R. Broucke, Algorithm 446, CACM., 16, 254 (1973).
241 /* NaNs propagated correctly */
244 /* Definition of function chebyshev_init removed. */
247 static gnm_float
chebyshev_eval(gnm_float x
, const gnm_float
*a
, const int n
)
249 gnm_float b0
, b1
, b2
, twox
;
252 if (n
< 1 || n
> 1000) ML_ERR_return_NAN
;
254 if (x
< -1.1 || x
> 1.1) ML_ERR_return_NAN
;
259 for (i
= 1; i
<= n
; i
++) {
262 b0
= twox
* b1
- b2
+ a
[n
- i
];
264 return (b0
- b2
) * 0.5;
267 /* ------------------------------------------------------------------------ */
268 /* Imported src/nmath/lgammacor.c from R. */
270 * Mathlib : A C Library of Special Functions
271 * Copyright (C) 1998 Ross Ihaka
272 * Copyright (C) 2000-2001 The R Development Core Team
274 * This program is free software; you can redistribute it and/or modify
275 * it under the terms of the GNU General Public License as published by
276 * the Free Software Foundation; either version 2 of the License, or
277 * (at your option) any later version.
279 * This program is distributed in the hope that it will be useful,
280 * but WITHOUT ANY WARRANTY; without even the implied warranty of
281 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
282 * GNU General Public License for more details.
284 * You should have received a copy of the GNU General Public License
285 * along with this program; if not, write to the Free Software
286 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
292 * double lgammacor(double x);
296 * Compute the log gamma correction factor for x >= 10 so that
298 * log(gamma(x)) = .5*log(2*pi) + (x-.5)*log(x) -x + lgammacor(x)
300 * [ lgammacor(x) is called Del(x) in other contexts (e.g. dcdflib)]
304 * This routine is a translation into C of a Fortran subroutine
305 * written by W. Fullerton of Los Alamos Scientific Laboratory.
309 * Loader(1999)'s stirlerr() {in ./stirlerr.c} is *very* similar in spirit,
310 * is faster and cleaner, but is only defined "fast" for half integers.
314 static gnm_float
lgammacor(gnm_float x
)
316 static const gnm_float algmcs
[15] = {
317 GNM_const(+.1666389480451863247205729650822e+0),
318 GNM_const(-.1384948176067563840732986059135e-4),
319 GNM_const(+.9810825646924729426157171547487e-8),
320 GNM_const(-.1809129475572494194263306266719e-10),
321 GNM_const(+.6221098041892605227126015543416e-13),
322 GNM_const(-.3399615005417721944303330599666e-15),
323 GNM_const(+.2683181998482698748957538846666e-17),
324 GNM_const(-.2868042435334643284144622399999e-19),
325 GNM_const(+.3962837061046434803679306666666e-21),
326 GNM_const(-.6831888753985766870111999999999e-23),
327 GNM_const(+.1429227355942498147573333333333e-24),
328 GNM_const(-.3547598158101070547199999999999e-26),
329 GNM_const(+.1025680058010470912000000000000e-27),
330 GNM_const(-.3401102254316748799999999999999e-29),
331 GNM_const(+.1276642195630062933333333333333e-30)
336 #ifdef NOMORE_FOR_THREADS
337 static int nalgm
= 0;
338 static gnm_float xbig
= 0, xmax
= 0;
340 /* Initialize machine dependent constants, the first time gamma() is called.
341 FIXME for threads ! */
343 /* For IEEE gnm_float precision : nalgm = 5 */
344 nalgm
= chebyshev_init(algmcs
, 15, GNM_EPSILON
/2);/*was d1mach(3)*/
345 xbig
= 1 / gnm_sqrt(GNM_EPSILON
/2); /* ~ 94906265.6 for IEEE gnm_float */
346 xmax
= gnm_exp(fmin2(gnm_log(GNM_MAX
/ 12), -gnm_log(12 * GNM_MIN
)));
347 /* = GNM_MAX / 48 ~= 3.745e306 for IEEE gnm_float */
350 /* For IEEE gnm_float precision GNM_EPSILON = 2^-52 = GNM_const(2.220446049250313e-16) :
352 * xmax = GNM_MAX / 48 = 2^1020 / 3 */
354 # define xbig GNM_const(94906265.62425156)
355 # define xmax GNM_const(3.745194030963158e306)
360 else if (x
>= xmax
) {
361 ML_ERROR(ME_UNDERFLOW
);
366 return chebyshev_eval(tmp
* tmp
* 2 - 1, algmcs
, nalgm
) / x
;
368 else return 1 / (x
* 12);
370 /* Cleaning up done by tools/import-R: */
375 /* ------------------------------------------------------------------------ */
376 /* Imported src/nmath/lbeta.c from R. */
378 * Mathlib : A C Library of Special Functions
379 * Copyright (C) 1998 Ross Ihaka
380 * Copyright (C) 2000 The R Development Core Team
381 * Copyright (C) 2003 The R Foundation
383 * This program is free software; you can redistribute it and/or modify
384 * it under the terms of the GNU General Public License as published by
385 * the Free Software Foundation; either version 2 of the License, or
386 * (at your option) any later version.
388 * This program is distributed in the hope that it will be useful,
389 * but WITHOUT ANY WARRANTY; without even the implied warranty of
390 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
391 * GNU General Public License for more details.
393 * You should have received a copy of the GNU General Public License
394 * along with this program; if not, write to the Free Software
395 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
401 * double lbeta(double a, double b);
405 * This function returns the value of the log beta function.
409 * This routine is a translation into C of a Fortran subroutine
410 * by W. Fullerton of Los Alamos Scientific Laboratory.
414 gnm_float
gnm_lbeta(gnm_float a
, gnm_float b
)
416 gnm_float corr
, p
, q
;
419 if(b
< p
) p
= b
;/* := min(a,b) */
420 if(b
> q
) q
= b
;/* := max(a,b) */
423 if(gnm_isnan(a
) || gnm_isnan(b
))
427 /* both arguments must be >= 0 */
434 else if (!gnm_finite(q
)) {
439 /* p and q are big. */
440 corr
= lgammacor(p
) + lgammacor(q
) - lgammacor(p
+ q
);
441 return gnm_log(q
) * -0.5 + M_LN_SQRT_2PI
+ corr
442 + (p
- 0.5) * gnm_log(p
/ (p
+ q
)) + q
* gnm_log1p(-p
/ (p
+ q
));
445 /* p is small, but q is big. */
446 corr
= lgammacor(q
) - lgammacor(p
+ q
);
447 return gnm_lgamma(p
) + corr
+ p
- p
* gnm_log(p
+ q
)
448 + (q
- 0.5) * gnm_log1p(-p
/ (p
+ q
));
451 /* p and q are small: p <= q < 10. */
452 return gnm_lgamma (p
) + gnm_lgamma (q
) - gnm_lgamma (p
+ q
);
455 /* ------------------------------------------------------------------------ */
458 gnm_gammax (gnm_float x
, int *exp2
)
461 (void) qgammaf (x
, &r
, exp2
);
462 return gnm_quad_value (&r
);
469 * Returns: the Gamma function evaluated at @x for positive or
473 gnm_gamma (gnm_float x
)
476 gnm_float r
= gnm_gammax (x
, &e
);
477 return gnm_ldexp (r
, e
);
480 /* ------------------------------------------------------------------------- */
483 gnm_factx (gnm_float x
, int *exp2
)
486 (void)qfactf (x
, &r
, exp2
);
487 return gnm_quad_value (&r
);
494 * Returns: the factorial of @x, which must not be a negative integer.
497 gnm_fact (gnm_float x
)
500 gnm_float r
= gnm_factx (x
, &e
);
501 return gnm_ldexp (r
, e
);
504 /* ------------------------------------------------------------------------- */
506 /* 0: ok, 1: overflow, 2: nan */
508 qbetaf (gnm_float a
, gnm_float b
, GnmQuad
*mant
, int *exp2
)
512 gnm_float ab
= a
+ b
;
514 if (gnm_isnan (ab
) ||
515 (a
<= 0 && a
== gnm_floor (a
)) ||
516 (b
<= 0 && b
== gnm_floor (b
)))
519 if (ab
<= 0 && ab
== gnm_floor (ab
)) {
520 gnm_quad_init (mant
, 0);
531 if (a
> 1 && gnm_abs (b
) < 1) {
533 if (qgammaf (b
, &mb
, &eb
))
535 state
= gnm_quad_start ();
536 pochhammer_small_n (a
, b
, &ma
);
537 gnm_quad_div (mant
, &mb
, &ma
);
538 gnm_quad_end (state
);
543 if (!qgammaf (a
, &ma
, &ea
) &&
544 !qgammaf (b
, &mb
, &eb
) &&
545 !qgammaf (ab
, &mab
, &eab
)) {
546 void *state
= gnm_quad_start ();
547 gnm_quad_mul (&ma
, &ma
, &mb
);
548 gnm_quad_div (mant
, &ma
, &mab
);
549 gnm_quad_end (state
);
550 *exp2
= ea
+ eb
- eab
;
561 * Returns: the Beta function evaluated at @a and @b.
564 gnm_beta (gnm_float a
, gnm_float b
)
569 switch (qbetaf (a
, b
, &r
, &e
)) {
570 case 0: return gnm_ldexp (gnm_quad_value (&r
), e
);
571 case 1: return gnm_pinf
;
572 default: return gnm_nan
;
580 * @sign: (out): the sign
582 * Returns: the logarithm of the absolute value of the Beta function
583 * evaluated at @a and @b. The sign will be stored in @sign as -1 or
584 * +1. This function is useful because the result of the beta
585 * function can be too large for doubles.
588 gnm_lbeta3 (gnm_float a
, gnm_float b
, int *sign
)
590 int sign_a
, sign_b
, sign_ab
;
591 gnm_float ab
= a
+ b
;
592 gnm_float res_a
, res_b
, res_ab
;
596 switch (qbetaf (a
, b
, &r
, &e
)) {
598 gnm_float m
= gnm_quad_value (&r
);
599 *sign
= (m
>= 0 ? +1 : -1);
600 return gnm_log (gnm_abs (m
)) + e
* M_LN2gnum
;
610 if (a
> 0 && b
> 0) {
612 return gnm_lbeta (a
, b
);
616 res_a
= gnm_lgamma_r (a
, &sign_a
);
617 res_b
= gnm_lgamma_r (b
, &sign_b
);
618 res_ab
= gnm_lgamma_r (ab
, &sign_ab
);
620 *sign
= sign_a
* sign_b
* sign_ab
;
621 return res_a
+ res_b
- res_ab
;
624 /* ------------------------------------------------------------------------- */
626 * This computes the E(x) such that
628 * Gamma(x) = sqrt(2Pi) * x^(x-1/2) * exp(-x) * E(x)
630 * x should be >0 and the result is, roughly, 1+1/(12x).
633 gamma_error_factor (GnmQuad
*res
, const GnmQuad
*x
)
642 GNM_const(-534703531.),
643 GNM_const(-4483131259.),
644 GNM_const(432261921612371.)
651 GNM_const(209018880.),
652 GNM_const(75246796800.),
653 GNM_const(902961561600.),
654 GNM_const(86684309913600.),
655 GNM_const(514904800886784000.)
659 gnm_float xval
= gnm_quad_value (x
);
662 g_return_if_fail (xval
> 0);
664 // We want x >= 20 for the asymptotic expansion
665 n
= (xval
< 20) ? (int)gnm_floor (21 - xval
) : 0;
666 gnm_quad_init (&xpn
, n
);
667 gnm_quad_add (&xpn
, &xpn
, x
);
669 gnm_quad_init (&zn
, 1);
672 for (i
= 0; i
< (int)G_N_ELEMENTS (num
); i
++) {
674 gnm_quad_mul (&zn
, &zn
, &xpn
);
675 gnm_quad_init (&c
, den
[i
]);
676 gnm_quad_mul (&t
, &zn
, &c
);
677 gnm_quad_init (&c
, num
[i
]);
678 gnm_quad_div (&t
, &c
, &t
);
679 gnm_quad_add (res
, res
, &t
);
684 GnmQuad en
, xxn
, xph
;
686 // Gamma(x) = sqrt(2Pi) * x^(x-1/2) * exp(-x) * E(x)
687 // Gamma(x+n) = sqrt(2Pi) * (x+n)^(x+n-1/2) * exp(-x-n) * E(x+n)
690 // Gamma(x+n)/Gamma(x) * (x^(x-1/2) * exp(-x)) / ((x+n)^(x+n-1/2) * exp(-x-n)) =
691 // (x*(x+1)*...*(x+n-1)) * exp(n) * (x/(x+n))^(x-1/2) / (x+n)^n =
692 // ((x+1)*...*(x+n-1)) * exp(n) * (x/(x+n))^(x+1/2) / (x+n)^(n-1) =
693 // ((x+1)/(x+n)*...*(x+n-1)/(x+n)) * exp(n) * (x/(x+n))^(x+1/2)
695 for (i
= 1; i
< n
; i
++) {
698 gnm_quad_init (&xpi
, i
);
699 gnm_quad_add (&xpi
, &xpi
, x
);
700 gnm_quad_div (res
, res
, &xpi
);
701 gnm_quad_mul (res
, res
, &xpn
);
705 gnm_quad_init (&en
, n
);
706 gnm_quad_exp (&en
, NULL
, &en
);
707 gnm_quad_div (res
, res
, &en
);
709 // /= (x/(x+n))^(x+1/2)
710 gnm_quad_init (&xph
, 0.5);
711 gnm_quad_add (&xph
, &xph
, x
);
712 gnm_quad_div (&xxn
, x
, &xpn
);
713 gnm_quad_pow (&xxn
, NULL
, &xxn
, &xph
);
714 gnm_quad_div (res
, res
, &xxn
);
718 /* ------------------------------------------------------------------------- */
721 pochhammer_small_n (gnm_float x
, gnm_float n
, GnmQuad
*res
)
723 GnmQuad qx
, qn
, qr
, qs
, f1
, f2
, f3
, f4
, f5
;
725 gboolean debug
= FALSE
;
727 g_return_if_fail (x
>= 1);
728 g_return_if_fail (gnm_abs (n
) <= 1);
731 * G(x) = c * x^(x-1/2) * exp(-x) * E(x)
732 * G(x+n) = c * (x+n)^(x+n-1/2) * exp(-(x+n)) * E(x+n)
733 * = c * (x+n)^(x-1/2) * (x+n)^n * exp(-x) * exp(-n) * E(x+n)
736 * = (1+n/x)^(x-1/2) * (x+n)^n * exp(-n) * E(x+n)/E(x)
737 * = (1+n/x)^x / sqrt(1+n/x) * (x+n)^n * exp(-n) * E(x+n)/E(x)
738 * = exp(x*log(1+n/x) - n) / sqrt(1+n/x) * (x+n)^n * E(x+n)/E(x)
739 * = exp(x*log1p(n/x) - n) / sqrt(1+n/x) * (x+n)^n * E(x+n)/E(x)
740 * = exp(x*(log1pmx(n/x)+n/x) - n) / sqrt(1+n/x) * (x+n)^n * E(x+n)/E(x)
741 * = exp(x*log1pmx(n/x) + n - n) / sqrt(1+n/x) * (x+n)^n * E(x+n)/E(x)
742 * = exp(x*log1pmx(n/x)) / sqrt(1+n/x) * (x+n)^n * E(x+n)/E(x)
745 gnm_quad_init (&qx
, x
);
746 gnm_quad_init (&qn
, n
);
748 gnm_quad_div (&qr
, &qn
, &qx
);
749 r
= gnm_quad_value (&qr
);
751 gnm_quad_add (&qs
, &qx
, &qn
);
753 /* exp(x*log1pmx(n/x)) */
754 gnm_quad_mul12 (&f1
, log1pmx (r
), x
); /* sub-opt */
755 gnm_quad_exp (&f1
, NULL
, &f1
);
756 if (debug
) g_printerr ("f1=%.20g\n", gnm_quad_value (&f1
));
759 gnm_quad_add (&f2
, &gnm_quad_one
, &qr
);
760 gnm_quad_sqrt (&f2
, &f2
);
761 if (debug
) g_printerr ("f2=%.20g\n", gnm_quad_value (&f2
));
764 gnm_quad_pow (&f3
, NULL
, &qs
, &qn
);
765 if (debug
) g_printerr ("f3=%.20g\n", gnm_quad_value (&f3
));
768 gamma_error_factor (&f4
, &qs
);
769 if (debug
) g_printerr ("f4=%.20g\n", gnm_quad_value (&f4
));
772 gamma_error_factor (&f5
, &qx
);
773 if (debug
) g_printerr ("f5=%.20g\n", gnm_quad_value (&f5
));
775 gnm_quad_div (res
, &f1
, &f2
);
776 gnm_quad_mul (res
, res
, &f3
);
777 gnm_quad_mul (res
, res
, &f4
);
778 gnm_quad_div (res
, res
, &f5
);
782 pochhammer_naive (gnm_float x
, int n
)
784 void *state
= gnm_quad_start ();
789 gnm_quad_init (&qx
, x
);
791 gnm_quad_mul (&qp
, &qp
, &qx
);
792 gnm_quad_add (&qx
, &qx
, &gnm_quad_one
);
794 r
= gnm_quad_value (&qp
);
795 gnm_quad_end (state
);
803 * @n: a real number, often an integer
805 * This function computes Pochhammer's symbol at @x and @n, i.e.,
806 * Gamma(@x+@n)/Gamma(@x). This is well defined unless @x or @x+@n is a
807 * non-negative integer. The ratio has a removable singlularity at @n=0
808 * and the result is 1.
810 * Returns: Pochhammer's symbol (@x)_@n.
813 pochhammer (gnm_float x
, gnm_float n
)
815 gnm_float rn
, rx
, lr
;
819 if (gnm_isnan (x
) || gnm_isnan (n
))
829 * Use naive multiplication when n is a small integer.
830 * We don't want to use this if x is also an integer
831 * (but we might do so below if x is insanely large).
833 if (n
== rn
&& x
!= rx
&& n
>= 0 && n
< 40)
834 return pochhammer_naive (x
, (int)n
);
836 if (!qfactf (x
+ n
- 1, &m1
, &e1
) &&
837 !qfactf (x
- 1, &m2
, &e2
)) {
838 void *state
= gnm_quad_start ();
843 gnm_quad_div (&qr
, &m1
, &m2
);
844 r
= gnm_quad_value (&qr
);
845 gnm_quad_end (state
);
847 return gnm_ldexp (r
, de
);
850 if (x
== rx
&& x
<= 0) {
856 : ((gnm_fmod (-n
, 2) == 0 ? +1 : -1) /
863 * We have left the common cases. One of x+n and x is
864 * insanely big, possibly both.
871 return 1 / pochhammer (x
+ n
, -n
);
873 if (n
== rn
&& n
>= 0 && n
< 100)
874 return pochhammer_naive (x
, (int)n
);
876 if (gnm_abs (n
) < 1) {
878 void *state
= gnm_quad_start ();
881 pochhammer_small_n (x
, n
, &qr
);
882 r
= gnm_quad_value (&qr
);
883 gnm_quad_end (state
);
888 g_printerr ("x=%.20g n=%.20g\n", x
, n
);
889 lr
= ((x
- 0.5) * gnm_log1p (n
/ x
) +
890 n
* gnm_log (x
+ n
) -
892 (lgammacor (x
+ n
) - lgammacor (x
)));
896 /* ------------------------------------------------------------------------- */
899 rescale_mant_exp (GnmQuad
*mant
, int *exp2
)
904 (void)gnm_frexp (gnm_quad_value (mant
), &e
);
906 gnm_quad_init (&s
, gnm_ldexp (1.0, -e
));
907 gnm_quad_mul (mant
, mant
, &s
);
910 /* Tabulate up to, but not including, this number. */
911 #define QFACTI_LIMIT 10000
914 qfacti (int n
, GnmQuad
*mant
, int *exp2
)
916 static GnmQuad mants
[QFACTI_LIMIT
];
917 static int exp2s
[QFACTI_LIMIT
];
920 if (n
< 0 || n
>= QFACTI_LIMIT
) {
921 *mant
= gnm_quad_zero
;
927 void *state
= gnm_quad_start ();
930 gnm_quad_init (&mants
[0], 0.5);
938 gnm_quad_init (&m
, init
);
939 gnm_quad_mul (&mants
[init
], &m
, &mants
[init
- 1]);
940 exp2s
[init
] = exp2s
[init
- 1];
941 rescale_mant_exp (&mants
[init
], &exp2s
[init
]);
946 gnm_quad_end (state
);
954 /* 0: ok, 1: overflow, 2: nan */
956 qfactf (gnm_float x
, GnmQuad
*mant
, int *exp2
)
963 if (gnm_isnan (x
) || (x
< 0 && x
== gnm_floor (x
))) {
964 mant
->h
= mant
->l
= gnm_nan
;
968 if (x
>= G_MAXINT
/ 2) {
969 mant
->h
= mant
->l
= gnm_pinf
;
973 if (x
== gnm_floor (x
)) {
975 if (!qfacti ((int)x
, mant
, exp2
))
979 state
= gnm_quad_start ();
982 if (qfactf (-x
- 1, mant
, exp2
))
987 gnm_quad_init (&b
, -x
);
988 gnm_quad_sinpi (&b
, &b
);
989 gnm_quad_mul (&b
, &b
, mant
);
990 gnm_quad_div (mant
, &gnm_quad_pi
, &b
);
993 } else if (x
>= QFACTI_LIMIT
- 0.5) {
995 * Let y = x + 1 = m * 2^e; c = sqrt(2Pi).
997 * G(y) = c * y^(y-1/2) * exp(-y) * E(y)
998 * = c * (y/e)^y / sqrt(y) * E(y)
1000 GnmQuad y
, f1
, f2
, f3
, f4
;
1002 gboolean debug
= FALSE
;
1004 if (debug
) g_printerr ("x=%.20g\n", x
);
1006 gnm_quad_init (&y
, x
+ 1);
1010 gnm_quad_sqrt (&f1
, &gnm_quad_2pi
);
1011 if (debug
) g_printerr ("f1=%.20g\n", gnm_quad_value (&f1
));
1014 gnm_quad_div (&f2
, &y
, &gnm_quad_e
);
1015 gnm_quad_pow (&f2
, &ef2
, &f2
, &y
);
1016 if (ef2
> G_MAXINT
|| ef2
< G_MININT
) {
1018 f2
.h
= f2
.l
= gnm_pinf
;
1021 if (debug
) g_printerr ("f2=%.20g\n", gnm_quad_value (&f2
));
1024 gnm_quad_sqrt (&f3
, &y
);
1025 if (debug
) g_printerr ("f3=%.20g\n", gnm_quad_value (&f3
));
1028 gamma_error_factor (&f4
, &y
);
1029 if (debug
) g_printerr ("f4=%.20g\n", gnm_quad_value (&f4
));
1031 gnm_quad_mul (mant
, &f1
, &f2
);
1032 gnm_quad_div (mant
, mant
, &f3
);
1033 gnm_quad_mul (mant
, mant
, &f4
);
1035 if (debug
) g_printerr ("G(x+1)=%.20g * 2^%d %s\n", gnm_quad_value (mant
), *exp2
, res
? "overflow" : "");
1042 * w integer, |f|<=0.5, x=w+f.
1044 * Do this before we do the stepping below which would kill
1045 * up to 4 bits of accuracy of f.
1047 w
= gnm_floor (x
+ 0.5);
1049 gnm_quad_init (&qx
, x
);
1051 gnm_quad_init (&s
, 1);
1053 gnm_quad_add (&qx
, &qx
, &gnm_quad_one
);
1055 gnm_quad_mul (&s
, &s
, &qx
);
1058 if (qfacti ((int)w
, &mFw
, &eFw
)) {
1059 mant
->h
= mant
->l
= gnm_pinf
;
1064 pochhammer_small_n (w
+ 1, f
, &r
);
1065 gnm_quad_mul (mant
, &mFw
, &r
);
1066 gnm_quad_div (mant
, mant
, &s
);
1072 rescale_mant_exp (mant
, exp2
);
1074 gnm_quad_end (state
);
1078 /* 0: ok, 1: overflow, 2: nan */
1080 qgammaf (gnm_float x
, GnmQuad
*mant
, int *exp2
)
1082 if (x
< -1.5 || x
> 0.5)
1083 return qfactf (x
- 1, mant
, exp2
);
1084 else if (gnm_isnan (x
) || x
== gnm_floor (x
)) {
1086 mant
->h
= mant
->l
= gnm_nan
;
1089 void *state
= gnm_quad_start ();
1092 qfactf (x
, mant
, exp2
);
1093 gnm_quad_init (&qx
, x
);
1094 gnm_quad_div (mant
, mant
, &qx
);
1095 rescale_mant_exp (mant
, exp2
);
1096 gnm_quad_end (state
);
1101 /* ------------------------------------------------------------------------- */
1104 combin (gnm_float n
, gnm_float k
)
1110 if (k
< 0 || k
> n
|| n
!= gnm_floor (n
) || k
!= gnm_floor (k
))
1119 ok
= (n
< G_MAXINT
&&
1120 !qfactf (n
, &m1
, &e1
) &&
1121 !qfactf (k
, &m2
, &e2
) &&
1122 !qfactf (n
- k
, &m3
, &e3
));
1125 void *state
= gnm_quad_start ();
1127 gnm_quad_mul (&m2
, &m2
, &m3
);
1128 gnm_quad_div (&m1
, &m1
, &m2
);
1129 c
= gnm_ldexp (gnm_quad_value (&m1
), e1
- e2
- e3
);
1130 gnm_quad_end (state
);
1135 void *state
= gnm_quad_start ();
1140 gnm_quad_init (&p
, 1);
1141 for (i
= 0; i
< k
; i
++) {
1142 gnm_quad_init (&a
, n
- i
);
1143 gnm_quad_mul (&p
, &p
, &a
);
1145 gnm_quad_init (&b
, i
+ 1);
1146 gnm_quad_div (&p
, &p
, &b
);
1149 c
= gnm_quad_value (&p
);
1150 gnm_quad_end (state
);
1154 return pochhammer (n
- k
+ 1, k
) / gnm_fact (k
);
1158 permut (gnm_float n
, gnm_float k
)
1160 if (k
< 0 || k
> n
|| n
!= gnm_floor (n
) || k
!= gnm_floor (k
))
1163 return pochhammer (n
- k
+ 1, k
);
1166 /* ------------------------------------------------------------------------- */
1168 #ifdef GNM_SUPPLIES_LGAMMA
1169 /* Avoid using signgam. It may be missing in system libraries. */
1175 return lgamma_r (x
, &signgam
);
1179 #ifdef GNM_SUPPLIES_LGAMMA_R
1181 lgamma_r (double x
, int *signp
)
1196 return (M_LN_SQRT_2PI
+ (x
- 0.5) * gnm_log(x
) -
1197 x
+ lgammacor(x
)) - gnm_log (f
);
1199 gnm_float axm2
= gnm_fmod (-x
, 2.0);
1200 gnm_float y
= gnm_sinpi (axm2
) / M_PIgnum
;
1202 *signp
= axm2
> 1.0 ? +1 : -1;
1206 : - gnm_log (gnm_abs (y
)) - lgamma1p (-x
);
1211 /* ------------------------------------------------------------------------- */
1214 static const gnm_float lanczos_g
= GNM_const (808618867.0) / 134217728;
1217 * This Mathematica sniplet computes the Lanczos gamma coefficients:
1219 * Dr[k_]:=DiagonalMatrix[Join[{1},Array[-Binomial[2*#-1,#]*#&,k]]]
1220 * c[k_]:= Array[If[#1+#2==2,1/2,If[#1>=#2,(-1)^(#1+#2)*4^(#2-1)*(#1-1)*(#1+#2-3)!/(#1-#2)!/(2*#2-2)!,0]]&,{k+1,k+1}]
1221 * Dc[k_]:=DiagonalMatrix[Array[2*(2*#-3)!!&,k+1]]
1222 * B[k_]:=Array[If[#1==1,1,If[#1<=#2,(-1)^(#2-#1)*Binomial[#1+#2-3,#1+#1-3],0]]&,{k+1,k+1}]
1223 * M[k_]:=(Dr[k].B[k]).(c[k].Dc[k])
1224 * f[g_,k_]:=Array[Sqrt[2]*(E/(2*(#-1+g)+1))^(#-1/2)&,k+1]
1225 * a[g_,k_]:=M[k].f[g,k]*Exp[g]/Sqrt[2*Pi]
1227 * The result of a[g,k] will contain both positive and negative constants.
1228 * Most people using the Lanczos series do not understand that a naive
1229 * implemetation will suffer significant cancellation errors. The error
1230 * estimates assume the series is computed without loss!
1232 * Following Boost we multiply the entire partial fraction by Pochhammer[z+1,k]
1233 * That gives us a polynomium with positive coefficient. For kicks we toss
1234 * the constant factor back in.
1236 * b[g_,k_]:=Sum[a[g,k][[i+1]]/If[i==0,1,(z+i)],{i,0,k}]*Pochhammer[z+1,k]
1237 * c13b:=Block[{$MaxExtraPrecision=500},FullSimplify[N[b[808618867/134217728,12]*Sqrt[2*Pi]/Exp[808618867/134217728],300]]]
1239 * Finally we recast that in terms of gamma's argument:
1241 * N[CoefficientList[c13b /. z->(zp-1),{zp}],50]
1243 * Enter complex numbers, exit simplicity. The error bounds for the
1244 * Lanczos approximation are bounds for the absolute value of the result.
1245 * The relative error on one of the coordinates can be much higher.
1247 static const gnm_float lanczos_num
[] = {
1248 GNM_const(56906521.913471563880907910335591226868592353221448),
1249 GNM_const(103794043.11634454519062710536160702385539539810110),
1250 GNM_const(86363131.288138591455469272889778684223419113014358),
1251 GNM_const(43338889.324676138347737237405905333160850993321475),
1252 GNM_const(14605578.087685068084141699827913592185707234229516),
1253 GNM_const(3481712.1549806459088207101896477455646802362321652),
1254 GNM_const(601859.61716810987866702265336993523025071425740828),
1255 GNM_const(75999.293040145426498753034435989091370919973262979),
1256 GNM_const(6955.9996025153761403563101155151989875259157712039),
1257 GNM_const(449.94455690631681194468586076509884096232715968614),
1258 GNM_const(19.519927882476174828478609662356521362076846583112),
1259 GNM_const(0.50984166556566761881251786448046945099926051133936),
1260 GNM_const(0.0060618423462489065257837539645559368832224636654970)
1263 /* CoefficientList[Pochhammer[z,12],z] */
1264 static const guint32 lanczos_denom
[G_N_ELEMENTS(lanczos_num
)] = {
1265 0, 39916800, 120543840, 150917976, 105258076, 45995730,
1266 13339535, 2637558, 357423, 32670, 1925, 66, 1
1270 * gnm_complex_gamma:
1271 * @z: a complex number
1272 * @exp2: (out) (allow-none): Return location for power of 2.
1274 * Returns: (transfer full): the Gamma function evaluated at @z.
1277 gnm_complex_gamma (gnm_complex z
, int *exp2
)
1282 if (GNM_CREALP (z
)) {
1283 return GNM_CREAL (exp2
? gnm_gammax (z
.re
, exp2
) : gnm_gamma (z
.re
));
1284 } else if (z
.re
< 0) {
1285 /* Gamma(z) = pi / (sin(pi*z) * Gamma(-z+1)) */
1286 gnm_complex b
= GNM_CMAKE (M_PIgnum
* gnm_fmod (z
.re
, 2),
1288 /* Hmm... sin overflows when b.im is large. */
1289 gnm_complex res
= GNM_CDIV (GNM_CREAL (M_PIgnum
),
1290 GNM_CMUL (gnm_complex_fact (GNM_CNEG (z
), exp2
),
1296 gnm_complex zmh
, f
, p
, q
;
1299 i
= G_N_ELEMENTS(lanczos_num
) - 1;
1300 p
= GNM_CREAL (lanczos_num
[i
]);
1301 q
= GNM_CREAL (lanczos_denom
[i
]);
1303 p
= GNM_CMUL (p
, z
);
1304 p
.re
+= lanczos_num
[i
];
1305 q
= GNM_CMUL (q
, z
);
1306 q
.re
+= lanczos_denom
[i
];
1309 zmh
= GNM_CMAKE (z
.re
- 0.5, z
.im
);
1310 f
= GNM_CPOW (GNM_CADD (zmh
, GNM_CREAL (lanczos_g
)),
1311 GNM_CSCALE (zmh
, 0.5));
1313 return GNM_CMUL4 (f
, GNM_CEXP (GNM_CNEG (zmh
)), f
, GNM_CDIV (p
, q
));
1317 /* ------------------------------------------------------------------------- */
1321 * @z: a complex number
1322 * @exp2: (out) (allow-none): Return location for power of 2.
1324 * Returns: (transfer full): the factorial function evaluated at @z.
1327 gnm_complex_fact (gnm_complex z
, int *exp2
)
1332 if (GNM_CREALP (z
)) {
1333 return GNM_CREAL (exp2
? gnm_factx (z
.re
, exp2
) : gnm_fact (z
.re
));
1335 // This formula is valid for all arguments except zero
1336 // which we conveniently handled above.
1337 return GNM_CMUL (gnm_complex_gamma (z
, exp2
), z
);
1341 /* ------------------------------------------------------------------------- */
1343 // D(a,z) := z^a * exp(-z) / Gamma (a + 1)
1345 complex_temme_D (gnm_complex a
, gnm_complex z
)
1349 // The idea here is to control intermediate sizes and to avoid
1350 // accuracy problems caused by exp and pow. For now, do neither.
1352 t
= GNM_CDIV (GNM_CPOW (z
, a
), GNM_CEXP (z
));
1353 return GNM_CDIV (t
, gnm_complex_fact (a
, NULL
));
1357 typedef void (*GnmComplexContinuedFraction
) (gnm_complex
*ai
, gnm_complex
*bi
,
1358 size_t i
, const gnm_complex
*args
);
1361 gnm_complex_continued_fraction (gnm_complex
*dst
, size_t N
,
1362 GnmComplexContinuedFraction cf
,
1363 gnm_complex
const *args
)
1365 gnm_complex A0
, A1
, B0
, B1
;
1367 const gboolean debug_cf
= FALSE
;
1372 for (i
= 1; i
< N
; i
++) {
1373 gnm_complex ai
, bi
, t1
, t2
, c1
, c2
, A2
, B2
;
1375 const gnm_float BIG
= GNM_const(18446744073709551616.0);
1377 cf (&ai
, &bi
, i
, args
);
1380 t1
= GNM_CMUL (bi
, A1
);
1381 t2
= GNM_CMUL (ai
, A0
);
1382 A2
= GNM_CADD (t1
, t2
);
1386 t1
= GNM_CMUL (bi
, B1
);
1387 t2
= GNM_CMUL (ai
, B0
);
1388 B2
= GNM_CADD (t1
, t2
);
1392 m
= gnm_abs (B1
.re
) + gnm_abs (B1
.im
);
1393 if (m
>= BIG
|| m
<= 1 / BIG
) {
1400 (void)gnm_frexp (m
, &e
);
1402 g_printerr ("rescale by 2^%d\n", -e
);
1404 s
= gnm_ldexp (1, -e
);
1405 A0
= GNM_CSCALE (A0
, s
);
1406 A1
= GNM_CSCALE (A1
, s
);
1407 B0
= GNM_CSCALE (B0
, s
);
1408 B1
= GNM_CSCALE (B1
, s
);
1411 /* Check for convergence */
1412 t1
= GNM_CMUL (A1
, B0
);
1413 t2
= GNM_CMUL (A0
, B1
);
1414 c1
= GNM_CSUB (t1
, t2
);
1416 c2
= GNM_CMUL (B0
, B1
);
1418 t1
= GNM_CDIV (A1
, B1
);
1420 g_printerr (" a : %.20g + %.20g I\n", ai
.re
, ai
.im
);
1421 g_printerr (" b : %.20g + %.20g I\n", bi
.re
, bi
.im
);
1422 g_printerr (" A : %.20g + %.20g I\n", A1
.re
, A1
.im
);
1423 g_printerr (" B : %.20g + %.20g I\n", B1
.re
, B1
.im
);
1424 g_printerr ("%3zd : %.20g + %.20g I\n", i
, t1
.re
, t1
.im
);
1427 if (GNM_CABS (c1
) <= GNM_CABS (c2
) * (GNM_EPSILON
/2))
1432 g_printerr ("continued fraction failed to converge.\n");
1433 // Make the failure obvious.
1438 *dst
= GNM_CDIV (A1
, B1
);
1443 igamma_lower_coefs (gnm_complex
*ai
, gnm_complex
*bi
, size_t i
,
1444 gnm_complex
const *args
)
1446 gnm_complex
const *a
= args
+ 0;
1447 gnm_complex
const *z
= args
+ 1;
1452 *ai
= GNM_CSCALE (*z
, i
>> 1);
1454 gnm_complex f
= GNM_CMAKE (-(a
->re
+ ((i
>> 1) - 1)), -a
->im
);
1455 *ai
= GNM_CMUL (f
, *z
);
1458 *bi
= GNM_CMAKE (a
->re
+ (i
- 1), a
->im
);
1462 igamma_lower_cf (gnm_complex
*dst
, const gnm_complex
*a
, const gnm_complex
*z
)
1464 gnm_complex args
[2] = { *a
, *z
};
1467 if (!gnm_complex_continued_fraction (&res
, 100, igamma_lower_coefs
, args
))
1470 // FIXME: The following should be handled without creating big numbers.
1471 *dst
= GNM_CMUL3 (res
, GNM_CEXP (GNM_CNEG (*z
)), GNM_CPOW (*z
, *a
));
1477 igamma_upper_asymp (gnm_complex
*dst
, const gnm_complex
*a
, const gnm_complex
*z
)
1479 gnm_float am
= GNM_CABS (*a
);
1480 gnm_float zm
= GNM_CABS (*z
);
1483 gboolean debug
= FALSE
;
1489 // Things start to diverge here
1490 n0
= a
->re
+ gnm_sqrt (zm
* zm
- a
->im
* a
->im
);
1492 g_printerr ("n0=%g\n", n0
);
1495 // FIXME: Verify this condition for whether we have enough
1496 // precision at term n0
1497 if (2 * zm
< GNM_MANT_DIG
* M_LN2gnum
)
1502 t
= complex_temme_D (GNM_CSUB (*a
, GNM_C1
), *z
);
1504 for (i
= 0; i
< 100; i
++) {
1505 s
= GNM_CADD (s
, t
);
1508 g_printerr ("%3zd: t=%.20g + %.20g * I\n", i
, t
.re
, t
.im
);
1509 g_printerr (" : s=%.20g + %.20g * I\n", s
.re
, s
.im
);
1512 if (GNM_CABS (t
) <= GNM_CABS (s
) * GNM_EPSILON
) {
1514 g_printerr ("igamma_upper_asymp converged.\n");
1519 t
= GNM_CDIV (t
, *z
);
1520 t
= GNM_CMUL (t
, GNM_CSUB (*a
, GNM_CREAL (i
+ 1)));
1524 g_printerr ("igamma_upper_asymp failed to converge.\n");
1530 fixup_upper_real (gnm_complex
*res
, gnm_complex a
, gnm_complex z
)
1532 // This assumes we have an upper gamma regularized result.
1534 // It appears that upper algorithms have trouble with negative real z
1535 // (for example, such z being outside the allowed domain) in some cases.
1537 if (GNM_CREALP (z
) && z
.re
< 0 &&
1538 GNM_CREALP (a
) && a
.re
!= gnm_floor (a
.re
)) {
1539 // Everything in the lower power series is real expect z^a
1540 // which is not. So...
1541 // 1. Flip to lower gamma
1542 // 2. Assume modulus is correct
1543 // 3. Use exact angle for lower gamma
1544 // 4. Flip back to upper gamma
1545 gnm_complex lres
= GNM_CSUB (GNM_C1
, *res
);
1546 *res
= GNM_CPOLARPI (GNM_CABS (lres
), a
.re
);
1547 *res
= GNM_CSUB (GNM_C1
, *res
);
1552 * gnm_complex_igamma:
1553 * @a: a complex number
1554 * @z: a complex number
1555 * @lower: determines if upper or lower incomplete gamma is desired.
1556 * @regularized: determines if the result should be normalized by Gamma(@a).
1558 * Returns: (transfer full): the incomplete gamma function evaluated at
1562 gnm_complex_igamma (gnm_complex a
, gnm_complex z
,
1563 gboolean lower
, gboolean regularized
)
1565 gnm_complex res
, ga
;
1566 gboolean have_lower
, have_regularized
;
1567 gboolean have_ga
= FALSE
;
1569 if (regularized
&& GNM_CREALP (a
) &&
1570 a
.re
<= 0 && a
.re
== gnm_floor (a
.re
)) {
1573 have_regularized
= TRUE
;
1577 if (GNM_CREALP (a
) && a
.re
>= 0 &&
1578 GNM_CREALP (z
) && z
.re
>= 0) {
1579 res
= GNM_CREAL (pgamma (z
.re
, a
.re
, 1, lower
, FALSE
));
1581 have_regularized
= TRUE
;
1585 if (igamma_upper_asymp (&res
, &a
, &z
)) {
1587 have_regularized
= TRUE
;
1588 fixup_upper_real (&res
, a
, z
);
1592 if (igamma_lower_cf (&res
, &a
, &z
)) {
1594 have_regularized
= FALSE
;
1598 // Failure of all sub-methods.
1602 // Fixup to the desired form as needed. This is not ideal.
1603 // 1. Regularizing here is too late due to overflow.
1604 // 2. Upper/lower switch can have cancellation
1605 if (regularized
!= have_regularized
) {
1606 ga
= gnm_complex_gamma (a
, NULL
);
1609 if (have_regularized
)
1610 res
= GNM_CMUL (res
, ga
);
1612 res
= GNM_CDIV (res
, ga
);
1613 have_regularized
= TRUE
;
1616 if (lower
!= have_lower
) {
1617 if (have_regularized
) {
1618 res
= GNM_CSUB (GNM_C1
, res
);
1621 ga
= gnm_complex_gamma (a
, NULL
);
1622 res
= GNM_CSUB (ga
, res
);
1629 /* ------------------------------------------------------------------------- */