]> git.proxmox.com Git - mirror_edk2.git/blame - BaseTools/Source/C/BrotliCompress/enc/block_splitter.c
BaseTools: Copy Brotli algorithm 3rd party source code for tool
[mirror_edk2.git] / BaseTools / Source / C / BrotliCompress / enc / block_splitter.c
CommitLineData
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
24extern "C" {\r
25#endif\r
26\r
27static const size_t kMaxLiteralHistograms = 100;\r
28static const size_t kMaxCommandHistograms = 50;\r
29static const double kLiteralBlockSwitchCost = 28.1;\r
30static const double kCommandBlockSwitchCost = 13.5;\r
31static const double kDistanceBlockSwitchCost = 14.6;\r
32static const size_t kLiteralStrideLength = 70;\r
33static const size_t kCommandStrideLength = 40;\r
34static const size_t kSymbolsPerLiteralHistogram = 544;\r
35static const size_t kSymbolsPerCommandHistogram = 530;\r
36static const size_t kSymbolsPerDistanceHistogram = 544;\r
37static const size_t kMinLengthForBlockSplitting = 128;\r
38static const size_t kIterMulForRefining = 2;\r
39static const size_t kMinItersForRefining = 100;\r
40\r
41static 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
51static 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
77static 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
85static 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
111void 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
120void BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) {\r
121 BROTLI_FREE(m, self->types);\r
122 BROTLI_FREE(m, self->lengths);\r
123}\r
124\r
125void 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