View Javadoc
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 }