public double nextObservation() {
    double s;
    if (bridgeCounter == -1) {
      s = x0 + Ggen.nextDouble(stream, mu2dTOverNu, muOverNu);
      if (s <= x0) s = setLarger(x0);
      bridgeCounter = 0;
      observationIndex = d;
    } else {
      int j = bridgeCounter * 3;
      int oldIndexL = wIndexList[j];
      int newIndex = wIndexList[j + 1];
      int oldIndexR = wIndexList[j + 2];

      double y =
          Bgen.nextDouble(stream, bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 0.0, 1.0);
      s = path[oldIndexL] + (path[oldIndexR] - path[oldIndexL]) * y;
      // make sure the process is strictly increasing
      if (s <= path[oldIndexL]) s = setLarger(path, oldIndexL, oldIndexR);
      bridgeCounter++;
      observationIndex = newIndex;
    }
    observationCounter = bridgeCounter + 1;
    path[observationIndex] = s;
    return s;
  }
  public double[] generatePath() {
    int oldIndexL, oldIndexR, newIndex;
    double y;

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

      y = Bgen.nextDouble(stream, bMu2dtOverNuL[newIndex], bMu2dtOverNuR[newIndex], 0.0, 1.0);
      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;
  }