Coverage Report

Created: 2026-07-20 07:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libjxl/lib/jxl/quant_weights.cc
Line
Count
Source
1
// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2
//
3
// Use of this source code is governed by a BSD-style
4
// license that can be found in the LICENSE file.
5
#include "lib/jxl/quant_weights.h"
6
7
#include <jxl/memory_manager.h>
8
9
#include <cmath>
10
#include <cstdint>
11
#include <cstdio>
12
#include <cstdlib>
13
#include <vector>
14
15
#include "lib/jxl/ac_strategy.h"
16
#include "lib/jxl/base/compiler_specific.h"
17
#include "lib/jxl/base/status.h"
18
#include "lib/jxl/coeff_order_fwd.h"
19
#include "lib/jxl/dct_scales.h"
20
#include "lib/jxl/dec_bit_reader.h"
21
#include "lib/jxl/dec_modular.h"
22
#include "lib/jxl/fields.h"
23
#include "lib/jxl/frame_dimensions.h"
24
#include "lib/jxl/memory_manager_internal.h"
25
26
#undef HWY_TARGET_INCLUDE
27
#define HWY_TARGET_INCLUDE "lib/jxl/quant_weights.cc"
28
#include <hwy/foreach_target.h>
29
#include <hwy/highway.h>
30
31
#include "lib/jxl/base/fast_math-inl.h"
32
33
HWY_BEFORE_NAMESPACE();
34
namespace jxl {
35
namespace HWY_NAMESPACE {
36
37
// These templates are not found via ADL.
38
using hwy::HWY_NAMESPACE::Lt;
39
using hwy::HWY_NAMESPACE::MulAdd;
40
using hwy::HWY_NAMESPACE::Sqrt;
41
42
// kQuantWeights[N * N * c + N * y + x] is the relative weight of the (x, y)
43
// coefficient in component c. Higher weights correspond to finer quantization
44
// intervals and more bits spent in encoding.
45
46
static constexpr const float kAlmostZero = 1e-8f;
47
48
void GetQuantWeightsDCT2(const QuantEncoding::DCT2Weights& dct2weights,
49
3.16k
                         float* weights) {
50
12.6k
  for (size_t c = 0; c < 3; c++) {
51
9.49k
    size_t start = c * 64;
52
9.49k
    weights[start] = 0xBAD;
53
9.49k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
9.49k
    weights[start + 9] = dct2weights[c][1];
55
28.4k
    for (size_t y = 0; y < 2; y++) {
56
56.9k
      for (size_t x = 0; x < 2; x++) {
57
37.9k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
37.9k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
37.9k
      }
60
18.9k
    }
61
28.4k
    for (size_t y = 0; y < 2; y++) {
62
56.9k
      for (size_t x = 0; x < 2; x++) {
63
37.9k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
37.9k
      }
65
18.9k
    }
66
47.4k
    for (size_t y = 0; y < 4; y++) {
67
189k
      for (size_t x = 0; x < 4; x++) {
68
151k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
151k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
151k
      }
71
37.9k
    }
72
47.4k
    for (size_t y = 0; y < 4; y++) {
73
189k
      for (size_t x = 0; x < 4; x++) {
74
151k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
151k
      }
76
37.9k
    }
77
9.49k
  }
78
3.16k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
jxl::N_AVX2::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
Line
Count
Source
49
3.16k
                         float* weights) {
50
12.6k
  for (size_t c = 0; c < 3; c++) {
51
9.49k
    size_t start = c * 64;
52
9.49k
    weights[start] = 0xBAD;
53
9.49k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
9.49k
    weights[start + 9] = dct2weights[c][1];
55
28.4k
    for (size_t y = 0; y < 2; y++) {
56
56.9k
      for (size_t x = 0; x < 2; x++) {
57
37.9k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
37.9k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
37.9k
      }
60
18.9k
    }
61
28.4k
    for (size_t y = 0; y < 2; y++) {
62
56.9k
      for (size_t x = 0; x < 2; x++) {
63
37.9k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
37.9k
      }
65
18.9k
    }
66
47.4k
    for (size_t y = 0; y < 4; y++) {
67
189k
      for (size_t x = 0; x < 4; x++) {
68
151k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
151k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
151k
      }
71
37.9k
    }
72
47.4k
    for (size_t y = 0; y < 4; y++) {
73
189k
      for (size_t x = 0; x < 4; x++) {
74
151k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
151k
      }
76
37.9k
    }
77
9.49k
  }
78
3.16k
}
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeightsDCT2(std::__1::array<std::__1::array<float, 6ul>, 3ul> const&, float*)
79
80
void GetQuantWeightsIdentity(const QuantEncoding::IdWeights& idweights,
81
3.51k
                             float* weights) {
82
14.0k
  for (size_t c = 0; c < 3; c++) {
83
685k
    for (int i = 0; i < 64; i++) {
84
674k
      weights[64 * c + i] = idweights[c][0];
85
674k
    }
86
10.5k
    weights[64 * c + 1] = idweights[c][1];
87
10.5k
    weights[64 * c + 8] = idweights[c][1];
88
10.5k
    weights[64 * c + 9] = idweights[c][2];
89
10.5k
  }
90
3.51k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
jxl::N_AVX2::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
Line
Count
Source
81
3.51k
                             float* weights) {
82
14.0k
  for (size_t c = 0; c < 3; c++) {
83
685k
    for (int i = 0; i < 64; i++) {
84
674k
      weights[64 * c + i] = idweights[c][0];
85
674k
    }
86
10.5k
    weights[64 * c + 1] = idweights[c][1];
87
10.5k
    weights[64 * c + 8] = idweights[c][1];
88
10.5k
    weights[64 * c + 9] = idweights[c][2];
89
10.5k
  }
90
3.51k
}
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeightsIdentity(std::__1::array<std::__1::array<float, 3ul>, 3ul> const&, float*)
91
92
StatusOr<float> Interpolate(float pos, float max, const float* array,
93
125k
                            size_t len) {
94
125k
  float scaled_pos = pos * (len - 1) / max;
95
125k
  size_t idx = scaled_pos;
96
125k
  JXL_ENSURE(idx + 1 < len);
97
125k
  float a = array[idx];
98
125k
  float b = array[idx + 1];
99
125k
  return a * FastPowf(b / a, scaled_pos - idx);
100
125k
}
Unexecuted instantiation: jxl::N_SSE4::Interpolate(float, float, float const*, unsigned long)
jxl::N_AVX2::Interpolate(float, float, float const*, unsigned long)
Line
Count
Source
93
125k
                            size_t len) {
94
125k
  float scaled_pos = pos * (len - 1) / max;
95
125k
  size_t idx = scaled_pos;
96
125k
  JXL_ENSURE(idx + 1 < len);
97
125k
  float a = array[idx];
98
125k
  float b = array[idx + 1];
99
125k
  return a * FastPowf(b / a, scaled_pos - idx);
100
125k
}
Unexecuted instantiation: jxl::N_SSE2::Interpolate(float, float, float const*, unsigned long)
101
102
663k
float Mult(float v) {
103
663k
  if (v > 0.0f) return 1.0f + v;
104
663k
  return 1.0f / (1.0f - v);
105
663k
}
Unexecuted instantiation: jxl::N_SSE4::Mult(float)
jxl::N_AVX2::Mult(float)
Line
Count
Source
102
663k
float Mult(float v) {
103
663k
  if (v > 0.0f) return 1.0f + v;
104
663k
  return 1.0f / (1.0f - v);
105
663k
}
Unexecuted instantiation: jxl::N_SSE2::Mult(float)
106
107
using DF4 = HWY_CAPPED(float, 4);
108
109
hwy::HWY_NAMESPACE::Vec<DF4> InterpolateVec(
110
18.3M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
18.3M
  HWY_CAPPED(int32_t, 4) di;
112
113
18.3M
  auto idx = ConvertTo(di, scaled_pos);
114
115
18.3M
  auto frac = Sub(scaled_pos, ConvertTo(DF4(), idx));
116
117
  // TODO(veluca): in theory, this could be done with 8 TableLookupBytes, but
118
  // it's probably slower.
119
18.3M
  auto a = GatherIndex(DF4(), array, idx);
120
18.3M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
18.3M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
18.3M
}
Unexecuted instantiation: jxl::N_SSE4::InterpolateVec(hwy::N_SSE4::Vec128<float, 4ul>, float const*)
jxl::N_AVX2::InterpolateVec(hwy::N_AVX2::Vec128<float, 4ul>, float const*)
Line
Count
Source
110
18.3M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
18.3M
  HWY_CAPPED(int32_t, 4) di;
112
113
18.3M
  auto idx = ConvertTo(di, scaled_pos);
114
115
18.3M
  auto frac = Sub(scaled_pos, ConvertTo(DF4(), idx));
116
117
  // TODO(veluca): in theory, this could be done with 8 TableLookupBytes, but
118
  // it's probably slower.
119
18.3M
  auto a = GatherIndex(DF4(), array, idx);
120
18.3M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
18.3M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
18.3M
}
Unexecuted instantiation: jxl::N_SSE2::InterpolateVec(hwy::N_SSE2::Vec128<float, 4ul>, float const*)
124
125
// Computes quant weights for a COLS*ROWS-sized transform, using num_bands
126
// eccentricity bands and num_ebands eccentricity bands. If print_mode is 1,
127
// prints the resulting matrix; if print_mode is 2, prints the matrix in a
128
// format suitable for a 3d plot with gnuplot.
129
Status GetQuantWeights(
130
    size_t ROWS, size_t COLS,
131
    const DctQuantWeightParams::DistanceBandsArray& distance_bands,
132
40.2k
    size_t num_bands, float* out) {
133
160k
  for (size_t c = 0; c < 3; c++) {
134
120k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
120k
        distance_bands[c][0]};
136
120k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
752k
    for (size_t i = 1; i < num_bands; i++) {
138
632k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
632k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
632k
    }
141
120k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
120k
    float rcpcol = scale / (COLS - 1);
143
120k
    float rcprow = scale / (ROWS - 1);
144
120k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
120k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.95M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.83M
      float dy = y * rcprow;
148
1.83M
      float dy2 = dy * dy;
149
20.1M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
18.3M
        auto dx =
151
18.3M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
18.3M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
18.3M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
18.3M
                                     : InterpolateVec(scaled_distance, bands);
155
18.3M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
18.3M
      }
157
1.83M
    }
158
120k
  }
159
40.2k
  return true;
160
40.2k
}
Unexecuted instantiation: jxl::N_SSE4::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
jxl::N_AVX2::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
Line
Count
Source
132
40.2k
    size_t num_bands, float* out) {
133
160k
  for (size_t c = 0; c < 3; c++) {
134
120k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
120k
        distance_bands[c][0]};
136
120k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
752k
    for (size_t i = 1; i < num_bands; i++) {
138
632k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
632k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
632k
    }
141
120k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
120k
    float rcpcol = scale / (COLS - 1);
143
120k
    float rcprow = scale / (ROWS - 1);
144
120k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
120k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.95M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.83M
      float dy = y * rcprow;
148
1.83M
      float dy2 = dy * dy;
149
20.1M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
18.3M
        auto dx =
151
18.3M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
18.3M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
18.3M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
18.3M
                                     : InterpolateVec(scaled_distance, bands);
155
18.3M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
18.3M
      }
157
1.83M
    }
158
120k
  }
159
40.2k
  return true;
160
40.2k
}
Unexecuted instantiation: jxl::N_SSE2::GetQuantWeights(unsigned long, unsigned long, std::__1::array<std::__1::array<float, 17ul>, 3ul> const&, unsigned long, float*)
161
162
// TODO(veluca): SIMD-fy. With 256x256, this is actually slow.
163
Status ComputeQuantTable(const QuantEncoding& encoding,
164
                         float* JXL_RESTRICT table,
165
                         float* JXL_RESTRICT inv_table, size_t table_num,
166
43.4k
                         QuantTable kind, size_t* pos) {
167
43.4k
  constexpr size_t N = kBlockDim;
168
43.4k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
43.4k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
43.4k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
43.4k
  size_t num = wrows * wcols;
172
173
43.4k
  std::vector<float> weights(3 * num);
174
175
43.4k
  switch (encoding.mode) {
176
0
    case QuantEncoding::kQuantModeLibrary: {
177
      // Library and copy quant encoding should get replaced by the actual
178
      // parameters by the caller.
179
0
      JXL_ENSURE(false);
180
0
      break;
181
0
    }
182
3.51k
    case QuantEncoding::kQuantModeID: {
183
3.51k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.51k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.51k
      break;
186
3.51k
    }
187
3.16k
    case QuantEncoding::kQuantModeDCT2: {
188
3.16k
      JXL_ENSURE(num == kDCTBlockSize);
189
3.16k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
3.16k
      break;
191
3.16k
    }
192
2.98k
    case QuantEncoding::kQuantModeDCT4: {
193
2.98k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.98k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.98k
      JXL_RETURN_IF_ERROR(
197
2.98k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.98k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.9k
      for (size_t c = 0; c < 3; c++) {
200
80.4k
        for (size_t y = 0; y < kBlockDim; y++) {
201
643k
          for (size_t x = 0; x < kBlockDim; x++) {
202
571k
            weights[c * num + y * kBlockDim + x] =
203
571k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
571k
          }
205
71.4k
        }
206
8.93k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.93k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.93k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.93k
      }
210
2.97k
      break;
211
2.98k
    }
212
2.90k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.90k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.90k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.90k
      JXL_RETURN_IF_ERROR(
217
2.90k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.90k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.6k
      for (size_t c = 0; c < 3; c++) {
220
78.3k
        for (size_t y = 0; y < kBlockDim; y++) {
221
626k
          for (size_t x = 0; x < kBlockDim; x++) {
222
556k
            weights[c * num + y * kBlockDim + x] =
223
556k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
556k
          }
225
69.6k
        }
226
8.70k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.70k
      }
228
2.90k
      break;
229
2.90k
    }
230
27.3k
    case QuantEncoding::kQuantModeDCT: {
231
27.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
27.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
27.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
27.3k
      break;
235
27.3k
    }
236
27.3k
    case QuantEncoding::kQuantModeRAW: {
237
1
      if (!encoding.qraw.qtable || encoding.qraw.qtable->size() != 3 * num) {
238
0
        return JXL_FAILURE("Invalid table encoding");
239
0
      }
240
1
      int* qtable = encoding.qraw.qtable->data();
241
193
      for (size_t i = 0; i < 3 * num; i++) {
242
192
        weights[i] = 1.f / (encoding.qraw.qtable_den * qtable[i]);
243
192
      }
244
1
      break;
245
1
    }
246
3.49k
    case QuantEncoding::kQuantModeAFV: {
247
3.49k
      constexpr float kFreqs[] = {
248
3.49k
          0xBAD,
249
3.49k
          0xBAD,
250
3.49k
          0.8517778890324296,
251
3.49k
          5.37778436506804,
252
3.49k
          0xBAD,
253
3.49k
          0xBAD,
254
3.49k
          4.734747904497923,
255
3.49k
          5.449245381693219,
256
3.49k
          1.6598270267479331,
257
3.49k
          4,
258
3.49k
          7.275749096817861,
259
3.49k
          10.423227632456525,
260
3.49k
          2.662932286148962,
261
3.49k
          7.630657783650829,
262
3.49k
          8.962388608184032,
263
3.49k
          12.97166202570235,
264
3.49k
      };
265
266
3.49k
      float weights4x8[3 * 4 * 8];
267
3.49k
      JXL_RETURN_IF_ERROR((
268
3.49k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.49k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.49k
      float weights4x4[3 * 4 * 4];
271
3.49k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.49k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.49k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.49k
      constexpr float lo = 0.8517778890324296;
276
3.49k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
13.9k
      for (size_t c = 0; c < 3; c++) {
278
10.4k
        float bands[4];
279
10.4k
        bands[0] = encoding.afv_weights[c][5];
280
10.4k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
41.8k
        for (size_t i = 1; i < 4; i++) {
282
31.4k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
31.4k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
31.4k
        }
285
10.4k
        size_t start = c * 64;
286
177k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
177k
          weights[start + y * 8 + x] = val;
288
177k
        };
Unexecuted instantiation: quant_weights.cc:jxl::N_SSE4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
quant_weights.cc:jxl::N_AVX2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
Line
Count
Source
286
177k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
177k
          weights[start + y * 8 + x] = val;
288
177k
        };
Unexecuted instantiation: quant_weights.cc:jxl::N_SSE2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)::$_0::operator()(unsigned long, unsigned long, float) const
289
10.4k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
10.4k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
10.4k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
10.4k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
10.4k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
10.4k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
52.3k
        for (size_t y = 0; y < 4; y++) {
300
209k
          for (size_t x = 0; x < 4; x++) {
301
167k
            if (x < 2 && y < 2) continue;
302
251k
            JXL_ASSIGN_OR_RETURN(
303
251k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
251k
            set_weight(2 * x, 2 * y, val);
305
251k
          }
306
41.8k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
52.3k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
376k
          for (size_t x = 0; x < kBlockDim; x++) {
311
334k
            if (x == 0 && y == 0) continue;
312
324k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
324k
                weights4x8[c * 32 + y * 8 + x];
314
324k
          }
315
41.8k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
52.3k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
209k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
167k
            if (x == 0 && y == 0) continue;
320
157k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
157k
                weights4x4[c * 16 + y * 4 + x];
322
157k
          }
323
41.8k
        }
324
10.4k
      }
325
3.48k
      break;
326
3.49k
    }
327
43.4k
  }
328
43.4k
  size_t prev_pos = *pos;
329
43.4k
  HWY_CAPPED(float, 64) d;
330
9.48M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
9.44M
    auto inv_val = LoadU(d, weights.data() + i);
332
9.44M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
9.44M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
12
      return JXL_FAILURE("Invalid quantization table");
335
12
    }
336
9.44M
    auto val = Div(Set(d, 1.0f), inv_val);
337
9.44M
    StoreU(val, d, table + *pos + i);
338
9.44M
    StoreU(inv_val, d, inv_table + *pos + i);
339
9.44M
  }
340
43.4k
  (*pos) += 3 * num;
341
342
  // Ensure that the lowest frequencies have a 0 inverse table.
343
  // This does not affect en/decoding, but allows AC strategy selection to be
344
  // slightly simpler.
345
43.4k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
43.4k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
43.4k
  CoefficientLayout(&ys, &xs);
348
173k
  for (size_t c = 0; c < 3; c++) {
349
387k
    for (size_t y = 0; y < ys; y++) {
350
1.43M
      for (size_t x = 0; x < xs; x++) {
351
1.18M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.18M
                  x] = 0;
353
1.18M
      }
354
257k
    }
355
130k
  }
356
43.4k
  return true;
357
43.4k
}
Unexecuted instantiation: jxl::N_SSE4::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
jxl::N_AVX2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
Line
Count
Source
166
43.4k
                         QuantTable kind, size_t* pos) {
167
43.4k
  constexpr size_t N = kBlockDim;
168
43.4k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
43.4k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
43.4k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
43.4k
  size_t num = wrows * wcols;
172
173
43.4k
  std::vector<float> weights(3 * num);
174
175
43.4k
  switch (encoding.mode) {
176
0
    case QuantEncoding::kQuantModeLibrary: {
177
      // Library and copy quant encoding should get replaced by the actual
178
      // parameters by the caller.
179
0
      JXL_ENSURE(false);
180
0
      break;
181
0
    }
182
3.51k
    case QuantEncoding::kQuantModeID: {
183
3.51k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.51k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.51k
      break;
186
3.51k
    }
187
3.16k
    case QuantEncoding::kQuantModeDCT2: {
188
3.16k
      JXL_ENSURE(num == kDCTBlockSize);
189
3.16k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
3.16k
      break;
191
3.16k
    }
192
2.98k
    case QuantEncoding::kQuantModeDCT4: {
193
2.98k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.98k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.98k
      JXL_RETURN_IF_ERROR(
197
2.98k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.98k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.9k
      for (size_t c = 0; c < 3; c++) {
200
80.4k
        for (size_t y = 0; y < kBlockDim; y++) {
201
643k
          for (size_t x = 0; x < kBlockDim; x++) {
202
571k
            weights[c * num + y * kBlockDim + x] =
203
571k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
571k
          }
205
71.4k
        }
206
8.93k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.93k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.93k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.93k
      }
210
2.97k
      break;
211
2.98k
    }
212
2.90k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.90k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.90k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.90k
      JXL_RETURN_IF_ERROR(
217
2.90k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.90k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.6k
      for (size_t c = 0; c < 3; c++) {
220
78.3k
        for (size_t y = 0; y < kBlockDim; y++) {
221
626k
          for (size_t x = 0; x < kBlockDim; x++) {
222
556k
            weights[c * num + y * kBlockDim + x] =
223
556k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
556k
          }
225
69.6k
        }
226
8.70k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.70k
      }
228
2.90k
      break;
229
2.90k
    }
230
27.3k
    case QuantEncoding::kQuantModeDCT: {
231
27.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
27.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
27.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
27.3k
      break;
235
27.3k
    }
236
27.3k
    case QuantEncoding::kQuantModeRAW: {
237
1
      if (!encoding.qraw.qtable || encoding.qraw.qtable->size() != 3 * num) {
238
0
        return JXL_FAILURE("Invalid table encoding");
239
0
      }
240
1
      int* qtable = encoding.qraw.qtable->data();
241
193
      for (size_t i = 0; i < 3 * num; i++) {
242
192
        weights[i] = 1.f / (encoding.qraw.qtable_den * qtable[i]);
243
192
      }
244
1
      break;
245
1
    }
246
3.49k
    case QuantEncoding::kQuantModeAFV: {
247
3.49k
      constexpr float kFreqs[] = {
248
3.49k
          0xBAD,
249
3.49k
          0xBAD,
250
3.49k
          0.8517778890324296,
251
3.49k
          5.37778436506804,
252
3.49k
          0xBAD,
253
3.49k
          0xBAD,
254
3.49k
          4.734747904497923,
255
3.49k
          5.449245381693219,
256
3.49k
          1.6598270267479331,
257
3.49k
          4,
258
3.49k
          7.275749096817861,
259
3.49k
          10.423227632456525,
260
3.49k
          2.662932286148962,
261
3.49k
          7.630657783650829,
262
3.49k
          8.962388608184032,
263
3.49k
          12.97166202570235,
264
3.49k
      };
265
266
3.49k
      float weights4x8[3 * 4 * 8];
267
3.49k
      JXL_RETURN_IF_ERROR((
268
3.49k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.49k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.49k
      float weights4x4[3 * 4 * 4];
271
3.49k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.49k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.49k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.49k
      constexpr float lo = 0.8517778890324296;
276
3.49k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
13.9k
      for (size_t c = 0; c < 3; c++) {
278
10.4k
        float bands[4];
279
10.4k
        bands[0] = encoding.afv_weights[c][5];
280
10.4k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
41.8k
        for (size_t i = 1; i < 4; i++) {
282
31.4k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
31.4k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
31.4k
        }
285
10.4k
        size_t start = c * 64;
286
10.4k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
10.4k
          weights[start + y * 8 + x] = val;
288
10.4k
        };
289
10.4k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
10.4k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
10.4k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
10.4k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
10.4k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
10.4k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
52.3k
        for (size_t y = 0; y < 4; y++) {
300
209k
          for (size_t x = 0; x < 4; x++) {
301
167k
            if (x < 2 && y < 2) continue;
302
251k
            JXL_ASSIGN_OR_RETURN(
303
251k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
251k
            set_weight(2 * x, 2 * y, val);
305
251k
          }
306
41.8k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
52.3k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
376k
          for (size_t x = 0; x < kBlockDim; x++) {
311
334k
            if (x == 0 && y == 0) continue;
312
324k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
324k
                weights4x8[c * 32 + y * 8 + x];
314
324k
          }
315
41.8k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
52.3k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
209k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
167k
            if (x == 0 && y == 0) continue;
320
157k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
157k
                weights4x4[c * 16 + y * 4 + x];
322
157k
          }
323
41.8k
        }
324
10.4k
      }
325
3.48k
      break;
326
3.49k
    }
327
43.4k
  }
328
43.4k
  size_t prev_pos = *pos;
329
43.4k
  HWY_CAPPED(float, 64) d;
330
9.48M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
9.44M
    auto inv_val = LoadU(d, weights.data() + i);
332
9.44M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
9.44M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
12
      return JXL_FAILURE("Invalid quantization table");
335
12
    }
336
9.44M
    auto val = Div(Set(d, 1.0f), inv_val);
337
9.44M
    StoreU(val, d, table + *pos + i);
338
9.44M
    StoreU(inv_val, d, inv_table + *pos + i);
339
9.44M
  }
340
43.4k
  (*pos) += 3 * num;
341
342
  // Ensure that the lowest frequencies have a 0 inverse table.
343
  // This does not affect en/decoding, but allows AC strategy selection to be
344
  // slightly simpler.
345
43.4k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
43.4k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
43.4k
  CoefficientLayout(&ys, &xs);
348
173k
  for (size_t c = 0; c < 3; c++) {
349
387k
    for (size_t y = 0; y < ys; y++) {
350
1.43M
      for (size_t x = 0; x < xs; x++) {
351
1.18M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.18M
                  x] = 0;
353
1.18M
      }
354
257k
    }
355
130k
  }
356
43.4k
  return true;
357
43.4k
}
Unexecuted instantiation: jxl::N_SSE2::ComputeQuantTable(jxl::QuantEncoding const&, float*, float*, unsigned long, jxl::QuantTable, unsigned long*)
358
359
// NOLINTNEXTLINE(google-readability-namespace-comments)
360
}  // namespace HWY_NAMESPACE
361
}  // namespace jxl
362
HWY_AFTER_NAMESPACE();
363
364
#if HWY_ONCE
365
366
namespace jxl {
367
namespace {
368
369
HWY_EXPORT(ComputeQuantTable);
370
371
constexpr const float kAlmostZero = 1e-8f;
372
373
108
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
374
108
  params->num_distance_bands =
375
108
      br->ReadFixedBits<DctQuantWeightParams::kLog2MaxDistanceBands>() + 1;
376
356
  for (size_t c = 0; c < 3; c++) {
377
1.38k
    for (size_t i = 0; i < params->num_distance_bands; i++) {
378
1.10k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &params->distance_bands[c][i]));
379
1.10k
    }
380
278
    if (params->distance_bands[c][0] < kAlmostZero) {
381
30
      return JXL_FAILURE("Distance band seed is too small");
382
30
    }
383
248
    params->distance_bands[c][0] *= 64.0f;
384
248
  }
385
75
  return true;
386
108
}
387
388
Status Decode(JxlMemoryManager* memory_manager, BitReader* br,
389
              QuantEncoding* encoding, size_t required_size_x,
390
              size_t required_size_y, size_t idx,
391
5.10k
              ModularFrameDecoder* modular_frame_decoder) {
392
5.10k
  size_t required_size = required_size_x * required_size_y;
393
5.10k
  required_size_x *= kBlockDim;
394
5.10k
  required_size_y *= kBlockDim;
395
5.10k
  int mode = br->ReadFixedBits<kLog2NumQuantModes>();
396
5.10k
  switch (mode) {
397
4.78k
    case QuantEncoding::kQuantModeLibrary: {
398
4.78k
      encoding->predefined = br->ReadFixedBits<kCeilLog2NumPredefinedTables>();
399
4.78k
      if (encoding->predefined >= kNumPredefinedTables) {
400
0
        return JXL_FAILURE("Invalid predefined table");
401
0
      }
402
4.78k
      break;
403
4.78k
    }
404
4.78k
    case QuantEncoding::kQuantModeID: {
405
47
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
406
137
      for (size_t c = 0; c < 3; c++) {
407
410
        for (size_t i = 0; i < 3; i++) {
408
318
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->idweights[c][i]));
409
309
          if (std::abs(encoding->idweights[c][i]) < kAlmostZero) {
410
12
            return JXL_FAILURE("ID Quantizer is too small");
411
12
          }
412
297
          encoding->idweights[c][i] *= 64;
413
297
        }
414
113
      }
415
24
      break;
416
45
    }
417
63
    case QuantEncoding::kQuantModeDCT2: {
418
63
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
419
136
      for (size_t c = 0; c < 3; c++) {
420
691
        for (size_t i = 0; i < 6; i++) {
421
615
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->dct2weights[c][i]));
422
592
          if (std::abs(encoding->dct2weights[c][i]) < kAlmostZero) {
423
24
            return JXL_FAILURE("Quantizer is too small");
424
24
          }
425
568
          encoding->dct2weights[c][i] *= 64;
426
568
        }
427
123
      }
428
13
      break;
429
60
    }
430
39
    case QuantEncoding::kQuantModeDCT4X8: {
431
39
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
432
126
      for (size_t c = 0; c < 3; c++) {
433
100
        JXL_RETURN_IF_ERROR(
434
100
            F16Coder::Read(br, &encoding->dct4x8multipliers[c]));
435
92
        if (std::abs(encoding->dct4x8multipliers[c]) < kAlmostZero) {
436
3
          return JXL_FAILURE("DCT4X8 multiplier is too small");
437
3
        }
438
92
      }
439
26
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
440
21
      break;
441
26
    }
442
29
    case QuantEncoding::kQuantModeDCT4: {
443
29
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
444
81
      for (size_t c = 0; c < 3; c++) {
445
183
        for (size_t i = 0; i < 2; i++) {
446
130
          JXL_RETURN_IF_ERROR(
447
130
              F16Coder::Read(br, &encoding->dct4multipliers[c][i]));
448
123
          if (std::abs(encoding->dct4multipliers[c][i]) < kAlmostZero) {
449
9
            return JXL_FAILURE("DCT4 multiplier is too small");
450
9
          }
451
123
        }
452
69
      }
453
12
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
454
9
      break;
455
12
    }
456
51
    case QuantEncoding::kQuantModeAFV: {
457
51
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
458
138
      for (size_t c = 0; c < 3; c++) {
459
1.02k
        for (size_t i = 0; i < 9; i++) {
460
941
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->afv_weights[c][i]));
461
941
        }
462
616
        for (size_t i = 0; i < 6; i++) {
463
528
          encoding->afv_weights[c][i] *= 64;
464
528
        }
465
88
      }
466
20
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
467
11
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params_afv_4x4));
468
10
      break;
469
11
    }
470
39
    case QuantEncoding::kQuantModeDCT: {
471
39
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
472
24
      break;
473
39
    }
474
45
    case QuantEncoding::kQuantModeRAW: {
475
      // Set mode early, to avoid mem-leak.
476
45
      encoding->mode = QuantEncoding::kQuantModeRAW;
477
45
      JXL_RETURN_IF_ERROR(ModularFrameDecoder::DecodeQuantTable(
478
45
          memory_manager, required_size_x, required_size_y, br, encoding, idx,
479
45
          modular_frame_decoder));
480
14
      break;
481
45
    }
482
14
    default:
483
0
      return JXL_FAILURE("Invalid quantization table encoding");
484
5.10k
  }
485
4.90k
  encoding->mode = static_cast<QuantEncoding::Mode>(mode);
486
4.90k
  return true;
487
5.10k
}
488
489
}  // namespace
490
491
#if JXL_CXX_LANG < JXL_CXX_17
492
constexpr const std::array<int, 17> DequantMatrices::required_size_x;
493
constexpr const std::array<int, 17> DequantMatrices::required_size_y;
494
constexpr const size_t DequantMatrices::kSumRequiredXy;
495
#endif
496
497
Status DequantMatrices::Decode(JxlMemoryManager* memory_manager, BitReader* br,
498
4.67k
                               ModularFrameDecoder* modular_frame_decoder) {
499
4.67k
  size_t all_default = br->ReadBits(1);
500
4.67k
  size_t num_tables = all_default ? 0 : static_cast<size_t>(kNumQuantTables);
501
4.67k
  encodings_.clear();
502
4.67k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
503
9.57k
  for (size_t i = 0; i < num_tables; i++) {
504
5.10k
    JXL_RETURN_IF_ERROR(jxl::Decode(memory_manager, br, &encodings_[i],
505
5.10k
                                    required_size_x[i % kNumQuantTables],
506
5.10k
                                    required_size_y[i % kNumQuantTables], i,
507
5.10k
                                    modular_frame_decoder));
508
5.10k
  }
509
4.47k
  computed_mask_ = 0;
510
4.47k
  return true;
511
4.67k
}
512
513
40.8k
Status DequantMatrices::DecodeDC(BitReader* br) {
514
40.8k
  bool all_default = static_cast<bool>(br->ReadBits(1));
515
40.8k
  if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
516
40.5k
  if (!all_default) {
517
22.0k
    for (size_t c = 0; c < 3; c++) {
518
16.5k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &dc_quant_[c]));
519
16.5k
      dc_quant_[c] *= 1.0f / 128.0f;
520
      // Negative values and nearly zero are invalid values.
521
16.5k
      if (dc_quant_[c] < kAlmostZero) {
522
55
        return JXL_FAILURE("Invalid dc_quant: coefficient is too small.");
523
55
      }
524
16.5k
      inv_dc_quant_[c] = 1.0f / dc_quant_[c];
525
16.5k
    }
526
5.55k
  }
527
40.5k
  return true;
528
40.5k
}
529
530
0
constexpr float V(float v) { return static_cast<float>(v); }
531
532
namespace {
533
struct DequantMatricesLibraryDef {
534
  // DCT8
535
2
  static constexpr QuantEncodingInternal DCT() {
536
2
    return QuantEncodingInternal::DCT(DctQuantWeightParams({{{{
537
2
                                                                 V(3150.0),
538
2
                                                                 V(0.0),
539
2
                                                                 V(-0.4),
540
2
                                                                 V(-0.4),
541
2
                                                                 V(-0.4),
542
2
                                                                 V(-2.0),
543
2
                                                             }},
544
2
                                                             {{
545
2
                                                                 V(560.0),
546
2
                                                                 V(0.0),
547
2
                                                                 V(-0.3),
548
2
                                                                 V(-0.3),
549
2
                                                                 V(-0.3),
550
2
                                                                 V(-0.3),
551
2
                                                             }},
552
2
                                                             {{
553
2
                                                                 V(512.0),
554
2
                                                                 V(-2.0),
555
2
                                                                 V(-1.0),
556
2
                                                                 V(0.0),
557
2
                                                                 V(-1.0),
558
2
                                                                 V(-2.0),
559
2
                                                             }}}},
560
2
                                                           6));
561
2
  }
562
563
  // Identity
564
2
  static constexpr QuantEncodingInternal IDENTITY() {
565
2
    return QuantEncodingInternal::Identity({{{{
566
2
                                                 V(280.0),
567
2
                                                 V(3160.0),
568
2
                                                 V(3160.0),
569
2
                                             }},
570
2
                                             {{
571
2
                                                 V(60.0),
572
2
                                                 V(864.0),
573
2
                                                 V(864.0),
574
2
                                             }},
575
2
                                             {{
576
2
                                                 V(18.0),
577
2
                                                 V(200.0),
578
2
                                                 V(200.0),
579
2
                                             }}}});
580
2
  }
581
582
  // DCT2
583
2
  static constexpr QuantEncodingInternal DCT2X2() {
584
2
    return QuantEncodingInternal::DCT2({{{{
585
2
                                             V(3840.0),
586
2
                                             V(2560.0),
587
2
                                             V(1280.0),
588
2
                                             V(640.0),
589
2
                                             V(480.0),
590
2
                                             V(300.0),
591
2
                                         }},
592
2
                                         {{
593
2
                                             V(960.0),
594
2
                                             V(640.0),
595
2
                                             V(320.0),
596
2
                                             V(180.0),
597
2
                                             V(140.0),
598
2
                                             V(120.0),
599
2
                                         }},
600
2
                                         {{
601
2
                                             V(640.0),
602
2
                                             V(320.0),
603
2
                                             V(128.0),
604
2
                                             V(64.0),
605
2
                                             V(32.0),
606
2
                                             V(16.0),
607
2
                                         }}}});
608
2
  }
609
610
  // DCT4 (quant_kind 3)
611
4
  static constexpr QuantEncodingInternal DCT4X4() {
612
4
    return QuantEncodingInternal::DCT4(DctQuantWeightParams({{{{
613
4
                                                                  V(2200.0),
614
4
                                                                  V(0.0),
615
4
                                                                  V(0.0),
616
4
                                                                  V(0.0),
617
4
                                                              }},
618
4
                                                              {{
619
4
                                                                  V(392.0),
620
4
                                                                  V(0.0),
621
4
                                                                  V(0.0),
622
4
                                                                  V(0.0),
623
4
                                                              }},
624
4
                                                              {{
625
4
                                                                  V(112.0),
626
4
                                                                  V(-0.25),
627
4
                                                                  V(-0.25),
628
4
                                                                  V(-0.5),
629
4
                                                              }}}},
630
4
                                                            4),
631
                                       /* kMul */
632
4
                                       {{{{
633
4
                                             V(1.0),
634
4
                                             V(1.0),
635
4
                                         }},
636
4
                                         {{
637
4
                                             V(1.0),
638
4
                                             V(1.0),
639
4
                                         }},
640
4
                                         {{
641
4
                                             V(1.0),
642
4
                                             V(1.0),
643
4
                                         }}}});
644
4
  }
645
646
  // DCT16
647
2
  static constexpr QuantEncodingInternal DCT16X16() {
648
2
    return QuantEncodingInternal::DCT(
649
2
        DctQuantWeightParams({{{{
650
2
                                   V(8996.8725711814115328),
651
2
                                   V(-1.3000777393353804),
652
2
                                   V(-0.49424529824571225),
653
2
                                   V(-0.439093774457103443),
654
2
                                   V(-0.6350101832695744),
655
2
                                   V(-0.90177264050827612),
656
2
                                   V(-1.6162099239887414),
657
2
                               }},
658
2
                               {{
659
2
                                   V(3191.48366296844234752),
660
2
                                   V(-0.67424582104194355),
661
2
                                   V(-0.80745813428471001),
662
2
                                   V(-0.44925837484843441),
663
2
                                   V(-0.35865440981033403),
664
2
                                   V(-0.31322389111877305),
665
2
                                   V(-0.37615025315725483),
666
2
                               }},
667
2
                               {{
668
2
                                   V(1157.50408145487200256),
669
2
                                   V(-2.0531423165804414),
670
2
                                   V(-1.4),
671
2
                                   V(-0.50687130033378396),
672
2
                                   V(-0.42708730624733904),
673
2
                                   V(-1.4856834539296244),
674
2
                                   V(-4.9209142884401604),
675
2
                               }}}},
676
2
                             7));
677
2
  }
678
679
  // DCT32
680
2
  static constexpr QuantEncodingInternal DCT32X32() {
681
2
    return QuantEncodingInternal::DCT(
682
2
        DctQuantWeightParams({{{{
683
2
                                   V(15718.40830982518931456),
684
2
                                   V(-1.025),
685
2
                                   V(-0.98),
686
2
                                   V(-0.9012),
687
2
                                   V(-0.4),
688
2
                                   V(-0.48819395464),
689
2
                                   V(-0.421064),
690
2
                                   V(-0.27),
691
2
                               }},
692
2
                               {{
693
2
                                   V(7305.7636810695983104),
694
2
                                   V(-0.8041958212306401),
695
2
                                   V(-0.7633036457487539),
696
2
                                   V(-0.55660379990111464),
697
2
                                   V(-0.49785304658857626),
698
2
                                   V(-0.43699592683512467),
699
2
                                   V(-0.40180866526242109),
700
2
                                   V(-0.27321683125358037),
701
2
                               }},
702
2
                               {{
703
2
                                   V(3803.53173721215041536),
704
2
                                   V(-3.060733579805728),
705
2
                                   V(-2.0413270132490346),
706
2
                                   V(-2.0235650159727417),
707
2
                                   V(-0.5495389509954993),
708
2
                                   V(-0.4),
709
2
                                   V(-0.4),
710
2
                                   V(-0.3),
711
2
                               }}}},
712
2
                             8));
713
2
  }
714
715
  // DCT16X8
716
2
  static constexpr QuantEncodingInternal DCT8X16() {
717
2
    return QuantEncodingInternal::DCT(
718
2
        DctQuantWeightParams({{{{
719
2
                                   V(7240.7734393502),
720
2
                                   V(-0.7),
721
2
                                   V(-0.7),
722
2
                                   V(-0.2),
723
2
                                   V(-0.2),
724
2
                                   V(-0.2),
725
2
                                   V(-0.5),
726
2
                               }},
727
2
                               {{
728
2
                                   V(1448.15468787004),
729
2
                                   V(-0.5),
730
2
                                   V(-0.5),
731
2
                                   V(-0.5),
732
2
                                   V(-0.2),
733
2
                                   V(-0.2),
734
2
                                   V(-0.2),
735
2
                               }},
736
2
                               {{
737
2
                                   V(506.854140754517),
738
2
                                   V(-1.4),
739
2
                                   V(-0.2),
740
2
                                   V(-0.5),
741
2
                                   V(-0.5),
742
2
                                   V(-1.5),
743
2
                                   V(-3.6),
744
2
                               }}}},
745
2
                             7));
746
2
  }
747
748
  // DCT32X8
749
2
  static constexpr QuantEncodingInternal DCT8X32() {
750
2
    return QuantEncodingInternal::DCT(
751
2
        DctQuantWeightParams({{{{
752
2
                                   V(16283.2494710648897),
753
2
                                   V(-1.7812845336559429),
754
2
                                   V(-1.6309059012653515),
755
2
                                   V(-1.0382179034313539),
756
2
                                   V(-0.85),
757
2
                                   V(-0.7),
758
2
                                   V(-0.9),
759
2
                                   V(-1.2360638576849587),
760
2
                               }},
761
2
                               {{
762
2
                                   V(5089.15750884921511936),
763
2
                                   V(-0.320049391452786891),
764
2
                                   V(-0.35362849922161446),
765
2
                                   V(-0.30340000000000003),
766
2
                                   V(-0.61),
767
2
                                   V(-0.5),
768
2
                                   V(-0.5),
769
2
                                   V(-0.6),
770
2
                               }},
771
2
                               {{
772
2
                                   V(3397.77603275308720128),
773
2
                                   V(-0.321327362693153371),
774
2
                                   V(-0.34507619223117997),
775
2
                                   V(-0.70340000000000003),
776
2
                                   V(-0.9),
777
2
                                   V(-1.0),
778
2
                                   V(-1.0),
779
2
                                   V(-1.1754605576265209),
780
2
                               }}}},
781
2
                             8));
782
2
  }
783
784
  // DCT32X16
785
2
  static constexpr QuantEncodingInternal DCT16X32() {
786
2
    return QuantEncodingInternal::DCT(
787
2
        DctQuantWeightParams({{{{
788
2
                                   V(13844.97076442300573),
789
2
                                   V(-0.97113799999999995),
790
2
                                   V(-0.658),
791
2
                                   V(-0.42026),
792
2
                                   V(-0.22712),
793
2
                                   V(-0.2206),
794
2
                                   V(-0.226),
795
2
                                   V(-0.6),
796
2
                               }},
797
2
                               {{
798
2
                                   V(4798.964084220744293),
799
2
                                   V(-0.61125308982767057),
800
2
                                   V(-0.83770786552491361),
801
2
                                   V(-0.79014862079498627),
802
2
                                   V(-0.2692727459704829),
803
2
                                   V(-0.38272769465388551),
804
2
                                   V(-0.22924222653091453),
805
2
                                   V(-0.20719098826199578),
806
2
                               }},
807
2
                               {{
808
2
                                   V(1807.236946760964614),
809
2
                                   V(-1.2),
810
2
                                   V(-1.2),
811
2
                                   V(-0.7),
812
2
                                   V(-0.7),
813
2
                                   V(-0.7),
814
2
                                   V(-0.4),
815
2
                                   V(-0.5),
816
2
                               }}}},
817
2
                             8));
818
2
  }
819
820
  // DCT4X8 and 8x4
821
4
  static constexpr QuantEncodingInternal DCT4X8() {
822
4
    return QuantEncodingInternal::DCT4X8(
823
4
        DctQuantWeightParams({{
824
4
                                 {{
825
4
                                     V(2198.050556016380522),
826
4
                                     V(-0.96269623020744692),
827
4
                                     V(-0.76194253026666783),
828
4
                                     V(-0.6551140670773547),
829
4
                                 }},
830
4
                                 {{
831
4
                                     V(764.3655248643528689),
832
4
                                     V(-0.92630200888366945),
833
4
                                     V(-0.9675229603596517),
834
4
                                     V(-0.27845290869168118),
835
4
                                 }},
836
4
                                 {{
837
4
                                     V(527.107573587542228),
838
4
                                     V(-1.4594385811273854),
839
4
                                     V(-1.450082094097871593),
840
4
                                     V(-1.5843722511996204),
841
4
                                 }},
842
4
                             }},
843
4
                             4),
844
        /* kMuls */
845
4
        {{
846
4
            V(1.0),
847
4
            V(1.0),
848
4
            V(1.0),
849
4
        }});
850
4
  }
851
  // AFV
852
2
  static QuantEncodingInternal AFV0() {
853
2
    return QuantEncodingInternal::AFV(DCT4X8().dct_params, DCT4X4().dct_params,
854
2
                                      {{{{
855
                                            // 4x4/4x8 DC tendency.
856
2
                                            V(3072.0),
857
2
                                            V(3072.0),
858
                                            // AFV corner.
859
2
                                            V(256.0),
860
2
                                            V(256.0),
861
2
                                            V(256.0),
862
                                            // AFV high freqs.
863
2
                                            V(414.0),
864
2
                                            V(0.0),
865
2
                                            V(0.0),
866
2
                                            V(0.0),
867
2
                                        }},
868
2
                                        {{
869
                                            // 4x4/4x8 DC tendency.
870
2
                                            V(1024.0),
871
2
                                            V(1024.0),
872
                                            // AFV corner.
873
2
                                            V(50),
874
2
                                            V(50),
875
2
                                            V(50),
876
                                            // AFV high freqs.
877
2
                                            V(58.0),
878
2
                                            V(0.0),
879
2
                                            V(0.0),
880
2
                                            V(0.0),
881
2
                                        }},
882
2
                                        {{
883
                                            // 4x4/4x8 DC tendency.
884
2
                                            V(384.0),
885
2
                                            V(384.0),
886
                                            // AFV corner.
887
2
                                            V(12.0),
888
2
                                            V(12.0),
889
2
                                            V(12.0),
890
                                            // AFV high freqs.
891
2
                                            V(22.0),
892
2
                                            V(-0.25),
893
2
                                            V(-0.25),
894
2
                                            V(-0.25),
895
2
                                        }}}});
896
2
  }
897
898
  // DCT64
899
2
  static QuantEncodingInternal DCT64X64() {
900
2
    return QuantEncodingInternal::DCT(
901
2
        DctQuantWeightParams({{{{
902
2
                                   V(0.9 * 26629.073922049845),
903
2
                                   V(-1.025),
904
2
                                   V(-0.78),
905
2
                                   V(-0.65012),
906
2
                                   V(-0.19041574084286472),
907
2
                                   V(-0.20819395464),
908
2
                                   V(-0.421064),
909
2
                                   V(-0.32733845535848671),
910
2
                               }},
911
2
                               {{
912
2
                                   V(0.9 * 9311.3238710010046),
913
2
                                   V(-0.3041958212306401),
914
2
                                   V(-0.3633036457487539),
915
2
                                   V(-0.35660379990111464),
916
2
                                   V(-0.3443074455424403),
917
2
                                   V(-0.33699592683512467),
918
2
                                   V(-0.30180866526242109),
919
2
                                   V(-0.27321683125358037),
920
2
                               }},
921
2
                               {{
922
2
                                   V(0.9 * 4992.2486445538634),
923
2
                                   V(-1.2),
924
2
                                   V(-1.2),
925
2
                                   V(-0.8),
926
2
                                   V(-0.7),
927
2
                                   V(-0.7),
928
2
                                   V(-0.4),
929
2
                                   V(-0.5),
930
2
                               }}}},
931
2
                             8));
932
2
  }
933
934
  // DCT64X32
935
2
  static QuantEncodingInternal DCT32X64() {
936
2
    return QuantEncodingInternal::DCT(
937
2
        DctQuantWeightParams({{{{
938
2
                                   V(0.65 * 23629.073922049845),
939
2
                                   V(-1.025),
940
2
                                   V(-0.78),
941
2
                                   V(-0.65012),
942
2
                                   V(-0.19041574084286472),
943
2
                                   V(-0.20819395464),
944
2
                                   V(-0.421064),
945
2
                                   V(-0.32733845535848671),
946
2
                               }},
947
2
                               {{
948
2
                                   V(0.65 * 8611.3238710010046),
949
2
                                   V(-0.3041958212306401),
950
2
                                   V(-0.3633036457487539),
951
2
                                   V(-0.35660379990111464),
952
2
                                   V(-0.3443074455424403),
953
2
                                   V(-0.33699592683512467),
954
2
                                   V(-0.30180866526242109),
955
2
                                   V(-0.27321683125358037),
956
2
                               }},
957
2
                               {{
958
2
                                   V(0.65 * 4492.2486445538634),
959
2
                                   V(-1.2),
960
2
                                   V(-1.2),
961
2
                                   V(-0.8),
962
2
                                   V(-0.7),
963
2
                                   V(-0.7),
964
2
                                   V(-0.4),
965
2
                                   V(-0.5),
966
2
                               }}}},
967
2
                             8));
968
2
  }
969
  // DCT128X128
970
2
  static QuantEncodingInternal DCT128X128() {
971
2
    return QuantEncodingInternal::DCT(
972
2
        DctQuantWeightParams({{{{
973
2
                                   V(1.8 * 26629.073922049845),
974
2
                                   V(-1.025),
975
2
                                   V(-0.78),
976
2
                                   V(-0.65012),
977
2
                                   V(-0.19041574084286472),
978
2
                                   V(-0.20819395464),
979
2
                                   V(-0.421064),
980
2
                                   V(-0.32733845535848671),
981
2
                               }},
982
2
                               {{
983
2
                                   V(1.8 * 9311.3238710010046),
984
2
                                   V(-0.3041958212306401),
985
2
                                   V(-0.3633036457487539),
986
2
                                   V(-0.35660379990111464),
987
2
                                   V(-0.3443074455424403),
988
2
                                   V(-0.33699592683512467),
989
2
                                   V(-0.30180866526242109),
990
2
                                   V(-0.27321683125358037),
991
2
                               }},
992
2
                               {{
993
2
                                   V(1.8 * 4992.2486445538634),
994
2
                                   V(-1.2),
995
2
                                   V(-1.2),
996
2
                                   V(-0.8),
997
2
                                   V(-0.7),
998
2
                                   V(-0.7),
999
2
                                   V(-0.4),
1000
2
                                   V(-0.5),
1001
2
                               }}}},
1002
2
                             8));
1003
2
  }
1004
1005
  // DCT128X64
1006
2
  static QuantEncodingInternal DCT64X128() {
1007
2
    return QuantEncodingInternal::DCT(
1008
2
        DctQuantWeightParams({{{{
1009
2
                                   V(1.3 * 23629.073922049845),
1010
2
                                   V(-1.025),
1011
2
                                   V(-0.78),
1012
2
                                   V(-0.65012),
1013
2
                                   V(-0.19041574084286472),
1014
2
                                   V(-0.20819395464),
1015
2
                                   V(-0.421064),
1016
2
                                   V(-0.32733845535848671),
1017
2
                               }},
1018
2
                               {{
1019
2
                                   V(1.3 * 8611.3238710010046),
1020
2
                                   V(-0.3041958212306401),
1021
2
                                   V(-0.3633036457487539),
1022
2
                                   V(-0.35660379990111464),
1023
2
                                   V(-0.3443074455424403),
1024
2
                                   V(-0.33699592683512467),
1025
2
                                   V(-0.30180866526242109),
1026
2
                                   V(-0.27321683125358037),
1027
2
                               }},
1028
2
                               {{
1029
2
                                   V(1.3 * 4492.2486445538634),
1030
2
                                   V(-1.2),
1031
2
                                   V(-1.2),
1032
2
                                   V(-0.8),
1033
2
                                   V(-0.7),
1034
2
                                   V(-0.7),
1035
2
                                   V(-0.4),
1036
2
                                   V(-0.5),
1037
2
                               }}}},
1038
2
                             8));
1039
2
  }
1040
  // DCT256X256
1041
2
  static QuantEncodingInternal DCT256X256() {
1042
2
    return QuantEncodingInternal::DCT(
1043
2
        DctQuantWeightParams({{{{
1044
2
                                   V(3.6 * 26629.073922049845),
1045
2
                                   V(-1.025),
1046
2
                                   V(-0.78),
1047
2
                                   V(-0.65012),
1048
2
                                   V(-0.19041574084286472),
1049
2
                                   V(-0.20819395464),
1050
2
                                   V(-0.421064),
1051
2
                                   V(-0.32733845535848671),
1052
2
                               }},
1053
2
                               {{
1054
2
                                   V(3.6 * 9311.3238710010046),
1055
2
                                   V(-0.3041958212306401),
1056
2
                                   V(-0.3633036457487539),
1057
2
                                   V(-0.35660379990111464),
1058
2
                                   V(-0.3443074455424403),
1059
2
                                   V(-0.33699592683512467),
1060
2
                                   V(-0.30180866526242109),
1061
2
                                   V(-0.27321683125358037),
1062
2
                               }},
1063
2
                               {{
1064
2
                                   V(3.6 * 4992.2486445538634),
1065
2
                                   V(-1.2),
1066
2
                                   V(-1.2),
1067
2
                                   V(-0.8),
1068
2
                                   V(-0.7),
1069
2
                                   V(-0.7),
1070
2
                                   V(-0.4),
1071
2
                                   V(-0.5),
1072
2
                               }}}},
1073
2
                             8));
1074
2
  }
1075
1076
  // DCT256X128
1077
2
  static QuantEncodingInternal DCT128X256() {
1078
2
    return QuantEncodingInternal::DCT(
1079
2
        DctQuantWeightParams({{{{
1080
2
                                   V(2.6 * 23629.073922049845),
1081
2
                                   V(-1.025),
1082
2
                                   V(-0.78),
1083
2
                                   V(-0.65012),
1084
2
                                   V(-0.19041574084286472),
1085
2
                                   V(-0.20819395464),
1086
2
                                   V(-0.421064),
1087
2
                                   V(-0.32733845535848671),
1088
2
                               }},
1089
2
                               {{
1090
2
                                   V(2.6 * 8611.3238710010046),
1091
2
                                   V(-0.3041958212306401),
1092
2
                                   V(-0.3633036457487539),
1093
2
                                   V(-0.35660379990111464),
1094
2
                                   V(-0.3443074455424403),
1095
2
                                   V(-0.33699592683512467),
1096
2
                                   V(-0.30180866526242109),
1097
2
                                   V(-0.27321683125358037),
1098
2
                               }},
1099
2
                               {{
1100
2
                                   V(2.6 * 4492.2486445538634),
1101
2
                                   V(-1.2),
1102
2
                                   V(-1.2),
1103
2
                                   V(-0.8),
1104
2
                                   V(-0.7),
1105
2
                                   V(-0.7),
1106
2
                                   V(-0.4),
1107
2
                                   V(-0.5),
1108
2
                               }}}},
1109
2
                             8));
1110
2
  }
1111
};
1112
}  // namespace
1113
1114
2
DequantMatrices::DequantLibraryInternal DequantMatrices::LibraryInit() {
1115
2
  static_assert(kNumQuantTables == 17,
1116
2
                "Update this function when adding new quantization kinds.");
1117
2
  static_assert(kNumPredefinedTables == 1,
1118
2
                "Update this function when adding new quantization matrices to "
1119
2
                "the library.");
1120
1121
  // The library and the indices need to be kept in sync manually.
1122
2
  static_assert(0 == static_cast<uint8_t>(QuantTable::DCT),
1123
2
                "Update the DequantLibrary array below.");
1124
2
  static_assert(1 == static_cast<uint8_t>(QuantTable::IDENTITY),
1125
2
                "Update the DequantLibrary array below.");
1126
2
  static_assert(2 == static_cast<uint8_t>(QuantTable::DCT2X2),
1127
2
                "Update the DequantLibrary array below.");
1128
2
  static_assert(3 == static_cast<uint8_t>(QuantTable::DCT4X4),
1129
2
                "Update the DequantLibrary array below.");
1130
2
  static_assert(4 == static_cast<uint8_t>(QuantTable::DCT16X16),
1131
2
                "Update the DequantLibrary array below.");
1132
2
  static_assert(5 == static_cast<uint8_t>(QuantTable::DCT32X32),
1133
2
                "Update the DequantLibrary array below.");
1134
2
  static_assert(6 == static_cast<uint8_t>(QuantTable::DCT8X16),
1135
2
                "Update the DequantLibrary array below.");
1136
2
  static_assert(7 == static_cast<uint8_t>(QuantTable::DCT8X32),
1137
2
                "Update the DequantLibrary array below.");
1138
2
  static_assert(8 == static_cast<uint8_t>(QuantTable::DCT16X32),
1139
2
                "Update the DequantLibrary array below.");
1140
2
  static_assert(9 == static_cast<uint8_t>(QuantTable::DCT4X8),
1141
2
                "Update the DequantLibrary array below.");
1142
2
  static_assert(10 == static_cast<uint8_t>(QuantTable::AFV0),
1143
2
                "Update the DequantLibrary array below.");
1144
2
  static_assert(11 == static_cast<uint8_t>(QuantTable::DCT64X64),
1145
2
                "Update the DequantLibrary array below.");
1146
2
  static_assert(12 == static_cast<uint8_t>(QuantTable::DCT32X64),
1147
2
                "Update the DequantLibrary array below.");
1148
2
  static_assert(13 == static_cast<uint8_t>(QuantTable::DCT128X128),
1149
2
                "Update the DequantLibrary array below.");
1150
2
  static_assert(14 == static_cast<uint8_t>(QuantTable::DCT64X128),
1151
2
                "Update the DequantLibrary array below.");
1152
2
  static_assert(15 == static_cast<uint8_t>(QuantTable::DCT256X256),
1153
2
                "Update the DequantLibrary array below.");
1154
2
  static_assert(16 == static_cast<uint8_t>(QuantTable::DCT128X256),
1155
2
                "Update the DequantLibrary array below.");
1156
2
  return DequantMatrices::DequantLibraryInternal{{
1157
2
      DequantMatricesLibraryDef::DCT(),
1158
2
      DequantMatricesLibraryDef::IDENTITY(),
1159
2
      DequantMatricesLibraryDef::DCT2X2(),
1160
2
      DequantMatricesLibraryDef::DCT4X4(),
1161
2
      DequantMatricesLibraryDef::DCT16X16(),
1162
2
      DequantMatricesLibraryDef::DCT32X32(),
1163
2
      DequantMatricesLibraryDef::DCT8X16(),
1164
2
      DequantMatricesLibraryDef::DCT8X32(),
1165
2
      DequantMatricesLibraryDef::DCT16X32(),
1166
2
      DequantMatricesLibraryDef::DCT4X8(),
1167
2
      DequantMatricesLibraryDef::AFV0(),
1168
2
      DequantMatricesLibraryDef::DCT64X64(),
1169
2
      DequantMatricesLibraryDef::DCT32X64(),
1170
      // Same default for large transforms (128+) as for 64x* transforms.
1171
2
      DequantMatricesLibraryDef::DCT128X128(),
1172
2
      DequantMatricesLibraryDef::DCT64X128(),
1173
2
      DequantMatricesLibraryDef::DCT256X256(),
1174
2
      DequantMatricesLibraryDef::DCT128X256(),
1175
2
  }};
1176
2
}
1177
1178
7.29k
const QuantEncoding* DequantMatrices::Library() {
1179
7.29k
  static const DequantMatrices::DequantLibraryInternal kDequantLibrary =
1180
7.29k
      DequantMatrices::LibraryInit();
1181
  // Downcast the result to a const QuantEncoding* from QuantEncodingInternal*
1182
  // since the subclass (QuantEncoding) doesn't add any new members and users
1183
  // will need to upcast to QuantEncodingInternal to access the members of that
1184
  // class. This allows to have kDequantLibrary as a constexpr value while still
1185
  // allowing to create QuantEncoding::RAW() instances that use std::vector in
1186
  // C++11.
1187
7.29k
  return reinterpret_cast<const QuantEncoding*>(kDequantLibrary.data());
1188
7.29k
}
1189
1190
80.0k
DequantMatrices::DequantMatrices() {
1191
80.0k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
1192
80.0k
  size_t pos = 0;
1193
80.0k
  size_t offsets[kNumQuantTables * 3];
1194
1.44M
  for (size_t i = 0; i < static_cast<size_t>(kNumQuantTables); i++) {
1195
1.36M
    size_t num_blocks =
1196
1.36M
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1197
1.36M
    size_t num = num_blocks * kDCTBlockSize;
1198
5.44M
    for (size_t c = 0; c < 3; c++) {
1199
4.08M
      offsets[3 * i + c] = pos + c * num;
1200
4.08M
    }
1201
1.36M
    pos += 3 * num;
1202
1.36M
  }
1203
2.24M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1204
8.64M
    for (size_t c = 0; c < 3; c++) {
1205
6.48M
      table_offsets_[i * 3 + c] =
1206
6.48M
          offsets[static_cast<size_t>(kAcStrategyToQuantTableMap[i]) * 3 + c];
1207
6.48M
    }
1208
2.16M
  }
1209
80.0k
}
1210
1211
Status DequantMatrices::EnsureComputed(JxlMemoryManager* memory_manager,
1212
7.29k
                                       uint32_t acs_mask) {
1213
7.29k
  const QuantEncoding* library = Library();
1214
1215
7.29k
  if (!table_storage_) {
1216
7.29k
    size_t table_storage_bytes = 2 * kTotalTableSize * sizeof(float);
1217
7.29k
    JXL_ASSIGN_OR_RETURN(
1218
7.29k
        table_storage_,
1219
7.29k
        AlignedMemory::Create(memory_manager, table_storage_bytes));
1220
7.29k
    table_ = table_storage_.address<float>();
1221
7.29k
    inv_table_ = table_ + kTotalTableSize;
1222
7.29k
  }
1223
1224
7.29k
  size_t offsets[kNumQuantTables * 3 + 1];
1225
7.29k
  size_t pos = 0;
1226
131k
  for (size_t i = 0; i < kNumQuantTables; i++) {
1227
124k
    size_t num_blocks =
1228
124k
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1229
124k
    size_t num = num_blocks * kDCTBlockSize;
1230
496k
    for (size_t c = 0; c < 3; c++) {
1231
372k
      offsets[3 * i + c] = pos + c * num;
1232
372k
    }
1233
124k
    pos += 3 * num;
1234
124k
  }
1235
7.29k
  offsets[kNumQuantTables * 3] = pos;
1236
7.29k
  JXL_ENSURE(pos == kTotalTableSize);
1237
1238
7.29k
  uint32_t kind_mask = 0;
1239
204k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1240
197k
    if (acs_mask & (1u << i)) {
1241
66.0k
      kind_mask |= 1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1242
66.0k
    }
1243
197k
  }
1244
7.29k
  uint32_t computed_kind_mask = 0;
1245
204k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1246
197k
    if (computed_mask_ & (1u << i)) {
1247
0
      computed_kind_mask |=
1248
0
          1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1249
0
    }
1250
197k
  }
1251
130k
  for (size_t table = 0; table < kNumQuantTables; table++) {
1252
123k
    if ((1 << table) & computed_kind_mask) continue;
1253
123k
    if ((1 << table) & ~kind_mask) continue;
1254
43.4k
    size_t offset = offsets[table * 3];
1255
43.4k
    float* mutable_table = table_storage_.address<float>();
1256
43.4k
    if (encodings_[table].mode == QuantEncoding::kQuantModeLibrary) {
1257
43.3k
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1258
43.3k
          library[table], mutable_table, mutable_table + kTotalTableSize, table,
1259
43.3k
          QuantTable(table), &offset));
1260
43.3k
    } else {
1261
42
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1262
42
          encodings_[table], mutable_table, mutable_table + kTotalTableSize,
1263
42
          table, QuantTable(table), &offset));
1264
42
    }
1265
43.4k
    JXL_ENSURE(offset == offsets[table * 3 + 3]);
1266
43.4k
  }
1267
7.27k
  computed_mask_ |= acs_mask;
1268
1269
7.27k
  return true;
1270
7.29k
}
1271
1272
}  // namespace jxl
1273
#endif