prefix.h revision 771eb107985566d2e458e3f06f2c7bd1b21c2dca
1771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov/* Copyright 2013 Google Inc. All Rights Reserved.
2771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov
3771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov   Distributed under MIT license, or public domain if desired and
4771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov   recognized in your jurisdiction.
5771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
6771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov*/
7771eb107985566d2e458e3f06f2c7bd1b21c2dcaEugene Klyuchnikov
8c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// Functions for encoding of integers into prefix codes the amount of extra
9c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka// bits, and the actual values of the extra bits.
10c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
11c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#ifndef BROTLI_ENC_PREFIX_H_
12c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#define BROTLI_ENC_PREFIX_H_
13c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
14b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka#include "./fast_log.h"
154a7024dcde1aaf30d824ade299e70711a30f4399Zoltan Szabadka#include "./types.h"
16c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
17c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkanamespace brotli {
18c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
19c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumInsertLenPrefixes = 24;
20c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumCopyLenPrefixes = 24;
21c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumCommandPrefixes = 704;
22c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumBlockLenPrefixes = 26;
23c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumDistanceShortCodes = 16;
24c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadkastatic const int kNumDistancePrefixes = 520;
25c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
26467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka// Represents the range of values belonging to a prefix code:
27467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka// [offset, offset + 2^nbits)
28467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadkastruct PrefixCodeRange {
29467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  int offset;
30467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  int nbits;
31467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka};
32467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka
33467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadkastatic const PrefixCodeRange kBlockLengthPrefixCode[kNumBlockLenPrefixes] = {
34467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  {   1,  2}, {    5,  2}, {  9,   2}, {  13,  2},
35467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  {  17,  3}, {   25,  3}, {  33,  3}, {  41,  3},
36467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  {  49,  4}, {   65,  4}, {  81,  4}, {  97,  4},
37467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  { 113,  5}, {  145,  5}, { 177,  5}, { 209,  5},
38467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  { 241,  6}, {  305,  6}, { 369,  7}, { 497,  8},
39467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  { 753,  9}, { 1265, 10}, {2289, 11}, {4337, 12},
40467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  {8433, 13}, {16625, 24}
41467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka};
42467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka
43467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadkainline void GetBlockLengthPrefixCode(int len,
44467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka                                     int* code, int* n_extra, int* extra) {
45467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  *code = 0;
46467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  while (*code < 25 && len >= kBlockLengthPrefixCode[*code + 1].offset) {
47467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka    ++(*code);
48467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  }
49467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  *n_extra = kBlockLengthPrefixCode[*code].nbits;
50467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka  *extra = len - kBlockLengthPrefixCode[*code].offset;
51467e6eef80d4967cf2020a54b0841855349dfc45Zoltan Szabadka}
52c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
53b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadkainline void PrefixEncodeCopyDistance(int distance_code,
54b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka                                     int num_direct_codes,
55b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka                                     int postfix_bits,
56b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka                                     uint16_t* code,
57b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka                                     uint32_t* extra_bits) {
58b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  if (distance_code < kNumDistanceShortCodes + num_direct_codes) {
59ea48ce5a6fa8a3224dd270a7f60428084e7b590dZoltan Szabadka    *code = static_cast<uint16_t>(distance_code);
60b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka    *extra_bits = 0;
61b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka    return;
62b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  }
63b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  distance_code -= kNumDistanceShortCodes + num_direct_codes;
64b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  distance_code += (1 << (postfix_bits + 2));
65b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int bucket = Log2Floor(distance_code) - 1;
66b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int postfix_mask = (1 << postfix_bits) - 1;
67b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int postfix = distance_code & postfix_mask;
68b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int prefix = (distance_code >> bucket) & 1;
69b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int offset = (2 + prefix) << bucket;
70b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  int nbits = bucket - postfix_bits;
71ea48ce5a6fa8a3224dd270a7f60428084e7b590dZoltan Szabadka  *code = static_cast<uint16_t>(
72ea48ce5a6fa8a3224dd270a7f60428084e7b590dZoltan Szabadka      (kNumDistanceShortCodes + num_direct_codes +
73ea48ce5a6fa8a3224dd270a7f60428084e7b590dZoltan Szabadka       ((2 * (nbits - 1) + prefix) << postfix_bits) + postfix));
74b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka  *extra_bits = (nbits << 24) | ((distance_code - offset) >> postfix_bits);
75b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka}
76b4f39bf540c7755909105b6a96c7ac89b79364adZoltan Szabadka
77c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka}  // namespace brotli
78c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka
79c66e4e3e4fc3ba36ca36a43eee3b704f7b989c60Zoltan Szabadka#endif  // BROTLI_ENC_PREFIX_H_
80