diff options
Diffstat (limited to 'c/enc/backward_references_hq.c')
-rw-r--r-- | c/enc/backward_references_hq.c | 91 |
1 files changed, 56 insertions, 35 deletions
diff --git a/c/enc/backward_references_hq.c b/c/enc/backward_references_hq.c index b05cb4f..f2f9918 100644 --- a/c/enc/backward_references_hq.c +++ b/c/enc/backward_references_hq.c @@ -25,6 +25,10 @@ extern "C" { #endif +#define BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE ( \ + BROTLI_NUM_DISTANCE_SHORT_CODES + (2 * BROTLI_LARGE_MAX_DISTANCE_BITS)) +/* BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE == 74 */ + static const float kInfinity = 1.7e38f; /* ~= 2 ^ 127 */ static const uint32_t kDistanceCacheIndex[] = { @@ -39,40 +43,40 @@ void BrotliInitZopfliNodes(ZopfliNode* array, size_t length) { size_t i; stub.length = 1; stub.distance = 0; - stub.insert_length = 0; + stub.dcode_insert_length = 0; stub.u.cost = kInfinity; for (i = 0; i < length; ++i) array[i] = stub; } static BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) { - return self->length & 0xffffff; + return self->length & 0x1FFFFFF; } static BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) { - const uint32_t modifier = self->length >> 24; + const uint32_t modifier = self->length >> 25; return ZopfliNodeCopyLength(self) + 9u - modifier; } static BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) { - return self->distance & 0x7ffffff; + return self->distance; } static BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) { - const uint32_t short_code = self->distance >> 27; + const uint32_t short_code = self->dcode_insert_length >> 27; return short_code == 0 ? ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 : short_code - 1; } static BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) { - return ZopfliNodeCopyLength(self) + self->insert_length; + return ZopfliNodeCopyLength(self) + (self->dcode_insert_length & 0x7FFFFFF); } /* Histogram based cost model for zopflification. */ typedef struct ZopfliCostModel { /* The insert and copy length symbols. */ float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS]; - float cost_dist_[BROTLI_NUM_DISTANCE_SYMBOLS]; + float cost_dist_[BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE]; /* Cumulative costs of literals per position in the stream. */ float* literal_costs_; float min_cost_cmd_; @@ -91,17 +95,26 @@ static void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) { } static void SetCost(const uint32_t* histogram, size_t histogram_size, - float* cost) { + BROTLI_BOOL literal_histogram, float* cost) { size_t sum = 0; + size_t missing_symbol_sum; float log2sum; + float missing_symbol_cost; size_t i; for (i = 0; i < histogram_size; i++) { sum += histogram[i]; } log2sum = (float)FastLog2(sum); + missing_symbol_sum = sum; + if (!literal_histogram) { + for (i = 0; i < histogram_size; i++) { + if (histogram[i] == 0) missing_symbol_sum++; + } + } + missing_symbol_cost = (float)FastLog2(missing_symbol_sum) + 2; for (i = 0; i < histogram_size; i++) { if (histogram[i] == 0) { - cost[i] = log2sum + 2; + cost[i] = missing_symbol_cost; continue; } @@ -122,7 +135,7 @@ static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, size_t last_insert_len) { uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS]; uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS]; - uint32_t histogram_dist[BROTLI_NUM_DISTANCE_SYMBOLS]; + uint32_t histogram_dist[BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE]; float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS]; size_t pos = position - last_insert_len; float min_cost_cmd = kInfinity; @@ -136,7 +149,7 @@ static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, for (i = 0; i < num_commands; i++) { size_t inslength = commands[i].insert_len_; size_t copylength = CommandCopyLen(&commands[i]); - size_t distcode = commands[i].dist_prefix_; + size_t distcode = commands[i].dist_prefix_ & 0x3FF; size_t cmdcode = commands[i].cmd_prefix_; size_t j; @@ -150,9 +163,12 @@ static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, pos += inslength + copylength; } - SetCost(histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, cost_literal); - SetCost(histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, cost_cmd); - SetCost(histogram_dist, BROTLI_NUM_DISTANCE_SYMBOLS, self->cost_dist_); + SetCost(histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_TRUE, + cost_literal); + SetCost(histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_FALSE, + cost_cmd); + SetCost(histogram_dist, BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE, BROTLI_FALSE, + self->cost_dist_); for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]); @@ -161,11 +177,14 @@ static void ZopfliCostModelSetFromCommands(ZopfliCostModel* self, { float* literal_costs = self->literal_costs_; + float literal_carry = 0.0; size_t num_bytes = self->num_bytes_; literal_costs[0] = 0.0; for (i = 0; i < num_bytes; ++i) { - literal_costs[i + 1] = literal_costs[i] + + literal_carry += cost_literal[ringbuffer[(position + i) & ringbuffer_mask]]; + literal_costs[i + 1] = literal_costs[i] + literal_carry; + literal_carry -= literal_costs[i + 1] - literal_costs[i]; } } } @@ -175,6 +194,7 @@ static void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self, const uint8_t* ringbuffer, size_t ringbuffer_mask) { float* literal_costs = self->literal_costs_; + float literal_carry = 0.0; float* cost_dist = self->cost_dist_; float* cost_cmd = self->cost_cmd_; size_t num_bytes = self->num_bytes_; @@ -183,12 +203,14 @@ static void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self, ringbuffer, &literal_costs[1]); literal_costs[0] = 0.0; for (i = 0; i < num_bytes; ++i) { - literal_costs[i + 1] += literal_costs[i]; + literal_carry += literal_costs[i + 1]; + literal_costs[i + 1] = literal_costs[i] + literal_carry; + literal_carry -= literal_costs[i + 1] - literal_costs[i]; } for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) { cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i); } - for (i = 0; i < BROTLI_NUM_DISTANCE_SYMBOLS; ++i) { + for (i = 0; i < BROTLI_SIMPLE_DISTANCE_ALPHABET_SIZE; ++i) { cost_dist[i] = (float)FastLog2(20 + (uint32_t)i); } self->min_cost_cmd_ = (float)FastLog2(11); @@ -221,9 +243,10 @@ static BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos, size_t start_pos, size_t len, size_t len_code, size_t dist, size_t short_code, float cost) { ZopfliNode* next = &nodes[pos + len]; - next->length = (uint32_t)(len | ((len + 9u - len_code) << 24)); - next->distance = (uint32_t)(dist | (short_code << 27)); - next->insert_length = (uint32_t)(pos - start_pos); + next->length = (uint32_t)(len | ((len + 9u - len_code) << 25)); + next->distance = (uint32_t)dist; + next->dcode_insert_length = (uint32_t)( + (short_code << 27) | (pos - start_pos)); next->u.cost = cost; } @@ -303,7 +326,7 @@ static uint32_t ComputeDistanceShortcut(const size_t block_start, const size_t gap, const ZopfliNode* nodes) { const size_t clen = ZopfliNodeCopyLength(&nodes[pos]); - const size_t ilen = nodes[pos].insert_length; + const size_t ilen = nodes[pos].dcode_insert_length & 0x7FFFFFF; const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]); /* Since |block_start + pos| is the end position of the command, the copy part starts from |block_start + pos - clen|. Distances that are greater than @@ -335,7 +358,7 @@ static void ComputeDistanceCache(const size_t pos, int idx = 0; size_t p = nodes[pos].u.shortcut; while (idx < 4 && p > 0) { - const size_t ilen = nodes[p].insert_length; + const size_t ilen = nodes[p].dcode_insert_length & 0x7FFFFFF; const size_t clen = ZopfliNodeCopyLength(&nodes[p]); const size_t dist = ZopfliNodeCopyDistance(&nodes[p]); dist_cache[idx++] = (int)dist; @@ -483,9 +506,9 @@ static size_t UpdateNodes( float dist_cost; size_t max_match_len; PrefixEncodeCopyDistance(dist_code, 0, 0, &dist_symbol, &distextra); - distnumextra = distextra >> 24; + distnumextra = dist_symbol >> 10; dist_cost = base_cost + (float)distnumextra + - ZopfliCostModelGetDistanceCost(model, dist_symbol); + ZopfliCostModelGetDistanceCost(model, dist_symbol & 0x3FF); /* Try all copy lengths up until the maximum copy length corresponding to this distance. If the distance refers to the static dictionary, or @@ -517,7 +540,8 @@ static size_t ComputeShortestPathFromNodes(size_t num_bytes, ZopfliNode* nodes) { size_t index = num_bytes; size_t num_commands = 0; - while (nodes[index].insert_length == 0 && nodes[index].length == 1) --index; + while ((nodes[index].dcode_insert_length & 0x7FFFFFF) == 0 && + nodes[index].length == 1) --index; nodes[index].u.next = BROTLI_UINT32_MAX; while (index != 0) { size_t len = ZopfliNodeCommandLength(&nodes[index]); @@ -546,7 +570,7 @@ void BrotliZopfliCreateCommands(const size_t num_bytes, for (i = 0; offset != BROTLI_UINT32_MAX; i++) { const ZopfliNode* next = &nodes[pos + offset]; size_t copy_length = ZopfliNodeCopyLength(next); - size_t insert_length = next->insert_length; + size_t insert_length = next->dcode_insert_length & 0x7FFFFFF; pos += insert_length; offset = next->u.next; if (i == 0) { @@ -624,7 +648,6 @@ static size_t ZopfliIterate(size_t num_bytes, /* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, - const BrotliDictionary* dictionary, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, const BrotliEncoderParams* params, const size_t max_backward_limit, const int* dist_cache, HasherHandle hasher, @@ -649,9 +672,9 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, const size_t pos = position + i; const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit); size_t skip; - size_t num_matches = FindAllMatchesH10(hasher, dictionary, ringbuffer, - ringbuffer_mask, pos, num_bytes - i, max_distance, gap, params, - &matches[lz_matches_offset]); + size_t num_matches = FindAllMatchesH10(hasher, ¶ms->dictionary, + ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance, gap, + params, &matches[lz_matches_offset]); if (num_matches > 0 && BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) { matches[0] = matches[num_matches - 1]; @@ -683,7 +706,6 @@ size_t BrotliZopfliComputeShortestPath(MemoryManager* m, } void BrotliCreateZopfliBackwardReferences(MemoryManager* m, - const BrotliDictionary* dictionary, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache, size_t* last_insert_len, @@ -693,7 +715,7 @@ void BrotliCreateZopfliBackwardReferences(MemoryManager* m, nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1); if (BROTLI_IS_OOM(m)) return; BrotliInitZopfliNodes(nodes, num_bytes + 1); - *num_commands += BrotliZopfliComputeShortestPath(m, dictionary, + *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes, position, ringbuffer, ringbuffer_mask, params, max_backward_limit, dist_cache, hasher, nodes); if (BROTLI_IS_OOM(m)) return; @@ -703,7 +725,6 @@ void BrotliCreateZopfliBackwardReferences(MemoryManager* m, } void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, - const BrotliDictionary* dictionary, size_t num_bytes, size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask, const BrotliEncoderParams* params, HasherHandle hasher, int* dist_cache, size_t* last_insert_len, @@ -736,8 +757,8 @@ void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size, cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches); if (BROTLI_IS_OOM(m)) return; - num_found_matches = FindAllMatchesH10(hasher, dictionary, - ringbuffer, ringbuffer_mask, pos, max_length, + num_found_matches = FindAllMatchesH10(hasher, + ¶ms->dictionary, ringbuffer, ringbuffer_mask, pos, max_length, max_distance, gap, params, &matches[cur_match_pos + shadow_matches]); cur_match_end = cur_match_pos + num_found_matches; for (j = cur_match_pos; j + 1 < cur_match_end; ++j) { |