public double barF(int x) {
    if (x < 1) return 1.0;
    if (p >= 1.0) // In fact, p == 1
    return 0.0;
    if (p <= 0.0) // In fact, p == 0
    return 1.0;

    if (cdf == null)
      // return BinomialDist.cdf (x - 1 + n, p, n - 1);
      return BetaDist.barF(n, x, 15, p);

    if (x > xmax)
      // return BinomialDist.cdf (x - 1 + n, p, n - 1);
      return BetaDist.barF(n, x, 15, p);

    if (x <= xmin) return 1.0;
    if (x > xmed)
      // We keep the complementary distribution in the upper part of cdf
      return cdf[x - xmin];
    else return 1.0 - cdf[x - 1 - xmin];
  }
  /** Computes the distribution function. */
  public static double cdf(double n, double p, int x) {
    final double EPSILON = DiscreteDistributionInt.EPSILON;
    final int LIM1 = 100000;
    double sum, term, termmode;
    int i, mode;
    final double q = 1.0 - p;

    if (p < 0.0 || p > 1.0) throw new IllegalArgumentException("p not in [0, 1]");
    if (n <= 0.0) throw new IllegalArgumentException("n <= 0.0");

    if (x < 0) return 0.0;
    if (p >= 1.0) // In fact, p == 1
    return 1.0;
    if (p <= 0.0) // In fact, p == 0
    return 0.0;

    // Compute the maximum term
    mode = 1 + (int) Math.floor((n * q - 1.0) / p);
    if (mode < 0) mode = 0;
    else if (mode > x) mode = x;

    if (mode <= LIM1) {
      sum = term = termmode = prob(n, p, mode);
      for (i = mode; i > 0; i--) {
        term *= i / (q * (n + i - 1.0));
        if (term < EPSILON) break;
        sum += term;
      }

      term = termmode;
      for (i = mode; i < x; i++) {
        term *= q * (n + i) / (i + 1);
        if (term < EPSILON) break;
        sum += term;
      }
      if (sum <= 1.0) return sum;
      else return 1.0;
    } else
      // return 1.0 - BinomialDist.cdf (x + n, p, n - 1);
      return BetaDist.cdf(n, x + 1.0, 15, p);
  }
  public double[] generatePath(double[] uniform01) {
    int oldIndexL, oldIndexR, newIndex;
    double y;

    path[d] = x0 + GammaDist.inverseF(mu2dTOverNu, muOverNu, 10, uniform01[0]);
    for (int j = 0; j < 3 * (d - 1); j += 3) {
      oldIndexL = wIndexList[j];
      newIndex = wIndexList[j + 1];
      oldIndexR = wIndexList[j + 2];

      y =
          BetaDist.inverseF(
              bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 8, uniform01[1 + j / 3]);

      path[newIndex] = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y;
      // make sure the process is strictly increasing
      if (path[newIndex] <= path[oldIndexL]) setLarger(path, oldIndexL, newIndex, oldIndexR);
    }
    // resetStartProcess();
    observationIndex = d;
    observationCounter = d;
    return path;
  }