| File: | out/../deps/brotli/c/enc/./block_splitter_inc.h |
| Warning: | line 17, column 32 Division by zero |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* Copyright 2013 Google Inc. All Rights Reserved. | |||
| 2 | ||||
| 3 | Distributed under MIT license. | |||
| 4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | |||
| 5 | */ | |||
| 6 | ||||
| 7 | /* Block split point selection utilities. */ | |||
| 8 | ||||
| 9 | #include "./block_splitter.h" | |||
| 10 | ||||
| 11 | #include <string.h> /* memcpy, memset */ | |||
| 12 | ||||
| 13 | #include "../common/platform.h" | |||
| 14 | #include "./bit_cost.h" | |||
| 15 | #include "./cluster.h" | |||
| 16 | #include "./command.h" | |||
| 17 | #include "./fast_log.h" | |||
| 18 | #include "./histogram.h" | |||
| 19 | #include "./memory.h" | |||
| 20 | #include "./quality.h" | |||
| 21 | ||||
| 22 | #if defined(__cplusplus) || defined(c_plusplus) | |||
| 23 | extern "C" { | |||
| 24 | #endif | |||
| 25 | ||||
| 26 | static const size_t kMaxLiteralHistograms = 100; | |||
| 27 | static const size_t kMaxCommandHistograms = 50; | |||
| 28 | static const double kLiteralBlockSwitchCost = 28.1; | |||
| 29 | static const double kCommandBlockSwitchCost = 13.5; | |||
| 30 | static const double kDistanceBlockSwitchCost = 14.6; | |||
| 31 | static const size_t kLiteralStrideLength = 70; | |||
| 32 | static const size_t kCommandStrideLength = 40; | |||
| 33 | static const size_t kSymbolsPerLiteralHistogram = 544; | |||
| 34 | static const size_t kSymbolsPerCommandHistogram = 530; | |||
| 35 | static const size_t kSymbolsPerDistanceHistogram = 544; | |||
| 36 | static const size_t kMinLengthForBlockSplitting = 128; | |||
| 37 | static const size_t kIterMulForRefining = 2; | |||
| 38 | static const size_t kMinItersForRefining = 100; | |||
| 39 | ||||
| 40 | static size_t CountLiterals(const Command* cmds, const size_t num_commands) { | |||
| 41 | /* Count how many we have. */ | |||
| 42 | size_t total_length = 0; | |||
| 43 | size_t i; | |||
| 44 | for (i = 0; i < num_commands; ++i) { | |||
| 45 | total_length += cmds[i].insert_len_; | |||
| 46 | } | |||
| 47 | return total_length; | |||
| 48 | } | |||
| 49 | ||||
| 50 | static void CopyLiteralsToByteArray(const Command* cmds, | |||
| 51 | const size_t num_commands, | |||
| 52 | const uint8_t* data, | |||
| 53 | const size_t offset, | |||
| 54 | const size_t mask, | |||
| 55 | uint8_t* literals) { | |||
| 56 | size_t pos = 0; | |||
| 57 | size_t from_pos = offset & mask; | |||
| 58 | size_t i; | |||
| 59 | for (i = 0; i < num_commands; ++i) { | |||
| 60 | size_t insert_len = cmds[i].insert_len_; | |||
| 61 | if (from_pos + insert_len > mask) { | |||
| 62 | size_t head_size = mask + 1 - from_pos; | |||
| 63 | memcpy(literals + pos, data + from_pos, head_size); | |||
| 64 | from_pos = 0; | |||
| 65 | pos += head_size; | |||
| 66 | insert_len -= head_size; | |||
| 67 | } | |||
| 68 | if (insert_len > 0) { | |||
| 69 | memcpy(literals + pos, data + from_pos, insert_len); | |||
| 70 | pos += insert_len; | |||
| 71 | } | |||
| 72 | from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask; | |||
| 73 | } | |||
| 74 | } | |||
| 75 | ||||
| 76 | static BROTLI_INLINEinline __attribute__((__always_inline__)) uint32_t MyRand(uint32_t* seed) { | |||
| 77 | /* Initial seed should be 7. In this case, loop length is (1 << 29). */ | |||
| 78 | *seed *= 16807U; | |||
| 79 | return *seed; | |||
| 80 | } | |||
| 81 | ||||
| 82 | static BROTLI_INLINEinline __attribute__((__always_inline__)) double BitCost(size_t count) { | |||
| 83 | return count == 0 ? -2.0 : FastLog2(count); | |||
| 84 | } | |||
| 85 | ||||
| 86 | #define HISTOGRAMS_PER_BATCH64 64 | |||
| 87 | #define CLUSTERS_PER_BATCH16 16 | |||
| 88 | ||||
| 89 | #define FN(X) X ## Literal | |||
| 90 | #define DataType uint8_t | |||
| 91 | /* NOLINTNEXTLINE(build/include) */ | |||
| 92 | #include "./block_splitter_inc.h" | |||
| 93 | #undef DataType | |||
| 94 | #undef FN | |||
| 95 | ||||
| 96 | #define FN(X) X ## Command | |||
| 97 | #define DataType uint16_t | |||
| 98 | /* NOLINTNEXTLINE(build/include) */ | |||
| 99 | #include "./block_splitter_inc.h" | |||
| 100 | #undef FN | |||
| 101 | ||||
| 102 | #define FN(X) X ## Distance | |||
| 103 | /* NOLINTNEXTLINE(build/include) */ | |||
| 104 | #include "./block_splitter_inc.h" | |||
| 105 | #undef DataType | |||
| 106 | #undef FN | |||
| 107 | ||||
| 108 | void BrotliInitBlockSplit(BlockSplit* self) { | |||
| 109 | self->num_types = 0; | |||
| 110 | self->num_blocks = 0; | |||
| 111 | self->types = 0; | |||
| 112 | self->lengths = 0; | |||
| 113 | self->types_alloc_size = 0; | |||
| 114 | self->lengths_alloc_size = 0; | |||
| 115 | } | |||
| 116 | ||||
| 117 | void BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) { | |||
| 118 | BROTLI_FREE(m, self->types){ BrotliFree((m), (self->types)); self->types = ((void* )0); }; | |||
| 119 | BROTLI_FREE(m, self->lengths){ BrotliFree((m), (self->lengths)); self->lengths = ((void *)0); }; | |||
| 120 | } | |||
| 121 | ||||
| 122 | void BrotliSplitBlock(MemoryManager* m, | |||
| 123 | const Command* cmds, | |||
| 124 | const size_t num_commands, | |||
| 125 | const uint8_t* data, | |||
| 126 | const size_t pos, | |||
| 127 | const size_t mask, | |||
| 128 | const BrotliEncoderParams* params, | |||
| 129 | BlockSplit* literal_split, | |||
| 130 | BlockSplit* insert_and_copy_split, | |||
| 131 | BlockSplit* dist_split) { | |||
| 132 | { | |||
| 133 | size_t literals_count = CountLiterals(cmds, num_commands); | |||
| 134 | uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count)((literals_count) > 0 ? ((uint8_t*)BrotliAllocate((m), (literals_count ) * sizeof(uint8_t))) : ((void*)0)); | |||
| ||||
| 135 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(literals)(!!0)) return; | |||
| 136 | /* Create a continuous array of literals. */ | |||
| 137 | CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals); | |||
| 138 | /* Create the block split on the array of literals. | |||
| 139 | Literal histograms have alphabet size 256. */ | |||
| 140 | SplitByteVectorLiteral( | |||
| 141 | m, literals, literals_count, | |||
| 142 | kSymbolsPerLiteralHistogram, kMaxLiteralHistograms, | |||
| 143 | kLiteralStrideLength, kLiteralBlockSwitchCost, params, | |||
| 144 | literal_split); | |||
| 145 | if (BROTLI_IS_OOM(m)(!!0)) return; | |||
| 146 | BROTLI_FREE(m, literals){ BrotliFree((m), (literals)); literals = ((void*)0); }; | |||
| 147 | } | |||
| 148 | ||||
| 149 | { | |||
| 150 | /* Compute prefix codes for commands. */ | |||
| 151 | uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands)((num_commands) > 0 ? ((uint16_t*)BrotliAllocate((m), (num_commands ) * sizeof(uint16_t))) : ((void*)0)); | |||
| 152 | size_t i; | |||
| 153 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(insert_and_copy_codes)(!!0)) return; | |||
| 154 | for (i = 0; i < num_commands; ++i) { | |||
| 155 | insert_and_copy_codes[i] = cmds[i].cmd_prefix_; | |||
| 156 | } | |||
| 157 | /* Create the block split on the array of command prefixes. */ | |||
| 158 | SplitByteVectorCommand( | |||
| 159 | m, insert_and_copy_codes, num_commands, | |||
| 160 | kSymbolsPerCommandHistogram, kMaxCommandHistograms, | |||
| 161 | kCommandStrideLength, kCommandBlockSwitchCost, params, | |||
| 162 | insert_and_copy_split); | |||
| 163 | if (BROTLI_IS_OOM(m)(!!0)) return; | |||
| 164 | /* TODO: reuse for distances? */ | |||
| 165 | BROTLI_FREE(m, insert_and_copy_codes){ BrotliFree((m), (insert_and_copy_codes)); insert_and_copy_codes = ((void*)0); }; | |||
| 166 | } | |||
| 167 | ||||
| 168 | { | |||
| 169 | /* Create a continuous array of distance prefixes. */ | |||
| 170 | uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands)((num_commands) > 0 ? ((uint16_t*)BrotliAllocate((m), (num_commands ) * sizeof(uint16_t))) : ((void*)0)); | |||
| 171 | size_t j = 0; | |||
| 172 | size_t i; | |||
| 173 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(distance_prefixes)(!!0)) return; | |||
| 174 | for (i = 0; i < num_commands; ++i) { | |||
| 175 | const Command* cmd = &cmds[i]; | |||
| 176 | if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) { | |||
| 177 | distance_prefixes[j++] = cmd->dist_prefix_ & 0x3FF; | |||
| 178 | } | |||
| 179 | } | |||
| 180 | /* Create the block split on the array of distance prefixes. */ | |||
| 181 | SplitByteVectorDistance( | |||
| 182 | m, distance_prefixes, j, | |||
| 183 | kSymbolsPerDistanceHistogram, kMaxCommandHistograms, | |||
| 184 | kCommandStrideLength, kDistanceBlockSwitchCost, params, | |||
| 185 | dist_split); | |||
| 186 | if (BROTLI_IS_OOM(m)(!!0)) return; | |||
| 187 | BROTLI_FREE(m, distance_prefixes){ BrotliFree((m), (distance_prefixes)); distance_prefixes = ( (void*)0); }; | |||
| 188 | } | |||
| 189 | } | |||
| 190 | ||||
| 191 | ||||
| 192 | #if defined(__cplusplus) || defined(c_plusplus) | |||
| 193 | } /* extern "C" */ | |||
| 194 | #endif |
| 1 | /* NOLINT(build/header_guard) */ | ||||
| 2 | /* Copyright 2013 Google Inc. All Rights Reserved. | ||||
| 3 | |||||
| 4 | Distributed under MIT license. | ||||
| 5 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | ||||
| 6 | */ | ||||
| 7 | |||||
| 8 | /* template parameters: FN, DataType */ | ||||
| 9 | |||||
| 10 | #define HistogramType FN(Histogram) | ||||
| 11 | |||||
| 12 | static void FN(InitialEntropyCodes)(const DataType* data, size_t length, | ||||
| 13 | size_t stride, | ||||
| 14 | size_t num_histograms, | ||||
| 15 | HistogramType* histograms) { | ||||
| 16 | uint32_t seed = 7; | ||||
| 17 | size_t block_length = length / num_histograms; | ||||
| |||||
| 18 | size_t i; | ||||
| 19 | FN(ClearHistograms)(histograms, num_histograms); | ||||
| 20 | for (i = 0; i < num_histograms; ++i) { | ||||
| 21 | size_t pos = length * i / num_histograms; | ||||
| 22 | if (i != 0) { | ||||
| 23 | pos += MyRand(&seed) % block_length; | ||||
| 24 | } | ||||
| 25 | if (pos + stride >= length) { | ||||
| 26 | pos = length - stride - 1; | ||||
| 27 | } | ||||
| 28 | FN(HistogramAddVector)(&histograms[i], data + pos, stride); | ||||
| 29 | } | ||||
| 30 | } | ||||
| 31 | |||||
| 32 | static void FN(RandomSample)(uint32_t* seed, | ||||
| 33 | const DataType* data, | ||||
| 34 | size_t length, | ||||
| 35 | size_t stride, | ||||
| 36 | HistogramType* sample) { | ||||
| 37 | size_t pos = 0; | ||||
| 38 | if (stride >= length) { | ||||
| 39 | stride = length; | ||||
| 40 | } else { | ||||
| 41 | pos = MyRand(seed) % (length - stride + 1); | ||||
| 42 | } | ||||
| 43 | FN(HistogramAddVector)(sample, data + pos, stride); | ||||
| 44 | } | ||||
| 45 | |||||
| 46 | static void FN(RefineEntropyCodes)(const DataType* data, size_t length, | ||||
| 47 | size_t stride, | ||||
| 48 | size_t num_histograms, | ||||
| 49 | HistogramType* histograms) { | ||||
| 50 | size_t iters = | ||||
| 51 | kIterMulForRefining * length / stride + kMinItersForRefining; | ||||
| 52 | uint32_t seed = 7; | ||||
| 53 | size_t iter; | ||||
| 54 | iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms; | ||||
| 55 | for (iter = 0; iter < iters; ++iter) { | ||||
| 56 | HistogramType sample; | ||||
| 57 | FN(HistogramClear)(&sample); | ||||
| 58 | FN(RandomSample)(&seed, data, length, stride, &sample); | ||||
| 59 | FN(HistogramAddHistogram)(&histograms[iter % num_histograms], &sample); | ||||
| 60 | } | ||||
| 61 | } | ||||
| 62 | |||||
| 63 | /* Assigns a block id from the range [0, num_histograms) to each data element | ||||
| 64 | in data[0..length) and fills in block_id[0..length) with the assigned values. | ||||
| 65 | Returns the number of blocks, i.e. one plus the number of block switches. */ | ||||
| 66 | static size_t FN(FindBlocks)(const DataType* data, const size_t length, | ||||
| 67 | const double block_switch_bitcost, | ||||
| 68 | const size_t num_histograms, | ||||
| 69 | const HistogramType* histograms, | ||||
| 70 | double* insert_cost, | ||||
| 71 | double* cost, | ||||
| 72 | uint8_t* switch_signal, | ||||
| 73 | uint8_t* block_id) { | ||||
| 74 | const size_t data_size = FN(HistogramDataSize)(); | ||||
| 75 | const size_t bitmaplen = (num_histograms + 7) >> 3; | ||||
| 76 | size_t num_blocks = 1; | ||||
| 77 | size_t i; | ||||
| 78 | size_t j; | ||||
| 79 | BROTLI_DCHECK(num_histograms <= 256); | ||||
| 80 | if (num_histograms <= 1) { | ||||
| 81 | for (i = 0; i < length; ++i) { | ||||
| 82 | block_id[i] = 0; | ||||
| 83 | } | ||||
| 84 | return 1; | ||||
| 85 | } | ||||
| 86 | memset(insert_cost, 0, sizeof(insert_cost[0]) * data_size * num_histograms); | ||||
| 87 | for (i = 0; i < num_histograms; ++i) { | ||||
| 88 | insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_); | ||||
| 89 | } | ||||
| 90 | for (i = data_size; i != 0;) { | ||||
| 91 | --i; | ||||
| 92 | for (j = 0; j < num_histograms; ++j) { | ||||
| 93 | insert_cost[i * num_histograms + j] = | ||||
| 94 | insert_cost[j] - BitCost(histograms[j].data_[i]); | ||||
| 95 | } | ||||
| 96 | } | ||||
| 97 | memset(cost, 0, sizeof(cost[0]) * num_histograms); | ||||
| 98 | memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmaplen); | ||||
| 99 | /* After each iteration of this loop, cost[k] will contain the difference | ||||
| 100 | between the minimum cost of arriving at the current byte position using | ||||
| 101 | entropy code k, and the minimum cost of arriving at the current byte | ||||
| 102 | position. This difference is capped at the block switch cost, and if it | ||||
| 103 | reaches block switch cost, it means that when we trace back from the last | ||||
| 104 | position, we need to switch here. */ | ||||
| 105 | for (i = 0; i < length; ++i) { | ||||
| 106 | const size_t byte_ix = i; | ||||
| 107 | size_t ix = byte_ix * bitmaplen; | ||||
| 108 | size_t insert_cost_ix = data[byte_ix] * num_histograms; | ||||
| 109 | double min_cost = 1e99; | ||||
| 110 | double block_switch_cost = block_switch_bitcost; | ||||
| 111 | size_t k; | ||||
| 112 | for (k = 0; k < num_histograms; ++k) { | ||||
| 113 | /* We are coding the symbol in data[byte_ix] with entropy code k. */ | ||||
| 114 | cost[k] += insert_cost[insert_cost_ix + k]; | ||||
| 115 | if (cost[k] < min_cost) { | ||||
| 116 | min_cost = cost[k]; | ||||
| 117 | block_id[byte_ix] = (uint8_t)k; | ||||
| 118 | } | ||||
| 119 | } | ||||
| 120 | /* More blocks for the beginning. */ | ||||
| 121 | if (byte_ix < 2000) { | ||||
| 122 | block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000; | ||||
| 123 | } | ||||
| 124 | for (k = 0; k < num_histograms; ++k) { | ||||
| 125 | cost[k] -= min_cost; | ||||
| 126 | if (cost[k] >= block_switch_cost) { | ||||
| 127 | const uint8_t mask = (uint8_t)(1u << (k & 7)); | ||||
| 128 | cost[k] = block_switch_cost; | ||||
| 129 | BROTLI_DCHECK((k >> 3) < bitmaplen); | ||||
| 130 | switch_signal[ix + (k >> 3)] |= mask; | ||||
| 131 | } | ||||
| 132 | } | ||||
| 133 | } | ||||
| 134 | { /* Trace back from the last position and switch at the marked places. */ | ||||
| 135 | size_t byte_ix = length - 1; | ||||
| 136 | size_t ix = byte_ix * bitmaplen; | ||||
| 137 | uint8_t cur_id = block_id[byte_ix]; | ||||
| 138 | while (byte_ix > 0) { | ||||
| 139 | const uint8_t mask = (uint8_t)(1u << (cur_id & 7)); | ||||
| 140 | BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmaplen); | ||||
| 141 | --byte_ix; | ||||
| 142 | ix -= bitmaplen; | ||||
| 143 | if (switch_signal[ix + (cur_id >> 3)] & mask) { | ||||
| 144 | if (cur_id != block_id[byte_ix]) { | ||||
| 145 | cur_id = block_id[byte_ix]; | ||||
| 146 | ++num_blocks; | ||||
| 147 | } | ||||
| 148 | } | ||||
| 149 | block_id[byte_ix] = cur_id; | ||||
| 150 | } | ||||
| 151 | } | ||||
| 152 | return num_blocks; | ||||
| 153 | } | ||||
| 154 | |||||
| 155 | static size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length, | ||||
| 156 | uint16_t* new_id, const size_t num_histograms) { | ||||
| 157 | static const uint16_t kInvalidId = 256; | ||||
| 158 | uint16_t next_id = 0; | ||||
| 159 | size_t i; | ||||
| 160 | for (i = 0; i < num_histograms; ++i) { | ||||
| 161 | new_id[i] = kInvalidId; | ||||
| 162 | } | ||||
| 163 | for (i = 0; i < length; ++i) { | ||||
| 164 | BROTLI_DCHECK(block_ids[i] < num_histograms); | ||||
| 165 | if (new_id[block_ids[i]] == kInvalidId) { | ||||
| 166 | new_id[block_ids[i]] = next_id++; | ||||
| 167 | } | ||||
| 168 | } | ||||
| 169 | for (i = 0; i < length; ++i) { | ||||
| 170 | block_ids[i] = (uint8_t)new_id[block_ids[i]]; | ||||
| 171 | BROTLI_DCHECK(block_ids[i] < num_histograms); | ||||
| 172 | } | ||||
| 173 | BROTLI_DCHECK(next_id <= num_histograms); | ||||
| 174 | return next_id; | ||||
| 175 | } | ||||
| 176 | |||||
| 177 | static void FN(BuildBlockHistograms)(const DataType* data, const size_t length, | ||||
| 178 | const uint8_t* block_ids, | ||||
| 179 | const size_t num_histograms, | ||||
| 180 | HistogramType* histograms) { | ||||
| 181 | size_t i; | ||||
| 182 | FN(ClearHistograms)(histograms, num_histograms); | ||||
| 183 | for (i = 0; i < length; ++i) { | ||||
| 184 | FN(HistogramAdd)(&histograms[block_ids[i]], data[i]); | ||||
| 185 | } | ||||
| 186 | } | ||||
| 187 | |||||
| 188 | static void FN(ClusterBlocks)(MemoryManager* m, | ||||
| 189 | const DataType* data, const size_t length, | ||||
| 190 | const size_t num_blocks, | ||||
| 191 | uint8_t* block_ids, | ||||
| 192 | BlockSplit* split) { | ||||
| 193 | uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks)((num_blocks) > 0 ? ((uint32_t*)BrotliAllocate((m), (num_blocks ) * sizeof(uint32_t))) : ((void*)0)); | ||||
| 194 | uint32_t* block_lengths = BROTLI_ALLOC(m, uint32_t, num_blocks)((num_blocks) > 0 ? ((uint32_t*)BrotliAllocate((m), (num_blocks ) * sizeof(uint32_t))) : ((void*)0)); | ||||
| 195 | const size_t expected_num_clusters = CLUSTERS_PER_BATCH16 * | ||||
| 196 | (num_blocks + HISTOGRAMS_PER_BATCH64 - 1) / HISTOGRAMS_PER_BATCH64; | ||||
| 197 | size_t all_histograms_size = 0; | ||||
| 198 | size_t all_histograms_capacity = expected_num_clusters; | ||||
| 199 | HistogramType* all_histograms = | ||||
| 200 | BROTLI_ALLOC(m, HistogramType, all_histograms_capacity)((all_histograms_capacity) > 0 ? ((HistogramType*)BrotliAllocate ((m), (all_histograms_capacity) * sizeof(HistogramType))) : ( (void*)0)); | ||||
| 201 | size_t cluster_size_size = 0; | ||||
| 202 | size_t cluster_size_capacity = expected_num_clusters; | ||||
| 203 | uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity)((cluster_size_capacity) > 0 ? ((uint32_t*)BrotliAllocate( (m), (cluster_size_capacity) * sizeof(uint32_t))) : ((void*)0 )); | ||||
| 204 | size_t num_clusters = 0; | ||||
| 205 | HistogramType* histograms = BROTLI_ALLOC(m, HistogramType,(((brotli_min_size_t((num_blocks), (64)))) > 0 ? ((HistogramType *)BrotliAllocate((m), ((brotli_min_size_t((num_blocks), (64)) )) * sizeof(HistogramType))) : ((void*)0)) | ||||
| 206 | BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH))(((brotli_min_size_t((num_blocks), (64)))) > 0 ? ((HistogramType *)BrotliAllocate((m), ((brotli_min_size_t((num_blocks), (64)) )) * sizeof(HistogramType))) : ((void*)0)); | ||||
| 207 | size_t max_num_pairs = | ||||
| 208 | HISTOGRAMS_PER_BATCH64 * HISTOGRAMS_PER_BATCH64 / 2; | ||||
| 209 | size_t pairs_capacity = max_num_pairs + 1; | ||||
| 210 | HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity)((pairs_capacity) > 0 ? ((HistogramPair*)BrotliAllocate((m ), (pairs_capacity) * sizeof(HistogramPair))) : ((void*)0)); | ||||
| 211 | size_t pos = 0; | ||||
| 212 | uint32_t* clusters; | ||||
| 213 | size_t num_final_clusters; | ||||
| 214 | static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX(~((uint32_t)0)); | ||||
| 215 | uint32_t* new_index; | ||||
| 216 | size_t i; | ||||
| 217 | uint32_t sizes[HISTOGRAMS_PER_BATCH64] = { 0 }; | ||||
| 218 | uint32_t new_clusters[HISTOGRAMS_PER_BATCH64] = { 0 }; | ||||
| 219 | uint32_t symbols[HISTOGRAMS_PER_BATCH64] = { 0 }; | ||||
| 220 | uint32_t remap[HISTOGRAMS_PER_BATCH64] = { 0 }; | ||||
| 221 | |||||
| 222 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(histogram_symbols)(!!0) || | ||||
| 223 | BROTLI_IS_NULL(block_lengths)(!!0) || BROTLI_IS_NULL(all_histograms)(!!0) || | ||||
| 224 | BROTLI_IS_NULL(cluster_size)(!!0) || BROTLI_IS_NULL(histograms)(!!0) || | ||||
| 225 | BROTLI_IS_NULL(pairs)(!!0)) { | ||||
| 226 | return; | ||||
| 227 | } | ||||
| 228 | |||||
| 229 | memset(block_lengths, 0, num_blocks * sizeof(uint32_t)); | ||||
| 230 | |||||
| 231 | { | ||||
| 232 | size_t block_idx = 0; | ||||
| 233 | for (i = 0; i < length; ++i) { | ||||
| 234 | BROTLI_DCHECK(block_idx < num_blocks); | ||||
| 235 | ++block_lengths[block_idx]; | ||||
| 236 | if (i + 1 == length || block_ids[i] != block_ids[i + 1]) { | ||||
| 237 | ++block_idx; | ||||
| 238 | } | ||||
| 239 | } | ||||
| 240 | BROTLI_DCHECK(block_idx == num_blocks); | ||||
| 241 | } | ||||
| 242 | |||||
| 243 | for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH64) { | ||||
| 244 | const size_t num_to_combine = | ||||
| 245 | BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH)(brotli_min_size_t((num_blocks - i), (64))); | ||||
| 246 | size_t num_new_clusters; | ||||
| 247 | size_t j; | ||||
| 248 | for (j = 0; j < num_to_combine; ++j) { | ||||
| 249 | size_t k; | ||||
| 250 | FN(HistogramClear)(&histograms[j]); | ||||
| 251 | for (k = 0; k < block_lengths[i + j]; ++k) { | ||||
| 252 | FN(HistogramAdd)(&histograms[j], data[pos++]); | ||||
| 253 | } | ||||
| 254 | histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]); | ||||
| 255 | new_clusters[j] = (uint32_t)j; | ||||
| 256 | symbols[j] = (uint32_t)j; | ||||
| 257 | sizes[j] = 1; | ||||
| 258 | } | ||||
| 259 | num_new_clusters = FN(BrotliHistogramCombine)( | ||||
| 260 | histograms, sizes, symbols, new_clusters, pairs, num_to_combine, | ||||
| 261 | num_to_combine, HISTOGRAMS_PER_BATCH64, max_num_pairs); | ||||
| 262 | BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms,{ if (all_histograms_capacity < (all_histograms_size + num_new_clusters )) { size_t _new_size = (all_histograms_capacity == 0) ? (all_histograms_size + num_new_clusters) : all_histograms_capacity; HistogramType * new_array; while (_new_size < (all_histograms_size + num_new_clusters )) _new_size *= 2; new_array = ((_new_size) > 0 ? ((HistogramType *)BrotliAllocate(((m)), (_new_size) * sizeof(HistogramType))) : ((void*)0)); if (!(!!0) && !(!!0) && all_histograms_capacity != 0) memcpy(new_array, all_histograms, all_histograms_capacity * sizeof(HistogramType)); { BrotliFree(((m)), (all_histograms )); all_histograms = ((void*)0); }; all_histograms = new_array ; all_histograms_capacity = _new_size; } } | ||||
| 263 | all_histograms_capacity, all_histograms_size + num_new_clusters){ if (all_histograms_capacity < (all_histograms_size + num_new_clusters )) { size_t _new_size = (all_histograms_capacity == 0) ? (all_histograms_size + num_new_clusters) : all_histograms_capacity; HistogramType * new_array; while (_new_size < (all_histograms_size + num_new_clusters )) _new_size *= 2; new_array = ((_new_size) > 0 ? ((HistogramType *)BrotliAllocate(((m)), (_new_size) * sizeof(HistogramType))) : ((void*)0)); if (!(!!0) && !(!!0) && all_histograms_capacity != 0) memcpy(new_array, all_histograms, all_histograms_capacity * sizeof(HistogramType)); { BrotliFree(((m)), (all_histograms )); all_histograms = ((void*)0); }; all_histograms = new_array ; all_histograms_capacity = _new_size; } }; | ||||
| 264 | BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size,{ if (cluster_size_capacity < (cluster_size_size + num_new_clusters )) { size_t _new_size = (cluster_size_capacity == 0) ? (cluster_size_size + num_new_clusters) : cluster_size_capacity; uint32_t* new_array ; while (_new_size < (cluster_size_size + num_new_clusters )) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint32_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint32_t))) : (( void*)0)); if (!(!!0) && !(!!0) && cluster_size_capacity != 0) memcpy(new_array, cluster_size, cluster_size_capacity * sizeof(uint32_t)); { BrotliFree(((m)), (cluster_size)); cluster_size = ((void*)0); }; cluster_size = new_array; cluster_size_capacity = _new_size; } } | ||||
| 265 | cluster_size_capacity, cluster_size_size + num_new_clusters){ if (cluster_size_capacity < (cluster_size_size + num_new_clusters )) { size_t _new_size = (cluster_size_capacity == 0) ? (cluster_size_size + num_new_clusters) : cluster_size_capacity; uint32_t* new_array ; while (_new_size < (cluster_size_size + num_new_clusters )) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint32_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint32_t))) : (( void*)0)); if (!(!!0) && !(!!0) && cluster_size_capacity != 0) memcpy(new_array, cluster_size, cluster_size_capacity * sizeof(uint32_t)); { BrotliFree(((m)), (cluster_size)); cluster_size = ((void*)0); }; cluster_size = new_array; cluster_size_capacity = _new_size; } }; | ||||
| 266 | if (BROTLI_IS_OOM(m)(!!0)) return; | ||||
| 267 | for (j = 0; j < num_new_clusters; ++j) { | ||||
| 268 | all_histograms[all_histograms_size++] = histograms[new_clusters[j]]; | ||||
| 269 | cluster_size[cluster_size_size++] = sizes[new_clusters[j]]; | ||||
| 270 | remap[new_clusters[j]] = (uint32_t)j; | ||||
| 271 | } | ||||
| 272 | for (j = 0; j < num_to_combine; ++j) { | ||||
| 273 | histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]]; | ||||
| 274 | } | ||||
| 275 | num_clusters += num_new_clusters; | ||||
| 276 | BROTLI_DCHECK(num_clusters == cluster_size_size); | ||||
| 277 | BROTLI_DCHECK(num_clusters == all_histograms_size); | ||||
| 278 | } | ||||
| 279 | BROTLI_FREE(m, histograms){ BrotliFree((m), (histograms)); histograms = ((void*)0); }; | ||||
| 280 | |||||
| 281 | max_num_pairs = | ||||
| 282 | BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters)(brotli_min_size_t((64 * num_clusters), ((num_clusters / 2) * num_clusters))); | ||||
| 283 | if (pairs_capacity < max_num_pairs + 1) { | ||||
| 284 | BROTLI_FREE(m, pairs){ BrotliFree((m), (pairs)); pairs = ((void*)0); }; | ||||
| 285 | pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1)((max_num_pairs + 1) > 0 ? ((HistogramPair*)BrotliAllocate ((m), (max_num_pairs + 1) * sizeof(HistogramPair))) : ((void* )0)); | ||||
| 286 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(pairs)(!!0)) return; | ||||
| 287 | } | ||||
| 288 | |||||
| 289 | clusters = BROTLI_ALLOC(m, uint32_t, num_clusters)((num_clusters) > 0 ? ((uint32_t*)BrotliAllocate((m), (num_clusters ) * sizeof(uint32_t))) : ((void*)0)); | ||||
| 290 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(clusters)(!!0)) return; | ||||
| 291 | for (i = 0; i < num_clusters; ++i) { | ||||
| 292 | clusters[i] = (uint32_t)i; | ||||
| 293 | } | ||||
| 294 | num_final_clusters = FN(BrotliHistogramCombine)( | ||||
| 295 | all_histograms, cluster_size, histogram_symbols, clusters, pairs, | ||||
| 296 | num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES256, | ||||
| 297 | max_num_pairs); | ||||
| 298 | BROTLI_FREE(m, pairs){ BrotliFree((m), (pairs)); pairs = ((void*)0); }; | ||||
| 299 | BROTLI_FREE(m, cluster_size){ BrotliFree((m), (cluster_size)); cluster_size = ((void*)0); }; | ||||
| 300 | |||||
| 301 | new_index = BROTLI_ALLOC(m, uint32_t, num_clusters)((num_clusters) > 0 ? ((uint32_t*)BrotliAllocate((m), (num_clusters ) * sizeof(uint32_t))) : ((void*)0)); | ||||
| 302 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(new_index)(!!0)) return; | ||||
| 303 | for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex; | ||||
| 304 | pos = 0; | ||||
| 305 | { | ||||
| 306 | uint32_t next_index = 0; | ||||
| 307 | for (i = 0; i < num_blocks; ++i) { | ||||
| 308 | HistogramType histo; | ||||
| 309 | size_t j; | ||||
| 310 | uint32_t best_out; | ||||
| 311 | double best_bits; | ||||
| 312 | FN(HistogramClear)(&histo); | ||||
| 313 | for (j = 0; j < block_lengths[i]; ++j) { | ||||
| 314 | FN(HistogramAdd)(&histo, data[pos++]); | ||||
| 315 | } | ||||
| 316 | best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1]; | ||||
| 317 | best_bits = | ||||
| 318 | FN(BrotliHistogramBitCostDistance)(&histo, &all_histograms[best_out]); | ||||
| 319 | for (j = 0; j < num_final_clusters; ++j) { | ||||
| 320 | const double cur_bits = FN(BrotliHistogramBitCostDistance)( | ||||
| 321 | &histo, &all_histograms[clusters[j]]); | ||||
| 322 | if (cur_bits < best_bits) { | ||||
| 323 | best_bits = cur_bits; | ||||
| 324 | best_out = clusters[j]; | ||||
| 325 | } | ||||
| 326 | } | ||||
| 327 | histogram_symbols[i] = best_out; | ||||
| 328 | if (new_index[best_out] == kInvalidIndex) { | ||||
| 329 | new_index[best_out] = next_index++; | ||||
| 330 | } | ||||
| 331 | } | ||||
| 332 | } | ||||
| 333 | BROTLI_FREE(m, clusters){ BrotliFree((m), (clusters)); clusters = ((void*)0); }; | ||||
| 334 | BROTLI_FREE(m, all_histograms){ BrotliFree((m), (all_histograms)); all_histograms = ((void* )0); }; | ||||
| 335 | BROTLI_ENSURE_CAPACITY({ if (split->types_alloc_size < (num_blocks)) { size_t _new_size = (split->types_alloc_size == 0) ? (num_blocks) : split-> types_alloc_size; uint8_t* new_array; while (_new_size < ( num_blocks)) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof(uint8_t ))) : ((void*)0)); if (!(!!0) && !(!!0) && split ->types_alloc_size != 0) memcpy(new_array, split->types , split->types_alloc_size * sizeof(uint8_t)); { BrotliFree (((m)), (split->types)); split->types = ((void*)0); }; split ->types = new_array; split->types_alloc_size = _new_size ; } } | ||||
| 336 | m, uint8_t, split->types, split->types_alloc_size, num_blocks){ if (split->types_alloc_size < (num_blocks)) { size_t _new_size = (split->types_alloc_size == 0) ? (num_blocks) : split-> types_alloc_size; uint8_t* new_array; while (_new_size < ( num_blocks)) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint8_t*)BrotliAllocate(((m)), (_new_size) * sizeof(uint8_t ))) : ((void*)0)); if (!(!!0) && !(!!0) && split ->types_alloc_size != 0) memcpy(new_array, split->types , split->types_alloc_size * sizeof(uint8_t)); { BrotliFree (((m)), (split->types)); split->types = ((void*)0); }; split ->types = new_array; split->types_alloc_size = _new_size ; } }; | ||||
| 337 | BROTLI_ENSURE_CAPACITY({ if (split->lengths_alloc_size < (num_blocks)) { size_t _new_size = (split->lengths_alloc_size == 0) ? (num_blocks ) : split->lengths_alloc_size; uint32_t* new_array; while ( _new_size < (num_blocks)) _new_size *= 2; new_array = ((_new_size ) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size) * sizeof (uint32_t))) : ((void*)0)); if (!(!!0) && !(!!0) && split->lengths_alloc_size != 0) memcpy(new_array, split-> lengths, split->lengths_alloc_size * sizeof(uint32_t)); { BrotliFree (((m)), (split->lengths)); split->lengths = ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size = _new_size; } } | ||||
| 338 | m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks){ if (split->lengths_alloc_size < (num_blocks)) { size_t _new_size = (split->lengths_alloc_size == 0) ? (num_blocks ) : split->lengths_alloc_size; uint32_t* new_array; while ( _new_size < (num_blocks)) _new_size *= 2; new_array = ((_new_size ) > 0 ? ((uint32_t*)BrotliAllocate(((m)), (_new_size) * sizeof (uint32_t))) : ((void*)0)); if (!(!!0) && !(!!0) && split->lengths_alloc_size != 0) memcpy(new_array, split-> lengths, split->lengths_alloc_size * sizeof(uint32_t)); { BrotliFree (((m)), (split->lengths)); split->lengths = ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size = _new_size; } }; | ||||
| 339 | if (BROTLI_IS_OOM(m)(!!0)) return; | ||||
| 340 | { | ||||
| 341 | uint32_t cur_length = 0; | ||||
| 342 | size_t block_idx = 0; | ||||
| 343 | uint8_t max_type = 0; | ||||
| 344 | for (i = 0; i < num_blocks; ++i) { | ||||
| 345 | cur_length += block_lengths[i]; | ||||
| 346 | if (i + 1 == num_blocks || | ||||
| 347 | histogram_symbols[i] != histogram_symbols[i + 1]) { | ||||
| 348 | const uint8_t id = (uint8_t)new_index[histogram_symbols[i]]; | ||||
| 349 | split->types[block_idx] = id; | ||||
| 350 | split->lengths[block_idx] = cur_length; | ||||
| 351 | max_type = BROTLI_MAX(uint8_t, max_type, id)(brotli_max_uint8_t((max_type), (id))); | ||||
| 352 | cur_length = 0; | ||||
| 353 | ++block_idx; | ||||
| 354 | } | ||||
| 355 | } | ||||
| 356 | split->num_blocks = block_idx; | ||||
| 357 | split->num_types = (size_t)max_type + 1; | ||||
| 358 | } | ||||
| 359 | BROTLI_FREE(m, new_index){ BrotliFree((m), (new_index)); new_index = ((void*)0); }; | ||||
| 360 | BROTLI_FREE(m, block_lengths){ BrotliFree((m), (block_lengths)); block_lengths = ((void*)0 ); }; | ||||
| 361 | BROTLI_FREE(m, histogram_symbols){ BrotliFree((m), (histogram_symbols)); histogram_symbols = ( (void*)0); }; | ||||
| 362 | } | ||||
| 363 | |||||
| 364 | static void FN(SplitByteVector)(MemoryManager* m, | ||||
| 365 | const DataType* data, const size_t length, | ||||
| 366 | const size_t literals_per_histogram, | ||||
| 367 | const size_t max_histograms, | ||||
| 368 | const size_t sampling_stride_length, | ||||
| 369 | const double block_switch_cost, | ||||
| 370 | const BrotliEncoderParams* params, | ||||
| 371 | BlockSplit* split) { | ||||
| 372 | const size_t data_size = FN(HistogramDataSize)(); | ||||
| 373 | size_t num_histograms = length / literals_per_histogram + 1; | ||||
| 374 | HistogramType* histograms; | ||||
| 375 | if (num_histograms > max_histograms) { | ||||
| 376 | num_histograms = max_histograms; | ||||
| 377 | } | ||||
| 378 | if (length
| ||||
| 379 | split->num_types = 1; | ||||
| 380 | return; | ||||
| 381 | } else if (length < kMinLengthForBlockSplitting) { | ||||
| 382 | BROTLI_ENSURE_CAPACITY(m, uint8_t,{ if (split->types_alloc_size < (split->num_blocks + 1)) { size_t _new_size = (split->types_alloc_size == 0) ? (split->num_blocks + 1) : split->types_alloc_size; uint8_t * new_array; while (_new_size < (split->num_blocks + 1) ) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint8_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint8_t))) : ((void *)0)); if (!(!!0) && !(!!0) && split->types_alloc_size != 0) memcpy(new_array, split->types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree(((m)), (split->types)); split ->types = ((void*)0); }; split->types = new_array; split ->types_alloc_size = _new_size; } } | ||||
| 383 | split->types, split->types_alloc_size, split->num_blocks + 1){ if (split->types_alloc_size < (split->num_blocks + 1)) { size_t _new_size = (split->types_alloc_size == 0) ? (split->num_blocks + 1) : split->types_alloc_size; uint8_t * new_array; while (_new_size < (split->num_blocks + 1) ) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint8_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint8_t))) : ((void *)0)); if (!(!!0) && !(!!0) && split->types_alloc_size != 0) memcpy(new_array, split->types, split->types_alloc_size * sizeof(uint8_t)); { BrotliFree(((m)), (split->types)); split ->types = ((void*)0); }; split->types = new_array; split ->types_alloc_size = _new_size; } }; | ||||
| 384 | BROTLI_ENSURE_CAPACITY(m, uint32_t,{ if (split->lengths_alloc_size < (split->num_blocks + 1)) { size_t _new_size = (split->lengths_alloc_size == 0 ) ? (split->num_blocks + 1) : split->lengths_alloc_size ; uint32_t* new_array; while (_new_size < (split->num_blocks + 1)) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint32_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint32_t))) : (( void*)0)); if (!(!!0) && !(!!0) && split-> lengths_alloc_size != 0) memcpy(new_array, split->lengths, split->lengths_alloc_size * sizeof(uint32_t)); { BrotliFree (((m)), (split->lengths)); split->lengths = ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size = _new_size; } } | ||||
| 385 | split->lengths, split->lengths_alloc_size, split->num_blocks + 1){ if (split->lengths_alloc_size < (split->num_blocks + 1)) { size_t _new_size = (split->lengths_alloc_size == 0 ) ? (split->num_blocks + 1) : split->lengths_alloc_size ; uint32_t* new_array; while (_new_size < (split->num_blocks + 1)) _new_size *= 2; new_array = ((_new_size) > 0 ? ((uint32_t *)BrotliAllocate(((m)), (_new_size) * sizeof(uint32_t))) : (( void*)0)); if (!(!!0) && !(!!0) && split-> lengths_alloc_size != 0) memcpy(new_array, split->lengths, split->lengths_alloc_size * sizeof(uint32_t)); { BrotliFree (((m)), (split->lengths)); split->lengths = ((void*)0); }; split->lengths = new_array; split->lengths_alloc_size = _new_size; } }; | ||||
| 386 | if (BROTLI_IS_OOM(m)(!!0)) return; | ||||
| 387 | split->num_types = 1; | ||||
| 388 | split->types[split->num_blocks] = 0; | ||||
| 389 | split->lengths[split->num_blocks] = (uint32_t)length; | ||||
| 390 | split->num_blocks++; | ||||
| 391 | return; | ||||
| 392 | } | ||||
| 393 | histograms = BROTLI_ALLOC(m, HistogramType, num_histograms)((num_histograms) > 0 ? ((HistogramType*)BrotliAllocate((m ), (num_histograms) * sizeof(HistogramType))) : ((void*)0)); | ||||
| 394 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(histograms)(!!0)) return; | ||||
| 395 | /* Find good entropy codes. */ | ||||
| 396 | FN(InitialEntropyCodes)(data, length, | ||||
| 397 | sampling_stride_length, | ||||
| 398 | num_histograms, histograms); | ||||
| 399 | FN(RefineEntropyCodes)(data, length, | ||||
| 400 | sampling_stride_length, | ||||
| 401 | num_histograms, histograms); | ||||
| 402 | { | ||||
| 403 | /* Find a good path through literals with the good entropy codes. */ | ||||
| 404 | uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length)((length) > 0 ? ((uint8_t*)BrotliAllocate((m), (length) * sizeof (uint8_t))) : ((void*)0)); | ||||
| 405 | size_t num_blocks = 0; | ||||
| 406 | const size_t bitmaplen = (num_histograms + 7) >> 3; | ||||
| 407 | double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms)((data_size * num_histograms) > 0 ? ((double*)BrotliAllocate ((m), (data_size * num_histograms) * sizeof(double))) : ((void *)0)); | ||||
| 408 | double* cost = BROTLI_ALLOC(m, double, num_histograms)((num_histograms) > 0 ? ((double*)BrotliAllocate((m), (num_histograms ) * sizeof(double))) : ((void*)0)); | ||||
| 409 | uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen)((length * bitmaplen) > 0 ? ((uint8_t*)BrotliAllocate((m), (length * bitmaplen) * sizeof(uint8_t))) : ((void*)0)); | ||||
| 410 | uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms)((num_histograms) > 0 ? ((uint16_t*)BrotliAllocate((m), (num_histograms ) * sizeof(uint16_t))) : ((void*)0)); | ||||
| 411 | const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY11 ? 3 : 10; | ||||
| 412 | size_t i; | ||||
| 413 | if (BROTLI_IS_OOM(m)(!!0) || BROTLI_IS_NULL(block_ids)(!!0) || | ||||
| 414 | BROTLI_IS_NULL(insert_cost)(!!0) || BROTLI_IS_NULL(cost)(!!0) || | ||||
| 415 | BROTLI_IS_NULL(switch_signal)(!!0) || BROTLI_IS_NULL(new_id)(!!0)) { | ||||
| 416 | return; | ||||
| 417 | } | ||||
| 418 | for (i = 0; i < iters; ++i) { | ||||
| 419 | num_blocks = FN(FindBlocks)(data, length, | ||||
| 420 | block_switch_cost, | ||||
| 421 | num_histograms, histograms, | ||||
| 422 | insert_cost, cost, switch_signal, | ||||
| 423 | block_ids); | ||||
| 424 | num_histograms = FN(RemapBlockIds)(block_ids, length, | ||||
| 425 | new_id, num_histograms); | ||||
| 426 | FN(BuildBlockHistograms)(data, length, block_ids, | ||||
| 427 | num_histograms, histograms); | ||||
| 428 | } | ||||
| 429 | BROTLI_FREE(m, insert_cost){ BrotliFree((m), (insert_cost)); insert_cost = ((void*)0); }; | ||||
| 430 | BROTLI_FREE(m, cost){ BrotliFree((m), (cost)); cost = ((void*)0); }; | ||||
| 431 | BROTLI_FREE(m, switch_signal){ BrotliFree((m), (switch_signal)); switch_signal = ((void*)0 ); }; | ||||
| 432 | BROTLI_FREE(m, new_id){ BrotliFree((m), (new_id)); new_id = ((void*)0); }; | ||||
| 433 | BROTLI_FREE(m, histograms){ BrotliFree((m), (histograms)); histograms = ((void*)0); }; | ||||
| 434 | FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split); | ||||
| 435 | if (BROTLI_IS_OOM(m)(!!0)) return; | ||||
| 436 | BROTLI_FREE(m, block_ids){ BrotliFree((m), (block_ids)); block_ids = ((void*)0); }; | ||||
| 437 | } | ||||
| 438 | } | ||||
| 439 | |||||
| 440 | #undef HistogramType |