/**
   * Samples the number of tables given the number of customers in a dirichlet process distribution.
   *
   * @param n number of customers
   * @param alpha concentration parameter
   * @param beta base distribution probability of type
   * @return number of tables
   */
  public static int sampleDirichletProcessTables(int n, double alpha, double beta) {
    if (beta <= 0d) {
      return 1;
    } else {
      double c0 = logGamma(alpha * beta) - logGamma(alpha * beta + (double) n);
      double c1 = Math.log(alpha) + Math.log(beta);

      double cuSum = 0;
      double r = rng.nextDouble();

      int m = 0;
      for (int i = 1; i <= n; i++) {
        cuSum += Math.exp(c0 + lsn.get(n, i) + i * c1);
        if (cuSum > r) {
          m = i;
          break;
        }
      }

      assert m > 0 : "alpha = " + alpha + " beta = " + beta;

      return m;
    }
  }
  /**
   * Gets the log probability of the given number of tables in the Dirichlet process distribution.
   *
   * @param m tables
   * @param n count
   * @param alpha concentration
   * @param beta probability of type in base distribution
   * @return score
   */
  public static double logProbTablesDirichletProcess(int m, int n, double alpha, double beta) {
    double c0 = logGamma(alpha * beta) - logGamma(alpha * beta + (double) n);
    double c1 = Math.log(alpha) + Math.log(beta);

    return c0 + lsn.get(n, m) + m * c1;
  }