Remove old CodeLength initializer from Encoding(Huffman)Tree

This commit is contained in:
Timofey Solomko
2019-03-12 22:31:24 +03:00
parent 250c9fbd4c
commit 142fd44dd2
5 changed files with 12 additions and 36 deletions
+4 -3
View File
@@ -121,10 +121,11 @@ extension BZip2: CompressionAlgorithm {
selectors.append(minimumSelector)
} else {
// Otherwise, let's create a new table and check if it gives us better results.
// First, we calculate code lengths for our current stats.
// First, we calculate code lengths and codes for our current stats.
let lengths = BZip2.lengths(from: stats)
// Then, using these code lengths, we create a new Huffman tree.
let table = EncodingHuffmanTree(lengths: lengths, bitWriter)
let codes = Code.huffmanCodes(from: lengths)
// Then, using these codes, we create a new Huffman tree.
let table = EncodingHuffmanTree(codes: codes.codes, bitWriter)
if table.bitSize(for: stats) < minimumSize {
tables.append(table)
tablesLengths.append(lengths.sorted { $0.symbol < $1.symbol }.map { $0.codeLength })
@@ -12,35 +12,6 @@ final class EncodingHuffmanTree {
private let codingIndices: [[Int]]
/// `lengths` don't have to be properly sorted, but there must not be any 0 code lengths.
/// If `reverseCodes` is true, then bit order of tree codes will be reversed. Necessary for Deflate.
init(lengths: [CodeLength], _ bitWriter: BitWriter, reverseCodes: Bool = false) {
self.bitWriter = bitWriter
// Sort `lengths` array to calculate canonical Huffman code.
let sortedLengths = lengths.sorted()
var codingIndices = Array(repeating: [-1, -1], count: sortedLengths.count)
// Calculates symbols for each length in 'sortedLengths' array and put them in the tree.
var loopBits = -1
var symbol = -1
for length in sortedLengths {
precondition(length.codeLength > 0, "Code length must not be 0 during HuffmanTree initialisation.")
symbol += 1
// We sometimes need to make symbol to have length.bits bit length.
let bits = length.codeLength
if bits != loopBits {
symbol <<= (bits - loopBits)
loopBits = bits
}
// Then we reverse bit order of the symbol, if necessary.
let treeCode = reverseCodes ? symbol.reversed(bits: loopBits) : symbol
codingIndices[length.symbol] = [treeCode, bits]
}
self.codingIndices = codingIndices
}
init(codes: [Code], _ bitWriter: BitWriter, reverseCodes: Bool = false) {
self.bitWriter = bitWriter
+2 -2
View File
@@ -106,10 +106,10 @@ extension Deflate: CompressionAlgorithm {
// Constructing Huffman trees for the case of block with preset alphabets.
// In this case codes for literals and distances are fixed.
/// Huffman tree for literal and length symbols/codes.
let mainLiterals = EncodingHuffmanTree(lengths: Constants.staticHuffmanBootstrap,
let mainLiterals = EncodingHuffmanTree(codes: Constants.staticHuffmanBootstrap.codes,
bitWriter, reverseCodes: true)
/// Huffman tree for backward distance symbols/codes.
let mainDistances = EncodingHuffmanTree(lengths: Constants.staticHuffmanDistancesBootstrap,
let mainDistances = EncodingHuffmanTree(codes: Constants.staticHuffmanDistancesBootstrap.codes,
bitWriter, reverseCodes: true)
for code in bldCodes {
+5 -2
View File
@@ -8,9 +8,12 @@ import Foundation
extension Deflate {
struct Constants {
// TODO: Combine length bootstrapping and code generation.
// Bootstraps for Static Huffman trees (first element in tuple is code, second is number of bits).
static let staticHuffmanBootstrap = CodeLength.lengths(from: [(0, 8), (144, 9), (256, 7), (280, 8), (288, -1)])
static let staticHuffmanDistancesBootstrap = CodeLength.lengths(from: [(0, 5), (32, -1)])
static let staticHuffmanBootstrap = Code.huffmanCodes(from:
CodeLength.lengths(from: [(0, 8), (144, 9), (256, 7), (280, 8), (288, -1)]))
static let staticHuffmanDistancesBootstrap = Code.huffmanCodes(from:
CodeLength.lengths(from: [(0, 5), (32, -1)]))
static let codeLengthOrders: [Int] =
[16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]
+1
View File
@@ -8,6 +8,7 @@ import Foundation
// Deflate specific functions for generation of HuffmanLength arrays from different inputs.
extension Deflate {
// TODO: Make this work for both arrays and array slices.
/// - Note: Skips zero codeLengths.
static func lengths(from orderedCodeLengths: [Int]) -> [CodeLength] {
var lengths = [CodeLength]()