static void lengthLimitedCodeLengths(Cookie cookie, int[] frequencies, int maxBits,
      int[] bitLengths) {
    cookie.resetPool();
    int n = frequencies.length;
    int nn = 0;
    Node[] leaves = cookie.leaves1;
    for (int i = 0; i < n; i++) {
      if (frequencies[i] != 0) {
        leaves[nn] = cookie.node(frequencies[i], i, null);
        nn++;
      }
    }

    if (nn == 0) {
      return;
    }
    if (nn == 1) {
      bitLengths[leaves[0].count] = 1;
      return;
    }

    Node[] leaves2 = cookie.leaves2;
    System.arraycopy(leaves, 0, leaves2, 0, nn);
    sort(leaves2, leaves, 0, nn);

    Node[] list0 = cookie.list0;
    Node node0 = cookie.node(leaves[0].weight, 1, null);

    Node[] list1 = cookie.list1;
    Node node1 = cookie.node(leaves[1].weight, 2, null);

    for (int i = 0; i < maxBits; ++i) {
      list0[i] = node0;
      list1[i] = node1;
    }

    int numBoundaryPmRuns = 2 * nn - 4;
    for (int i = 0; i < numBoundaryPmRuns; i++) {
      boolean last = i == numBoundaryPmRuns - 1;
      boundaryPm(cookie, leaves, list0, list1, nn, maxBits - 1, last);
    }

    for (Node node = list1[maxBits - 1]; node != null; node = node.tail) {
      for (int i = node.count - 1; i >= 0; --i) {
        bitLengths[leaves[i].count]++;
      }
    }
  }