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 |