]>
Commit | Line | Data |
---|---|---|
11b7501a SB |
1 | /* Copyright 2013 Google Inc. All Rights Reserved.\r |
2 | \r | |
3 | Distributed under MIT license.\r | |
4 | See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\r | |
5 | */\r | |
6 | \r | |
7 | /* Block split point selection utilities. */\r | |
8 | \r | |
9 | #include "./block_splitter.h"\r | |
10 | \r | |
11 | #include <assert.h>\r | |
12 | #include <string.h> /* memcpy, memset */\r | |
13 | \r | |
14 | #include "./bit_cost.h"\r | |
15 | #include "./cluster.h"\r | |
16 | #include "./command.h"\r | |
17 | #include "./fast_log.h"\r | |
18 | #include "./histogram.h"\r | |
19 | #include "./memory.h"\r | |
20 | #include "./port.h"\r | |
21 | #include "./quality.h"\r | |
22 | \r | |
23 | #if defined(__cplusplus) || defined(c_plusplus)\r | |
24 | extern "C" {\r | |
25 | #endif\r | |
26 | \r | |
27 | static const size_t kMaxLiteralHistograms = 100;\r | |
28 | static const size_t kMaxCommandHistograms = 50;\r | |
29 | static const double kLiteralBlockSwitchCost = 28.1;\r | |
30 | static const double kCommandBlockSwitchCost = 13.5;\r | |
31 | static const double kDistanceBlockSwitchCost = 14.6;\r | |
32 | static const size_t kLiteralStrideLength = 70;\r | |
33 | static const size_t kCommandStrideLength = 40;\r | |
34 | static const size_t kSymbolsPerLiteralHistogram = 544;\r | |
35 | static const size_t kSymbolsPerCommandHistogram = 530;\r | |
36 | static const size_t kSymbolsPerDistanceHistogram = 544;\r | |
37 | static const size_t kMinLengthForBlockSplitting = 128;\r | |
38 | static const size_t kIterMulForRefining = 2;\r | |
39 | static const size_t kMinItersForRefining = 100;\r | |
40 | \r | |
41 | static size_t CountLiterals(const Command* cmds, const size_t num_commands) {\r | |
42 | /* Count how many we have. */\r | |
43 | size_t total_length = 0;\r | |
44 | size_t i;\r | |
45 | for (i = 0; i < num_commands; ++i) {\r | |
46 | total_length += cmds[i].insert_len_;\r | |
47 | }\r | |
48 | return total_length;\r | |
49 | }\r | |
50 | \r | |
51 | static void CopyLiteralsToByteArray(const Command* cmds,\r | |
52 | const size_t num_commands,\r | |
53 | const uint8_t* data,\r | |
54 | const size_t offset,\r | |
55 | const size_t mask,\r | |
56 | uint8_t* literals) {\r | |
57 | size_t pos = 0;\r | |
58 | size_t from_pos = offset & mask;\r | |
59 | size_t i;\r | |
60 | for (i = 0; i < num_commands; ++i) {\r | |
61 | size_t insert_len = cmds[i].insert_len_;\r | |
62 | if (from_pos + insert_len > mask) {\r | |
63 | size_t head_size = mask + 1 - from_pos;\r | |
64 | memcpy(literals + pos, data + from_pos, head_size);\r | |
65 | from_pos = 0;\r | |
66 | pos += head_size;\r | |
67 | insert_len -= head_size;\r | |
68 | }\r | |
69 | if (insert_len > 0) {\r | |
70 | memcpy(literals + pos, data + from_pos, insert_len);\r | |
71 | pos += insert_len;\r | |
72 | }\r | |
73 | from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask;\r | |
74 | }\r | |
75 | }\r | |
76 | \r | |
77 | static BROTLI_INLINE unsigned int MyRand(unsigned int* seed) {\r | |
78 | *seed *= 16807U;\r | |
79 | if (*seed == 0) {\r | |
80 | *seed = 1;\r | |
81 | }\r | |
82 | return *seed;\r | |
83 | }\r | |
84 | \r | |
85 | static BROTLI_INLINE double BitCost(size_t count) {\r | |
86 | return count == 0 ? -2.0 : FastLog2(count);\r | |
87 | }\r | |
88 | \r | |
89 | #define HISTOGRAMS_PER_BATCH 64\r | |
90 | #define CLUSTERS_PER_BATCH 16\r | |
91 | \r | |
92 | #define FN(X) X ## Literal\r | |
93 | #define DataType uint8_t\r | |
94 | /* NOLINTNEXTLINE(build/include) */\r | |
95 | #include "./block_splitter_inc.h"\r | |
96 | #undef DataType\r | |
97 | #undef FN\r | |
98 | \r | |
99 | #define FN(X) X ## Command\r | |
100 | #define DataType uint16_t\r | |
101 | /* NOLINTNEXTLINE(build/include) */\r | |
102 | #include "./block_splitter_inc.h"\r | |
103 | #undef FN\r | |
104 | \r | |
105 | #define FN(X) X ## Distance\r | |
106 | /* NOLINTNEXTLINE(build/include) */\r | |
107 | #include "./block_splitter_inc.h"\r | |
108 | #undef DataType\r | |
109 | #undef FN\r | |
110 | \r | |
111 | void BrotliInitBlockSplit(BlockSplit* self) {\r | |
112 | self->num_types = 0;\r | |
113 | self->num_blocks = 0;\r | |
114 | self->types = 0;\r | |
115 | self->lengths = 0;\r | |
116 | self->types_alloc_size = 0;\r | |
117 | self->lengths_alloc_size = 0;\r | |
118 | }\r | |
119 | \r | |
120 | void BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) {\r | |
121 | BROTLI_FREE(m, self->types);\r | |
122 | BROTLI_FREE(m, self->lengths);\r | |
123 | }\r | |
124 | \r | |
125 | void BrotliSplitBlock(MemoryManager* m,\r | |
126 | const Command* cmds,\r | |
127 | const size_t num_commands,\r | |
128 | const uint8_t* data,\r | |
129 | const size_t pos,\r | |
130 | const size_t mask,\r | |
131 | const BrotliEncoderParams* params,\r | |
132 | BlockSplit* literal_split,\r | |
133 | BlockSplit* insert_and_copy_split,\r | |
134 | BlockSplit* dist_split) {\r | |
135 | {\r | |
136 | size_t literals_count = CountLiterals(cmds, num_commands);\r | |
137 | uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count);\r | |
138 | if (BROTLI_IS_OOM(m)) return;\r | |
139 | /* Create a continuous array of literals. */\r | |
140 | CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals);\r | |
141 | /* Create the block split on the array of literals.\r | |
142 | Literal histograms have alphabet size 256. */\r | |
143 | SplitByteVectorLiteral(\r | |
144 | m, literals, literals_count,\r | |
145 | kSymbolsPerLiteralHistogram, kMaxLiteralHistograms,\r | |
146 | kLiteralStrideLength, kLiteralBlockSwitchCost, params,\r | |
147 | literal_split);\r | |
148 | if (BROTLI_IS_OOM(m)) return;\r | |
149 | BROTLI_FREE(m, literals);\r | |
150 | }\r | |
151 | \r | |
152 | {\r | |
153 | /* Compute prefix codes for commands. */\r | |
154 | uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands);\r | |
155 | size_t i;\r | |
156 | if (BROTLI_IS_OOM(m)) return;\r | |
157 | for (i = 0; i < num_commands; ++i) {\r | |
158 | insert_and_copy_codes[i] = cmds[i].cmd_prefix_;\r | |
159 | }\r | |
160 | /* Create the block split on the array of command prefixes. */\r | |
161 | SplitByteVectorCommand(\r | |
162 | m, insert_and_copy_codes, num_commands,\r | |
163 | kSymbolsPerCommandHistogram, kMaxCommandHistograms,\r | |
164 | kCommandStrideLength, kCommandBlockSwitchCost, params,\r | |
165 | insert_and_copy_split);\r | |
166 | if (BROTLI_IS_OOM(m)) return;\r | |
167 | /* TODO: reuse for distances? */\r | |
168 | BROTLI_FREE(m, insert_and_copy_codes);\r | |
169 | }\r | |
170 | \r | |
171 | {\r | |
172 | /* Create a continuous array of distance prefixes. */\r | |
173 | uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands);\r | |
174 | size_t j = 0;\r | |
175 | size_t i;\r | |
176 | if (BROTLI_IS_OOM(m)) return;\r | |
177 | for (i = 0; i < num_commands; ++i) {\r | |
178 | const Command* cmd = &cmds[i];\r | |
179 | if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\r | |
180 | distance_prefixes[j++] = cmd->dist_prefix_;\r | |
181 | }\r | |
182 | }\r | |
183 | /* Create the block split on the array of distance prefixes. */\r | |
184 | SplitByteVectorDistance(\r | |
185 | m, distance_prefixes, j,\r | |
186 | kSymbolsPerDistanceHistogram, kMaxCommandHistograms,\r | |
187 | kCommandStrideLength, kDistanceBlockSwitchCost, params,\r | |
188 | dist_split);\r | |
189 | if (BROTLI_IS_OOM(m)) return;\r | |
190 | BROTLI_FREE(m, distance_prefixes);\r | |
191 | }\r | |
192 | }\r | |
193 | \r | |
194 | \r | |
195 | #if defined(__cplusplus) || defined(c_plusplus)\r | |
196 | } /* extern "C" */\r | |
197 | #endif\r |