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]++;
            }
        }
    }