Files
Timofey Solomko e32887084c [Huffman] Change Decoding/Encoding tree to structs
This seems to have a positive impact on the performance of Deflate and BZip2 decompression and compression. It is unclear to me why these two were declared as classes in the first place.
2026-03-01 20:35:22 +08:00

62 lines
1.8 KiB
Swift

// Copyright (c) 2026 Timofey Solomko
// Licensed under MIT License
//
// See LICENSE for license information
import BitByteData
fileprivate struct CodingIndex {
let treeCode: Int
let bitSize: Int
}
struct EncodingTree {
private let bitWriter: BitWriter
private let codingIndices: [CodingIndex]
init(_ codes: [Code], _ bitWriter: BitWriter, reverseCodes: Bool = false) {
self.bitWriter = bitWriter
var codingIndices = Array(repeating: CodingIndex(treeCode: -1, bitSize: -1), count: codes.count)
for code in codes {
// Codes have already been reversed.
// TODO: This assumption may be only correct for Huffman codes.
let treeCode = reverseCodes ? code.code : code.code.reversed(bits: code.bits)
codingIndices[code.symbol] = CodingIndex(treeCode: treeCode, bitSize: code.bits)
}
self.codingIndices = codingIndices
}
func code(symbol: Int) {
guard symbol < self.codingIndices.count
else { fatalError("Symbol is not found.") }
let codingIndex = self.codingIndices[symbol]
guard codingIndex.treeCode > -1
else { fatalError("Symbol is not found.") }
self.bitWriter.write(number: codingIndex.treeCode, bitsCount: codingIndex.bitSize)
}
func bitSize(for stats: [Int]) -> Int {
var totalSize = 0
for (symbol, count) in stats.enumerated() where count > 0 {
guard symbol < self.codingIndices.count
else { fatalError("Symbol is not found.") }
let codingIndex = self.codingIndices[symbol]
guard codingIndex.treeCode > -1
else { fatalError("Symbol is not found.") }
totalSize += count * codingIndex.bitSize
}
return totalSize
}
}