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