private void createHuffmanDecodingTables (final int alphabetSize, final byte[][] tableCodeLengths) {

		for (int table = 0; table < tableCodeLengths.length; table++) {

			final int[] tableBases = this.codeBases[table];
			final int[] tableLimits = this.codeLimits[table];
			final int[] tableSymbols = this.codeSymbols[table];

			final byte[] codeLengths = tableCodeLengths[table];
			int minimumLength = BZip2Constants.HUFFMAN_DECODE_MAXIMUM_CODE_LENGTH;
			int maximumLength = 0;

			// Find the minimum and maximum code length for the table
			for (int i = 0; i < alphabetSize; i++) {
				maximumLength = Math.max (codeLengths[i], maximumLength);
				minimumLength = Math.min (codeLengths[i], minimumLength);
			}
			this.minimumLengths[table] = minimumLength;

			// Calculate the first output symbol for each code length
			for (int i = 0; i < alphabetSize; i++) {
				tableBases[codeLengths[i] + 1]++;
			}
			for (int i = 1; i < BZip2Constants.HUFFMAN_DECODE_MAXIMUM_CODE_LENGTH + 2; i++) {
				tableBases[i] += tableBases[i - 1];
			}

			// Calculate the first and last Huffman code for each code length (codes at a given
			// length are sequential in value)
			int code = 0;
			for (int i = minimumLength; i <= maximumLength; i++) {
				int base = code;
				code += tableBases[i + 1] - tableBases[i];
				tableBases[i] = base - tableBases[i];
				tableLimits[i] = code - 1;
				code <<= 1;
			}

			// Populate the mapping from canonical code index to output symbol
			int codeIndex = 0;
			for (int bitLength = minimumLength; bitLength <= maximumLength; bitLength++) {
				for (int symbol = 0; symbol < alphabetSize; symbol++) {
					if (codeLengths[symbol] == bitLength) {
						tableSymbols[codeIndex++] = symbol;
					}
				}
			}

		}

	}