docs: public static double regularizedGammaP(double a,
                                             double x,
                                             double epsilon,
                                             int maxIterations) {
          double ret;
  
          if (Double.isNaN(a) || Double.isNaN(x) || (a <= 0.0) || (x < 0.0)) {
              ret = Double.NaN;
          } else if (x == 0.0) {
              ret = 0.0;
          } else if (x >= a + 1) {
              // use regularizedGammaQ because it should converge faster in this
              // case.
              ret = 1.0 - regularizedGammaQ(a, x, epsilon, maxIterations);
          } else {
              // calculate series
              double n = 0.0; // current element index
              double an = 1.0 / a; // n-th element in the series
              double sum = an; // partial sum
              while (Math.abs(an / sum) > epsilon &&
                      n < maxIterations &&
                      sum < Double.POSITIVE_INFINITY) {
                  // compute next element in the series
                  n += 1.0;
                  an *= x / (a + n);
  
                  // update partial sum
                  sum += an;
              }
              if (n >= maxIterations) {
                  throw new IllegalStateException("max count exceeded: " + maxIterations);
              } else if (Double.isInfinite(sum)) {
                  ret = 1.0;
              } else {
                  ret = Math.exp(-x + (a * Math.log(x)) - logGamma(a)) * sum;
              }
          }
  
          return ret;
      }