BoostBeta.java

  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. //  Copyright John Maddock 2006.
  18. //  Use, modification and distribution are subject to the
  19. //  Boost Software License, Version 1.0. (See accompanying file
  20. //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

  21. package org.apache.commons.numbers.gamma;

  22. import java.util.function.DoubleSupplier;
  23. import java.util.function.Supplier;
  24. import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction;
  25. import org.apache.commons.numbers.fraction.GeneralizedContinuedFraction.Coefficient;

  26. /**
  27.  * Implementation of the
  28.  * <a href="https://mathworld.wolfram.com/RegularizedBetaFunction.html">regularized beta functions</a> and
  29.  * <a href="https://mathworld.wolfram.com/IncompleteBetaFunction.html">incomplete beta functions</a>.
  30.  *
  31.  * <p>This code has been adapted from the <a href="https://www.boost.org/">Boost</a>
  32.  * {@code c++} implementation {@code <boost/math/special_functions/beta.hpp>}.
  33.  * All work is copyright to the original authors and subject to the Boost Software License.
  34.  *
  35.  * @see
  36.  * <a href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_beta.html">
  37.  * Boost C++ beta functions</a>
  38.  */
  39. final class BoostBeta {
  40.     //
  41.     // Code ported from Boost 1.77.0
  42.     //
  43.     // boost/math/special_functions/beta.hpp
  44.     //
  45.     // Original code comments are preserved.
  46.     //
  47.     // Changes to the Boost implementation:
  48.     // - Update method names to replace underscores with camel case
  49.     // - Remove checks for under/overflow. In this implementation no error is raised
  50.     //   for overflow (infinity is returned) or underflow (sub-normal or zero is returned).
  51.     //   This follows the conventions in java.lang.Math for the same conditions.
  52.     // - Removed the pointer p_derivative in the betaIncompleteImp. This is used
  53.     //   in the Boost code for the beta_inv functions for a derivative
  54.     //   based inverse function. This is currently not supported.
  55.     // - Altered series generators to use integer counters added to the double term
  56.     //   replacing directly incrementing a double term. When the term is large it cannot
  57.     //   be incremented: 1e16 + 1 == 1e16.
  58.     // - Added the use of the classic continued fraction representation for cases
  59.     //   where the Boost implementation detects sub-normal terms and does not evaluate.
  60.     // - Updated the method used to compute the binomialCoefficient. This can use a
  61.     //   series evaluation when n > max factorial given that n - k < 40.
  62.     // - Changed convergence criteria for betaSmallBLargeASeries to stop when r has
  63.     //   no effect on the sum. The Boost code uses machine epsilon (ignoring the policy eps).

  64.     /** Default epsilon value for relative error.
  65.      * This is equal to the Boost constant {@code boost::math::EPSILON}. */
  66.     private static final double EPSILON = 0x1.0p-52;
  67.     /** Approximate value for ln(Double.MAX_VALUE).
  68.      * This is equal to the Boost constant {@code boost::math::tools::log_max_value<double>()}.
  69.      * No term {@code x} should be used in {@code exp(x)} if {@code x > LOG_MAX_VALUE} to avoid
  70.      * overflow. */
  71.     private static final int LOG_MAX_VALUE = 709;
  72.     /** Approximate value for ln(Double.MIN_VALUE).
  73.      * This is equal to the Boost constant {@code boost::math::tools::log_min_value<double>()}.
  74.      * No term {@code x} should be used in {@code exp(x)} if {@code x < LOG_MIN_VALUE} to avoid
  75.      * underflow to sub-normal or zero. */
  76.     private static final int LOG_MIN_VALUE = -708;
  77.     /** pi/2. */
  78.     private static final double HALF_PI = Math.PI / 2;
  79.     /** The largest factorial that can be represented as a double.
  80.      * This is equal to the Boost constant {@code boost::math::max_factorial<double>::value}. */
  81.     private static final int MAX_FACTORIAL = 170;
  82.     /** Size of the table of Pn's.
  83.      * Equal to {@code Pn_size<double>} suitable for 16-20 digit accuracy. */
  84.     private static final int PN_SIZE = 30;
  85.     /** 2^53. Used to scale sub-normal values. */
  86.     private static final double TWO_POW_53 = 0x1.0p53;
  87.     /** 2^-53. Used to rescale values. */
  88.     private static final double TWO_POW_M53 = 0x1.0p-53;

  89.     /** Private constructor. */
  90.     private BoostBeta() {
  91.         // intentionally empty.
  92.     }

  93.     /**
  94.      * Beta function.
  95.      * <p>\[ B(p, q) = \frac{\Gamma(p) \Gamma(q)}{\Gamma(p+q)} \]
  96.      *
  97.      * @param p Argument p
  98.      * @param q Argument q
  99.      * @return beta value
  100.      */
  101.     static double beta(double p, double q) {
  102.         if (!(p > 0 && q > 0)) {
  103.             // Domain error
  104.             return Double.NaN;
  105.         }

  106.         final double c = p + q;

  107.         // Special cases:
  108.         if (c == p && q < EPSILON) {
  109.             return 1 / q;
  110.         } else if (c == q && p < EPSILON) {
  111.             return 1 / p;
  112.         }
  113.         if (q == 1) {
  114.             return 1 / p;
  115.         } else if (p == 1) {
  116.             return 1 / q;
  117.         } else if (c < EPSILON) {
  118.             return (c / p) / q;
  119.         }

  120.         // Create input a > b
  121.         final double a = p < q ? q : p;
  122.         final double b = p < q ? p : q;

  123.         // Lanczos calculation:
  124.         final double agh = a + BoostGamma.Lanczos.GMH;
  125.         final double bgh = b + BoostGamma.Lanczos.GMH;
  126.         final double cgh = c + BoostGamma.Lanczos.GMH;
  127.         double result = BoostGamma.Lanczos.lanczosSumExpGScaled(a) *
  128.                 (BoostGamma.Lanczos.lanczosSumExpGScaled(b) / BoostGamma.Lanczos.lanczosSumExpGScaled(c));
  129.         final double ambh = a - 0.5f - b;
  130.         if (Math.abs(b * ambh) < cgh * 100 && a > 100) {
  131.             // Special case where the base of the power term is close to 1
  132.             // compute (1+x)^y instead:
  133.             result *= Math.exp(ambh * Math.log1p(-b / cgh));
  134.         } else {
  135.             result *= Math.pow(agh / cgh, ambh);
  136.         }

  137.         if (cgh > 1e10f) {
  138.             // this avoids possible overflow, but appears to be marginally less accurate:
  139.             result *= Math.pow((agh / cgh) * (bgh / cgh), b);
  140.         } else {
  141.             result *= Math.pow((agh * bgh) / (cgh * cgh), b);
  142.         }
  143.         result *= Math.sqrt(Math.E / bgh);

  144.         return result;
  145.     }

  146.     /**
  147.      * Derivative of the regularised incomplete beta.
  148.      * <p>\[ \frac{\delta}{\delta x} I_x(a, b) = \frac{(1-x)^{b-1} x^{a-1}}{\B(a, b)} \]
  149.      *
  150.      * <p>Adapted from {@code boost::math::ibeta_derivative}.
  151.      *
  152.      * @param a Argument a
  153.      * @param b Argument b
  154.      * @param x Argument x
  155.      * @return ibeta derivative
  156.      */
  157.     static double ibetaDerivative(double a, double b, double x) {
  158.         //
  159.         // start with the usual error checks:
  160.         //
  161.         if (!(a > 0 && b > 0) || !(x >= 0 && x <= 1)) {
  162.             // Domain error
  163.             return Double.NaN;
  164.         }
  165.         //
  166.         // Now the corner cases:
  167.         //
  168.         if (x == 0) {
  169.             if (a > 1) {
  170.                 return 0;
  171.             }
  172.             // a == 1 : return 1 / beta(a, b) == b
  173.             return a == 1 ? b : Double.POSITIVE_INFINITY;
  174.         } else if (x == 1) {
  175.             if (b > 1) {
  176.                 return 0;
  177.             }
  178.             // b == 1 : return 1 / beta(a, b) == a
  179.             return b == 1 ? a : Double.POSITIVE_INFINITY;
  180.         }

  181.         // Update with extra edge cases
  182.         if (b == 1) {
  183.             // ibeta = x^a
  184.             return a * Math.pow(x, a - 1);
  185.         }
  186.         if (a == 1) {
  187.             // ibeta = 1 - (1-x)^b
  188.             if (x >= 0.5) {
  189.                 return b * Math.pow(1 - x, b - 1);
  190.             }
  191.             return b * Math.exp(Math.log1p(-x) * (b - 1));
  192.         }

  193.         //
  194.         // Now the regular cases:
  195.         //
  196.         final double y = (1 - x) * x;
  197.         return ibetaPowerTerms(a, b, x, 1 - x, true, 1 / y);
  198.     }

  199.     /**
  200.      * Compute the leading power terms in the incomplete Beta.
  201.      *
  202.      * <p>Utility function to call
  203.      * {@link #ibetaPowerTerms(double, double, double, double, boolean, double)}
  204.      * using a multiplication prefix of {@code 1.0}.
  205.      *
  206.      * @param a Argument a
  207.      * @param b Argument b
  208.      * @param x Argument x
  209.      * @param y Argument 1-x
  210.      * @param normalised true to divide by beta(a, b)
  211.      * @return incomplete beta power terms
  212.      */
  213.     private static double ibetaPowerTerms(double a, double b, double x,
  214.             double y, boolean normalised) {
  215.         return ibetaPowerTerms(a, b, x, y, normalised, 1);
  216.     }

  217.     /**
  218.      * Compute the leading power terms in the incomplete Beta.
  219.      *
  220.      * <pre>
  221.      * (x^a)(y^b)/Beta(a,b) when normalised, and
  222.      * (x^a)(y^b) otherwise.
  223.      * </pre>
  224.      *
  225.      * <p>Almost all of the error in the incomplete beta comes from this function:
  226.      * particularly when a and b are large. Computing large powers are *hard*
  227.      * though, and using logarithms just leads to horrendous cancellation errors.
  228.      *
  229.      * @param a Argument a
  230.      * @param b Argument b
  231.      * @param x Argument x
  232.      * @param y Argument 1-x
  233.      * @param normalised true to divide by beta(a, b)
  234.      * @param prefix Prefix to multiply by the result
  235.      * @return incomplete beta power terms
  236.      */
  237.     private static double ibetaPowerTerms(double a, double b, double x,
  238.             double y, boolean normalised, double prefix) {
  239.         if (!normalised) {
  240.             // can we do better here?
  241.             return Math.pow(x, a) * Math.pow(y, b);
  242.         }

  243.         double result;

  244.         final double c = a + b;

  245.         // combine power terms with Lanczos approximation:
  246.         final double agh = a + BoostGamma.Lanczos.GMH;
  247.         final double bgh = b + BoostGamma.Lanczos.GMH;
  248.         final double cgh = c + BoostGamma.Lanczos.GMH;
  249.         result = BoostGamma.Lanczos.lanczosSumExpGScaled(c) /
  250.                 (BoostGamma.Lanczos.lanczosSumExpGScaled(a) * BoostGamma.Lanczos.lanczosSumExpGScaled(b));
  251.         result *= prefix;
  252.         // combine with the leftover terms from the Lanczos approximation:
  253.         result *= Math.sqrt(bgh / Math.E);
  254.         result *= Math.sqrt(agh / cgh);

  255.         // l1 and l2 are the base of the exponents minus one:
  256.         double l1 = (x * b - y * agh) / agh;
  257.         double l2 = (y * a - x * bgh) / bgh;
  258.         if (Math.min(Math.abs(l1), Math.abs(l2)) < 0.2) {
  259.             // when the base of the exponent is very near 1 we get really
  260.             // gross errors unless extra care is taken:
  261.             if (l1 * l2 > 0 || Math.min(a, b) < 1) {
  262.                 //
  263.                 // This first branch handles the simple cases where either:
  264.                 //
  265.                 // * The two power terms both go in the same direction
  266.                 // (towards zero or towards infinity). In this case if either
  267.                 // term overflows or underflows, then the product of the two must
  268.                 // do so also.
  269.                 // * Alternatively if one exponent is less than one, then we
  270.                 // can't productively use it to eliminate overflow or underflow
  271.                 // from the other term. Problems with spurious overflow/underflow
  272.                 // can't be ruled out in this case, but it is *very* unlikely
  273.                 // since one of the power terms will evaluate to a number close to 1.
  274.                 //
  275.                 if (Math.abs(l1) < 0.1) {
  276.                     result *= Math.exp(a * Math.log1p(l1));
  277.                 } else {
  278.                     result *= Math.pow((x * cgh) / agh, a);
  279.                 }
  280.                 if (Math.abs(l2) < 0.1) {
  281.                     result *= Math.exp(b * Math.log1p(l2));
  282.                 } else {
  283.                     result *= Math.pow((y * cgh) / bgh, b);
  284.                 }
  285.             } else if (Math.max(Math.abs(l1), Math.abs(l2)) < 0.5) {
  286.                 //
  287.                 // Both exponents are near one and both the exponents are
  288.                 // greater than one and further these two
  289.                 // power terms tend in opposite directions (one towards zero,
  290.                 // the other towards infinity), so we have to combine the terms
  291.                 // to avoid any risk of overflow or underflow.
  292.                 //
  293.                 // We do this by moving one power term inside the other, we have:
  294.                 //
  295.                 //   (1 + l1)^a * (1 + l2)^b
  296.                 // = ((1 + l1)*(1 + l2)^(b/a))^a
  297.                 // = (1 + l1 + l3 + l1*l3)^a ; l3 = (1 + l2)^(b/a) - 1
  298.                 //                                = exp((b/a) * log(1 + l2)) - 1
  299.                 //
  300.                 // The tricky bit is deciding which term to move inside :-)
  301.                 // By preference we move the larger term inside, so that the
  302.                 // size of the largest exponent is reduced. However, that can
  303.                 // only be done as long as l3 (see above) is also small.
  304.                 //
  305.                 final boolean smallA = a < b;
  306.                 final double ratio = b / a;
  307.                 if ((smallA && ratio * l2 < 0.1) || (!smallA && l1 / ratio > 0.1)) {
  308.                     double l3 = Math.expm1(ratio * Math.log1p(l2));
  309.                     l3 = l1 + l3 + l3 * l1;
  310.                     l3 = a * Math.log1p(l3);
  311.                     result *= Math.exp(l3);
  312.                 } else {
  313.                     double l3 = Math.expm1(Math.log1p(l1) / ratio);
  314.                     l3 = l2 + l3 + l3 * l2;
  315.                     l3 = b * Math.log1p(l3);
  316.                     result *= Math.exp(l3);
  317.                 }
  318.             } else if (Math.abs(l1) < Math.abs(l2)) {
  319.                 // First base near 1 only:
  320.                 double l = a * Math.log1p(l1) + b * Math.log((y * cgh) / bgh);
  321.                 if (l <= LOG_MIN_VALUE || l >= LOG_MAX_VALUE) {
  322.                     l += Math.log(result);
  323.                     // Update: Allow overflow to infinity
  324.                     result = Math.exp(l);
  325.                 } else {
  326.                     result *= Math.exp(l);
  327.                 }
  328.             } else {
  329.                 // Second base near 1 only:
  330.                 double l = b * Math.log1p(l2) + a * Math.log((x * cgh) / agh);
  331.                 if (l <= LOG_MIN_VALUE || l >= LOG_MAX_VALUE) {
  332.                     l += Math.log(result);
  333.                     // Update: Allow overflow to infinity
  334.                     result = Math.exp(l);
  335.                 } else {
  336.                     result *= Math.exp(l);
  337.                 }
  338.             }
  339.         } else {
  340.             // general case:
  341.             final double b1 = (x * cgh) / agh;
  342.             final double b2 = (y * cgh) / bgh;
  343.             l1 = a * Math.log(b1);
  344.             l2 = b * Math.log(b2);
  345.             if (l1 >= LOG_MAX_VALUE || l1 <= LOG_MIN_VALUE || l2 >= LOG_MAX_VALUE || l2 <= LOG_MIN_VALUE) {
  346.                 // Oops, under/overflow, sidestep if we can:
  347.                 if (a < b) {
  348.                     final double p1 = Math.pow(b2, b / a);
  349.                     final double l3 = a * (Math.log(b1) + Math.log(p1));
  350.                     if (l3 < LOG_MAX_VALUE && l3 > LOG_MIN_VALUE) {
  351.                         result *= Math.pow(p1 * b1, a);
  352.                     } else {
  353.                         l2 += l1 + Math.log(result);
  354.                         // Update: Allow overflow to infinity
  355.                         result = Math.exp(l2);
  356.                     }
  357.                 } else {
  358.                     final double p1 = Math.pow(b1, a / b);
  359.                     final double l3 = (Math.log(p1) + Math.log(b2)) * b;
  360.                     if (l3 < LOG_MAX_VALUE && l3 > LOG_MIN_VALUE) {
  361.                         result *= Math.pow(p1 * b2, b);
  362.                     } else {
  363.                         l2 += l1 + Math.log(result);
  364.                         // Update: Allow overflow to infinity
  365.                         result = Math.exp(l2);
  366.                     }
  367.                 }
  368.             } else {
  369.                 // finally the normal case:
  370.                 result *= Math.pow(b1, a) * Math.pow(b2, b);
  371.             }
  372.         }

  373.         return result;
  374.     }

  375.     /**
  376.      * Full incomplete beta.
  377.      * <p>\[ B_x(a,b) = \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
  378.      *
  379.      * @param a Argument a
  380.      * @param b Argument b
  381.      * @param x Argument x
  382.      * @return lower beta value
  383.      */
  384.     static double beta(double a, double b, double x) {
  385.         return betaIncompleteImp(a, b, x, Policy.getDefault(), false, false);
  386.     }

  387.     /**
  388.      * Full incomplete beta.
  389.      * <p>\[ B_x(a,b) = \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
  390.      *
  391.      * @param a Argument a
  392.      * @param b Argument b
  393.      * @param x Argument x
  394.      * @param policy Function evaluation policy
  395.      * @return lower beta value
  396.      */
  397.     static double beta(double a, double b, double x, Policy policy) {
  398.         return betaIncompleteImp(a, b, x, policy, false, false);
  399.     }

  400.     /**
  401.      * Complement of the incomplete beta.
  402.      * <p>\[ betac(a, b, x) = beta(b, a, 1-x) = B_{1-x}(b,a) \]
  403.      *
  404.      * @param a Argument a
  405.      * @param b Argument b
  406.      * @param x Argument x
  407.      * @return upper beta value
  408.      */
  409.     static double betac(double a, double b, double x) {
  410.         return betaIncompleteImp(a, b, x, Policy.getDefault(), false, true);
  411.     }

  412.     /**
  413.      * Complement of the incomplete beta.
  414.      * <p>\[ betac(a, b, x) = beta(b, a, 1-x) = B_{1-x}(b,a) \]
  415.      *
  416.      * @param a Argument a
  417.      * @param b Argument b
  418.      * @param x Argument x
  419.      * @param policy Function evaluation policy
  420.      * @return upper beta value
  421.      */
  422.     static double betac(double a, double b, double x, Policy policy) {
  423.         return betaIncompleteImp(a, b, x, policy, false, true);
  424.     }

  425.     /**
  426.      * Regularised incomplete beta.
  427.      * <p>\[ I_x(a,b) = \frac{1}{B(a, b)} \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
  428.      *
  429.      * @param a Argument a
  430.      * @param b Argument b
  431.      * @param x Argument x
  432.      * @return p
  433.      */
  434.     static double ibeta(double a, double b, double x) {
  435.         return betaIncompleteImp(a, b, x, Policy.getDefault(), true, false);
  436.     }

  437.     /**
  438.      * Regularised incomplete beta.
  439.      * <p>\[ I_x(a,b) = \frac{1}{B(a, b)} \int_0^x t^{a-1}\,(1-t)^{b-1}\,dt \]
  440.      *
  441.      * @param a Argument a
  442.      * @param b Argument b
  443.      * @param x Argument x
  444.      * @param policy Function evaluation policy
  445.      * @return p
  446.      */
  447.     static double ibeta(double a, double b, double x, Policy policy) {
  448.         return betaIncompleteImp(a, b, x, policy, true, false);
  449.     }

  450.     /**
  451.      * Complement of the regularised incomplete beta.
  452.      * <p>\[ ibetac(a, b, x) = 1 - I_x(a,b) = I_{1-x}(b, a) \]
  453.      *
  454.      * @param a Argument a
  455.      * @param b Argument b
  456.      * @param x Argument x
  457.      * @return q
  458.      */
  459.     static double ibetac(double a, double b, double x) {
  460.         return betaIncompleteImp(a, b, x, Policy.getDefault(), true, true);
  461.     }

  462.     /**
  463.      * Complement of the regularised incomplete beta.
  464.      * <p>\[ ibetac(a, b, x) = 1 - I_x(a,b) = I_{1-x}(b, a) \]
  465.      *
  466.      * @param a Argument a
  467.      * @param b Argument b
  468.      * @param x Argument x
  469.      * @param policy Function evaluation policy
  470.      * @return q
  471.      */
  472.     static double ibetac(double a, double b, double x, Policy policy) {
  473.         return betaIncompleteImp(a, b, x, policy, true, true);
  474.     }

  475.     /**
  476.      * Main incomplete beta entry point, handles all four incomplete betas.
  477.      * Adapted from {@code boost::math::detail::ibeta_imp}.
  478.      *
  479.      * <p>The Boost code has a pointer {@code p_derivative} that can be set to the
  480.      * value of the derivative. This is used for the inverse incomplete
  481.      * beta functions. It is not required for the forward evaluation functions.
  482.      *
  483.      * @param a Argument a
  484.      * @param b Argument b
  485.      * @param x Argument x
  486.      * @param pol Function evaluation policy
  487.      * @param normalised true to compute the regularised value
  488.      * @param inv true to compute the complement value
  489.      * @return incomplete beta value
  490.      */
  491.     private static double betaIncompleteImp(double a, double b, double x,
  492.             Policy pol, boolean normalised, boolean inv) {
  493.         //
  494.         // The incomplete beta function implementation:
  495.         // This is just a big bunch of spaghetti code to divide up the
  496.         // input range and select the right implementation method for
  497.         // each domain:
  498.         //

  499.         if (!(x >= 0 && x <= 1)) {
  500.             // Domain error
  501.             return Double.NaN;
  502.         }

  503.         if (normalised) {
  504.             if (!(a >= 0 && b >= 0)) {
  505.                 // Domain error
  506.                 return Double.NaN;
  507.             }
  508.             // extend to a few very special cases:
  509.             if (a == 0) {
  510.                 if (b == 0) {
  511.                     // a and b cannot both be zero
  512.                     return Double.NaN;
  513.                 }
  514.                 // Assume b > 0
  515.                 return inv ? 0 : 1;
  516.             } else if (b == 0) {
  517.                 // assume a > 0
  518.                 return inv ? 1 : 0;
  519.             }
  520.         } else {
  521.             if (!(a > 0 && b > 0)) {
  522.                 // Domain error
  523.                 return Double.NaN;
  524.             }
  525.         }

  526.         if (x == 0) {
  527.             if (inv) {
  528.                 return normalised ? 1 : beta(a, b);
  529.             }
  530.             return 0;
  531.         }
  532.         if (x == 1) {
  533.             if (!inv) {
  534.                 return normalised ? 1 : beta(a, b);
  535.             }
  536.             return 0;
  537.         }

  538.         if (a == 0.5f && b == 0.5f) {
  539.             // We have an arcsine distribution:
  540.             final double z = inv ? 1 - x : x;
  541.             final double asin = Math.asin(Math.sqrt(z));
  542.             return normalised ? asin / HALF_PI : 2 * asin;
  543.         }

  544.         boolean invert = inv;
  545.         double y = 1 - x;
  546.         if (a == 1) {
  547.             // swap(a, b)
  548.             double tmp = a;
  549.             a = b;
  550.             b = tmp;
  551.             // swap(x, y)
  552.             tmp = x;
  553.             x = y;
  554.             y = tmp;
  555.             invert = !invert;
  556.         }
  557.         if (b == 1) {
  558.             //
  559.             // Special case see:
  560.             // http://functions.wolfram.com/GammaBetaErf/BetaRegularized/03/01/01/
  561.             //
  562.             if (a == 1) {
  563.                 return invert ? y : x;
  564.             }

  565.             double p;
  566.             if (y < 0.5) {
  567.                 p = invert ? -Math.expm1(a * Math.log1p(-y)) : Math.exp(a * Math.log1p(-y));
  568.             } else {
  569.                 p = invert ? -BoostMath.powm1(x, a) : Math.pow(x, a);
  570.             }
  571.             if (!normalised) {
  572.                 p /= a;
  573.             }
  574.             return p;
  575.         }

  576.         double fract;
  577.         if (Math.min(a, b) <= 1) {
  578.             if (x > 0.5) {
  579.                 // swap(a, b)
  580.                 double tmp = a;
  581.                 a = b;
  582.                 b = tmp;
  583.                 // swap(x, y)
  584.                 tmp = x;
  585.                 x = y;
  586.                 y = tmp;
  587.                 invert = !invert;
  588.             }
  589.             if (Math.max(a, b) <= 1) {
  590.                 // Both a,b < 1:
  591.                 if (a >= Math.min(0.2, b) || Math.pow(x, a) <= 0.9) {
  592.                     if (invert) {
  593.                         fract = -(normalised ? 1 : beta(a, b));
  594.                         invert = false;
  595.                         fract = -ibetaSeries(a, b, x, fract, normalised, pol);
  596.                     } else {
  597.                         fract = ibetaSeries(a, b, x, 0, normalised, pol);
  598.                     }
  599.                 } else {
  600.                     // swap(a, b)
  601.                     double tmp = a;
  602.                     a = b;
  603.                     b = tmp;
  604.                     // swap(x, y)
  605.                     tmp = x;
  606.                     x = y;
  607.                     y = tmp;
  608.                     invert = !invert;
  609.                     if (y >= 0.3) {
  610.                         if (invert) {
  611.                             fract = -(normalised ? 1 : beta(a, b));
  612.                             invert = false;
  613.                             fract = -ibetaSeries(a, b, x, fract, normalised, pol);
  614.                         } else {
  615.                             fract = ibetaSeries(a, b, x, 0, normalised, pol);
  616.                         }
  617.                     } else {
  618.                         // Sidestep on a, and then use the series representation:
  619.                         final double prefix;
  620.                         if (normalised) {
  621.                             prefix = 1;
  622.                         } else {
  623.                             prefix = risingFactorialRatio(a + b, a, 20);
  624.                         }
  625.                         fract = ibetaAStep(a, b, x, y, 20, normalised);
  626.                         if (invert) {
  627.                             fract -= normalised ? 1 : beta(a, b);
  628.                             invert = false;
  629.                             fract = -betaSmallBLargeASeries(a + 20, b, x, y, fract, prefix, pol, normalised);
  630.                         } else {
  631.                             fract = betaSmallBLargeASeries(a + 20, b, x, y, fract, prefix, pol, normalised);
  632.                         }
  633.                     }
  634.                 }
  635.             } else {
  636.                 // One of a, b < 1 only:
  637.                 if (b <= 1 || (x < 0.1 && Math.pow(b * x, a) <= 0.7)) {
  638.                     if (invert) {
  639.                         fract = -(normalised ? 1 : beta(a, b));
  640.                         invert = false;
  641.                         fract = -ibetaSeries(a, b, x, fract, normalised, pol);
  642.                     } else {
  643.                         fract = ibetaSeries(a, b, x, 0, normalised, pol);
  644.                     }
  645.                 } else {
  646.                     // swap(a, b)
  647.                     double tmp = a;
  648.                     a = b;
  649.                     b = tmp;
  650.                     // swap(x, y)
  651.                     tmp = x;
  652.                     x = y;
  653.                     y = tmp;
  654.                     invert = !invert;

  655.                     if (y >= 0.3) {
  656.                         if (invert) {
  657.                             fract = -(normalised ? 1 : beta(a, b));
  658.                             invert = false;
  659.                             fract = -ibetaSeries(a, b, x, fract, normalised, pol);
  660.                         } else {
  661.                             fract = ibetaSeries(a, b, x, 0, normalised, pol);
  662.                         }
  663.                     } else if (a >= 15) {
  664.                         if (invert) {
  665.                             fract = -(normalised ? 1 : beta(a, b));
  666.                             invert = false;
  667.                             fract = -betaSmallBLargeASeries(a, b, x, y, fract, 1, pol, normalised);
  668.                         } else {
  669.                             fract = betaSmallBLargeASeries(a, b, x, y, 0, 1, pol, normalised);
  670.                         }
  671.                     } else {
  672.                         // Sidestep to improve errors:
  673.                         final double prefix;
  674.                         if (normalised) {
  675.                             prefix = 1;
  676.                         } else {
  677.                             prefix = risingFactorialRatio(a + b, a, 20);
  678.                         }
  679.                         fract = ibetaAStep(a, b, x, y, 20, normalised);
  680.                         if (invert) {
  681.                             fract -= normalised ? 1 : beta(a, b);
  682.                             invert = false;
  683.                             fract = -betaSmallBLargeASeries(a + 20, b, x, y, fract, prefix, pol, normalised);
  684.                         } else {
  685.                             fract = betaSmallBLargeASeries(a + 20, b, x, y, fract, prefix, pol, normalised);
  686.                         }
  687.                     }
  688.                 }
  689.             }
  690.         } else {
  691.             // Both a,b >= 1:
  692.             // Note:
  693.             // median ~ (a - 1/3) / (a + b - 2/3) ~ a / (a + b)
  694.             // if x > a / (a + b) => a - (a + b) * x < 0
  695.             final double lambda;
  696.             if (a < b) {
  697.                 lambda = a - (a + b) * x;
  698.             } else {
  699.                 lambda = (a + b) * y - b;
  700.             }
  701.             if (lambda < 0) {
  702.                 // swap(a, b)
  703.                 double tmp = a;
  704.                 a = b;
  705.                 b = tmp;
  706.                 // swap(x, y)
  707.                 tmp = x;
  708.                 x = y;
  709.                 y = tmp;
  710.                 invert = !invert;
  711.             }

  712.             if (b < 40) {
  713.                 // Note: y != 1 check is required for non-zero x < epsilon
  714.                 if (Math.rint(a) == a && Math.rint(b) == b && a < (Integer.MAX_VALUE - 100) && y != 1) {
  715.                     // Here: a in [2, 2^31 - 102] && b in [2, 39]

  716.                     // relate to the binomial distribution and use a finite sum:
  717.                     final int k = (int) (a - 1);
  718.                     final int n = (int) (b + k);
  719.                     fract = binomialCCdf(n, k, x, y);
  720.                     if (!normalised) {
  721.                         fract *= beta(a, b);
  722.                     }
  723.                 } else if (b * x <= 0.7) {
  724.                     if (invert) {
  725.                         fract = -(normalised ? 1 : beta(a, b));
  726.                         invert = false;
  727.                         fract = -ibetaSeries(a, b, x, fract, normalised, pol);
  728.                     } else {
  729.                         fract = ibetaSeries(a, b, x, 0, normalised, pol);
  730.                     }
  731.                 } else if (a > 15) {
  732.                     // sidestep so we can use the series representation:
  733.                     int n = (int) b;
  734.                     if (n == b) {
  735.                         --n;
  736.                     }
  737.                     final double bbar = b - n;
  738.                     final double prefix;
  739.                     if (normalised) {
  740.                         prefix = 1;
  741.                     } else {
  742.                         prefix = risingFactorialRatio(a + bbar, bbar, n);
  743.                     }
  744.                     fract = ibetaAStep(bbar, a, y, x, n, normalised);
  745.                     fract = betaSmallBLargeASeries(a, bbar, x, y, fract, 1, pol, normalised);
  746.                     fract /= prefix;
  747.                 } else if (normalised) {
  748.                     // The formula here for the non-normalised case is tricky to figure
  749.                     // out (for me!!), and requires two pochhammer calculations rather
  750.                     // than one, so leave it for now and only use this in the normalized case....
  751.                     int n = (int) Math.floor(b);
  752.                     double bbar = b - n;
  753.                     if (bbar <= 0) {
  754.                         --n;
  755.                         bbar += 1;
  756.                     }
  757.                     fract = ibetaAStep(bbar, a, y, x, n, normalised);
  758.                     fract += ibetaAStep(a, bbar, x, y, 20, normalised);
  759.                     if (invert) {
  760.                         // Note this line would need changing if we ever enable this branch in
  761.                         // non-normalized case
  762.                         fract -= 1;
  763.                     }
  764.                     fract = betaSmallBLargeASeries(a + 20, bbar, x, y, fract, 1, pol, normalised);
  765.                     if (invert) {
  766.                         fract = -fract;
  767.                         invert = false;
  768.                     }
  769.                 } else {
  770.                     fract = ibetaFraction2(a, b, x, y, pol, normalised);
  771.                 }
  772.             } else {
  773.                 fract = ibetaFraction2(a, b, x, y, pol, normalised);
  774.             }
  775.         }
  776.         if (invert) {
  777.             return (normalised ? 1 : beta(a, b)) - fract;
  778.         }
  779.         return fract;
  780.     }

  781.     /**
  782.      * Series approximation to the incomplete beta.
  783.      *
  784.      * @param a Argument a
  785.      * @param b Argument b
  786.      * @param x Argument x
  787.      * @param s0 Initial sum for the series
  788.      * @param normalised true to compute the regularised value
  789.      * @param pol Function evaluation policy
  790.      * @return incomplete beta series
  791.      */
  792.     private static double ibetaSeries(double a, double b, double x, double s0, boolean normalised, Policy pol) {
  793.         double result;

  794.         if (normalised) {
  795.             final double c = a + b;

  796.             // incomplete beta power term, combined with the Lanczos approximation:
  797.             final double agh = a + BoostGamma.Lanczos.GMH;
  798.             final double bgh = b + BoostGamma.Lanczos.GMH;
  799.             final double cgh = c + BoostGamma.Lanczos.GMH;
  800.             result = BoostGamma.Lanczos.lanczosSumExpGScaled(c) /
  801.                     (BoostGamma.Lanczos.lanczosSumExpGScaled(a) * BoostGamma.Lanczos.lanczosSumExpGScaled(b));

  802.             final double l1 = Math.log(cgh / bgh) * (b - 0.5f);
  803.             final double l2 = Math.log(x * cgh / agh) * a;
  804.             //
  805.             // Check for over/underflow in the power terms:
  806.             //
  807.             if (l1 > LOG_MIN_VALUE && l1 < LOG_MAX_VALUE && l2 > LOG_MIN_VALUE && l2 < LOG_MAX_VALUE) {
  808.                 if (a * b < bgh * 10) {
  809.                     result *= Math.exp((b - 0.5f) * Math.log1p(a / bgh));
  810.                 } else {
  811.                     result *= Math.pow(cgh / bgh, b - 0.5f);
  812.                 }
  813.                 result *= Math.pow(x * cgh / agh, a);
  814.                 result *= Math.sqrt(agh / Math.E);
  815.             } else {
  816.                 //
  817.                 // Oh dear, we need logs, and this *will* cancel:
  818.                 //
  819.                 result = Math.log(result) + l1 + l2 + (Math.log(agh) - 1) / 2;
  820.                 result = Math.exp(result);
  821.             }
  822.         } else {
  823.             // Non-normalised, just compute the power:
  824.             result = Math.pow(x, a);
  825.         }
  826.         double rescale = 1.0;
  827.         if (result < Double.MIN_NORMAL) {
  828.             // Safeguard: series can't cope with denorms.

  829.             // Update:
  830.             // The entire series is only based on the magnitude of 'result'.
  831.             // If the first term can be added to s0 (e.g. if s0 == 0) then
  832.             // scale s0 and result, compute the series and then rescale.

  833.             // Intentional floating-point equality check.
  834.             if (s0 + result / a == s0) {
  835.                 return s0;
  836.             }
  837.             s0 *= TWO_POW_53;
  838.             result *= TWO_POW_53;
  839.             rescale = TWO_POW_M53;
  840.         }

  841.         final double eps = pol.getEps();
  842.         final int maxIterations = pol.getMaxIterations();

  843.         // Create effectively final 'result' for initialisation
  844.         final double result1 = result;
  845.         final DoubleSupplier gen = new DoubleSupplier() {
  846.             /** Next result term. */
  847.             private double result = result1;
  848.             /** Pochhammer term. */
  849.             private final double poch = -b;
  850.             /** Iteration. */
  851.             private int n;

  852.             @Override
  853.             public double getAsDouble() {
  854.                 final double r = result / (a + n);
  855.                 n++;
  856.                 result *= (n + poch) * x / n;
  857.                 return r;
  858.             }
  859.         };

  860.         return BoostTools.sumSeries(gen, eps, maxIterations, s0) * rescale;
  861.     }

  862.     /**
  863.      * Rising factorial ratio.
  864.      * This function is only needed for the non-regular incomplete beta,
  865.      * it computes the delta in:
  866.      * <pre>
  867.      * beta(a,b,x) = prefix + delta * beta(a+k,b,x)
  868.      * </pre>
  869.      * <p>It is currently only called for small k.
  870.      *
  871.      * @param a Argument a
  872.      * @param b Argument b
  873.      * @param k Argument k
  874.      * @return the rising factorial ratio
  875.      */
  876.     private static double risingFactorialRatio(double a, double b, int k) {
  877.         // calculate:
  878.         // (a)(a+1)(a+2)...(a+k-1)
  879.         // _______________________
  880.         // (b)(b+1)(b+2)...(b+k-1)

  881.         // This is only called with small k, for large k
  882.         // it is grossly inefficient, do not use outside it's
  883.         // intended purpose!!!
  884.         double result = 1;
  885.         for (int i = 0; i < k; ++i) {
  886.             result *= (a + i) / (b + i);
  887.         }
  888.         return result;
  889.     }

  890.     /**
  891.      * Binomial complementary cdf.
  892.      * For integer arguments we can relate the incomplete beta to the
  893.      * complement of the binomial distribution cdf and use this finite sum.
  894.      *
  895.      * @param n Argument n (called with {@code [2, 39] + k})
  896.      * @param k Argument k (called with {@code k in [1, Integer.MAX_VALUE - 102]})
  897.      * @param x Argument x
  898.      * @param y Argument 1-x
  899.      * @return Binomial complementary cdf
  900.      */
  901.     private static double binomialCCdf(int n, int k, double x, double y) {
  902.         double result = Math.pow(x, n);

  903.         if (result > Double.MIN_NORMAL) {
  904.             double term = result;
  905.             for (int i = n - 1; i > k; --i) {
  906.                 term *= ((i + 1) * y) / ((n - i) * x);
  907.                 result += term;
  908.             }
  909.         } else {
  910.             // First term underflows so we need to start at the mode of the
  911.             // distribution and work outwards:
  912.             int start = (int) (n * x);
  913.             if (start <= k + 1) {
  914.                 start = k + 2;
  915.             }
  916.             // Update:
  917.             // Carefully compute this term to guard against extreme parameterisation
  918.             result = binomialTerm(n, start, x, y);
  919.             if (result == 0) {
  920.                 // OK, starting slightly above the mode didn't work,
  921.                 // we'll have to sum the terms the old fashioned way:
  922.                 for (int i = start - 1; i > k; --i) {
  923.                     result += binomialTerm(n, i, x, y);
  924.                 }
  925.             } else {
  926.                 double term = result;
  927.                 final double startTerm = result;
  928.                 for (int i = start - 1; i > k; --i) {
  929.                     term *= ((i + 1) * y) / ((n - i) * x);
  930.                     result += term;
  931.                 }
  932.                 term = startTerm;
  933.                 for (int i = start + 1; i <= n; ++i) {
  934.                     term *= (n - i + 1) * x / (i * y);
  935.                     result += term;
  936.                 }
  937.             }
  938.         }

  939.         return result;
  940.     }

  941.     /**
  942.      * Compute the binomial term.
  943.      * <pre>
  944.      * x^k * (1-x)^(n-k) * binomial(n, k)
  945.      * </pre>
  946.      * <p>This is a helper function used to guard against extreme values generated
  947.      * in the term which can produce NaN from zero multiplied by infinity.
  948.      *
  949.      * @param n Argument n
  950.      * @param k Argument k
  951.      * @param x Argument x
  952.      * @param y Argument 1-x
  953.      * @return Binomial term
  954.      */
  955.     private static double binomialTerm(int n, int k, double x, double y) {
  956.         // This function can be called with the following extreme that will overflow:
  957.         // binomial(2147483545 + 39, 38) ~ 7.84899e309
  958.         // Guard this as the power functions are very likely to be zero with large n and k.

  959.         final double binom = binomialCoefficient(n, k);
  960.         if (!Double.isFinite(binom)) {
  961.             // Product of the power functions will be zero with large n and k
  962.             return 0;
  963.         }

  964.         // The power terms are below 1.
  965.         // Multiply by the largest so that any sub-normal term is used last
  966.         // This method is called where x^n is sub-normal so assume the other term is larger.
  967.         return binom * Math.pow(y, n - k) * Math.pow(x, k);
  968.     }

  969.     /**
  970.      * Computes the binomial coefficient.
  971.      *
  972.      * <p>Adapted from
  973.      * {@code org.apache.commons.numbers.combinatorics.BinomialCoefficientDouble}.
  974.      *
  975.      * <p>Note: This does not use {@code BinomialCoefficientDouble}
  976.      * to avoid a circular dependency as the combinatorics depends on the gamma package.
  977.      * No checks are made on the arguments.
  978.      *
  979.      * @param n Size of the set (must be positive).
  980.      * @param k Size of the subsets to be counted (must be in [0, n]).
  981.      * @return {@code n choose k}.
  982.      */
  983.     static double binomialCoefficient(int n, int k) {
  984.         // Assume: n >= 0; 0 <= k <= n
  985.         // Use symmetry
  986.         final int m = Math.min(k, n - k);

  987.         // This function is typically called with m <= 3 so handle these special cases
  988.         if (m == 0) {
  989.             return 1;
  990.         }
  991.         if (m == 1) {
  992.             return n;
  993.         }
  994.         if (m == 2) {
  995.             return 0.5 * n * (n - 1);
  996.         }
  997.         if (m == 3) {
  998.             // Divide by 3 at the end to avoid using an 1/6 inexact initial multiplier.
  999.             return 0.5 * n * (n - 1) * (n - 2) / 3;
  1000.         }

  1001.         double result;
  1002.         if (n <= MAX_FACTORIAL) {
  1003.             // Use fast table lookup:
  1004.             result = BoostGamma.uncheckedFactorial(n);
  1005.             // Smaller m will have a more accurate factorial
  1006.             result /= BoostGamma.uncheckedFactorial(m);
  1007.             result /= BoostGamma.uncheckedFactorial(n - m);
  1008.         } else {
  1009.             // Updated:
  1010.             // Do not use the beta function as per <boost/math/special_functions/binomial.hpp>,
  1011.             // e.g. result = 1 / (m * beta(m, n - m + 1)) == gamma(n+1) / (m * gamma(m) * gamma(n-m+1))

  1012.             // Use a summation as per BinomialCoefficientDouble which is more accurate
  1013.             // than using the beta function. This is only used up to m = 39 so
  1014.             // may overflow *only* on the final term (i.e. m << n when overflow can occur).

  1015.             result = 1;
  1016.             for (int i = 1; i < m; i++) {
  1017.                 result *= n - m + i;
  1018.                 result /= i;
  1019.             }
  1020.             // Final term may cause overflow.
  1021.             if (result * n > Double.MAX_VALUE) {
  1022.                 result /= m;
  1023.                 result *= n;
  1024.             } else {
  1025.                 result *= n;
  1026.                 result /= m;
  1027.             }
  1028.         }
  1029.         // convert to nearest integer:
  1030.         return Math.ceil(result - 0.5f);
  1031.     }

  1032.     /**
  1033.      * Computes the difference between ibeta(a,b,x) and ibeta(a+k,b,x).
  1034.      *
  1035.      * @param a Argument a
  1036.      * @param b Argument b
  1037.      * @param x Argument x
  1038.      * @param y Argument 1-x
  1039.      * @param k Argument k
  1040.      * @param normalised true to compute the regularised value
  1041.      * @return ibeta difference
  1042.      */
  1043.     private static double ibetaAStep(double a, double b, double x, double y, int k, boolean normalised) {
  1044.         double prefix = ibetaPowerTerms(a, b, x, y, normalised);
  1045.         prefix /= a;
  1046.         if (prefix == 0) {
  1047.             return prefix;
  1048.         }
  1049.         double sum = 1;
  1050.         double term = 1;
  1051.         // series summation from 0 to k-1:
  1052.         for (int i = 0; i < k - 1; ++i) {
  1053.             term *= (a + b + i) * x / (a + i + 1);
  1054.             sum += term;
  1055.         }
  1056.         prefix *= sum;

  1057.         return prefix;
  1058.     }

  1059.     /**
  1060.      * Computes beta(a, b, x) using small b and large a.
  1061.      *
  1062.      * @param a Argument a
  1063.      * @param b Argument b
  1064.      * @param x Argument x
  1065.      * @param y Argument 1-x
  1066.      * @param s0 Initial sum for the series
  1067.      * @param mult Multiplication prefix factor
  1068.      * @param pol Function evaluation policy
  1069.      * @param normalised true to compute the regularised value
  1070.      * @return beta series
  1071.      */
  1072.     private static double betaSmallBLargeASeries(double a, double b, double x, double y, double s0, double mult,
  1073.             Policy pol, boolean normalised) {
  1074.         //
  1075.         // This is DiDonato and Morris's BGRAT routine, see Eq's 9 through 9.6.
  1076.         //
  1077.         // Some values we'll need later, these are Eq 9.1:
  1078.         //
  1079.         final double bm1 = b - 1;
  1080.         final double t = a + bm1 / 2;
  1081.         final double lx;
  1082.         if (y < 0.35) {
  1083.             lx = Math.log1p(-y);
  1084.         } else {
  1085.             lx = Math.log(x);
  1086.         }
  1087.         final double u = -t * lx;
  1088.         // and from from 9.2:
  1089.         final double h = BoostGamma.regularisedGammaPrefix(b, u);
  1090.         if (h <= Double.MIN_NORMAL) {
  1091.             // Update:
  1092.             // Boost returns s0.
  1093.             // If this is zero then compute an expected sub-normal value
  1094.             // using the classic continued fraction representation.
  1095.             if (s0 == 0) {
  1096.                 return ibetaFraction(a, b, x, y, pol, normalised);
  1097.             }
  1098.             return s0;
  1099.         }
  1100.         double prefix;
  1101.         if (normalised) {
  1102.             prefix = h / GammaRatio.delta(a, b);
  1103.             prefix /= Math.pow(t, b);
  1104.         } else {
  1105.             prefix = BoostGamma.fullIgammaPrefix(b, u) / Math.pow(t, b);
  1106.         }
  1107.         prefix *= mult;
  1108.         //
  1109.         // now we need the quantity Pn, unfortunately this is computed
  1110.         // recursively, and requires a full history of all the previous values
  1111.         // so no choice but to declare a big table and hope it's big enough...
  1112.         //
  1113.         final double[] p = new double[PN_SIZE];
  1114.         // see 9.3.
  1115.         p[0] = 1;
  1116.         //
  1117.         // Now an initial value for J, see 9.6:
  1118.         //
  1119.         double j = BoostGamma.gammaQ(b, u, pol) / h;
  1120.         //
  1121.         // Now we can start to pull things together and evaluate the sum in Eq 9:
  1122.         //
  1123.         // Value at N = 0
  1124.         double sum = s0 + prefix * j;
  1125.         // some variables we'll need:
  1126.         // 2*N+1
  1127.         int tnp1 = 1;
  1128.         double lx2 = lx / 2;
  1129.         lx2 *= lx2;
  1130.         double lxp = 1;
  1131.         final double t4 = 4 * t * t;
  1132.         double b2n = b;

  1133.         for (int n = 1; n < PN_SIZE; ++n) {
  1134.             //
  1135.             // begin by evaluating the next Pn from Eq 9.4:
  1136.             //
  1137.             tnp1 += 2;
  1138.             p[n] = 0;
  1139.             int tmp1 = 3;
  1140.             for (int m = 1; m < n; ++m) {
  1141.                 final double mbn = m * b - n;
  1142.                 p[n] += mbn * p[n - m] / BoostGamma.uncheckedFactorial(tmp1);
  1143.                 tmp1 += 2;
  1144.             }
  1145.             p[n] /= n;
  1146.             p[n] += bm1 / BoostGamma.uncheckedFactorial(tnp1);
  1147.             //
  1148.             // Now we want Jn from Jn-1 using Eq 9.6:
  1149.             //
  1150.             j = (b2n * (b2n + 1) * j + (u + b2n + 1) * lxp) / t4;
  1151.             lxp *= lx2;
  1152.             b2n += 2;
  1153.             //
  1154.             // pull it together with Eq 9:
  1155.             //
  1156.             final double r = prefix * p[n] * j;
  1157.             final double previous = sum;
  1158.             sum += r;
  1159.             // Update:
  1160.             // This continues until convergence at machine epsilon
  1161.             // |r| < eps * |sum|; r < 1
  1162.             // |r| / eps < |sum|; r > 1
  1163.             if (sum == previous) {
  1164.                 break;
  1165.             }
  1166.         }
  1167.         return sum;
  1168.     }

  1169.     /**
  1170.      * Evaluate the incomplete beta via a continued fraction representation.
  1171.      *
  1172.      * <p>Note: This is not a generic continued fraction. The formula is from <a
  1173.      * href="https://dl.acm.org/doi/10.1145/131766.131776">Didonato and Morris</a> and is
  1174.      * only used when a and b are above 1. See <a
  1175.      * href="https://www.boost.org/doc/libs/1_77_0/libs/math/doc/html/math_toolkit/sf_beta/ibeta_function.html">Incomplete
  1176.      * Beta Function: Implementation</a>.
  1177.      *
  1178.      * @param a Argument a
  1179.      * @param b Argument b
  1180.      * @param x Argument x
  1181.      * @param y Argument 1-x
  1182.      * @param pol Function evaluation policy
  1183.      * @param normalised true to compute the regularised value
  1184.      * @return incomplete beta
  1185.      */
  1186.     static double ibetaFraction2(double a, double b, double x, double y, Policy pol, boolean normalised) {
  1187.         final double result = ibetaPowerTerms(a, b, x, y, normalised);
  1188.         if (result == 0) {
  1189.             return result;
  1190.         }

  1191.         final double eps = pol.getEps();
  1192.         final int maxIterations = pol.getMaxIterations();

  1193.         final Supplier<Coefficient> gen = new Supplier<Coefficient>() {
  1194.             /** Iteration. */
  1195.             private int m;

  1196.             @Override
  1197.             public Coefficient get() {
  1198.                 double aN = (a + m - 1) * (a + b + m - 1) * m * (b - m) * x * x;
  1199.                 final double denom = a + 2 * m - 1;
  1200.                 aN /= denom * denom;

  1201.                 double bN = m;
  1202.                 bN += (m * (b - m) * x) / (a + 2 * m - 1);
  1203.                 bN += ((a + m) * (a * y - b * x + 1 + m * (2 - x))) / (a + 2 * m + 1);

  1204.                 ++m;
  1205.                 return Coefficient.of(aN, bN);
  1206.             }
  1207.         };

  1208.         // Note: The first generated term a0 is discarded
  1209.         final double fract = GeneralizedContinuedFraction.value(gen, eps, maxIterations);
  1210.         return result / fract;
  1211.     }

  1212.     /**
  1213.      * Evaluate the incomplete beta via the classic continued fraction representation.
  1214.      *
  1215.      * <p>Note: This is not part of the Boost C++ implementation.
  1216.      * This is a generic continued fraction applicable to all arguments.
  1217.      * It is used when alternative methods are unsuitable due to the presence of sub-normal
  1218.      * terms and the result is expected to be sub-normal. In this case the original Boost
  1219.      * implementation would return zero.
  1220.      *
  1221.      * <p>This continued fraction was the evaluation method used in Commons Numbers 1.0.
  1222.      * This method has been updated to use the {@code ibetaPowerTerms} function to compute
  1223.      * the power terms. Reversal of the arguments to call {@code 1 - ibetaFraction(b, a, 1 - x)}
  1224.      * is not performed as the result is expected to be very small and this optimisation
  1225.      * for accuracy is not required.
  1226.      *
  1227.      * @param a Argument a
  1228.      * @param b Argument b
  1229.      * @param x Argument x
  1230.      * @param y Argument 1-x
  1231.      * @param pol Function evaluation policy
  1232.      * @param normalised true to compute the regularised value
  1233.      * @return incomplete beta
  1234.      */
  1235.     static double ibetaFraction(double a, double b, double x, double y, Policy pol, boolean normalised) {
  1236.         final double result = ibetaPowerTerms(a, b, x, y, normalised);
  1237.         if (result == 0) {
  1238.             return result;
  1239.         }

  1240.         final double eps = pol.getEps();
  1241.         final int maxIterations = pol.getMaxIterations();

  1242.         final Supplier<Coefficient> gen = new Supplier<Coefficient>() {
  1243.             /** Iteration. */
  1244.             private int n;

  1245.             @Override
  1246.             public Coefficient get() {
  1247.                 // https://functions.wolfram.com/GammaBetaErf/Beta3/10/0001/

  1248.                 final int m = n;
  1249.                 final int k = m / 2;
  1250.                 final double aN;
  1251.                 if ((m & 0x1) == 0) {
  1252.                     // even
  1253.                     // m = 2k
  1254.                     aN = (k * (b - k) * x) /
  1255.                         ((a + m - 1) * (a + m));
  1256.                 } else {
  1257.                     // odd
  1258.                     // k = (m - 1) / 2 due to integer truncation
  1259.                     // m - 1 = 2k
  1260.                     aN = -((a + k) * (a + b + k) * x) /
  1261.                         ((a + m - 1) * (a + m));
  1262.                 }

  1263.                 n = m + 1;
  1264.                 return Coefficient.of(aN, 1);
  1265.             }
  1266.         };

  1267.         // Note: The first generated term a0 is discarded
  1268.         final double fract = GeneralizedContinuedFraction.value(gen, eps, maxIterations);
  1269.         return (result / a) / fract;
  1270.     }
  1271. }