1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 // Copyright John Maddock 2006-7, 2013-20.
19 // Copyright Paul A. Bristow 2007, 2013-14.
20 // Copyright Nikhar Agrawal 2013-14
21 // Copyright Christopher Kormanyos 2013-14, 2020
22 // Use, modification and distribution are subject to the
23 // Boost Software License, Version 1.0. (See accompanying file
24 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
25
26 package org.apache.commons.numbers.gamma;
27
28 import java.util.function.DoubleSupplier;
29 import java.util.function.Supplier;
30 import org.apache.commons.numbers.core.Sum;
31 import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction;
32 import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction.Coefficient;
33
34 /**
35 * Implementation of the
36 * <a href="https://mathworld.wolfram.com/RegularizedGammaFunction.html">Regularized Gamma functions</a> and
37 * <a href="https://mathworld.wolfram.com/IncompleteGammaFunction.html">Incomplete Gamma functions</a>.
38 *
39 * <p>This code has been adapted from the <a href="https://www.boost.org/">Boost</a>
40 * {@code c++} implementation {@code <boost/math/special_functions/gamma.hpp>}.
41 * All work is copyright to the original authors and subject to the Boost Software License.
42 *
43 * @see
44 * <a href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_gamma.html">
45 * Boost C++ Gamma functions</a>
46 */
47 final class BoostGamma {
48 //
49 // Code ported from Boost 1.77.0
50 //
51 // boost/math/special_functions/gamma.hpp
52 // boost/math/special_functions/detail/igamma_large.hpp
53 // boost/math/special_functions/lanczos.hpp
54 //
55 // Original code comments are preserved.
56 //
57 // Changes to the Boost implementation:
58 // - Update method names to replace underscores with camel case
59 // - Explicitly inline the polynomial function evaluation
60 // using Horner's method (https://en.wikipedia.org/wiki/Horner%27s_method)
61 // - Remove checks for under/overflow. In this implementation no error is raised
62 // for overflow (infinity is returned) or underflow (sub-normal or zero is returned).
63 // This follows the conventions in java.lang.Math for the same conditions.
64 // - Removed the pointer p_derivative in the gammaIncompleteImp. This is used
65 // in the Boost code for the gamma_(p|q)_inv functions for a derivative
66 // based inverse function. This is currently not supported.
67 // - Added extended precision arithmetic for some series summations or other computations.
68 // The Boost default policy is to evaluate in long double for a double result. Extended
69 // precision is not possible for the entire computation but has been used where
70 // possible for some terms to reduce errors. Error reduction verified on the test data.
71 // - Altered the tgamma(x) function to use the double-precision NSWC Library of Mathematics
72 // Subroutines when the error is lower. This is for the non Lanczos code.
73 // - Altered the condition used for the asymptotic approximation method to avoid
74 // loss of precision in the series summation when a ~ z.
75 // - Altered series generators to use integer counters added to the double term
76 // replacing directly incrementing a double term. When the term is large it cannot
77 // be incremented: 1e16 + 1 == 1e16.
78 // - Removed unreachable code branch in tgammaDeltaRatioImpLanczos when z + delta == z.
79 //
80 // Note:
81 // The major source of error is in the function regularisedGammaPrefix when computing
82 // (z^a)(e^-z)/tgamma(a) with extreme input to the power and exponential terms.
83 // An extended precision pow and exp function returning a quad length result would
84 // be required to reduce error for these arguments. Tests using the Dfp class
85 // from o.a.c.math4.legacy.core have been demonstrated to effectively eliminate the
86 // errors from the power terms and improve accuracy on the current test data.
87 // In the interest of performance the Dfp class is not used in this version.
88
89 /** Default epsilon value for relative error.
90 * This is equal to the Boost constant {@code boost::math::tools::epsilon<double>()}. */
91 private static final double EPSILON = 0x1.0p-52;
92 /** Value for the sqrt of the epsilon for relative error.
93 * This is equal to the Boost constant {@code boost::math::tools::root_epsilon<double>()}. */
94 private static final double ROOT_EPSILON = 1.4901161193847656E-8;
95 /** Approximate value for ln(Double.MAX_VALUE).
96 * This is equal to the Boost constant {@code boost::math::tools::log_max_value<double>()}.
97 * No term {@code x} should be used in {@code exp(x)} if {@code x > LOG_MAX_VALUE} to avoid
98 * overflow. */
99 private static final int LOG_MAX_VALUE = 709;
100 /** Approximate value for ln(Double.MIN_VALUE).
101 * This is equal to the Boost constant {@code boost::math::tools::log_min_value<double>()}.
102 * No term {@code x} should be used in {@code exp(x)} if {@code x < LOG_MIN_VALUE} to avoid
103 * underflow to sub-normal or zero. */
104 private static final int LOG_MIN_VALUE = -708;
105 /** The largest factorial that can be represented as a double.
106 * This is equal to the Boost constant {@code boost::math::max_factorial<double>::value}. */
107 private static final int MAX_FACTORIAL = 170;
108 /** The largest integer value for gamma(z) that can be represented as a double. */
109 private static final int MAX_GAMMA_Z = MAX_FACTORIAL + 1;
110 /** ln(sqrt(2 pi)). Computed to 25-digits precision. */
111 private static final double LOG_ROOT_TWO_PI = 0.9189385332046727417803297;
112 /** ln(pi). Computed to 25-digits precision. */
113 private static final double LOG_PI = 1.144729885849400174143427;
114 /** Euler's constant. */
115 private static final double EULER = 0.5772156649015328606065120900824024310;
116 /** The threshold value for choosing the Lanczos approximation. */
117 private static final int LANCZOS_THRESHOLD = 20;
118 /** 2^53. */
119 private static final double TWO_POW_53 = 0x1.0p53;
120
121 /** All factorials that can be represented as a double. Size = 171. */
122 private static final double[] FACTORIAL = {
123 1,
124 1,
125 2,
126 6,
127 24,
128 120,
129 720,
130 5040,
131 40320,
132 362880.0,
133 3628800.0,
134 39916800.0,
135 479001600.0,
136 6227020800.0,
137 87178291200.0,
138 1307674368000.0,
139 20922789888000.0,
140 355687428096000.0,
141 6402373705728000.0,
142 121645100408832000.0,
143 0.243290200817664e19,
144 0.5109094217170944e20,
145 0.112400072777760768e22,
146 0.2585201673888497664e23,
147 0.62044840173323943936e24,
148 0.15511210043330985984e26,
149 0.403291461126605635584e27,
150 0.10888869450418352160768e29,
151 0.304888344611713860501504e30,
152 0.8841761993739701954543616e31,
153 0.26525285981219105863630848e33,
154 0.822283865417792281772556288e34,
155 0.26313083693369353016721801216e36,
156 0.868331761881188649551819440128e37,
157 0.29523279903960414084761860964352e39,
158 0.103331479663861449296666513375232e41,
159 0.3719933267899012174679994481508352e42,
160 0.137637530912263450463159795815809024e44,
161 0.5230226174666011117600072241000742912e45,
162 0.203978820811974433586402817399028973568e47,
163 0.815915283247897734345611269596115894272e48,
164 0.3345252661316380710817006205344075166515e50,
165 0.1405006117752879898543142606244511569936e52,
166 0.6041526306337383563735513206851399750726e53,
167 0.265827157478844876804362581101461589032e55,
168 0.1196222208654801945619631614956577150644e57,
169 0.5502622159812088949850305428800254892962e58,
170 0.2586232415111681806429643551536119799692e60,
171 0.1241391559253607267086228904737337503852e62,
172 0.6082818640342675608722521633212953768876e63,
173 0.3041409320171337804361260816606476884438e65,
174 0.1551118753287382280224243016469303211063e67,
175 0.8065817517094387857166063685640376697529e68,
176 0.427488328406002556429801375338939964969e70,
177 0.2308436973392413804720927426830275810833e72,
178 0.1269640335365827592596510084756651695958e74,
179 0.7109985878048634518540456474637249497365e75,
180 0.4052691950487721675568060190543232213498e77,
181 0.2350561331282878571829474910515074683829e79,
182 0.1386831185456898357379390197203894063459e81,
183 0.8320987112741390144276341183223364380754e82,
184 0.507580213877224798800856812176625227226e84,
185 0.3146997326038793752565312235495076408801e86,
186 0.1982608315404440064116146708361898137545e88,
187 0.1268869321858841641034333893351614808029e90,
188 0.8247650592082470666723170306785496252186e91,
189 0.5443449390774430640037292402478427526443e93,
190 0.3647111091818868528824985909660546442717e95,
191 0.2480035542436830599600990418569171581047e97,
192 0.1711224524281413113724683388812728390923e99,
193 0.1197857166996989179607278372168909873646e101,
194 0.8504785885678623175211676442399260102886e102,
195 0.6123445837688608686152407038527467274078e104,
196 0.4470115461512684340891257138125051110077e106,
197 0.3307885441519386412259530282212537821457e108,
198 0.2480914081139539809194647711659403366093e110,
199 0.188549470166605025498793226086114655823e112,
200 0.1451830920282858696340707840863082849837e114,
201 0.1132428117820629783145752115873204622873e116,
202 0.8946182130782975286851441715398316520698e117,
203 0.7156945704626380229481153372318653216558e119,
204 0.5797126020747367985879734231578109105412e121,
205 0.4753643337012841748421382069894049466438e123,
206 0.3945523969720658651189747118012061057144e125,
207 0.3314240134565353266999387579130131288001e127,
208 0.2817104114380550276949479442260611594801e129,
209 0.2422709538367273238176552320344125971528e131,
210 0.210775729837952771721360051869938959523e133,
211 0.1854826422573984391147968456455462843802e135,
212 0.1650795516090846108121691926245361930984e137,
213 0.1485715964481761497309522733620825737886e139,
214 0.1352001527678402962551665687594951421476e141,
215 0.1243841405464130725547532432587355307758e143,
216 0.1156772507081641574759205162306240436215e145,
217 0.1087366156656743080273652852567866010042e147,
218 0.103299784882390592625997020993947270954e149,
219 0.9916779348709496892095714015418938011582e150,
220 0.9619275968248211985332842594956369871234e152,
221 0.942689044888324774562618574305724247381e154,
222 0.9332621544394415268169923885626670049072e156,
223 0.9332621544394415268169923885626670049072e158,
224 0.9425947759838359420851623124482936749562e160,
225 0.9614466715035126609268655586972595484554e162,
226 0.990290071648618040754671525458177334909e164,
227 0.1029901674514562762384858386476504428305e167,
228 0.1081396758240290900504101305800329649721e169,
229 0.1146280563734708354534347384148349428704e171,
230 0.1226520203196137939351751701038733888713e173,
231 0.132464181945182897449989183712183259981e175,
232 0.1443859583202493582204882102462797533793e177,
233 0.1588245541522742940425370312709077287172e179,
234 0.1762952551090244663872161047107075788761e181,
235 0.1974506857221074023536820372759924883413e183,
236 0.2231192748659813646596607021218715118256e185,
237 0.2543559733472187557120132004189335234812e187,
238 0.2925093693493015690688151804817735520034e189,
239 0.339310868445189820119825609358857320324e191,
240 0.396993716080872089540195962949863064779e193,
241 0.4684525849754290656574312362808384164393e195,
242 0.5574585761207605881323431711741977155627e197,
243 0.6689502913449127057588118054090372586753e199,
244 0.8094298525273443739681622845449350829971e201,
245 0.9875044200833601362411579871448208012564e203,
246 0.1214630436702532967576624324188129585545e206,
247 0.1506141741511140879795014161993280686076e208,
248 0.1882677176888926099743767702491600857595e210,
249 0.237217324288004688567714730513941708057e212,
250 0.3012660018457659544809977077527059692324e214,
251 0.3856204823625804217356770659234636406175e216,
252 0.4974504222477287440390234150412680963966e218,
253 0.6466855489220473672507304395536485253155e220,
254 0.8471580690878820510984568758152795681634e222,
255 0.1118248651196004307449963076076169029976e225,
256 0.1487270706090685728908450891181304809868e227,
257 0.1992942746161518876737324194182948445223e229,
258 0.269047270731805048359538766214698040105e231,
259 0.3659042881952548657689727220519893345429e233,
260 0.5012888748274991661034926292112253883237e235,
261 0.6917786472619488492228198283114910358867e237,
262 0.9615723196941089004197195613529725398826e239,
263 0.1346201247571752460587607385894161555836e242,
264 0.1898143759076170969428526414110767793728e244,
265 0.2695364137888162776588507508037290267094e246,
266 0.3854370717180072770521565736493325081944e248,
267 0.5550293832739304789551054660550388118e250,
268 0.80479260574719919448490292577980627711e252,
269 0.1174997204390910823947958271638517164581e255,
270 0.1727245890454638911203498659308620231933e257,
271 0.2556323917872865588581178015776757943262e259,
272 0.380892263763056972698595524350736933546e261,
273 0.571338395644585459047893286526105400319e263,
274 0.8627209774233240431623188626544191544816e265,
275 0.1311335885683452545606724671234717114812e268,
276 0.2006343905095682394778288746989117185662e270,
277 0.308976961384735088795856467036324046592e272,
278 0.4789142901463393876335775239063022722176e274,
279 0.7471062926282894447083809372938315446595e276,
280 0.1172956879426414428192158071551315525115e279,
281 0.1853271869493734796543609753051078529682e281,
282 0.2946702272495038326504339507351214862195e283,
283 0.4714723635992061322406943211761943779512e285,
284 0.7590705053947218729075178570936729485014e287,
285 0.1229694218739449434110178928491750176572e290,
286 0.2004401576545302577599591653441552787813e292,
287 0.3287218585534296227263330311644146572013e294,
288 0.5423910666131588774984495014212841843822e296,
289 0.9003691705778437366474261723593317460744e298,
290 0.1503616514864999040201201707840084015944e301,
291 0.2526075744973198387538018869171341146786e303,
292 0.4269068009004705274939251888899566538069e305,
293 0.7257415615307998967396728211129263114717e307,
294 };
295
296 /**
297 * 53-bit precision implementation of the Lanczos approximation.
298 *
299 * <p>This implementation is in partial fraction form with the leading constant
300 * of \( \sqrt{2\pi} \) absorbed into the sum.
301 *
302 * <p>It is related to the Gamma function by the following equation
303 * \[
304 * \Gamma(z) = \frac{(z + g - 0.5)^{z - 0.5}}{e^{z + g - 0.5}} \mathrm{lanczos}(z)
305 * \]
306 * where \( g \) is the Lanczos constant.
307 *
308 * <h2>Warning</h2>
309 *
310 * <p>This is not a substitute for {@link LanczosApproximation}. The approximation is
311 * written in partial fraction form with the leading constants absorbed by the
312 * coefficients in the sum.
313 *
314 * @see <a href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/lanczos.html">
315 * Boost Lanczos Approximation</a>
316 */
317 static final class Lanczos {
318 // Optimal values for G for each N are taken from
319 // http://web.mala.bc.ca/pughg/phdThesis/phdThesis.pdf,
320 // as are the theoretical error bounds.
321 //
322 // Constants calculated using the method described by Godfrey
323 // http://my.fit.edu/~gabdo/gamma.txt and elaborated by Toth at
324 // http://www.rskey.org/gamma.htm using NTL::RR at 1000 bit precision.
325
326 //
327 // Lanczos Coefficients for N=13 G=6.024680040776729583740234375
328 // Max experimental error (with arbitrary precision arithmetic) 1.196214e-17
329 // Generated with compiler: Microsoft Visual C++ version 8.0 on Win32 at Mar 23 2006
330 //
331
332 /**
333 * Lanczos constant G.
334 */
335 static final double G = 6.024680040776729583740234375;
336
337 /**
338 * Lanczos constant G - half.
339 *
340 * <p>Note: The form {@code (g - 0.5)} is used when computing the gamma function.
341 */
342 static final double GMH = 5.524680040776729583740234375;
343
344 /** Common denominator used for the rational evaluation. */
345 private static final int[] DENOM = {
346 0,
347 39916800,
348 120543840,
349 150917976,
350 105258076,
351 45995730,
352 13339535,
353 2637558,
354 357423,
355 32670,
356 1925,
357 66,
358 1
359 };
360
361 /** Private constructor. */
362 private Lanczos() {
363 // intentionally empty.
364 }
365
366 /**
367 * Computes the Lanczos approximation.
368 *
369 * @param z Argument.
370 * @return the Lanczos approximation.
371 */
372 static double lanczosSum(double z) {
373 final double[] num = {
374 23531376880.41075968857200767445163675473,
375 42919803642.64909876895789904700198885093,
376 35711959237.35566804944018545154716670596,
377 17921034426.03720969991975575445893111267,
378 6039542586.35202800506429164430729792107,
379 1439720407.311721673663223072794912393972,
380 248874557.8620541565114603864132294232163,
381 31426415.58540019438061423162831820536287,
382 2876370.628935372441225409051620849613599,
383 186056.2653952234950402949897160456992822,
384 8071.672002365816210638002902272250613822,
385 210.8242777515793458725097339207133627117,
386 2.506628274631000270164908177133837338626
387 };
388 return evaluateRational(num, DENOM, z);
389 }
390
391 /**
392 * Computes the Lanczos approximation scaled by {@code exp(g)}.
393 *
394 * @param z Argument.
395 * @return the scaled Lanczos approximation.
396 */
397 static double lanczosSumExpGScaled(double z) {
398 // As above with numerator divided by exp(g) = 413.509...
399 final double[] num = {
400 56906521.91347156388090791033559122686859,
401 103794043.1163445451906271053616070238554,
402 86363131.28813859145546927288977868422342,
403 43338889.32467613834773723740590533316085,
404 14605578.08768506808414169982791359218571,
405 3481712.15498064590882071018964774556468,
406 601859.6171681098786670226533699352302507,
407 75999.29304014542649875303443598909137092,
408 6955.999602515376140356310115515198987526,
409 449.9445569063168119446858607650988409623,
410 19.51992788247617482847860966235652136208,
411 0.5098416655656676188125178644804694509993,
412 0.006061842346248906525783753964555936883222
413 };
414 return evaluateRational(num, DENOM, z);
415 }
416
417 /**
418 * Evaluate the rational number as two polynomials.
419 *
420 * <p>Adapted from {@code boost/math/tools/detail/rational_horner3_13.hpp}.
421 * Note: There are 3 variations of the unrolled rational evaluation.
422 * These methods change the order based on the sign of x. This
423 * should be used for the Lanczos code as this comment in
424 * {@code boost/math/tools/rational.hpp} notes:
425 *
426 * <blockquote>
427 * However, there
428 * are some tricks we can use to prevent overflow that might otherwise
429 * occur in polynomial evaluation, if z is large. This is important
430 * in our Lanczos code for example.
431 * </blockquote>
432 *
433 * @param a Coefficients of the numerator polynomial
434 * @param b Coefficients of the denominator polynomial
435 * @param x Value
436 * @return the rational number
437 */
438 private static double evaluateRational(double[] a, int[] b, double x) {
439 // The choice of algorithm in Boost is based on the compiler
440 // to suite the available optimisations.
441 //
442 // Tests against rational_horner1_13.hpp which uses a first order
443 // Horner method (no x*x term) show only minor variations in
444 // error. rational_horner2_13.hpp has the same second order Horner
445 // method with different code layout of the same sum.
446
447 // rational_horner3_13.hpp
448 if (x <= 1) {
449 final double x2 = x * x;
450 double t0 = a[12] * x2 + a[10];
451 double t1 = a[11] * x2 + a[9];
452 double t2 = b[12] * x2 + b[10];
453 double t3 = b[11] * x2 + b[9];
454 t0 *= x2;
455 t1 *= x2;
456 t2 *= x2;
457 t3 *= x2;
458 t0 += a[8];
459 t1 += a[7];
460 t2 += b[8];
461 t3 += b[7];
462 t0 *= x2;
463 t1 *= x2;
464 t2 *= x2;
465 t3 *= x2;
466 t0 += a[6];
467 t1 += a[5];
468 t2 += b[6];
469 t3 += b[5];
470 t0 *= x2;
471 t1 *= x2;
472 t2 *= x2;
473 t3 *= x2;
474 t0 += a[4];
475 t1 += a[3];
476 t2 += b[4];
477 t3 += b[3];
478 t0 *= x2;
479 t1 *= x2;
480 t2 *= x2;
481 t3 *= x2;
482 t0 += a[2];
483 t1 += a[1];
484 t2 += b[2];
485 t3 += b[1];
486 t0 *= x2;
487 t2 *= x2;
488 t0 += a[0];
489 t2 += b[0];
490 t1 *= x;
491 t3 *= x;
492 return (t0 + t1) / (t2 + t3);
493 }
494 final double z = 1 / x;
495 final double z2 = 1 / (x * x);
496 double t0 = a[0] * z2 + a[2];
497 double t1 = a[1] * z2 + a[3];
498 double t2 = b[0] * z2 + b[2];
499 double t3 = b[1] * z2 + b[3];
500 t0 *= z2;
501 t1 *= z2;
502 t2 *= z2;
503 t3 *= z2;
504 t0 += a[4];
505 t1 += a[5];
506 t2 += b[4];
507 t3 += b[5];
508 t0 *= z2;
509 t1 *= z2;
510 t2 *= z2;
511 t3 *= z2;
512 t0 += a[6];
513 t1 += a[7];
514 t2 += b[6];
515 t3 += b[7];
516 t0 *= z2;
517 t1 *= z2;
518 t2 *= z2;
519 t3 *= z2;
520 t0 += a[8];
521 t1 += a[9];
522 t2 += b[8];
523 t3 += b[9];
524 t0 *= z2;
525 t1 *= z2;
526 t2 *= z2;
527 t3 *= z2;
528 t0 += a[10];
529 t1 += a[11];
530 t2 += b[10];
531 t3 += b[11];
532 t0 *= z2;
533 t2 *= z2;
534 t0 += a[12];
535 t2 += b[12];
536 t1 *= z;
537 t3 *= z;
538 return (t0 + t1) / (t2 + t3);
539 }
540
541 // Not implemented:
542 // lanczos_sum_near_1
543 // lanczos_sum_near_2
544 }
545
546 /** Private constructor. */
547 private BoostGamma() {
548 // intentionally empty.
549 }
550
551 /**
552 * All factorials that are representable as a double.
553 * This data is exposed for testing.
554 *
555 * @return factorials
556 */
557 static double[] getFactorials() {
558 return FACTORIAL.clone();
559 }
560
561 /**
562 * Returns the factorial of n.
563 * This is unchecked as an index out of bound exception will occur
564 * if the value n is not within the range [0, 170].
565 * This function is exposed for use in {@link BoostBeta}.
566 *
567 * @param n Argument n (must be in [0, 170])
568 * @return n!
569 */
570 static double uncheckedFactorial(int n) {
571 return FACTORIAL[n];
572 }
573
574 /**
575 * Gamma function.
576 *
577 * <p>For small {@code z} this is based on the <em>NSWC Library of Mathematics
578 * Subroutines</em> double precision implementation, {@code DGAMMA}.
579 *
580 * <p>For large {@code z} this is an implementation of the Boost C++ tgamma
581 * function with Lanczos support.
582 *
583 * <p>Integers are handled using a look-up table of factorials.
584 *
585 * <p>Note: The Boost C++ implementation uses the Lanczos sum for all {@code z}.
586 * When promotion of double to long double is not available this has larger
587 * errors than the double precision specific NSWC implementation. For larger
588 * {@code z} the Boost C++ Lanczos implementation incorporates the sqrt(2 pi)
589 * factor and has lower error than the implementation using the
590 * {@link LanczosApproximation} class.
591 *
592 * @param z Argument z
593 * @return gamma value
594 */
595 static double tgamma(double z) {
596 // Handle integers
597 if (Math.rint(z) == z) {
598 if (z <= 0) {
599 // Pole error
600 return Double.NaN;
601 }
602 if (z <= MAX_GAMMA_Z) {
603 // Gamma(n) = (n-1)!
604 return FACTORIAL[(int) z - 1];
605 }
606 // Overflow
607 return Double.POSITIVE_INFINITY;
608 }
609
610 if (Math.abs(z) <= LANCZOS_THRESHOLD) {
611 // Small z
612 // NSWC Library of Mathematics Subroutines
613 // Note:
614 // This does not benefit from using extended precision to track the sum (t).
615 // Extended precision on the product reduces the error but the majority
616 // of error remains in InvGamma1pm1.
617
618 if (z >= 1) {
619 /*
620 * From the recurrence relation
621 * Gamma(x) = (x - 1) * ... * (x - n) * Gamma(x - n),
622 * then
623 * Gamma(t) = 1 / [1 + InvGamma1pm1.value(t - 1)],
624 * where t = x - n. This means that t must satisfy
625 * -0.5 <= t - 1 <= 1.5.
626 */
627 double prod = 1;
628 double t = z;
629 while (t > 2.5) {
630 t -= 1;
631 prod *= t;
632 }
633 return prod / (1 + InvGamma1pm1.value(t - 1));
634 }
635 /*
636 * From the recurrence relation
637 * Gamma(x) = Gamma(x + n + 1) / [x * (x + 1) * ... * (x + n)]
638 * then
639 * Gamma(x + n + 1) = 1 / [1 + InvGamma1pm1.value(x + n)],
640 * which requires -0.5 <= x + n <= 1.5.
641 */
642 double prod = z;
643 double t = z;
644 while (t < -0.5) {
645 t += 1;
646 prod *= t;
647 }
648 return 1 / (prod * (1 + InvGamma1pm1.value(t)));
649 }
650
651 // Large non-integer z
652 // Boost C++ tgamma implementation
653
654 if (z < 0) {
655 /*
656 * From the reflection formula
657 * Gamma(x) * Gamma(1 - x) * sin(pi * x) = pi,
658 * and the recurrence relation
659 * Gamma(1 - x) = -x * Gamma(-x),
660 * it is found
661 * Gamma(x) = -pi / [x * sin(pi * x) * Gamma(-x)].
662 */
663 return -Math.PI / (sinpx(z) * tgamma(-z));
664 } else if (z > MAX_GAMMA_Z + 1) {
665 // Addition to the Boost code: Simple overflow detection
666 return Double.POSITIVE_INFINITY;
667 }
668
669 double result = Lanczos.lanczosSum(z);
670 final double zgh = z + Lanczos.GMH;
671 final double lzgh = Math.log(zgh);
672 if (z * lzgh > LOG_MAX_VALUE) {
673 // we're going to overflow unless this is done with care:
674
675 // Updated
676 // Check for overflow removed:
677 // if (lzgh * z / 2 > LOG_MAX_VALUE) ... overflow
678 // This is replaced by checking z > MAX_FACTORIAL + 2
679
680 final double hp = Math.pow(zgh, (z / 2) - 0.25);
681 result *= hp / Math.exp(zgh);
682 // Check for overflow has been removed:
683 // if (Double.MAX_VALUE / hp < result) ... overflow
684 result *= hp;
685 } else {
686 result *= Math.pow(zgh, z - 0.5) / Math.exp(zgh);
687 }
688
689 return result;
690 }
691
692 /**
693 * Ad hoc function calculates x * sin(pi * x), taking extra care near when x is
694 * near a whole number.
695 *
696 * @param x Value (assumed to be negative)
697 * @return x * sin(pi * x)
698 */
699 static double sinpx(double x) {
700 int sign = 1;
701 // This is always called with a negative
702 // if (x < 0)
703 x = -x;
704 double fl = Math.floor(x);
705 double dist;
706 if (isOdd(fl)) {
707 fl += 1;
708 dist = fl - x;
709 sign = -sign;
710 } else {
711 dist = x - fl;
712 }
713 if (dist > 0.5f) {
714 dist = 1 - dist;
715 }
716 final double result = Math.sin(dist * Math.PI);
717 return sign * x * result;
718 }
719
720 /**
721 * Checks if the value is odd.
722 *
723 * @param v Value (assumed to be positive and an integer)
724 * @return true if odd
725 */
726 private static boolean isOdd(double v) {
727 // Note:
728 // Any value larger than 2^53 should be even.
729 // If the input is positive then truncation of extreme doubles (>2^63)
730 // to the primitive long creates an odd value: 2^63-1.
731 // This is corrected by inverting the sign of v and the extreme is even: -2^63.
732 // This function is never called when the argument is this large
733 // as this is a pole error in tgamma so the effect is never observed.
734 // However the isOdd function is correct for all positive finite v.
735 return (((long) -v) & 0x1) == 1;
736 }
737
738 /**
739 * Log Gamma function.
740 * Defined as the natural logarithm of the absolute value of tgamma(z).
741 *
742 * @param z Argument z
743 * @return log gamma value
744 */
745 static double lgamma(double z) {
746 return lgamma(z, null);
747 }
748
749 /**
750 * Log Gamma function.
751 * Defined as the natural logarithm of the absolute value of tgamma(z).
752 *
753 * @param z Argument z
754 * @param sign If a non-zero length array the first index is set on output to the sign of tgamma(z)
755 * @return log gamma value
756 */
757 static double lgamma(double z, int[] sign) {
758 double result;
759 int sresult = 1;
760 if (z <= -ROOT_EPSILON) {
761 // reflection formula:
762 if (Math.rint(z) == z) {
763 // Pole error
764 return Double.NaN;
765 }
766
767 double t = sinpx(z);
768 z = -z;
769 if (t < 0) {
770 t = -t;
771 } else {
772 sresult = -sresult;
773 }
774
775 // This summation can have large magnitudes with opposite signs.
776 // Use an extended precision sum to reduce cancellation.
777 result = Sum.of(-lgamma(z)).add(-Math.log(t)).add(LOG_PI).getAsDouble();
778 } else if (z < ROOT_EPSILON) {
779 if (z == 0) {
780 // Pole error
781 return Double.NaN;
782 }
783 if (4 * Math.abs(z) < EPSILON) {
784 result = -Math.log(Math.abs(z));
785 } else {
786 result = Math.log(Math.abs(1 / z - EULER));
787 }
788 if (z < 0) {
789 sresult = -1;
790 }
791 } else if (z < 15) {
792 result = lgammaSmall(z, z - 1, z - 2);
793 // The z > 3 condition is always true
794 //} else if (z > 3 && z < 100) {
795 } else if (z < 100) {
796 // taking the log of tgamma reduces the error, no danger of overflow here:
797 result = Math.log(tgamma(z));
798 } else {
799 // regular evaluation:
800 final double zgh = z + Lanczos.GMH;
801 result = Math.log(zgh) - 1;
802 result *= z - 0.5f;
803 //
804 // Only add on the lanczos sum part if we're going to need it:
805 //
806 if (result * EPSILON < 20) {
807 result += Math.log(Lanczos.lanczosSumExpGScaled(z));
808 }
809 }
810
811 if (nonZeroLength(sign)) {
812 sign[0] = sresult;
813 }
814 return result;
815 }
816
817 /**
818 * Log Gamma function for small z.
819 *
820 * @param z Argument z
821 * @param zm1 {@code z - 1}
822 * @param zm2 {@code z - 2}
823 * @return log gamma value
824 */
825 private static double lgammaSmall(double z, double zm1, double zm2) {
826 // This version uses rational approximations for small
827 // values of z accurate enough for 64-bit mantissas
828 // (80-bit long doubles), works well for 53-bit doubles as well.
829
830 // Updated to use an extended precision sum
831 final Sum result = Sum.create();
832
833 // Note:
834 // Removed z < EPSILON branch.
835 // The function is called
836 // from lgamma:
837 // ROOT_EPSILON <= z < 15
838 // from tgamma1pm1:
839 // 1.5 <= z < 2
840 // 1 <= z < 3
841
842 if ((zm1 == 0) || (zm2 == 0)) {
843 // nothing to do, result is zero....
844 return 0;
845 } else if (z > 2) {
846 //
847 // Begin by performing argument reduction until
848 // z is in [2,3):
849 //
850 if (z >= 3) {
851 do {
852 z -= 1;
853 result.add(Math.log(z));
854 } while (z >= 3);
855 // Update zm2, we need it below:
856 zm2 = z - 2;
857 }
858
859 //
860 // Use the following form:
861 //
862 // lgamma(z) = (z-2)(z+1)(Y + R(z-2))
863 //
864 // where R(z-2) is a rational approximation optimised for
865 // low absolute error - as long as its absolute error
866 // is small compared to the constant Y - then any rounding
867 // error in its computation will get wiped out.
868 //
869 // R(z-2) has the following properties:
870 //
871 // At double: Max error found: 4.231e-18
872 // At long double: Max error found: 1.987e-21
873 // Maximum Deviation Found (approximation error): 5.900e-24
874 //
875 double P;
876 P = -0.324588649825948492091e-4;
877 P = -0.541009869215204396339e-3 + P * zm2;
878 P = -0.259453563205438108893e-3 + P * zm2;
879 P = 0.172491608709613993966e-1 + P * zm2;
880 P = 0.494103151567532234274e-1 + P * zm2;
881 P = 0.25126649619989678683e-1 + P * zm2;
882 P = -0.180355685678449379109e-1 + P * zm2;
883 double Q;
884 Q = -0.223352763208617092964e-6;
885 Q = 0.224936291922115757597e-3 + Q * zm2;
886 Q = 0.82130967464889339326e-2 + Q * zm2;
887 Q = 0.988504251128010129477e-1 + Q * zm2;
888 Q = 0.541391432071720958364e0 + Q * zm2;
889 Q = 0.148019669424231326694e1 + Q * zm2;
890 Q = 0.196202987197795200688e1 + Q * zm2;
891 Q = 0.1e1 + Q * zm2;
892
893 final float Y = 0.158963680267333984375e0f;
894
895 final double r = zm2 * (z + 1);
896 final double R = P / Q;
897
898 result.addProduct(r, Y).addProduct(r, R);
899 } else {
900 //
901 // If z is less than 1 use recurrence to shift to
902 // z in the interval [1,2]:
903 //
904 if (z < 1) {
905 result.add(-Math.log(z));
906 zm2 = zm1;
907 zm1 = z;
908 z += 1;
909 }
910 //
911 // Two approximations, one for z in [1,1.5] and
912 // one for z in [1.5,2]:
913 //
914 if (z <= 1.5) {
915 //
916 // Use the following form:
917 //
918 // lgamma(z) = (z-1)(z-2)(Y + R(z-1
919 //
920 // where R(z-1) is a rational approximation optimised for
921 // low absolute error - as long as its absolute error
922 // is small compared to the constant Y - then any rounding
923 // error in its computation will get wiped out.
924 //
925 // R(z-1) has the following properties:
926 //
927 // At double precision: Max error found: 1.230011e-17
928 // At 80-bit long double precision: Max error found: 5.631355e-21
929 // Maximum Deviation Found: 3.139e-021
930 // Expected Error Term: 3.139e-021
931
932 //
933 final float Y = 0.52815341949462890625f;
934
935 double P;
936 P = -0.100346687696279557415e-2;
937 P = -0.240149820648571559892e-1 + P * zm1;
938 P = -0.158413586390692192217e0 + P * zm1;
939 P = -0.406567124211938417342e0 + P * zm1;
940 P = -0.414983358359495381969e0 + P * zm1;
941 P = -0.969117530159521214579e-1 + P * zm1;
942 P = 0.490622454069039543534e-1 + P * zm1;
943 double Q;
944 Q = 0.195768102601107189171e-2;
945 Q = 0.577039722690451849648e-1 + Q * zm1;
946 Q = 0.507137738614363510846e0 + Q * zm1;
947 Q = 0.191415588274426679201e1 + Q * zm1;
948 Q = 0.348739585360723852576e1 + Q * zm1;
949 Q = 0.302349829846463038743e1 + Q * zm1;
950 Q = 0.1e1 + Q * zm1;
951
952 final double r = P / Q;
953 final double prefix = zm1 * zm2;
954
955 result.addProduct(prefix, Y).addProduct(prefix, r);
956 } else {
957 //
958 // Use the following form:
959 //
960 // lgamma(z) = (2-z)(1-z)(Y + R(2-z
961 //
962 // where R(2-z) is a rational approximation optimised for
963 // low absolute error - as long as its absolute error
964 // is small compared to the constant Y - then any rounding
965 // error in its computation will get wiped out.
966 //
967 // R(2-z) has the following properties:
968 //
969 // At double precision, max error found: 1.797565e-17
970 // At 80-bit long double precision, max error found: 9.306419e-21
971 // Maximum Deviation Found: 2.151e-021
972 // Expected Error Term: 2.150e-021
973 //
974 final float Y = 0.452017307281494140625f;
975
976 final double mzm2 = -zm2;
977 double P;
978 P = 0.431171342679297331241e-3;
979 P = -0.850535976868336437746e-2 + P * mzm2;
980 P = 0.542809694055053558157e-1 + P * mzm2;
981 P = -0.142440390738631274135e0 + P * mzm2;
982 P = 0.144216267757192309184e0 + P * mzm2;
983 P = -0.292329721830270012337e-1 + P * mzm2;
984 double Q;
985 Q = -0.827193521891290553639e-6;
986 Q = -0.100666795539143372762e-2 + Q * mzm2;
987 Q = 0.25582797155975869989e-1 + Q * mzm2;
988 Q = -0.220095151814995745555e0 + Q * mzm2;
989 Q = 0.846973248876495016101e0 + Q * mzm2;
990 Q = -0.150169356054485044494e1 + Q * mzm2;
991 Q = 0.1e1 + Q * mzm2;
992 final double r = zm2 * zm1;
993 final double R = P / Q;
994
995 result.addProduct(r, Y).addProduct(r, R);
996 }
997 }
998 return result.getAsDouble();
999 }
1000
1001 /**
1002 * Calculates tgamma(1+dz)-1.
1003 *
1004 * @param dz Argument
1005 * @return tgamma(1+dz)-1
1006 */
1007 static double tgamma1pm1(double dz) {
1008 //
1009 // This helper calculates tgamma(1+dz)-1 without cancellation errors,
1010 // used by the upper incomplete gamma with z < 1:
1011 //
1012 final double result;
1013 if (dz < 0) {
1014 if (dz < -0.5) {
1015 // Best method is simply to subtract 1 from tgamma:
1016 result = tgamma(1 + dz) - 1;
1017 } else {
1018 // Use expm1 on lgamma:
1019 result = Math.expm1(-Math.log1p(dz) + lgammaSmall(dz + 2, dz + 1, dz));
1020 }
1021 } else {
1022 if (dz < 2) {
1023 // Use expm1 on lgamma:
1024 result = Math.expm1(lgammaSmall(dz + 1, dz, dz - 1));
1025 } else {
1026 // Best method is simply to subtract 1 from tgamma:
1027 result = tgamma(1 + dz) - 1;
1028 }
1029 }
1030
1031 return result;
1032 }
1033
1034 /**
1035 * Full upper incomplete gamma.
1036 *
1037 * @param a Argument a
1038 * @param x Argument x
1039 * @return upper gamma value
1040 */
1041 static double tgamma(double a, double x) {
1042 return gammaIncompleteImp(a, x, false, true, Policy.getDefault());
1043 }
1044
1045 /**
1046 * Full upper incomplete gamma.
1047 *
1048 * @param a Argument a
1049 * @param x Argument x
1050 * @param policy Function evaluation policy
1051 * @return upper gamma value
1052 */
1053 static double tgamma(double a, double x, Policy policy) {
1054 return gammaIncompleteImp(a, x, false, true, policy);
1055 }
1056
1057 /**
1058 * Full lower incomplete gamma.
1059 *
1060 * @param a Argument a
1061 * @param x Argument x
1062 * @return lower gamma value
1063 */
1064 static double tgammaLower(double a, double x) {
1065 return gammaIncompleteImp(a, x, false, false, Policy.getDefault());
1066 }
1067
1068 /**
1069 * Full lower incomplete gamma.
1070 *
1071 * @param a Argument a
1072 * @param x Argument x
1073 * @param policy Function evaluation policy
1074 * @return lower gamma value
1075 */
1076 static double tgammaLower(double a, double x, Policy policy) {
1077 return gammaIncompleteImp(a, x, false, false, policy);
1078 }
1079
1080 /**
1081 * Regularised upper incomplete gamma.
1082 *
1083 * @param a Argument a
1084 * @param x Argument x
1085 * @return q
1086 */
1087 static double gammaQ(double a, double x) {
1088 return gammaIncompleteImp(a, x, true, true, Policy.getDefault());
1089 }
1090
1091 /**
1092 * Regularised upper incomplete gamma.
1093 *
1094 * @param a Argument a
1095 * @param x Argument x
1096 * @param policy Function evaluation policy
1097 * @return q
1098 */
1099 static double gammaQ(double a, double x, Policy policy) {
1100 return gammaIncompleteImp(a, x, true, true, policy);
1101 }
1102
1103 /**
1104 * Regularised lower incomplete gamma.
1105 *
1106 * @param a Argument a
1107 * @param x Argument x
1108 * @return p
1109 */
1110 static double gammaP(double a, double x) {
1111 return gammaIncompleteImp(a, x, true, false, Policy.getDefault());
1112 }
1113
1114 /**
1115 * Regularised lower incomplete gamma.
1116 *
1117 * @param a Argument a
1118 * @param x Argument x
1119 * @param policy Function evaluation policy
1120 * @return p
1121 */
1122 static double gammaP(double a, double x, Policy policy) {
1123 return gammaIncompleteImp(a, x, true, false, policy);
1124 }
1125
1126 /**
1127 * Derivative of the regularised lower incomplete gamma.
1128 * <p>\( \frac{e^{-x} x^{a-1}}{\Gamma(a)} \)
1129 *
1130 * <p>Adapted from {@code boost::math::detail::gamma_p_derivative_imp}
1131 *
1132 * @param a Argument a
1133 * @param x Argument x
1134 * @return p derivative
1135 */
1136 static double gammaPDerivative(double a, double x) {
1137 //
1138 // Usual error checks first:
1139 //
1140 if (Double.isNaN(a) || Double.isNaN(x) || a <= 0 || x < 0) {
1141 return Double.NaN;
1142 }
1143 //
1144 // Now special cases:
1145 //
1146 if (x == 0) {
1147 if (a > 1) {
1148 return 0;
1149 }
1150 return (a == 1) ? 1 : Double.POSITIVE_INFINITY;
1151 }
1152 //
1153 // Normal case:
1154 //
1155 double f1 = regularisedGammaPrefix(a, x);
1156 if (f1 == 0) {
1157 // Underflow in calculation, use logs instead:
1158 f1 = a * Math.log(x) - x - lgamma(a) - Math.log(x);
1159 f1 = Math.exp(f1);
1160 } else {
1161 // Will overflow when (x < 1) && (Double.MAX_VALUE * x < f1).
1162 // There is no exception for this case so just return the result.
1163 f1 /= x;
1164 }
1165
1166 return f1;
1167 }
1168
1169 /**
1170 * Main incomplete gamma entry point, handles all four incomplete gammas.
1171 * Adapted from {@code boost::math::detail::gamma_incomplete_imp}.
1172 *
1173 * <p>The Boost code has a pointer {@code p_derivative} that can be set to the
1174 * value of the derivative. This is used for the inverse incomplete
1175 * gamma functions {@code gamma_(p|q)_inv_imp}. It is not required for the forward
1176 * evaluation functions.
1177 *
1178 * @param a Argument a
1179 * @param x Argument x
1180 * @param normalised true to compute the regularised value
1181 * @param invert true to compute the upper value Q (default is lower value P)
1182 * @param pol Function evaluation policy
1183 * @return gamma value
1184 */
1185 private static double gammaIncompleteImp(double a, double x,
1186 boolean normalised, boolean invert, Policy pol) {
1187 if (Double.isNaN(a) || Double.isNaN(x) || a <= 0 || x < 0) {
1188 return Double.NaN;
1189 }
1190
1191 double result = 0;
1192
1193 if (a >= MAX_FACTORIAL && !normalised) {
1194 //
1195 // When we're computing the non-normalized incomplete gamma
1196 // and a is large the result is rather hard to compute unless
1197 // we use logs. There are really two options - if x is a long
1198 // way from a in value then we can reliably use methods 2 and 4
1199 // below in logarithmic form and go straight to the result.
1200 // Otherwise we let the regularized gamma take the strain
1201 // (the result is unlikely to underflow in the central region anyway)
1202 // and combine with lgamma in the hopes that we get a finite result.
1203 //
1204
1205 if (invert && (a * 4 < x)) {
1206 // This is method 4 below, done in logs:
1207 result = a * Math.log(x) - x;
1208 result += Math.log(upperGammaFraction(a, x, pol));
1209 } else if (!invert && (a > 4 * x)) {
1210 // This is method 2 below, done in logs:
1211 result = a * Math.log(x) - x;
1212 result += Math.log(lowerGammaSeries(a, x, 0, pol) / a);
1213 } else {
1214 result = gammaIncompleteImp(a, x, true, invert, pol);
1215 if (result == 0) {
1216 if (invert) {
1217 // Try http://functions.wolfram.com/06.06.06.0039.01
1218 result = 1 + 1 / (12 * a) + 1 / (288 * a * a);
1219 result = Math.log(result) - a + (a - 0.5f) * Math.log(a) + LOG_ROOT_TWO_PI;
1220 } else {
1221 // This is method 2 below, done in logs, we're really outside the
1222 // range of this method, but since the result is almost certainly
1223 // infinite, we should probably be OK:
1224 result = a * Math.log(x) - x;
1225 result += Math.log(lowerGammaSeries(a, x, 0, pol) / a);
1226 }
1227 } else {
1228 result = Math.log(result) + lgamma(a);
1229 }
1230 }
1231 // If result is > log(MAX_VALUE) the result will overflow.
1232 // There is no exception for this case so just return the result.
1233 return Math.exp(result);
1234 }
1235
1236 final boolean isInt;
1237 final boolean isHalfInt;
1238 // Update. x must be safe for exp(-x). Change to -x > LOG_MIN_VALUE.
1239 final boolean isSmallA = (a < 30) && (a <= x + 1) && (-x > LOG_MIN_VALUE);
1240 if (isSmallA) {
1241 final double fa = Math.floor(a);
1242 isInt = fa == a;
1243 isHalfInt = !isInt && (Math.abs(fa - a) == 0.5f);
1244 } else {
1245 isInt = isHalfInt = false;
1246 }
1247
1248 final int evalMethod;
1249
1250 if (isInt && (x > 0.6)) {
1251 // calculate Q via finite sum:
1252 invert = !invert;
1253 evalMethod = 0;
1254 } else if (isHalfInt && (x > 0.2)) {
1255 // calculate Q via finite sum for half integer a:
1256 invert = !invert;
1257 evalMethod = 1;
1258 } else if ((x < ROOT_EPSILON) && (a > 1)) {
1259 evalMethod = 6;
1260 } else if ((x > 1000) && (a < x * 0.75f)) {
1261 // Note:
1262 // The branch is used in Boost when:
1263 // ((x > 1000) && ((a < x) || (Math.abs(a - 50) / x < 1)))
1264 //
1265 // This case was added after Boost 1_68_0.
1266 // See: https://github.com/boostorg/math/issues/168
1267 //
1268 // When using only double precision for the evaluation
1269 // it is a source of error when a ~ z as the asymptotic approximation
1270 // sums terms t_n+1 = t_n * (a - n - 1) / z starting from t_0 = 1.
1271 // These terms are close to 1 when a ~ z and the sum has many terms
1272 // with reduced precision.
1273 // This has been updated to allow only cases with fast convergence.
1274 // It will be used when x -> infinity and a << x.
1275
1276 // calculate Q via asymptotic approximation:
1277 invert = !invert;
1278 evalMethod = 7;
1279 } else if (x < 0.5) {
1280 //
1281 // Changeover criterion chosen to give a changeover at Q ~ 0.33
1282 //
1283 if (-0.4 / Math.log(x) < a) {
1284 // Compute P
1285 evalMethod = 2;
1286 } else {
1287 evalMethod = 3;
1288 }
1289 } else if (x < 1.1) {
1290 //
1291 // Changover here occurs when P ~ 0.75 or Q ~ 0.25:
1292 //
1293 if (x * 0.75f < a) {
1294 // Compute P
1295 evalMethod = 2;
1296 } else {
1297 evalMethod = 3;
1298 }
1299 } else {
1300 //
1301 // Begin by testing whether we're in the "bad" zone
1302 // where the result will be near 0.5 and the usual
1303 // series and continued fractions are slow to converge:
1304 //
1305 boolean useTemme = false;
1306 if (normalised && (a > 20)) {
1307 final double sigma = Math.abs((x - a) / a);
1308 if (a > 200) {
1309 //
1310 // This limit is chosen so that we use Temme's expansion
1311 // only if the result would be larger than about 10^-6.
1312 // Below that the regular series and continued fractions
1313 // converge OK, and if we use Temme's method we get increasing
1314 // errors from the dominant erfc term as its (inexact) argument
1315 // increases in magnitude.
1316 //
1317 if (20 / a > sigma * sigma) {
1318 useTemme = true;
1319 }
1320 } else {
1321 // Note in this zone we can't use Temme's expansion for
1322 // types longer than an 80-bit real:
1323 // it would require too many terms in the polynomials.
1324 if (sigma < 0.4) {
1325 useTemme = true;
1326 }
1327 }
1328 }
1329 if (useTemme) {
1330 evalMethod = 5;
1331 } else {
1332 //
1333 // Regular case where the result will not be too close to 0.5.
1334 //
1335 // Changeover here occurs at P ~ Q ~ 0.5
1336 // Note that series computation of P is about x2 faster than continued fraction
1337 // calculation of Q, so try and use the CF only when really necessary,
1338 // especially for small x.
1339 //
1340 if (x - (1 / (3 * x)) < a) {
1341 evalMethod = 2;
1342 } else {
1343 evalMethod = 4;
1344 invert = !invert;
1345 }
1346 }
1347 }
1348
1349 switch (evalMethod) {
1350 case 0:
1351 result = finiteGammaQ(a, x);
1352 if (!normalised) {
1353 result *= tgamma(a);
1354 }
1355 break;
1356 case 1:
1357 result = finiteHalfGammaQ(a, x);
1358 if (!normalised) {
1359 result *= tgamma(a);
1360 }
1361 break;
1362 case 2:
1363 // Compute P:
1364 result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1365 if (result != 0) {
1366 //
1367 // If we're going to be inverting the result then we can
1368 // reduce the number of series evaluations by quite
1369 // a few iterations if we set an initial value for the
1370 // series sum based on what we'll end up subtracting it from
1371 // at the end.
1372 // Have to be careful though that this optimization doesn't
1373 // lead to spurious numeric overflow. Note that the
1374 // scary/expensive overflow checks below are more often
1375 // than not bypassed in practice for "sensible" input
1376 // values:
1377 //
1378
1379 double initValue = 0;
1380 boolean optimisedInvert = false;
1381 if (invert) {
1382 initValue = normalised ? 1 : tgamma(a);
1383 if (normalised || (result >= 1) || (Double.MAX_VALUE * result > initValue)) {
1384 initValue /= result;
1385 if (normalised || (a < 1) || (Double.MAX_VALUE / a > initValue)) {
1386 initValue *= -a;
1387 optimisedInvert = true;
1388 } else {
1389 initValue = 0;
1390 }
1391 } else {
1392 initValue = 0;
1393 }
1394 }
1395 result *= lowerGammaSeries(a, x, initValue, pol) / a;
1396 if (optimisedInvert) {
1397 invert = false;
1398 result = -result;
1399 }
1400 }
1401 break;
1402 case 3:
1403 // Compute Q:
1404 invert = !invert;
1405 final double[] g = {0};
1406 result = tgammaSmallUpperPart(a, x, pol, g, invert);
1407 invert = false;
1408 if (normalised) {
1409 // Addition to the Boost code:
1410 if (g[0] == Double.POSITIVE_INFINITY) {
1411 // Very small a will overflow gamma(a). Resort to logs.
1412 // This method requires improvement as the error is very large.
1413 // It is better than returning zero for a non-zero result.
1414 result = Math.exp(Math.log(result) - lgamma(a));
1415 } else {
1416 result /= g[0];
1417 }
1418 }
1419 break;
1420 case 4:
1421 // Compute Q:
1422 result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1423 if (result != 0) {
1424 result *= upperGammaFraction(a, x, pol);
1425 }
1426 break;
1427 case 5:
1428 // Call 53-bit version
1429 result = igammaTemmeLarge(a, x);
1430 if (x >= a) {
1431 invert = !invert;
1432 }
1433 break;
1434 case 6:
1435 // x is so small that P is necessarily very small too, use
1436 // http://functions.wolfram.com/GammaBetaErf/GammaRegularized/06/01/05/01/01/
1437 if (normalised) {
1438 // If tgamma overflows then result = 0
1439 result = Math.pow(x, a) / tgamma(a + 1);
1440 } else {
1441 result = Math.pow(x, a) / a;
1442 }
1443 result *= 1 - a * x / (a + 1);
1444 break;
1445 case 7:
1446 default:
1447 // x is large,
1448 // Compute Q:
1449 result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1450 result /= x;
1451 if (result != 0) {
1452 result *= incompleteTgammaLargeX(a, x, pol);
1453 }
1454 break;
1455 }
1456
1457 if (normalised && (result > 1)) {
1458 result = 1;
1459 }
1460 if (invert) {
1461 final double gam = normalised ? 1 : tgamma(a);
1462 result = gam - result;
1463 }
1464
1465 return result;
1466 }
1467
1468 /**
1469 * Upper gamma fraction.
1470 * Multiply result by z^a * e^-z to get the full
1471 * upper incomplete integral. Divide by tgamma(z)
1472 * to normalise.
1473 *
1474 * @param a Argument a
1475 * @param z Argument z
1476 * @param pol Function evaluation policy
1477 * @return upper gamma fraction
1478 */
1479 // This is package-private for testing
1480 static double upperGammaFraction(double a, double z, Policy pol) {
1481 final double eps = pol.getEps();
1482 final int maxIterations = pol.getMaxIterations();
1483
1484 // This is computing:
1485 // 1
1486 // ------------------------------
1487 // b0 + a1 / (b1 + a2 )
1488 // -------------
1489 // b2 + a3
1490 // --------
1491 // b3 + ...
1492 //
1493 // b0 = z - a + 1
1494 // a1 = a - 1
1495 //
1496 // It can be done several ways with variations in accuracy.
1497 // The current implementation has the best accuracy and matches the Boost code.
1498
1499 final double zma1 = z - a + 1;
1500
1501 final Supplier<Coefficient> gen = new Supplier<Coefficient>() {
1502 /** Iteration. */
1503 private int k;
1504
1505 @Override
1506 public Coefficient get() {
1507 ++k;
1508 return Coefficient.of(k * (a - k), zma1 + 2.0 * k);
1509 }
1510 };
1511
1512 return 1 / GeneralizedContinuedFraction.value(zma1, gen, eps, maxIterations);
1513 }
1514
1515 /**
1516 * Upper gamma fraction for integer a.
1517 * Called when {@code a < 30} and {@code -x > LOG_MIN_VALUE}.
1518 *
1519 * @param a Argument a (assumed to be small)
1520 * @param x Argument x
1521 * @return upper gamma fraction
1522 */
1523 private static double finiteGammaQ(double a, double x) {
1524 //
1525 // Calculates normalised Q when a is an integer:
1526 //
1527
1528 // Update:
1529 // Assume -x > log min value and no underflow to zero.
1530
1531 double sum = Math.exp(-x);
1532 double term = sum;
1533 for (int n = 1; n < a; ++n) {
1534 term /= n;
1535 term *= x;
1536 sum += term;
1537 }
1538 return sum;
1539 }
1540
1541 /**
1542 * Upper gamma fraction for half integer a.
1543 * Called when {@code a < 30} and {@code -x > LOG_MIN_VALUE}.
1544 *
1545 * @param a Argument a (assumed to be small)
1546 * @param x Argument x
1547 * @return upper gamma fraction
1548 */
1549 private static double finiteHalfGammaQ(double a, double x) {
1550 //
1551 // Calculates normalised Q when a is a half-integer:
1552 //
1553
1554 // Update:
1555 // Assume -x > log min value:
1556 // erfc(sqrt(708)) = erfc(26.6) => erfc has a non-zero value
1557
1558 double e = BoostErf.erfc(Math.sqrt(x));
1559 if (a > 1) {
1560 double term = Math.exp(-x) / Math.sqrt(Math.PI * x);
1561 term *= x;
1562 term /= 0.5;
1563 double sum = term;
1564 for (int n = 2; n < a; ++n) {
1565 term /= n - 0.5;
1566 term *= x;
1567 sum += term;
1568 }
1569 e += sum;
1570 }
1571 return e;
1572 }
1573
1574 /**
1575 * Lower gamma series.
1576 * Multiply result by ((z^a) * (e^-z) / a) to get the full
1577 * lower incomplete integral. Then divide by tgamma(a)
1578 * to get the normalised value.
1579 *
1580 * @param a Argument a
1581 * @param z Argument z
1582 * @param initValue Initial value
1583 * @param pol Function evaluation policy
1584 * @return lower gamma series
1585 */
1586 // This is package-private for testing
1587 static double lowerGammaSeries(double a, double z, double initValue, Policy pol) {
1588 final double eps = pol.getEps();
1589 final int maxIterations = pol.getMaxIterations();
1590
1591 // Lower gamma series representation.
1592 final DoubleSupplier gen = new DoubleSupplier() {
1593 /** Next result. */
1594 private double result = 1;
1595 /** Iteration. */
1596 private int n;
1597
1598 @Override
1599 public double getAsDouble() {
1600 final double r = result;
1601 n++;
1602 result *= z / (a + n);
1603 return r;
1604 }
1605 };
1606
1607 return BoostTools.kahanSumSeries(gen, eps, maxIterations, initValue);
1608 }
1609
1610 /**
1611 * Upper gamma fraction for very small a.
1612 *
1613 * @param a Argument a (assumed to be small)
1614 * @param x Argument x
1615 * @param pol Function evaluation policy
1616 * @param pgam set to value of gamma(a) on output
1617 * @param invert true to invert the result
1618 * @return upper gamma fraction
1619 */
1620 private static double tgammaSmallUpperPart(double a, double x, Policy pol, double[] pgam, boolean invert) {
1621 //
1622 // Compute the full upper fraction (Q) when a is very small:
1623 //
1624 double result;
1625 result = tgamma1pm1(a);
1626
1627 // Note: Replacing this with tgamma(a) does not reduce error on current test data.
1628
1629 // gamma(1+z) = z gamma(z)
1630 // pgam[0] == gamma(a)
1631 pgam[0] = (result + 1) / a;
1632
1633 double p = BoostMath.powm1(x, a);
1634 result -= p;
1635 result /= a;
1636 // Removed subtraction of 10 from this value
1637 final int maxIter = pol.getMaxIterations();
1638 p += 1;
1639 final double initValue = invert ? pgam[0] : 0;
1640
1641 // Series representation for upper fraction when z is small.
1642 final DoubleSupplier gen = new DoubleSupplier() {
1643 /** Result term. */
1644 private double result = -x;
1645 /** Argument x (this is negated on purpose). */
1646 private final double z = -x;
1647 /** Iteration. */
1648 private int n = 1;
1649
1650 @Override
1651 public double getAsDouble() {
1652 final double r = result / (a + n);
1653 n++;
1654 result = result * z / n;
1655 return r;
1656 }
1657 };
1658
1659 result = -p * BoostTools.kahanSumSeries(gen, pol.getEps(), maxIter, (initValue - result) / p);
1660 if (invert) {
1661 result = -result;
1662 }
1663 return result;
1664 }
1665
1666 /**
1667 * Calculate power term prefix (z^a)(e^-z) used in the non-normalised
1668 * incomplete gammas.
1669 *
1670 * @param a Argument a
1671 * @param z Argument z
1672 * @return incomplete gamma prefix
1673 */
1674 static double fullIgammaPrefix(double a, double z) {
1675 if (z > Double.MAX_VALUE) {
1676 return 0;
1677 }
1678 final double alz = a * Math.log(z);
1679 final double prefix;
1680
1681 if (z >= 1) {
1682 if ((alz < LOG_MAX_VALUE) && (-z > LOG_MIN_VALUE)) {
1683 prefix = Math.pow(z, a) * Math.exp(-z);
1684 } else if (a >= 1) {
1685 prefix = Math.pow(z / Math.exp(z / a), a);
1686 } else {
1687 prefix = Math.exp(alz - z);
1688 }
1689 } else {
1690 if (alz > LOG_MIN_VALUE) {
1691 prefix = Math.pow(z, a) * Math.exp(-z);
1692 } else {
1693 // Updated to remove unreachable final branch using Math.exp(alz - z).
1694 // This branch requires (z / a < LOG_MAX_VALUE) to avoid overflow in exp.
1695 // At this point:
1696 // 1. log(z) is negative;
1697 // 2. a * log(z) <= -708 requires a > -708 / log(z).
1698 // For any z < 1: -708 / log(z) is > z. Thus a is > z and
1699 // z / a < LOG_MAX_VALUE is always true.
1700 prefix = Math.pow(z / Math.exp(z / a), a);
1701 }
1702 }
1703 // Removed overflow check. Return infinity if it occurs.
1704 return prefix;
1705 }
1706
1707 /**
1708 * Compute (z^a)(e^-z)/tgamma(a).
1709 * <p>Most of the error occurs in this function.
1710 *
1711 * @param a Argument a
1712 * @param z Argument z
1713 * @return regularized gamma prefix
1714 */
1715 // This is package-private for testing
1716 static double regularisedGammaPrefix(double a, double z) {
1717 if (z >= Double.MAX_VALUE) {
1718 return 0;
1719 }
1720
1721 // Update this condition from: a < 1
1722 if (a <= 1) {
1723 //
1724 // We have to treat a < 1 as a special case because our Lanczos
1725 // approximations are optimised against the factorials with a > 1,
1726 // and for high precision types especially (128-bit reals for example)
1727 // very small values of a can give rather erroneous results for gamma
1728 // unless we do this:
1729 //
1730 // Boost todo: is this still required? Lanczos approx should be better now?
1731 //
1732
1733 // Update this condition from: z <= LOG_MIN_VALUE
1734 // Require exp(-z) to not underflow:
1735 // -z > log(min_value)
1736 if (-z <= LOG_MIN_VALUE) {
1737 // Oh dear, have to use logs, should be free of cancellation errors though:
1738 return Math.exp(a * Math.log(z) - z - lgamma(a));
1739 }
1740 // direct calculation, no danger of overflow as gamma(a) < 1/a
1741 // for small a.
1742 return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1743 }
1744
1745 // Update to the Boost code.
1746 // Use some of the logic from fullIgammaPrefix(a, z) to use the direct
1747 // computation if it is valid. Assuming pow and exp are accurate to 1 ULP it
1748 // puts most of the error in evaluation of tgamma(a). This is accurate
1749 // enough that this reduces max error on the current test data.
1750 //
1751 // Overflow cases fall-through to the Lanczos approximation that incorporates
1752 // the pow and exp terms used in the tgamma(a) computation with the terms
1753 // z^a and e^-z into a single evaluation of pow and exp. See equation 15:
1754 // https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html
1755 if (a <= MAX_GAMMA_Z) {
1756 final double alz1 = a * Math.log(z);
1757 if (z >= 1) {
1758 if ((alz1 < LOG_MAX_VALUE) && (-z > LOG_MIN_VALUE)) {
1759 return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1760 }
1761 } else if (alz1 > LOG_MIN_VALUE) {
1762 return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1763 }
1764 }
1765
1766 //
1767 // For smallish a and x combining the power terms with the Lanczos approximation
1768 // gives the greatest accuracy
1769 //
1770
1771 final double agh = a + Lanczos.GMH;
1772 double prefix;
1773
1774 final double factor = Math.sqrt(agh / Math.E) / Lanczos.lanczosSumExpGScaled(a);
1775
1776 // Update to the Boost code.
1777 // Lower threshold for large a from 150 to 128 and compute d on demand.
1778 // See NUMBERS-179.
1779 if (a > 128) {
1780 final double d = ((z - a) - Lanczos.GMH) / agh;
1781 if (Math.abs(d * d * a) <= 100) {
1782 // special case for large a and a ~ z.
1783 // When a and x are large, we end up with a very large exponent with a base near one:
1784 // this will not be computed accurately via the pow function, and taking logs simply
1785 // leads to cancellation errors.
1786 prefix = a * SpecialMath.log1pmx(d) + z * -Lanczos.GMH / agh;
1787 prefix = Math.exp(prefix);
1788 return prefix * factor;
1789 }
1790 }
1791
1792 //
1793 // general case.
1794 // direct computation is most accurate, but use various fallbacks
1795 // for different parts of the problem domain:
1796 //
1797
1798 final double alz = a * Math.log(z / agh);
1799 final double amz = a - z;
1800 if ((Math.min(alz, amz) <= LOG_MIN_VALUE) || (Math.max(alz, amz) >= LOG_MAX_VALUE)) {
1801 final double amza = amz / a;
1802 if ((Math.min(alz, amz) / 2 > LOG_MIN_VALUE) && (Math.max(alz, amz) / 2 < LOG_MAX_VALUE)) {
1803 // compute square root of the result and then square it:
1804 final double sq = Math.pow(z / agh, a / 2) * Math.exp(amz / 2);
1805 prefix = sq * sq;
1806 } else if ((Math.min(alz, amz) / 4 > LOG_MIN_VALUE) &&
1807 (Math.max(alz, amz) / 4 < LOG_MAX_VALUE) && (z > a)) {
1808 // compute the 4th root of the result then square it twice:
1809 final double sq = Math.pow(z / agh, a / 4) * Math.exp(amz / 4);
1810 prefix = sq * sq;
1811 prefix *= prefix;
1812 } else if ((amza > LOG_MIN_VALUE) && (amza < LOG_MAX_VALUE)) {
1813 prefix = Math.pow((z * Math.exp(amza)) / agh, a);
1814 } else {
1815 prefix = Math.exp(alz + amz);
1816 }
1817 } else {
1818 prefix = Math.pow(z / agh, a) * Math.exp(amz);
1819 }
1820 prefix *= factor;
1821 return prefix;
1822 }
1823
1824 /**
1825 * Implements the asymptotic expansions of the incomplete
1826 * gamma functions P(a, x) and Q(a, x), used when a is large and
1827 * x ~ a.
1828 *
1829 * <p>The primary reference is:
1830 * <pre>
1831 * "The Asymptotic Expansion of the Incomplete Gamma Functions"
1832 * N. M. Temme.
1833 * Siam J. Math Anal. Vol 10 No 4, July 1979, p757.
1834 * </pre>
1835 *
1836 * <p>A different way of evaluating these expansions,
1837 * plus a lot of very useful background information is in:
1838 * <pre>
1839 * "A Set of Algorithms For the Incomplete Gamma Functions."
1840 * N. M. Temme.
1841 * Probability in the Engineering and Informational Sciences,
1842 * 8, 1994, 291.
1843 * </pre>
1844 *
1845 * <p>An alternative implementation is in:
1846 * <pre>
1847 * "Computation of the Incomplete Gamma Function Ratios and their Inverse."
1848 * A. R. Didonato and A. H. Morris.
1849 * ACM TOMS, Vol 12, No 4, Dec 1986, p377.
1850 * </pre>
1851 *
1852 * <p>This is a port of the function accurate for 53-bit mantissas
1853 * (IEEE double precision or 10^-17). To understand the code, refer to Didonato
1854 * and Morris, from Eq 17 and 18 onwards.
1855 *
1856 * <p>The coefficients used here are not taken from Didonato and Morris:
1857 * the domain over which these expansions are used is slightly different
1858 * to theirs, and their constants are not quite accurate enough for
1859 * 128-bit long doubles. Instead the coefficients were calculated
1860 * using the methods described by Temme p762 from Eq 3.8 onwards.
1861 * The values obtained agree with those obtained by Didonato and Morris
1862 * (at least to the first 30 digits that they provide).
1863 * At double precision the degrees of polynomial required for full
1864 * machine precision are close to those recommended to Didonato and Morris,
1865 * but of course many more terms are needed for larger types.
1866 *
1867 * <p>Adapted from {@code boost/math/special_functions/detail/igamma_large.hpp}.
1868 *
1869 * @param a the a
1870 * @param x the x
1871 * @return the double
1872 */
1873 // This is package-private for testing
1874 static double igammaTemmeLarge(double a, double x) {
1875 final double sigma = (x - a) / a;
1876 final double phi = -SpecialMath.log1pmx(sigma);
1877 final double y = a * phi;
1878 double z = Math.sqrt(2 * phi);
1879 if (x < a) {
1880 z = -z;
1881 }
1882
1883 // The following polynomials are evaluated with a loop
1884 // with Horner's method. Variations exist using
1885 // a second order Horner's method with an unrolled loop.
1886 // These are chosen in Boost based on the C++ compiler.
1887 // For example:
1888 // boost/math/tools/detail/polynomial_horner1_15.hpp
1889 // boost/math/tools/detail/polynomial_horner2_15.hpp
1890 // boost/math/tools/detail/polynomial_horner3_15.hpp
1891
1892 final double[] workspace = new double[10];
1893
1894 final double[] C0 = {
1895 -0.33333333333333333,
1896 0.083333333333333333,
1897 -0.014814814814814815,
1898 0.0011574074074074074,
1899 0.0003527336860670194,
1900 -0.00017875514403292181,
1901 0.39192631785224378e-4,
1902 -0.21854485106799922e-5,
1903 -0.185406221071516e-5,
1904 0.8296711340953086e-6,
1905 -0.17665952736826079e-6,
1906 0.67078535434014986e-8,
1907 0.10261809784240308e-7,
1908 -0.43820360184533532e-8,
1909 0.91476995822367902e-9,
1910 };
1911 workspace[0] = BoostTools.evaluatePolynomial(C0, z);
1912
1913 final double[] C1 = {
1914 -0.0018518518518518519,
1915 -0.0034722222222222222,
1916 0.0026455026455026455,
1917 -0.00099022633744855967,
1918 0.00020576131687242798,
1919 -0.40187757201646091e-6,
1920 -0.18098550334489978e-4,
1921 0.76491609160811101e-5,
1922 -0.16120900894563446e-5,
1923 0.46471278028074343e-8,
1924 0.1378633446915721e-6,
1925 -0.5752545603517705e-7,
1926 0.11951628599778147e-7,
1927 };
1928 workspace[1] = BoostTools.evaluatePolynomial(C1, z);
1929
1930 final double[] C2 = {
1931 0.0041335978835978836,
1932 -0.0026813271604938272,
1933 0.00077160493827160494,
1934 0.20093878600823045e-5,
1935 -0.00010736653226365161,
1936 0.52923448829120125e-4,
1937 -0.12760635188618728e-4,
1938 0.34235787340961381e-7,
1939 0.13721957309062933e-5,
1940 -0.6298992138380055e-6,
1941 0.14280614206064242e-6,
1942 };
1943 workspace[2] = BoostTools.evaluatePolynomial(C2, z);
1944
1945 final double[] C3 = {
1946 0.00064943415637860082,
1947 0.00022947209362139918,
1948 -0.00046918949439525571,
1949 0.00026772063206283885,
1950 -0.75618016718839764e-4,
1951 -0.23965051138672967e-6,
1952 0.11082654115347302e-4,
1953 -0.56749528269915966e-5,
1954 0.14230900732435884e-5,
1955 };
1956 workspace[3] = BoostTools.evaluatePolynomial(C3, z);
1957
1958 final double[] C4 = {
1959 -0.0008618882909167117,
1960 0.00078403922172006663,
1961 -0.00029907248030319018,
1962 -0.14638452578843418e-5,
1963 0.66414982154651222e-4,
1964 -0.39683650471794347e-4,
1965 0.11375726970678419e-4,
1966 };
1967 workspace[4] = BoostTools.evaluatePolynomial(C4, z);
1968
1969 final double[] C5 = {
1970 -0.00033679855336635815,
1971 -0.69728137583658578e-4,
1972 0.00027727532449593921,
1973 -0.00019932570516188848,
1974 0.67977804779372078e-4,
1975 0.1419062920643967e-6,
1976 -0.13594048189768693e-4,
1977 0.80184702563342015e-5,
1978 -0.22914811765080952e-5,
1979 };
1980 workspace[5] = BoostTools.evaluatePolynomial(C5, z);
1981
1982 final double[] C6 = {
1983 0.00053130793646399222,
1984 -0.00059216643735369388,
1985 0.00027087820967180448,
1986 0.79023532326603279e-6,
1987 -0.81539693675619688e-4,
1988 0.56116827531062497e-4,
1989 -0.18329116582843376e-4,
1990 };
1991 workspace[6] = BoostTools.evaluatePolynomial(C6, z);
1992
1993 final double[] C7 = {
1994 0.00034436760689237767,
1995 0.51717909082605922e-4,
1996 -0.00033493161081142236,
1997 0.0002812695154763237,
1998 -0.00010976582244684731,
1999 };
2000 workspace[7] = BoostTools.evaluatePolynomial(C7, z);
2001
2002 final double[] C8 = {
2003 -0.00065262391859530942,
2004 0.00083949872067208728,
2005 -0.00043829709854172101,
2006 };
2007 workspace[8] = BoostTools.evaluatePolynomial(C8, z);
2008 workspace[9] = -0.00059676129019274625;
2009
2010 double result = BoostTools.evaluatePolynomial(workspace, 1 / a);
2011 result *= Math.exp(-y) / Math.sqrt(2 * Math.PI * a);
2012 if (x < a) {
2013 result = -result;
2014 }
2015
2016 result += BoostErf.erfc(Math.sqrt(y)) / 2;
2017
2018 return result;
2019 }
2020
2021 /**
2022 * Incomplete tgamma for large X.
2023 *
2024 * <p>This summation is a source of error as the series starts at 1 and descends to zero.
2025 * It can have thousands of iterations when a and z are large and close in value.
2026 *
2027 * @param a Argument a
2028 * @param x Argument x
2029 * @param pol Function evaluation policy
2030 * @return incomplete tgamma
2031 */
2032 // This is package-private for testing
2033 static double incompleteTgammaLargeX(double a, double x, Policy pol) {
2034 final double eps = pol.getEps();
2035 final int maxIterations = pol.getMaxIterations();
2036
2037 // Asymptotic approximation for large argument, see: https://dlmf.nist.gov/8.11#E2.
2038 final DoubleSupplier gen = new DoubleSupplier() {
2039 /** Result term. */
2040 private double term = 1;
2041 /** Iteration. */
2042 private int n;
2043
2044 @Override
2045 public double getAsDouble() {
2046 final double result = term;
2047 n++;
2048 term *= (a - n) / x;
2049 return result;
2050 }
2051 };
2052
2053 return BoostTools.kahanSumSeries(gen, eps, maxIterations);
2054 }
2055
2056 /**
2057 * Return true if the array is not null and has non-zero length.
2058 *
2059 * @param array Array
2060 * @return true if a non-zero length array
2061 */
2062 private static boolean nonZeroLength(int[] array) {
2063 return array != null && array.length != 0;
2064 }
2065
2066 /**
2067 * Ratio of gamma functions.
2068 *
2069 * <p>\[ tgamma_ratio(z, delta) = \frac{\Gamma(z)}{\Gamma(z + delta)} \]
2070 *
2071 * <p>Adapted from {@code tgamma_delta_ratio_imp}. The use of
2072 * {@code max_factorial<double>::value == 170} has been replaced with
2073 * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2074 * to call the gamma function without overflow.
2075 *
2076 * @param z Argument z
2077 * @param delta The difference
2078 * @return gamma ratio
2079 */
2080 static double tgammaDeltaRatio(double z, double delta) {
2081 final double zDelta = z + delta;
2082 if (Double.isNaN(zDelta)) {
2083 // One or both arguments are NaN
2084 return Double.NaN;
2085 }
2086 if (z <= 0 || zDelta <= 0) {
2087 // This isn't very sophisticated, or accurate, but it does work:
2088 return tgamma(z) / tgamma(zDelta);
2089 }
2090
2091 // Note: Directly calling tgamma(z) / tgamma(z + delta) if possible
2092 // without overflow is not more accurate
2093
2094 if (Math.rint(delta) == delta) {
2095 if (delta == 0) {
2096 return 1;
2097 }
2098 //
2099 // If both z and delta are integers, see if we can just use table lookup
2100 // of the factorials to get the result:
2101 //
2102 if (Math.rint(z) == z &&
2103 z <= MAX_GAMMA_Z && zDelta <= MAX_GAMMA_Z) {
2104 return FACTORIAL[(int) z - 1] / FACTORIAL[(int) zDelta - 1];
2105 }
2106 if (Math.abs(delta) < 20) {
2107 //
2108 // delta is a small integer, we can use a finite product:
2109 //
2110 if (delta < 0) {
2111 z -= 1;
2112 double result = z;
2113 for (int d = (int) (delta + 1); d != 0; d++) {
2114 z -= 1;
2115 result *= z;
2116 }
2117 return result;
2118 }
2119 double result = 1 / z;
2120 for (int d = (int) (delta - 1); d != 0; d--) {
2121 z += 1;
2122 result /= z;
2123 }
2124 return result;
2125 }
2126 }
2127 return tgammaDeltaRatioImpLanczos(z, delta);
2128 }
2129
2130 /**
2131 * Ratio of gamma functions using Lanczos support.
2132 *
2133 * <p>\[ tgamma_delta_ratio(z, delta) = \frac{\Gamma(z)}{\Gamma(z + delta)}
2134 *
2135 * <p>Adapted from {@code tgamma_delta_ratio_imp_lanczos}. The use of
2136 * {@code max_factorial<double>::value == 170} has been replaced with
2137 * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2138 * to use the precomputed factorial table.
2139 *
2140 * @param z Argument z
2141 * @param delta The difference
2142 * @return gamma ratio
2143 */
2144 private static double tgammaDeltaRatioImpLanczos(double z, double delta) {
2145 if (z < EPSILON) {
2146 //
2147 // We get spurious numeric overflow unless we're very careful, this
2148 // can occur either inside Lanczos::lanczos_sum(z) or in the
2149 // final combination of terms, to avoid this, split the product up
2150 // into 2 (or 3) parts:
2151 //
2152 // G(z) / G(L) = 1 / (z * G(L)) ; z < eps, L = z + delta = delta
2153 // z * G(L) = z * G(lim) * (G(L)/G(lim)) ; lim = largest factorial
2154 //
2155 if (MAX_GAMMA_Z < delta) {
2156 double ratio = tgammaDeltaRatioImpLanczos(delta, MAX_GAMMA_Z - delta);
2157 ratio *= z;
2158 ratio *= FACTORIAL[MAX_FACTORIAL];
2159 return 1 / ratio;
2160 }
2161 return 1 / (z * tgamma(z + delta));
2162 }
2163 final double zgh = z + Lanczos.GMH;
2164 double result;
2165 if (z + delta == z) {
2166 // Here:
2167 // lanczosSum(z) / lanczosSum(z + delta) == 1
2168
2169 // Update to the Boost code to remove unreachable code:
2170 // Given z + delta == z then |delta / z| < EPSILON; and z < zgh
2171 // assume (abs(delta / zgh) < EPSILON) and remove unreachable
2172 // else branch which sets result = 1
2173
2174 // We have:
2175 // result = exp((0.5 - z) * log1p(delta / zgh));
2176 // 0.5 - z == -z
2177 // log1p(delta / zgh) = delta / zgh = delta / z
2178 // multiplying we get -delta.
2179
2180 // Note:
2181 // This can be different from
2182 // exp((0.5 - z) * log1p(delta / zgh)) when z is small.
2183 // In this case the result is exp(small) and the result
2184 // is within 1 ULP of 1.0. This is left as the original
2185 // Boost method using exp(-delta).
2186
2187 result = Math.exp(-delta);
2188 } else {
2189 if (Math.abs(delta) < 10) {
2190 result = Math.exp((0.5 - z) * Math.log1p(delta / zgh));
2191 } else {
2192 result = Math.pow(zgh / (zgh + delta), z - 0.5);
2193 }
2194 // Split the calculation up to avoid spurious overflow:
2195 result *= Lanczos.lanczosSum(z) / Lanczos.lanczosSum(z + delta);
2196 }
2197 result *= Math.pow(Math.E / (zgh + delta), delta);
2198 return result;
2199 }
2200
2201 /**
2202 * Ratio of gamma functions.
2203 *
2204 * <p>\[ tgamma_ratio(x, y) = \frac{\Gamma(x)}{\Gamma(y)}
2205 *
2206 * <p>Adapted from {@code tgamma_ratio_imp}. The use of
2207 * {@code max_factorial<double>::value == 170} has been replaced with
2208 * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2209 * to call the gamma function without overflow.
2210 *
2211 * @param x Argument x (must be positive finite)
2212 * @param y Argument y (must be positive finite)
2213 * @return gamma ratio (or nan)
2214 */
2215 static double tgammaRatio(double x, double y) {
2216 if (x <= 0 || !Double.isFinite(x) || y <= 0 || !Double.isFinite(y)) {
2217 return Double.NaN;
2218 }
2219 if (x <= Double.MIN_NORMAL) {
2220 // Special case for denorms...Ugh.
2221 return TWO_POW_53 * tgammaRatio(x * TWO_POW_53, y);
2222 }
2223
2224 if (x <= MAX_GAMMA_Z && y <= MAX_GAMMA_Z) {
2225 // Rather than subtracting values, lets just call the gamma functions directly:
2226 return tgamma(x) / tgamma(y);
2227 }
2228 double prefix = 1;
2229 if (x < 1) {
2230 if (y < 2 * MAX_GAMMA_Z) {
2231 // We need to sidestep on x as well, otherwise we'll underflow
2232 // before we get to factor in the prefix term:
2233 prefix /= x;
2234 x += 1;
2235 while (y >= MAX_GAMMA_Z) {
2236 y -= 1;
2237 prefix /= y;
2238 }
2239 return prefix * tgamma(x) / tgamma(y);
2240 }
2241 //
2242 // result is almost certainly going to underflow to zero, try logs just in case:
2243 //
2244 return Math.exp(lgamma(x) - lgamma(y));
2245 }
2246 if (y < 1) {
2247 if (x < 2 * MAX_GAMMA_Z) {
2248 // We need to sidestep on y as well, otherwise we'll overflow
2249 // before we get to factor in the prefix term:
2250 prefix *= y;
2251 y += 1;
2252 while (x >= MAX_GAMMA_Z) {
2253 x -= 1;
2254 prefix *= x;
2255 }
2256 return prefix * tgamma(x) / tgamma(y);
2257 }
2258 //
2259 // Result will almost certainly overflow, try logs just in case:
2260 //
2261 return Math.exp(lgamma(x) - lgamma(y));
2262 }
2263 //
2264 // Regular case, x and y both large and similar in magnitude:
2265 //
2266 return tgammaDeltaRatio(x, y - x);
2267 }
2268 }