histogram.c (3261B)
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 /* Build per-context histograms of literals, commands and distance codes. */ 8 9 #include "histogram.h" 10 11 #include "../common/context.h" 12 #include "../common/platform.h" 13 #include "block_splitter.h" 14 #include "command.h" 15 16 #if defined(__cplusplus) || defined(c_plusplus) 17 extern "C" { 18 #endif 19 20 typedef struct BlockSplitIterator { 21 const BlockSplit* split_; /* Not owned. */ 22 size_t idx_; 23 size_t type_; 24 size_t length_; 25 } BlockSplitIterator; 26 27 static void InitBlockSplitIterator(BlockSplitIterator* self, 28 const BlockSplit* split) { 29 self->split_ = split; 30 self->idx_ = 0; 31 self->type_ = 0; 32 self->length_ = split->lengths ? split->lengths[0] : 0; 33 } 34 35 static void BlockSplitIteratorNext(BlockSplitIterator* self) { 36 if (self->length_ == 0) { 37 ++self->idx_; 38 self->type_ = self->split_->types[self->idx_]; 39 self->length_ = self->split_->lengths[self->idx_]; 40 } 41 --self->length_; 42 } 43 44 void BrotliBuildHistogramsWithContext( 45 const Command* cmds, const size_t num_commands, 46 const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split, 47 const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos, 48 size_t mask, uint8_t prev_byte, uint8_t prev_byte2, 49 const ContextType* context_modes, HistogramLiteral* literal_histograms, 50 HistogramCommand* insert_and_copy_histograms, 51 HistogramDistance* copy_dist_histograms) { 52 size_t pos = start_pos; 53 BlockSplitIterator literal_it; 54 BlockSplitIterator insert_and_copy_it; 55 BlockSplitIterator dist_it; 56 size_t i; 57 58 InitBlockSplitIterator(&literal_it, literal_split); 59 InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split); 60 InitBlockSplitIterator(&dist_it, dist_split); 61 for (i = 0; i < num_commands; ++i) { 62 const Command* cmd = &cmds[i]; 63 size_t j; 64 BlockSplitIteratorNext(&insert_and_copy_it); 65 HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_], 66 cmd->cmd_prefix_); 67 /* TODO(eustas): unwrap iterator blocks. */ 68 for (j = cmd->insert_len_; j != 0; --j) { 69 size_t context; 70 BlockSplitIteratorNext(&literal_it); 71 context = literal_it.type_; 72 if (context_modes) { 73 ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]); 74 context = (context << BROTLI_LITERAL_CONTEXT_BITS) + 75 BROTLI_CONTEXT(prev_byte, prev_byte2, lut); 76 } 77 HistogramAddLiteral(&literal_histograms[context], 78 ringbuffer[pos & mask]); 79 prev_byte2 = prev_byte; 80 prev_byte = ringbuffer[pos & mask]; 81 ++pos; 82 } 83 pos += CommandCopyLen(cmd); 84 if (CommandCopyLen(cmd)) { 85 prev_byte2 = ringbuffer[(pos - 2) & mask]; 86 prev_byte = ringbuffer[(pos - 1) & mask]; 87 if (cmd->cmd_prefix_ >= 128) { 88 size_t context; 89 BlockSplitIteratorNext(&dist_it); 90 context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) + 91 CommandDistanceContext(cmd); 92 HistogramAddDistance(©_dist_histograms[context], 93 cmd->dist_prefix_ & 0x3FF); 94 } 95 } 96 } 97 } 98 99 #if defined(__cplusplus) || defined(c_plusplus) 100 } /* extern "C" */ 101 #endif