public void optimizeParam(int numItns) {

    // update histograms and set the max # of times that each topic
    // has occurred in any document...

    int[] limits = new int[T];
    Arrays.fill(limits, -1);

    for (int j=0; j<T; j++) {

      Arrays.fill(topicDocHist[j], 0);

      for (int d=0; d<D; d++)
        topicDocHist[j][topicDocCounts[j][d]]++;

      for (int n=0; n<topicDocHist[j].length; n++)
        if (topicDocHist[j][n] > 0)
          limits[j] = n;
    }

    // optimize hyperparameters

    for (int i=0; i<numItns; i++) {

      double denominator = 0.0;
      double currentDigamma = 0.0;

      for (int n=1; n<topicDocNormHist.length; n++) {
        currentDigamma += 1.0 / (paramSum + n - 1);
        denominator += topicDocNormHist[n] * currentDigamma;
      }

      paramSum = 0.0;

      for (int j=0; j<T; j++) {

        int limit = limits[j];

        double oldParam = param[j];
        param[j] = 0.0;
        currentDigamma = 0;

        for (int n=1; n<=limit; n++) {
          currentDigamma += 1.0 / (oldParam + n - 1);
          param[j] += topicDocHist[j][n] * currentDigamma;
        }

        param[j] *= oldParam / denominator;

        if (param[j] == 0.0)
          param[j] = 1e-10;

        paramSum += param[j];
      }
    }
  }