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="http://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 = 0;
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 
779         } else if (z < ROOT_EPSILON) {
780             if (z == 0) {
781                 // Pole error
782                 return Double.NaN;
783             }
784             if (4 * Math.abs(z) < EPSILON) {
785                 result = -Math.log(Math.abs(z));
786             } else {
787                 result = Math.log(Math.abs(1 / z - EULER));
788             }
789             if (z < 0) {
790                 sresult = -1;
791             }
792         } else if (z < 15) {
793             result = lgammaSmall(z, z - 1, z - 2);
794         // The z > 3 condition is always true
795         //} else if (z > 3 && z < 100) {
796         } else if (z < 100) {
797             // taking the log of tgamma reduces the error, no danger of overflow here:
798             result = Math.log(tgamma(z));
799         } else {
800             // regular evaluation:
801             final double zgh = z + Lanczos.GMH;
802             result = Math.log(zgh) - 1;
803             result *= z - 0.5f;
804             //
805             // Only add on the lanczos sum part if we're going to need it:
806             //
807             if (result * EPSILON < 20) {
808                 result += Math.log(Lanczos.lanczosSumExpGScaled(z));
809             }
810         }
811 
812         if (nonZeroLength(sign)) {
813             sign[0] = sresult;
814         }
815         return result;
816     }
817 
818     /**
819      * Log Gamma function for small z.
820      *
821      * @param z Argument z
822      * @param zm1 {@code z - 1}
823      * @param zm2 {@code z - 2}
824      * @return log gamma value
825      */
826     private static double lgammaSmall(double z, double zm1, double zm2) {
827         // This version uses rational approximations for small
828         // values of z accurate enough for 64-bit mantissas
829         // (80-bit long doubles), works well for 53-bit doubles as well.
830 
831         // Updated to use an extended precision sum
832         final Sum result = Sum.create();
833 
834         // Note:
835         // Removed z < EPSILON branch.
836         // The function is called
837         // from lgamma:
838         //   ROOT_EPSILON <= z < 15
839         // from tgamma1pm1:
840         //   1.5 <= z < 2
841         //   1 <= z < 3
842 
843         if ((zm1 == 0) || (zm2 == 0)) {
844             // nothing to do, result is zero....
845             return 0;
846         } else if (z > 2) {
847             //
848             // Begin by performing argument reduction until
849             // z is in [2,3):
850             //
851             if (z >= 3) {
852                 do {
853                     z -= 1;
854                     result.add(Math.log(z));
855                 } while (z >= 3);
856                 // Update zm2, we need it below:
857                 zm2 = z - 2;
858             }
859 
860             //
861             // Use the following form:
862             //
863             // lgamma(z) = (z-2)(z+1)(Y + R(z-2))
864             //
865             // where R(z-2) is a rational approximation optimised for
866             // low absolute error - as long as its absolute error
867             // is small compared to the constant Y - then any rounding
868             // error in its computation will get wiped out.
869             //
870             // R(z-2) has the following properties:
871             //
872             // At double: Max error found:                    4.231e-18
873             // At long double: Max error found:               1.987e-21
874             // Maximum Deviation Found (approximation error): 5.900e-24
875             //
876             double P;
877             P = -0.324588649825948492091e-4;
878             P = -0.541009869215204396339e-3 + P * zm2;
879             P = -0.259453563205438108893e-3 + P * zm2;
880             P =  0.172491608709613993966e-1 + P * zm2;
881             P =  0.494103151567532234274e-1 + P * zm2;
882             P =   0.25126649619989678683e-1 + P * zm2;
883             P = -0.180355685678449379109e-1 + P * zm2;
884             double Q;
885             Q = -0.223352763208617092964e-6;
886             Q =  0.224936291922115757597e-3 + Q * zm2;
887             Q =   0.82130967464889339326e-2 + Q * zm2;
888             Q =  0.988504251128010129477e-1 + Q * zm2;
889             Q =   0.541391432071720958364e0 + Q * zm2;
890             Q =   0.148019669424231326694e1 + Q * zm2;
891             Q =   0.196202987197795200688e1 + Q * zm2;
892             Q =                       0.1e1 + Q * zm2;
893 
894             final float Y = 0.158963680267333984375e0f;
895 
896             final double r = zm2 * (z + 1);
897             final double R = P / Q;
898 
899             result.addProduct(r, Y).addProduct(r, R);
900         } else {
901             //
902             // If z is less than 1 use recurrence to shift to
903             // z in the interval [1,2]:
904             //
905             if (z < 1) {
906                 result.add(-Math.log(z));
907                 zm2 = zm1;
908                 zm1 = z;
909                 z += 1;
910             }
911             //
912             // Two approximations, one for z in [1,1.5] and
913             // one for z in [1.5,2]:
914             //
915             if (z <= 1.5) {
916                 //
917                 // Use the following form:
918                 //
919                 // lgamma(z) = (z-1)(z-2)(Y + R(z-1
920                 //
921                 // where R(z-1) is a rational approximation optimised for
922                 // low absolute error - as long as its absolute error
923                 // is small compared to the constant Y - then any rounding
924                 // error in its computation will get wiped out.
925                 //
926                 // R(z-1) has the following properties:
927                 //
928                 // At double precision: Max error found:                1.230011e-17
929                 // At 80-bit long double precision:   Max error found:  5.631355e-21
930                 // Maximum Deviation Found:                             3.139e-021
931                 // Expected Error Term:                                 3.139e-021
932 
933                 //
934                 final float Y = 0.52815341949462890625f;
935 
936                 double P;
937                 P = -0.100346687696279557415e-2;
938                 P = -0.240149820648571559892e-1 + P * zm1;
939                 P =  -0.158413586390692192217e0 + P * zm1;
940                 P =  -0.406567124211938417342e0 + P * zm1;
941                 P =  -0.414983358359495381969e0 + P * zm1;
942                 P = -0.969117530159521214579e-1 + P * zm1;
943                 P =  0.490622454069039543534e-1 + P * zm1;
944                 double Q;
945                 Q = 0.195768102601107189171e-2;
946                 Q = 0.577039722690451849648e-1 + Q * zm1;
947                 Q =  0.507137738614363510846e0 + Q * zm1;
948                 Q =  0.191415588274426679201e1 + Q * zm1;
949                 Q =  0.348739585360723852576e1 + Q * zm1;
950                 Q =  0.302349829846463038743e1 + Q * zm1;
951                 Q =                      0.1e1 + Q * zm1;
952 
953                 final double r = P / Q;
954                 final double prefix = zm1 * zm2;
955 
956                 result.addProduct(prefix, Y).addProduct(prefix, r);
957             } else {
958                 //
959                 // Use the following form:
960                 //
961                 // lgamma(z) = (2-z)(1-z)(Y + R(2-z
962                 //
963                 // where R(2-z) is a rational approximation optimised for
964                 // low absolute error - as long as its absolute error
965                 // is small compared to the constant Y - then any rounding
966                 // error in its computation will get wiped out.
967                 //
968                 // R(2-z) has the following properties:
969                 //
970                 // At double precision, max error found:              1.797565e-17
971                 // At 80-bit long double precision, max error found:  9.306419e-21
972                 // Maximum Deviation Found:                           2.151e-021
973                 // Expected Error Term:                               2.150e-021
974                 //
975                 final float Y = 0.452017307281494140625f;
976 
977                 final double mzm2 = -zm2;
978                 double P;
979                 P =  0.431171342679297331241e-3;
980                 P = -0.850535976868336437746e-2 + P * mzm2;
981                 P =  0.542809694055053558157e-1 + P * mzm2;
982                 P =  -0.142440390738631274135e0 + P * mzm2;
983                 P =   0.144216267757192309184e0 + P * mzm2;
984                 P = -0.292329721830270012337e-1 + P * mzm2;
985                 double Q;
986                 Q = -0.827193521891290553639e-6;
987                 Q = -0.100666795539143372762e-2 + Q * mzm2;
988                 Q =   0.25582797155975869989e-1 + Q * mzm2;
989                 Q =  -0.220095151814995745555e0 + Q * mzm2;
990                 Q =   0.846973248876495016101e0 + Q * mzm2;
991                 Q =  -0.150169356054485044494e1 + Q * mzm2;
992                 Q =                       0.1e1 + Q * mzm2;
993                 final double r = zm2 * zm1;
994                 final double R = P / Q;
995 
996                 result.addProduct(r, Y).addProduct(r, R);
997             }
998         }
999         return result.getAsDouble();
1000     }
1001 
1002     /**
1003      * Calculates tgamma(1+dz)-1.
1004      *
1005      * @param dz Argument
1006      * @return tgamma(1+dz)-1
1007      */
1008     static double tgamma1pm1(double dz) {
1009         //
1010         // This helper calculates tgamma(1+dz)-1 without cancellation errors,
1011         // used by the upper incomplete gamma with z < 1:
1012         //
1013         double result;
1014         if (dz < 0) {
1015             if (dz < -0.5) {
1016                 // Best method is simply to subtract 1 from tgamma:
1017                 result = tgamma(1 + dz) - 1;
1018             } else {
1019                 // Use expm1 on lgamma:
1020                 result = Math.expm1(-Math.log1p(dz) + lgammaSmall(dz + 2, dz + 1, dz));
1021             }
1022         } else {
1023             if (dz < 2) {
1024                 // Use expm1 on lgamma:
1025                 result = Math.expm1(lgammaSmall(dz + 1, dz, dz - 1));
1026             } else {
1027                 // Best method is simply to subtract 1 from tgamma:
1028                 result = tgamma(1 + dz) - 1;
1029             }
1030         }
1031 
1032         return result;
1033     }
1034 
1035     /**
1036      * Full upper incomplete gamma.
1037      *
1038      * @param a Argument a
1039      * @param x Argument x
1040      * @return upper gamma value
1041      */
1042     static double tgamma(double a, double x) {
1043         return gammaIncompleteImp(a, x, false, true, Policy.getDefault());
1044     }
1045 
1046     /**
1047      * Full upper incomplete gamma.
1048      *
1049      * @param a Argument a
1050      * @param x Argument x
1051      * @param policy Function evaluation policy
1052      * @return upper gamma value
1053      */
1054     static double tgamma(double a, double x, Policy policy) {
1055         return gammaIncompleteImp(a, x, false, true, policy);
1056     }
1057 
1058     /**
1059      * Full lower incomplete gamma.
1060      *
1061      * @param a Argument a
1062      * @param x Argument x
1063      * @return lower gamma value
1064      */
1065     static double tgammaLower(double a, double x) {
1066         return gammaIncompleteImp(a, x, false, false, Policy.getDefault());
1067     }
1068 
1069     /**
1070      * Full lower incomplete gamma.
1071      *
1072      * @param a Argument a
1073      * @param x Argument x
1074      * @param policy Function evaluation policy
1075      * @return lower gamma value
1076      */
1077     static double tgammaLower(double a, double x, Policy policy) {
1078         return gammaIncompleteImp(a, x, false, false, policy);
1079     }
1080 
1081     /**
1082      * Regularised upper incomplete gamma.
1083      *
1084      * @param a Argument a
1085      * @param x Argument x
1086      * @return q
1087      */
1088     static double gammaQ(double a, double x) {
1089         return gammaIncompleteImp(a, x, true, true, Policy.getDefault());
1090     }
1091 
1092     /**
1093      * Regularised upper incomplete gamma.
1094      *
1095      * @param a Argument a
1096      * @param x Argument x
1097      * @param policy Function evaluation policy
1098      * @return q
1099      */
1100     static double gammaQ(double a, double x, Policy policy) {
1101         return gammaIncompleteImp(a, x, true, true, policy);
1102     }
1103 
1104     /**
1105      * Regularised lower incomplete gamma.
1106      *
1107      * @param a Argument a
1108      * @param x Argument x
1109      * @return p
1110      */
1111     static double gammaP(double a, double x) {
1112         return gammaIncompleteImp(a, x, true, false, Policy.getDefault());
1113     }
1114 
1115     /**
1116      * Regularised lower incomplete gamma.
1117      *
1118      * @param a Argument a
1119      * @param x Argument x
1120      * @param policy Function evaluation policy
1121      * @return p
1122      */
1123     static double gammaP(double a, double x, Policy policy) {
1124         return gammaIncompleteImp(a, x, true, false, policy);
1125     }
1126 
1127     /**
1128      * Derivative of the regularised lower incomplete gamma.
1129      * <p>\( \frac{e^{-x} x^{a-1}}{\Gamma(a)} \)
1130      *
1131      * <p>Adapted from {@code boost::math::detail::gamma_p_derivative_imp}
1132      *
1133      * @param a Argument a
1134      * @param x Argument x
1135      * @return p derivative
1136      */
1137     static double gammaPDerivative(double a, double x) {
1138         //
1139         // Usual error checks first:
1140         //
1141         if (Double.isNaN(a) || Double.isNaN(x) || a <= 0 || x < 0) {
1142             return Double.NaN;
1143         }
1144         //
1145         // Now special cases:
1146         //
1147         if (x == 0) {
1148             if (a > 1) {
1149                 return 0;
1150             }
1151             return (a == 1) ? 1 : Double.POSITIVE_INFINITY;
1152         }
1153         //
1154         // Normal case:
1155         //
1156         double f1 = regularisedGammaPrefix(a, x);
1157         if (f1 == 0) {
1158             // Underflow in calculation, use logs instead:
1159             f1 = a * Math.log(x) - x - lgamma(a) - Math.log(x);
1160             f1 = Math.exp(f1);
1161         } else {
1162             // Will overflow when (x < 1) && (Double.MAX_VALUE * x < f1).
1163             // There is no exception for this case so just return the result.
1164             f1 /= x;
1165         }
1166 
1167         return f1;
1168     }
1169 
1170     /**
1171      * Main incomplete gamma entry point, handles all four incomplete gammas.
1172      * Adapted from {@code boost::math::detail::gamma_incomplete_imp}.
1173      *
1174      * <p>The Boost code has a pointer {@code p_derivative} that can be set to the
1175      * value of the derivative. This is used for the inverse incomplete
1176      * gamma functions {@code gamma_(p|q)_inv_imp}. It is not required for the forward
1177      * evaluation functions.
1178      *
1179      * @param a Argument a
1180      * @param x Argument x
1181      * @param normalised true to compute the regularised value
1182      * @param invert true to compute the upper value Q (default is lower value P)
1183      * @param pol Function evaluation policy
1184      * @return gamma value
1185      */
1186     private static double gammaIncompleteImp(double a, double x,
1187             boolean normalised, boolean invert, Policy pol) {
1188         if (Double.isNaN(a) || Double.isNaN(x) || a <= 0 || x < 0) {
1189             return Double.NaN;
1190         }
1191 
1192         double result = 0;
1193 
1194         if (a >= MAX_FACTORIAL && !normalised) {
1195             //
1196             // When we're computing the non-normalized incomplete gamma
1197             // and a is large the result is rather hard to compute unless
1198             // we use logs. There are really two options - if x is a long
1199             // way from a in value then we can reliably use methods 2 and 4
1200             // below in logarithmic form and go straight to the result.
1201             // Otherwise we let the regularized gamma take the strain
1202             // (the result is unlikely to underflow in the central region anyway)
1203             // and combine with lgamma in the hopes that we get a finite result.
1204             //
1205 
1206             if (invert && (a * 4 < x)) {
1207                 // This is method 4 below, done in logs:
1208                 result = a * Math.log(x) - x;
1209                 result += Math.log(upperGammaFraction(a, x, pol));
1210             } else if (!invert && (a > 4 * x)) {
1211                 // This is method 2 below, done in logs:
1212                 result = a * Math.log(x) - x;
1213                 result += Math.log(lowerGammaSeries(a, x, 0, pol) / a);
1214             } else {
1215                 result = gammaIncompleteImp(a, x, true, invert, pol);
1216                 if (result == 0) {
1217                     if (invert) {
1218                         // Try http://functions.wolfram.com/06.06.06.0039.01
1219                         result = 1 + 1 / (12 * a) + 1 / (288 * a * a);
1220                         result = Math.log(result) - a + (a - 0.5f) * Math.log(a) + LOG_ROOT_TWO_PI;
1221                     } else {
1222                         // This is method 2 below, done in logs, we're really outside the
1223                         // range of this method, but since the result is almost certainly
1224                         // infinite, we should probably be OK:
1225                         result = a * Math.log(x) - x;
1226                         result += Math.log(lowerGammaSeries(a, x, 0, pol) / a);
1227                     }
1228                 } else {
1229                     result = Math.log(result) + lgamma(a);
1230                 }
1231             }
1232             // If result is > log(MAX_VALUE) the result will overflow.
1233             // There is no exception for this case so just return the result.
1234             return Math.exp(result);
1235         }
1236 
1237         boolean isInt;
1238         boolean isHalfInt;
1239         // Update. x must be safe for exp(-x). Change to -x > LOG_MIN_VALUE.
1240         final boolean isSmallA = (a < 30) && (a <= x + 1) && (-x > LOG_MIN_VALUE);
1241         if (isSmallA) {
1242             final double fa = Math.floor(a);
1243             isInt = fa == a;
1244             isHalfInt = !isInt && (Math.abs(fa - a) == 0.5f);
1245         } else {
1246             isInt = isHalfInt = false;
1247         }
1248 
1249         int evalMethod;
1250 
1251         if (isInt && (x > 0.6)) {
1252             // calculate Q via finite sum:
1253             invert = !invert;
1254             evalMethod = 0;
1255         } else if (isHalfInt && (x > 0.2)) {
1256             // calculate Q via finite sum for half integer a:
1257             invert = !invert;
1258             evalMethod = 1;
1259         } else if ((x < ROOT_EPSILON) && (a > 1)) {
1260             evalMethod = 6;
1261         } else if ((x > 1000) && (a < x * 0.75f)) {
1262             // Note:
1263             // The branch is used in Boost when:
1264             // ((x > 1000) && ((a < x) || (Math.abs(a - 50) / x < 1)))
1265             //
1266             // This case was added after Boost 1_68_0.
1267             // See: https://github.com/boostorg/math/issues/168
1268             //
1269             // When using only double precision for the evaluation
1270             // it is a source of error when a ~ z as the asymptotic approximation
1271             // sums terms t_n+1 = t_n * (a - n - 1) / z starting from t_0 = 1.
1272             // These terms are close to 1 when a ~ z and the sum has many terms
1273             // with reduced precision.
1274             // This has been updated to allow only cases with fast convergence.
1275             // It will be used when x -> infinity and a << x.
1276 
1277             // calculate Q via asymptotic approximation:
1278             invert = !invert;
1279             evalMethod = 7;
1280 
1281         } else if (x < 0.5) {
1282             //
1283             // Changeover criterion chosen to give a changeover at Q ~ 0.33
1284             //
1285             if (-0.4 / Math.log(x) < a) {
1286                 // Compute P
1287                 evalMethod = 2;
1288             } else {
1289                 evalMethod = 3;
1290             }
1291         } else if (x < 1.1) {
1292             //
1293             // Changover here occurs when P ~ 0.75 or Q ~ 0.25:
1294             //
1295             if (x * 0.75f < a) {
1296                 // Compute P
1297                 evalMethod = 2;
1298             } else {
1299                 evalMethod = 3;
1300             }
1301         } else {
1302             //
1303             // Begin by testing whether we're in the "bad" zone
1304             // where the result will be near 0.5 and the usual
1305             // series and continued fractions are slow to converge:
1306             //
1307             boolean useTemme = false;
1308             if (normalised && (a > 20)) {
1309                 final double sigma = Math.abs((x - a) / a);
1310                 if (a > 200) {
1311                     //
1312                     // This limit is chosen so that we use Temme's expansion
1313                     // only if the result would be larger than about 10^-6.
1314                     // Below that the regular series and continued fractions
1315                     // converge OK, and if we use Temme's method we get increasing
1316                     // errors from the dominant erfc term as its (inexact) argument
1317                     // increases in magnitude.
1318                     //
1319                     if (20 / a > sigma * sigma) {
1320                         useTemme = true;
1321                     }
1322                 } else {
1323                     // Note in this zone we can't use Temme's expansion for
1324                     // types longer than an 80-bit real:
1325                     // it would require too many terms in the polynomials.
1326                     if (sigma < 0.4) {
1327                         useTemme = true;
1328                     }
1329                 }
1330             }
1331             if (useTemme) {
1332                 evalMethod = 5;
1333             } else {
1334                 //
1335                 // Regular case where the result will not be too close to 0.5.
1336                 //
1337                 // Changeover here occurs at P ~ Q ~ 0.5
1338                 // Note that series computation of P is about x2 faster than continued fraction
1339                 // calculation of Q, so try and use the CF only when really necessary,
1340                 // especially for small x.
1341                 //
1342                 if (x - (1 / (3 * x)) < a) {
1343                     evalMethod = 2;
1344                 } else {
1345                     evalMethod = 4;
1346                     invert = !invert;
1347                 }
1348             }
1349         }
1350 
1351         switch (evalMethod) {
1352         case 0:
1353             result = finiteGammaQ(a, x);
1354             if (!normalised) {
1355                 result *= tgamma(a);
1356             }
1357             break;
1358         case 1:
1359             result = finiteHalfGammaQ(a, x);
1360             if (!normalised) {
1361                 result *= tgamma(a);
1362             }
1363             break;
1364         case 2:
1365             // Compute P:
1366             result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1367             if (result != 0) {
1368                 //
1369                 // If we're going to be inverting the result then we can
1370                 // reduce the number of series evaluations by quite
1371                 // a few iterations if we set an initial value for the
1372                 // series sum based on what we'll end up subtracting it from
1373                 // at the end.
1374                 // Have to be careful though that this optimization doesn't
1375                 // lead to spurious numeric overflow. Note that the
1376                 // scary/expensive overflow checks below are more often
1377                 // than not bypassed in practice for "sensible" input
1378                 // values:
1379                 //
1380 
1381                 double initValue = 0;
1382                 boolean optimisedInvert = false;
1383                 if (invert) {
1384                     initValue = normalised ? 1 : tgamma(a);
1385                     if (normalised || (result >= 1) || (Double.MAX_VALUE * result > initValue)) {
1386                         initValue /= result;
1387                         if (normalised || (a < 1) || (Double.MAX_VALUE / a > initValue)) {
1388                             initValue *= -a;
1389                             optimisedInvert = true;
1390                         } else {
1391                             initValue = 0;
1392                         }
1393                     } else {
1394                         initValue = 0;
1395                     }
1396                 }
1397                 result *= lowerGammaSeries(a, x, initValue, pol) / a;
1398                 if (optimisedInvert) {
1399                     invert = false;
1400                     result = -result;
1401                 }
1402             }
1403             break;
1404         case 3:
1405             // Compute Q:
1406             invert = !invert;
1407             final double[] g = {0};
1408             result = tgammaSmallUpperPart(a, x, pol, g, invert);
1409             invert = false;
1410             if (normalised) {
1411                 // Addition to the Boost code:
1412                 if (g[0] == Double.POSITIVE_INFINITY) {
1413                     // Very small a will overflow gamma(a). Resort to logs.
1414                     // This method requires improvement as the error is very large.
1415                     // It is better than returning zero for a non-zero result.
1416                     result = Math.exp(Math.log(result) - lgamma(a));
1417                 } else {
1418                     result /= g[0];
1419                 }
1420             }
1421             break;
1422         case 4:
1423             // Compute Q:
1424             result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1425             if (result != 0) {
1426                 result *= upperGammaFraction(a, x, pol);
1427             }
1428             break;
1429         case 5:
1430             // Call 53-bit version
1431             result = igammaTemmeLarge(a, x);
1432             if (x >= a) {
1433                 invert = !invert;
1434             }
1435             break;
1436         case 6:
1437             // x is so small that P is necessarily very small too, use
1438             // http://functions.wolfram.com/GammaBetaErf/GammaRegularized/06/01/05/01/01/
1439             if (normalised) {
1440                 // If tgamma overflows then result = 0
1441                 result = Math.pow(x, a) / tgamma(a + 1);
1442             } else {
1443                 result = Math.pow(x, a) / a;
1444             }
1445             result *= 1 - a * x / (a + 1);
1446             break;
1447         case 7:
1448         default:
1449             // x is large,
1450             // Compute Q:
1451             result = normalised ? regularisedGammaPrefix(a, x) : fullIgammaPrefix(a, x);
1452             result /= x;
1453             if (result != 0) {
1454                 result *= incompleteTgammaLargeX(a, x, pol);
1455             }
1456             break;
1457         }
1458 
1459         if (normalised && (result > 1)) {
1460             result = 1;
1461         }
1462         if (invert) {
1463             final double gam = normalised ? 1 : tgamma(a);
1464             result = gam - result;
1465         }
1466 
1467         return result;
1468     }
1469 
1470     /**
1471      * Upper gamma fraction.
1472      * Multiply result by z^a * e^-z to get the full
1473      * upper incomplete integral.  Divide by tgamma(z)
1474      * to normalise.
1475      *
1476      * @param a Argument a
1477      * @param z Argument z
1478      * @param pol Function evaluation policy
1479      * @return upper gamma fraction
1480      */
1481     // This is package-private for testing
1482     static double upperGammaFraction(double a, double z, Policy pol) {
1483         final double eps = pol.getEps();
1484         final int maxIterations = pol.getMaxIterations();
1485 
1486         // This is computing:
1487         //              1
1488         // ------------------------------
1489         // b0 + a1 / (b1 +     a2       )
1490         //                 -------------
1491         //                 b2 +    a3
1492         //                      --------
1493         //                      b3 + ...
1494         //
1495         // b0 = z - a + 1
1496         // a1 = a - 1
1497         //
1498         // It can be done several ways with variations in accuracy.
1499         // The current implementation has the best accuracy and matches the Boost code.
1500 
1501         final double zma1 = z - a + 1;
1502 
1503         final Supplier<Coefficient> gen = new Supplier<Coefficient>() {
1504             /** Iteration. */
1505             private int k;
1506 
1507             @Override
1508             public Coefficient get() {
1509                 ++k;
1510                 return Coefficient.of(k * (a - k), zma1 + 2.0 * k);
1511             }
1512         };
1513 
1514         return 1 / GeneralizedContinuedFraction.value(zma1, gen, eps, maxIterations);
1515     }
1516 
1517     /**
1518      * Upper gamma fraction for integer a.
1519      * Called when a < 30 and -x > LOG_MIN_VALUE.
1520      *
1521      * @param a Argument a (assumed to be small)
1522      * @param x Argument x
1523      * @return upper gamma fraction
1524      */
1525     private static double finiteGammaQ(double a, double x) {
1526         //
1527         // Calculates normalised Q when a is an integer:
1528         //
1529 
1530         // Update:
1531         // Assume -x > log min value and no underflow to zero.
1532 
1533         double sum = Math.exp(-x);
1534         double term = sum;
1535         for (int n = 1; n < a; ++n) {
1536             term /= n;
1537             term *= x;
1538             sum += term;
1539         }
1540         return sum;
1541     }
1542 
1543     /**
1544      * Upper gamma fraction for half integer a.
1545      * Called when a < 30 and -x > LOG_MIN_VALUE.
1546      *
1547      * @param a Argument a (assumed to be small)
1548      * @param x Argument x
1549      * @return upper gamma fraction
1550      */
1551     private static double finiteHalfGammaQ(double a, double x) {
1552         //
1553         // Calculates normalised Q when a is a half-integer:
1554         //
1555 
1556         // Update:
1557         // Assume -x > log min value:
1558         // erfc(sqrt(708)) = erfc(26.6) => erfc has a non-zero value
1559 
1560         double e = BoostErf.erfc(Math.sqrt(x));
1561         if (a > 1) {
1562             double term = Math.exp(-x) / Math.sqrt(Math.PI * x);
1563             term *= x;
1564             term /= 0.5;
1565             double sum = term;
1566             for (int n = 2; n < a; ++n) {
1567                 term /= n - 0.5;
1568                 term *= x;
1569                 sum += term;
1570             }
1571             e += sum;
1572         }
1573         return e;
1574     }
1575 
1576     /**
1577      * Lower gamma series.
1578      * Multiply result by ((z^a) * (e^-z) / a) to get the full
1579      * lower incomplete integral. Then divide by tgamma(a)
1580      * to get the normalised value.
1581      *
1582      * @param a Argument a
1583      * @param z Argument z
1584      * @param initValue Initial value
1585      * @param pol Function evaluation policy
1586      * @return lower gamma series
1587      */
1588     // This is package-private for testing
1589     static double lowerGammaSeries(double a, double z, double initValue, Policy pol) {
1590         final double eps = pol.getEps();
1591         final int maxIterations = pol.getMaxIterations();
1592 
1593         // Lower gamma series representation.
1594         final DoubleSupplier gen = new DoubleSupplier() {
1595             /** Next result. */
1596             private double result = 1;
1597             /** Iteration. */
1598             private int n;
1599 
1600             @Override
1601             public double getAsDouble() {
1602                 final double r = result;
1603                 n++;
1604                 result *= z / (a + n);
1605                 return r;
1606             }
1607         };
1608 
1609         return BoostTools.kahanSumSeries(gen, eps, maxIterations, initValue);
1610     }
1611 
1612     /**
1613      * Upper gamma fraction for very small a.
1614      *
1615      * @param a Argument a (assumed to be small)
1616      * @param x Argument x
1617      * @param pol Function evaluation policy
1618      * @param pgam set to value of gamma(a) on output
1619      * @param invert true to invert the result
1620      * @return upper gamma fraction
1621      */
1622     private static double tgammaSmallUpperPart(double a, double x, Policy pol, double[] pgam, boolean invert) {
1623         //
1624         // Compute the full upper fraction (Q) when a is very small:
1625         //
1626         double result;
1627         result = tgamma1pm1(a);
1628 
1629         // Note: Replacing this with tgamma(a) does not reduce error on current test data.
1630 
1631         // gamma(1+z) = z gamma(z)
1632         // pgam[0] == gamma(a)
1633         pgam[0] = (result + 1) / a;
1634 
1635         double p = BoostMath.powm1(x, a);
1636         result -= p;
1637         result /= a;
1638         // Removed subtraction of 10 from this value
1639         final int maxIter = pol.getMaxIterations();
1640         p += 1;
1641         final double initValue = invert ? pgam[0] : 0;
1642 
1643         // Series representation for upper fraction when z is small.
1644         final DoubleSupplier gen = new DoubleSupplier() {
1645             /** Result term. */
1646             private double result = -x;
1647             /** Argument x (this is negated on purpose). */
1648             private final double z = -x;
1649             /** Iteration. */
1650             private int n = 1;
1651 
1652             @Override
1653             public double getAsDouble() {
1654                 final double r = result / (a + n);
1655                 n++;
1656                 result = result * z / n;
1657                 return r;
1658             }
1659         };
1660 
1661         result = -p * BoostTools.kahanSumSeries(gen, pol.getEps(), maxIter, (initValue - result) / p);
1662         if (invert) {
1663             result = -result;
1664         }
1665         return result;
1666     }
1667 
1668     /**
1669      * Calculate power term prefix (z^a)(e^-z) used in the non-normalised
1670      * incomplete gammas.
1671      *
1672      * @param a Argument a
1673      * @param z Argument z
1674      * @return incomplete gamma prefix
1675      */
1676     static double fullIgammaPrefix(double a, double z) {
1677         if (z > Double.MAX_VALUE) {
1678             return 0;
1679         }
1680         final double alz = a * Math.log(z);
1681         double prefix;
1682 
1683         if (z >= 1) {
1684             if ((alz < LOG_MAX_VALUE) && (-z > LOG_MIN_VALUE)) {
1685                 prefix = Math.pow(z, a) * Math.exp(-z);
1686             } else if (a >= 1) {
1687                 prefix = Math.pow(z / Math.exp(z / a), a);
1688             } else {
1689                 prefix = Math.exp(alz - z);
1690             }
1691         } else {
1692             if (alz > LOG_MIN_VALUE) {
1693                 prefix = Math.pow(z, a) * Math.exp(-z);
1694             } else {
1695                 // Updated to remove unreachable final branch using Math.exp(alz - z).
1696                 // This branch requires (z / a < LOG_MAX_VALUE) to avoid overflow in exp.
1697                 // At this point:
1698                 // 1. log(z) is negative;
1699                 // 2. a * log(z) <= -708 requires a > -708 / log(z).
1700                 // For any z < 1: -708 / log(z) is > z. Thus a is > z and
1701                 // z / a < LOG_MAX_VALUE is always true.
1702                 prefix = Math.pow(z / Math.exp(z / a), a);
1703             }
1704         }
1705         // Removed overflow check. Return infinity if it occurs.
1706         return prefix;
1707     }
1708 
1709     /**
1710      * Compute (z^a)(e^-z)/tgamma(a).
1711      * <p>Most of the error occurs in this function.
1712      *
1713      * @param a Argument a
1714      * @param z Argument z
1715      * @return regularized gamma prefix
1716      */
1717     // This is package-private for testing
1718     static double regularisedGammaPrefix(double a, double z) {
1719         if (z >= Double.MAX_VALUE) {
1720             return 0;
1721         }
1722 
1723         // Update this condition from: a < 1
1724         if (a <= 1) {
1725             //
1726             // We have to treat a < 1 as a special case because our Lanczos
1727             // approximations are optimised against the factorials with a > 1,
1728             // and for high precision types especially (128-bit reals for example)
1729             // very small values of a can give rather erroneous results for gamma
1730             // unless we do this:
1731             //
1732             // Boost todo: is this still required? Lanczos approx should be better now?
1733             //
1734 
1735             // Update this condition from: z <= LOG_MIN_VALUE
1736             // Require exp(-z) to not underflow:
1737             // -z > log(min_value)
1738             if (-z <= LOG_MIN_VALUE) {
1739                 // Oh dear, have to use logs, should be free of cancellation errors though:
1740                 return Math.exp(a * Math.log(z) - z - lgamma(a));
1741             }
1742             // direct calculation, no danger of overflow as gamma(a) < 1/a
1743             // for small a.
1744             return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1745         }
1746 
1747         // Update to the Boost code.
1748         // Use some of the logic from fullIgammaPrefix(a, z) to use the direct
1749         // computation if it is valid. Assuming pow and exp are accurate to 1 ULP it
1750         // puts most of the the error in evaluation of tgamma(a). This is accurate
1751         // enough that this reduces max error on the current test data.
1752         //
1753         // Overflow cases fall-through to the Lanczos approximation that incorporates
1754         // the pow and exp terms used in the tgamma(a) computation with the terms
1755         // z^a and e^-z into a single evaluation of pow and exp. See equation 15:
1756         // https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_gamma/igamma.html
1757         if (a <= MAX_GAMMA_Z) {
1758             final double alz1 = a * Math.log(z);
1759             if (z >= 1) {
1760                 if ((alz1 < LOG_MAX_VALUE) && (-z > LOG_MIN_VALUE)) {
1761                     return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1762                 }
1763             } else if (alz1 > LOG_MIN_VALUE) {
1764                 return Math.pow(z, a) * Math.exp(-z) / tgamma(a);
1765             }
1766         }
1767 
1768         //
1769         // For smallish a and x combining the power terms with the Lanczos approximation
1770         // gives the greatest accuracy
1771         //
1772 
1773         final double agh = a + Lanczos.GMH;
1774         double prefix;
1775 
1776         final double factor = Math.sqrt(agh / Math.E) / Lanczos.lanczosSumExpGScaled(a);
1777 
1778         // Update to the Boost code.
1779         // Lower threshold for large a from 150 to 128 and compute d on demand.
1780         // See NUMBERS-179.
1781         if (a > 128) {
1782             final double d = ((z - a) - Lanczos.GMH) / agh;
1783             if (Math.abs(d * d * a) <= 100) {
1784                 // special case for large a and a ~ z.
1785                 // When a and x are large, we end up with a very large exponent with a base near one:
1786                 // this will not be computed accurately via the pow function, and taking logs simply
1787                 // leads to cancellation errors.
1788                 prefix = a * SpecialMath.log1pmx(d) + z * -Lanczos.GMH / agh;
1789                 prefix = Math.exp(prefix);
1790                 return prefix * factor;
1791             }
1792         }
1793 
1794         //
1795         // general case.
1796         // direct computation is most accurate, but use various fallbacks
1797         // for different parts of the problem domain:
1798         //
1799 
1800         final double alz = a * Math.log(z / agh);
1801         final double amz = a - z;
1802         if ((Math.min(alz, amz) <= LOG_MIN_VALUE) || (Math.max(alz, amz) >= LOG_MAX_VALUE)) {
1803             final double amza = amz / a;
1804             if ((Math.min(alz, amz) / 2 > LOG_MIN_VALUE) && (Math.max(alz, amz) / 2 < LOG_MAX_VALUE)) {
1805                 // compute square root of the result and then square it:
1806                 final double sq = Math.pow(z / agh, a / 2) * Math.exp(amz / 2);
1807                 prefix = sq * sq;
1808             } else if ((Math.min(alz, amz) / 4 > LOG_MIN_VALUE) &&
1809                     (Math.max(alz, amz) / 4 < LOG_MAX_VALUE) && (z > a)) {
1810                 // compute the 4th root of the result then square it twice:
1811                 final double sq = Math.pow(z / agh, a / 4) * Math.exp(amz / 4);
1812                 prefix = sq * sq;
1813                 prefix *= prefix;
1814             } else if ((amza > LOG_MIN_VALUE) && (amza < LOG_MAX_VALUE)) {
1815                 prefix = Math.pow((z * Math.exp(amza)) / agh, a);
1816             } else {
1817                 prefix = Math.exp(alz + amz);
1818             }
1819         } else {
1820             prefix = Math.pow(z / agh, a) * Math.exp(amz);
1821         }
1822         prefix *= factor;
1823         return prefix;
1824     }
1825 
1826     /**
1827      * Implements the asymptotic expansions of the incomplete
1828      * gamma functions P(a, x) and Q(a, x), used when a is large and
1829      * x ~ a.
1830      *
1831      * <p>The primary reference is:
1832      * <pre>
1833      * "The Asymptotic Expansion of the Incomplete Gamma Functions"
1834      * N. M. Temme.
1835      * Siam J. Math Anal. Vol 10 No 4, July 1979, p757.
1836      * </pre>
1837      *
1838      * <p>A different way of evaluating these expansions,
1839      * plus a lot of very useful background information is in:
1840      * <pre>
1841      * "A Set of Algorithms For the Incomplete Gamma Functions."
1842      * N. M. Temme.
1843      * Probability in the Engineering and Informational Sciences,
1844      * 8, 1994, 291.
1845      * </pre>
1846      *
1847      * <p>An alternative implementation is in:
1848      * <pre>
1849      * "Computation of the Incomplete Gamma Function Ratios and their Inverse."
1850      * A. R. Didonato and A. H. Morris.
1851      * ACM TOMS, Vol 12, No 4, Dec 1986, p377.
1852      * </pre>
1853      *
1854      * <p>This is a port of the function accurate for 53-bit mantissas
1855      * (IEEE double precision or 10^-17). To understand the code, refer to Didonato
1856      * and Morris, from Eq 17 and 18 onwards.
1857      *
1858      * <p>The coefficients used here are not taken from Didonato and Morris:
1859      * the domain over which these expansions are used is slightly different
1860      * to theirs, and their constants are not quite accurate enough for
1861      * 128-bit long doubles.  Instead the coefficients were calculated
1862      * using the methods described by Temme p762 from Eq 3.8 onwards.
1863      * The values obtained agree with those obtained by Didonato and Morris
1864      * (at least to the first 30 digits that they provide).
1865      * At double precision the degrees of polynomial required for full
1866      * machine precision are close to those recommended to Didonato and Morris,
1867      * but of course many more terms are needed for larger types.
1868      *
1869      * <p>Adapted from {@code boost/math/special_functions/detail/igamma_large.hpp}.
1870      *
1871      * @param a the a
1872      * @param x the x
1873      * @return the double
1874      */
1875     // This is package-private for testing
1876     static double igammaTemmeLarge(double a, double x) {
1877         final double sigma = (x - a) / a;
1878         final double phi = -SpecialMath.log1pmx(sigma);
1879         final double y = a * phi;
1880         double z = Math.sqrt(2 * phi);
1881         if (x < a) {
1882             z = -z;
1883         }
1884 
1885         // The following polynomials are evaluated with a loop
1886         // with Horner's method. Variations exist using
1887         // a second order Horner's method with an unrolled loop.
1888         // These are chosen in Boost based on the C++ compiler.
1889         // For example:
1890         // boost/math/tools/detail/polynomial_horner1_15.hpp
1891         // boost/math/tools/detail/polynomial_horner2_15.hpp
1892         // boost/math/tools/detail/polynomial_horner3_15.hpp
1893 
1894         final double[] workspace = new double[10];
1895 
1896         final double[] C0 = {
1897             -0.33333333333333333,
1898             0.083333333333333333,
1899             -0.014814814814814815,
1900             0.0011574074074074074,
1901             0.0003527336860670194,
1902             -0.00017875514403292181,
1903             0.39192631785224378e-4,
1904             -0.21854485106799922e-5,
1905             -0.185406221071516e-5,
1906             0.8296711340953086e-6,
1907             -0.17665952736826079e-6,
1908             0.67078535434014986e-8,
1909             0.10261809784240308e-7,
1910             -0.43820360184533532e-8,
1911             0.91476995822367902e-9,
1912         };
1913         workspace[0] = BoostTools.evaluatePolynomial(C0, z);
1914 
1915         final double[] C1 = {
1916             -0.0018518518518518519,
1917             -0.0034722222222222222,
1918             0.0026455026455026455,
1919             -0.00099022633744855967,
1920             0.00020576131687242798,
1921             -0.40187757201646091e-6,
1922             -0.18098550334489978e-4,
1923             0.76491609160811101e-5,
1924             -0.16120900894563446e-5,
1925             0.46471278028074343e-8,
1926             0.1378633446915721e-6,
1927             -0.5752545603517705e-7,
1928             0.11951628599778147e-7,
1929         };
1930         workspace[1] = BoostTools.evaluatePolynomial(C1, z);
1931 
1932         final double[] C2 = {
1933             0.0041335978835978836,
1934             -0.0026813271604938272,
1935             0.00077160493827160494,
1936             0.20093878600823045e-5,
1937             -0.00010736653226365161,
1938             0.52923448829120125e-4,
1939             -0.12760635188618728e-4,
1940             0.34235787340961381e-7,
1941             0.13721957309062933e-5,
1942             -0.6298992138380055e-6,
1943             0.14280614206064242e-6,
1944         };
1945         workspace[2] = BoostTools.evaluatePolynomial(C2, z);
1946 
1947         final double[] C3 = {
1948             0.00064943415637860082,
1949             0.00022947209362139918,
1950             -0.00046918949439525571,
1951             0.00026772063206283885,
1952             -0.75618016718839764e-4,
1953             -0.23965051138672967e-6,
1954             0.11082654115347302e-4,
1955             -0.56749528269915966e-5,
1956             0.14230900732435884e-5,
1957         };
1958         workspace[3] = BoostTools.evaluatePolynomial(C3, z);
1959 
1960         final double[] C4 = {
1961             -0.0008618882909167117,
1962             0.00078403922172006663,
1963             -0.00029907248030319018,
1964             -0.14638452578843418e-5,
1965             0.66414982154651222e-4,
1966             -0.39683650471794347e-4,
1967             0.11375726970678419e-4,
1968         };
1969         workspace[4] = BoostTools.evaluatePolynomial(C4, z);
1970 
1971         final double[] C5 = {
1972             -0.00033679855336635815,
1973             -0.69728137583658578e-4,
1974             0.00027727532449593921,
1975             -0.00019932570516188848,
1976             0.67977804779372078e-4,
1977             0.1419062920643967e-6,
1978             -0.13594048189768693e-4,
1979             0.80184702563342015e-5,
1980             -0.22914811765080952e-5,
1981         };
1982         workspace[5] = BoostTools.evaluatePolynomial(C5, z);
1983 
1984         final double[] C6 = {
1985             0.00053130793646399222,
1986             -0.00059216643735369388,
1987             0.00027087820967180448,
1988             0.79023532326603279e-6,
1989             -0.81539693675619688e-4,
1990             0.56116827531062497e-4,
1991             -0.18329116582843376e-4,
1992         };
1993         workspace[6] = BoostTools.evaluatePolynomial(C6, z);
1994 
1995         final double[] C7 = {
1996             0.00034436760689237767,
1997             0.51717909082605922e-4,
1998             -0.00033493161081142236,
1999             0.0002812695154763237,
2000             -0.00010976582244684731,
2001         };
2002         workspace[7] = BoostTools.evaluatePolynomial(C7, z);
2003 
2004         final double[] C8 = {
2005             -0.00065262391859530942,
2006             0.00083949872067208728,
2007             -0.00043829709854172101,
2008         };
2009         workspace[8] = BoostTools.evaluatePolynomial(C8, z);
2010         workspace[9] = -0.00059676129019274625;
2011 
2012         double result = BoostTools.evaluatePolynomial(workspace, 1 / a);
2013         result *= Math.exp(-y) / Math.sqrt(2 * Math.PI * a);
2014         if (x < a) {
2015             result = -result;
2016         }
2017 
2018         result += BoostErf.erfc(Math.sqrt(y)) / 2;
2019 
2020         return result;
2021     }
2022 
2023     /**
2024      * Incomplete tgamma for large X.
2025      *
2026      * <p>This summation is a source of error as the series starts at 1 and descends to zero.
2027      * It can have thousands of iterations when a and z are large and close in value.
2028      *
2029      * @param a Argument a
2030      * @param x Argument x
2031      * @param pol Function evaluation policy
2032      * @return incomplete tgamma
2033      */
2034     // This is package-private for testing
2035     static double incompleteTgammaLargeX(double a, double x, Policy pol) {
2036         final double eps = pol.getEps();
2037         final int maxIterations = pol.getMaxIterations();
2038 
2039         // Asymptotic approximation for large argument, see: https://dlmf.nist.gov/8.11#E2.
2040         final DoubleSupplier gen = new DoubleSupplier() {
2041             /** Result term. */
2042             private double term = 1;
2043             /** Iteration. */
2044             private int n;
2045 
2046             @Override
2047             public double getAsDouble() {
2048                 final double result = term;
2049                 n++;
2050                 term *= (a - n) / x;
2051                 return result;
2052             }
2053         };
2054 
2055         return BoostTools.kahanSumSeries(gen, eps, maxIterations);
2056     }
2057 
2058     /**
2059      * Return true if the array is not null and has non-zero length.
2060      *
2061      * @param array Array
2062      * @return true if a non-zero length array
2063      */
2064     private static boolean nonZeroLength(int[] array) {
2065         return array != null && array.length != 0;
2066     }
2067 
2068     /**
2069      * Ratio of gamma functions.
2070      *
2071      * <p>\[ tgamma_ratio(z, delta) = \frac{\Gamma(z)}{\Gamma(z + delta)} \]
2072      *
2073      * <p>Adapted from {@code tgamma_delta_ratio_imp}. The use of
2074      * {@code max_factorial<double>::value == 170} has been replaced with
2075      * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2076      * to call the gamma function without overflow.
2077      *
2078      * @param z Argument z
2079      * @param delta The difference
2080      * @return gamma ratio
2081      */
2082     static double tgammaDeltaRatio(double z, double delta) {
2083         final double zDelta = z + delta;
2084         if (Double.isNaN(zDelta)) {
2085             // One or both arguments are NaN
2086             return Double.NaN;
2087         }
2088         if (z <= 0 || zDelta <= 0) {
2089             // This isn't very sophisticated, or accurate, but it does work:
2090             return tgamma(z) / tgamma(zDelta);
2091         }
2092 
2093         // Note: Directly calling tgamma(z) / tgamma(z + delta) if possible
2094         // without overflow is not more accurate
2095 
2096         if (Math.rint(delta) == delta) {
2097             if (delta == 0) {
2098                 return 1;
2099             }
2100             //
2101             // If both z and delta are integers, see if we can just use table lookup
2102             // of the factorials to get the result:
2103             //
2104             if (Math.rint(z) == z &&
2105                 z <= MAX_GAMMA_Z && zDelta <= MAX_GAMMA_Z) {
2106                 return FACTORIAL[(int) z - 1] / FACTORIAL[(int) zDelta - 1];
2107             }
2108             if (Math.abs(delta) < 20) {
2109                 //
2110                 // delta is a small integer, we can use a finite product:
2111                 //
2112                 if (delta < 0) {
2113                     z -= 1;
2114                     double result = z;
2115                     for (int d = (int) (delta + 1); d != 0; d++) {
2116                         z -= 1;
2117                         result *= z;
2118                     }
2119                     return result;
2120                 }
2121                 double result = 1 / z;
2122                 for (int d = (int) (delta - 1); d != 0; d--) {
2123                     z += 1;
2124                     result /= z;
2125                 }
2126                 return result;
2127             }
2128         }
2129         return tgammaDeltaRatioImpLanczos(z, delta);
2130     }
2131 
2132     /**
2133      * Ratio of gamma functions using Lanczos support.
2134      *
2135      * <p>\[ tgamma_delta_ratio(z, delta) = \frac{\Gamma(z)}{\Gamma(z + delta)}
2136      *
2137      * <p>Adapted from {@code tgamma_delta_ratio_imp_lanczos}. The use of
2138      * {@code max_factorial<double>::value == 170} has been replaced with
2139      * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2140      * to use the precomputed factorial table.
2141      *
2142      * @param z Argument z
2143      * @param delta The difference
2144      * @return gamma ratio
2145      */
2146     private static double tgammaDeltaRatioImpLanczos(double z, double delta) {
2147         if (z < EPSILON) {
2148             //
2149             // We get spurious numeric overflow unless we're very careful, this
2150             // can occur either inside Lanczos::lanczos_sum(z) or in the
2151             // final combination of terms, to avoid this, split the product up
2152             // into 2 (or 3) parts:
2153             //
2154             // G(z) / G(L) = 1 / (z * G(L)) ; z < eps, L = z + delta = delta
2155             // z * G(L) = z * G(lim) * (G(L)/G(lim)) ; lim = largest factorial
2156             //
2157             if (MAX_GAMMA_Z < delta) {
2158                 double ratio = tgammaDeltaRatioImpLanczos(delta, MAX_GAMMA_Z - delta);
2159                 ratio *= z;
2160                 ratio *= FACTORIAL[MAX_FACTORIAL];
2161                 return 1 / ratio;
2162             }
2163             return 1 / (z * tgamma(z + delta));
2164         }
2165         final double zgh = z + Lanczos.GMH;
2166         double result;
2167         if (z + delta == z) {
2168             // Here:
2169             // lanczosSum(z) / lanczosSum(z + delta) == 1
2170 
2171             // Update to the Boost code to remove unreachable code:
2172             // Given z + delta == z then |delta / z| < EPSILON; and z < zgh
2173             // assume (abs(delta / zgh) < EPSILON) and remove unreachable
2174             // else branch which sets result = 1
2175 
2176             // We have:
2177             // result = exp((0.5 - z) * log1p(delta / zgh));
2178             // 0.5 - z == -z
2179             // log1p(delta / zgh) = delta / zgh = delta / z
2180             // multiplying we get -delta.
2181 
2182             // Note:
2183             // This can be different from
2184             // exp((0.5 - z) * log1p(delta / zgh)) when z is small.
2185             // In this case the result is exp(small) and the result
2186             // is within 1 ULP of 1.0. This is left as the original
2187             // Boost method using exp(-delta).
2188 
2189             result = Math.exp(-delta);
2190         } else {
2191             if (Math.abs(delta) < 10) {
2192                 result = Math.exp((0.5 - z) * Math.log1p(delta / zgh));
2193             } else {
2194                 result = Math.pow(zgh / (zgh + delta), z - 0.5);
2195             }
2196             // Split the calculation up to avoid spurious overflow:
2197             result *= Lanczos.lanczosSum(z) / Lanczos.lanczosSum(z + delta);
2198         }
2199         result *= Math.pow(Math.E / (zgh + delta), delta);
2200         return result;
2201     }
2202 
2203     /**
2204      * Ratio of gamma functions.
2205      *
2206      * <p>\[ tgamma_ratio(x, y) = \frac{\Gamma(x)}{\Gamma(y)}
2207      *
2208      * <p>Adapted from {@code tgamma_ratio_imp}. The use of
2209      * {@code max_factorial<double>::value == 170} has been replaced with
2210      * {@code MAX_GAMMA_Z == 171}. This threshold is used when it is possible
2211      * to call the gamma function without overflow.
2212      *
2213      * @param x Argument x (must be positive finite)
2214      * @param y Argument y (must be positive finite)
2215      * @return gamma ratio (or nan)
2216      */
2217     static double tgammaRatio(double x, double y) {
2218         if (x <= 0 || !Double.isFinite(x) || y <= 0 || !Double.isFinite(y)) {
2219             return Double.NaN;
2220         }
2221         if (x <= Double.MIN_NORMAL) {
2222             // Special case for denorms...Ugh.
2223             return TWO_POW_53 * tgammaRatio(x * TWO_POW_53, y);
2224         }
2225 
2226         if (x <= MAX_GAMMA_Z && y <= MAX_GAMMA_Z) {
2227             // Rather than subtracting values, lets just call the gamma functions directly:
2228             return tgamma(x) / tgamma(y);
2229         }
2230         double prefix = 1;
2231         if (x < 1) {
2232             if (y < 2 * MAX_GAMMA_Z) {
2233                 // We need to sidestep on x as well, otherwise we'll underflow
2234                 // before we get to factor in the prefix term:
2235                 prefix /= x;
2236                 x += 1;
2237                 while (y >= MAX_GAMMA_Z) {
2238                     y -= 1;
2239                     prefix /= y;
2240                 }
2241                 return prefix * tgamma(x) / tgamma(y);
2242             }
2243             //
2244             // result is almost certainly going to underflow to zero, try logs just in case:
2245             //
2246             return Math.exp(lgamma(x) - lgamma(y));
2247         }
2248         if (y < 1) {
2249             if (x < 2 * MAX_GAMMA_Z) {
2250                 // We need to sidestep on y as well, otherwise we'll overflow
2251                 // before we get to factor in the prefix term:
2252                 prefix *= y;
2253                 y += 1;
2254                 while (x >= MAX_GAMMA_Z) {
2255                     x -= 1;
2256                     prefix *= x;
2257                 }
2258                 return prefix * tgamma(x) / tgamma(y);
2259             }
2260             //
2261             // Result will almost certainly overflow, try logs just in case:
2262             //
2263             return Math.exp(lgamma(x) - lgamma(y));
2264         }
2265         //
2266         // Regular case, x and y both large and similar in magnitude:
2267         //
2268         return tgammaDeltaRatio(x, y - x);
2269     }
2270 }