OLD | NEW |
1 /* Copyright 2013 Google Inc. All Rights Reserved. | 1 /* Copyright 2013 Google Inc. All Rights Reserved. |
2 | 2 |
3 Distributed under MIT license. | 3 Distributed under MIT license. |
4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT | 4 See file LICENSE for detail or copy at https://opensource.org/licenses/MIT |
5 */ | 5 */ |
6 | 6 |
7 // Build per-context histograms of literals, commands and distance codes. | 7 /* Build per-context histograms of literals, commands and distance codes. */ |
8 | 8 |
9 #include "./histogram.h" | 9 #include "./histogram.h" |
10 | 10 |
11 #include <cmath> | |
12 | |
13 #include "./block_splitter.h" | 11 #include "./block_splitter.h" |
14 #include "./command.h" | 12 #include "./command.h" |
15 #include "./context.h" | 13 #include "./context.h" |
16 #include "./prefix.h" | |
17 | 14 |
18 namespace brotli { | 15 #if defined(__cplusplus) || defined(c_plusplus) |
| 16 extern "C" { |
| 17 #endif |
19 | 18 |
20 void BuildHistograms( | 19 typedef struct BlockSplitIterator { |
21 const Command* cmds, | 20 const BlockSplit* split_; /* Not owned. */ |
22 const size_t num_commands, | 21 size_t idx_; |
23 const BlockSplit& literal_split, | 22 size_t type_; |
24 const BlockSplit& insert_and_copy_split, | 23 size_t length_; |
25 const BlockSplit& dist_split, | 24 } BlockSplitIterator; |
26 const uint8_t* ringbuffer, | 25 |
27 size_t start_pos, | 26 static void InitBlockSplitIterator(BlockSplitIterator* self, |
28 size_t mask, | 27 const BlockSplit* split) { |
29 uint8_t prev_byte, | 28 self->split_ = split; |
30 uint8_t prev_byte2, | 29 self->idx_ = 0; |
31 const std::vector<ContextType>& context_modes, | 30 self->type_ = 0; |
32 std::vector<HistogramLiteral>* literal_histograms, | 31 self->length_ = split->lengths ? split->lengths[0] : 0; |
33 std::vector<HistogramCommand>* insert_and_copy_histograms, | 32 } |
34 std::vector<HistogramDistance>* copy_dist_histograms) { | 33 |
| 34 static void BlockSplitIteratorNext(BlockSplitIterator* self) { |
| 35 if (self->length_ == 0) { |
| 36 ++self->idx_; |
| 37 self->type_ = self->split_->types[self->idx_]; |
| 38 self->length_ = self->split_->lengths[self->idx_]; |
| 39 } |
| 40 --self->length_; |
| 41 } |
| 42 |
| 43 void BrotliBuildHistogramsWithContext( |
| 44 const Command* cmds, const size_t num_commands, |
| 45 const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, |
| 46 const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos, |
| 47 size_t mask, uint8_t prev_byte, uint8_t prev_byte2, |
| 48 const ContextType* context_modes, HistogramLiteral* literal_histograms, |
| 49 HistogramCommand* insert_and_copy_histograms, |
| 50 HistogramDistance* copy_dist_histograms) { |
35 size_t pos = start_pos; | 51 size_t pos = start_pos; |
36 BlockSplitIterator literal_it(literal_split); | 52 BlockSplitIterator literal_it; |
37 BlockSplitIterator insert_and_copy_it(insert_and_copy_split); | 53 BlockSplitIterator insert_and_copy_it; |
38 BlockSplitIterator dist_it(dist_split); | 54 BlockSplitIterator dist_it; |
39 for (size_t i = 0; i < num_commands; ++i) { | 55 size_t i; |
40 const Command &cmd = cmds[i]; | 56 |
41 insert_and_copy_it.Next(); | 57 InitBlockSplitIterator(&literal_it, literal_split); |
42 (*insert_and_copy_histograms)[insert_and_copy_it.type_].Add( | 58 InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split); |
43 cmd.cmd_prefix_); | 59 InitBlockSplitIterator(&dist_it, dist_split); |
44 for (size_t j = cmd.insert_len_; j != 0; --j) { | 60 for (i = 0; i < num_commands; ++i) { |
45 literal_it.Next(); | 61 const Command* cmd = &cmds[i]; |
46 size_t context = (literal_it.type_ << kLiteralContextBits) + | 62 size_t j; |
| 63 BlockSplitIteratorNext(&insert_and_copy_it); |
| 64 HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], |
| 65 cmd->cmd_prefix_); |
| 66 for (j = cmd->insert_len_; j != 0; --j) { |
| 67 size_t context; |
| 68 BlockSplitIteratorNext(&literal_it); |
| 69 context = (literal_it.type_ << BROTLI_LITERAL_CONTEXT_BITS) + |
47 Context(prev_byte, prev_byte2, context_modes[literal_it.type_]); | 70 Context(prev_byte, prev_byte2, context_modes[literal_it.type_]); |
48 (*literal_histograms)[context].Add(ringbuffer[pos & mask]); | 71 HistogramAddLiteral(&literal_histograms[context], |
| 72 ringbuffer[pos & mask]); |
49 prev_byte2 = prev_byte; | 73 prev_byte2 = prev_byte; |
50 prev_byte = ringbuffer[pos & mask]; | 74 prev_byte = ringbuffer[pos & mask]; |
51 ++pos; | 75 ++pos; |
52 } | 76 } |
53 pos += cmd.copy_len(); | 77 pos += CommandCopyLen(cmd); |
54 if (cmd.copy_len()) { | 78 if (CommandCopyLen(cmd)) { |
55 prev_byte2 = ringbuffer[(pos - 2) & mask]; | 79 prev_byte2 = ringbuffer[(pos - 2) & mask]; |
56 prev_byte = ringbuffer[(pos - 1) & mask]; | 80 prev_byte = ringbuffer[(pos - 1) & mask]; |
57 if (cmd.cmd_prefix_ >= 128) { | 81 if (cmd->cmd_prefix_ >= 128) { |
58 dist_it.Next(); | 82 size_t context; |
59 size_t context = (dist_it.type_ << kDistanceContextBits) + | 83 BlockSplitIteratorNext(&dist_it); |
60 cmd.DistanceContext(); | 84 context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) + |
61 (*copy_dist_histograms)[context].Add(cmd.dist_prefix_); | 85 CommandDistanceContext(cmd); |
| 86 HistogramAddDistance(©_dist_histograms[context], |
| 87 cmd->dist_prefix_); |
62 } | 88 } |
63 } | 89 } |
64 } | 90 } |
65 } | 91 } |
66 | 92 |
67 } // namespace brotli | 93 #if defined(__cplusplus) || defined(c_plusplus) |
| 94 } /* extern "C" */ |
| 95 #endif |
OLD | NEW |