Coverage Report

Created: 2026-05-16 07:22

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.00k
                         float* weights) {
50
12.0k
  for (size_t c = 0; c < 3; c++) {
51
9.00k
    size_t start = c * 64;
52
9.00k
    weights[start] = 0xBAD;
53
9.00k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
9.00k
    weights[start + 9] = dct2weights[c][1];
55
27.0k
    for (size_t y = 0; y < 2; y++) {
56
54.0k
      for (size_t x = 0; x < 2; x++) {
57
36.0k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
36.0k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
36.0k
      }
60
18.0k
    }
61
27.0k
    for (size_t y = 0; y < 2; y++) {
62
54.0k
      for (size_t x = 0; x < 2; x++) {
63
36.0k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
36.0k
      }
65
18.0k
    }
66
45.0k
    for (size_t y = 0; y < 4; y++) {
67
180k
      for (size_t x = 0; x < 4; x++) {
68
144k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
144k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
144k
      }
71
36.0k
    }
72
45.0k
    for (size_t y = 0; y < 4; y++) {
73
180k
      for (size_t x = 0; x < 4; x++) {
74
144k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
144k
      }
76
36.0k
    }
77
9.00k
  }
78
3.00k
}
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.00k
                         float* weights) {
50
12.0k
  for (size_t c = 0; c < 3; c++) {
51
9.00k
    size_t start = c * 64;
52
9.00k
    weights[start] = 0xBAD;
53
9.00k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
9.00k
    weights[start + 9] = dct2weights[c][1];
55
27.0k
    for (size_t y = 0; y < 2; y++) {
56
54.0k
      for (size_t x = 0; x < 2; x++) {
57
36.0k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
36.0k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
36.0k
      }
60
18.0k
    }
61
27.0k
    for (size_t y = 0; y < 2; y++) {
62
54.0k
      for (size_t x = 0; x < 2; x++) {
63
36.0k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
36.0k
      }
65
18.0k
    }
66
45.0k
    for (size_t y = 0; y < 4; y++) {
67
180k
      for (size_t x = 0; x < 4; x++) {
68
144k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
144k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
144k
      }
71
36.0k
    }
72
45.0k
    for (size_t y = 0; y < 4; y++) {
73
180k
      for (size_t x = 0; x < 4; x++) {
74
144k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
144k
      }
76
36.0k
    }
77
9.00k
  }
78
3.00k
}
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.39k
                             float* weights) {
82
13.5k
  for (size_t c = 0; c < 3; c++) {
83
661k
    for (int i = 0; i < 64; i++) {
84
650k
      weights[64 * c + i] = idweights[c][0];
85
650k
    }
86
10.1k
    weights[64 * c + 1] = idweights[c][1];
87
10.1k
    weights[64 * c + 8] = idweights[c][1];
88
10.1k
    weights[64 * c + 9] = idweights[c][2];
89
10.1k
  }
90
3.39k
}
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.39k
                             float* weights) {
82
13.5k
  for (size_t c = 0; c < 3; c++) {
83
661k
    for (int i = 0; i < 64; i++) {
84
650k
      weights[64 * c + i] = idweights[c][0];
85
650k
    }
86
10.1k
    weights[64 * c + 1] = idweights[c][1];
87
10.1k
    weights[64 * c + 8] = idweights[c][1];
88
10.1k
    weights[64 * c + 9] = idweights[c][2];
89
10.1k
  }
90
3.39k
}
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
119k
                            size_t len) {
94
119k
  float scaled_pos = pos * (len - 1) / max;
95
119k
  size_t idx = scaled_pos;
96
119k
  JXL_ENSURE(idx + 1 < len);
97
119k
  float a = array[idx];
98
119k
  float b = array[idx + 1];
99
119k
  return a * FastPowf(b / a, scaled_pos - idx);
100
119k
}
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
119k
                            size_t len) {
94
119k
  float scaled_pos = pos * (len - 1) / max;
95
119k
  size_t idx = scaled_pos;
96
119k
  JXL_ENSURE(idx + 1 < len);
97
119k
  float a = array[idx];
98
119k
  float b = array[idx + 1];
99
119k
  return a * FastPowf(b / a, scaled_pos - idx);
100
119k
}
Unexecuted instantiation: jxl::N_SSE2::Interpolate(float, float, float const*, unsigned long)
101
102
638k
float Mult(float v) {
103
638k
  if (v > 0.0f) return 1.0f + v;
104
637k
  return 1.0f / (1.0f - v);
105
638k
}
Unexecuted instantiation: jxl::N_SSE4::Mult(float)
jxl::N_AVX2::Mult(float)
Line
Count
Source
102
638k
float Mult(float v) {
103
638k
  if (v > 0.0f) return 1.0f + v;
104
637k
  return 1.0f / (1.0f - v);
105
638k
}
Unexecuted instantiation: jxl::N_SSE2::Mult(float)
106
107
using DF4 = HWY_CAPPED(float, 4);
108
109
hwy::HWY_NAMESPACE::Vec<DF4> InterpolateVec(
110
17.6M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
17.6M
  HWY_CAPPED(int32_t, 4) di;
112
113
17.6M
  auto idx = ConvertTo(di, scaled_pos);
114
115
17.6M
  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
17.6M
  auto a = GatherIndex(DF4(), array, idx);
120
17.6M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
17.6M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
17.6M
}
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
17.6M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
17.6M
  HWY_CAPPED(int32_t, 4) di;
112
113
17.6M
  auto idx = ConvertTo(di, scaled_pos);
114
115
17.6M
  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
17.6M
  auto a = GatherIndex(DF4(), array, idx);
120
17.6M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
17.6M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
17.6M
}
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
38.7k
    size_t num_bands, float* out) {
133
154k
  for (size_t c = 0; c < 3; c++) {
134
116k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
116k
        distance_bands[c][0]};
136
116k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
724k
    for (size_t i = 1; i < num_bands; i++) {
138
608k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
608k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
608k
    }
141
116k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
116k
    float rcpcol = scale / (COLS - 1);
143
116k
    float rcprow = scale / (ROWS - 1);
144
116k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
116k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.88M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.76M
      float dy = y * rcprow;
148
1.76M
      float dy2 = dy * dy;
149
19.4M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
17.6M
        auto dx =
151
17.6M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
17.6M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
17.6M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
17.6M
                                     : InterpolateVec(scaled_distance, bands);
155
17.6M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
17.6M
      }
157
1.76M
    }
158
116k
  }
159
38.7k
  return true;
160
38.7k
}
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
38.7k
    size_t num_bands, float* out) {
133
154k
  for (size_t c = 0; c < 3; c++) {
134
116k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
116k
        distance_bands[c][0]};
136
116k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
724k
    for (size_t i = 1; i < num_bands; i++) {
138
608k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
608k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
608k
    }
141
116k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
116k
    float rcpcol = scale / (COLS - 1);
143
116k
    float rcprow = scale / (ROWS - 1);
144
116k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
116k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.88M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.76M
      float dy = y * rcprow;
148
1.76M
      float dy2 = dy * dy;
149
19.4M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
17.6M
        auto dx =
151
17.6M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
17.6M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
17.6M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
17.6M
                                     : InterpolateVec(scaled_distance, bands);
155
17.6M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
17.6M
      }
157
1.76M
    }
158
116k
  }
159
38.7k
  return true;
160
38.7k
}
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
41.7k
                         QuantTable kind, size_t* pos) {
167
41.7k
  constexpr size_t N = kBlockDim;
168
41.7k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
41.7k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
41.7k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
41.7k
  size_t num = wrows * wcols;
172
173
41.7k
  std::vector<float> weights(3 * num);
174
175
41.7k
  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.39k
    case QuantEncoding::kQuantModeID: {
183
3.39k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.39k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.39k
      break;
186
3.39k
    }
187
3.00k
    case QuantEncoding::kQuantModeDCT2: {
188
3.00k
      JXL_ENSURE(num == kDCTBlockSize);
189
3.00k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
3.00k
      break;
191
3.00k
    }
192
2.88k
    case QuantEncoding::kQuantModeDCT4: {
193
2.88k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.88k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.88k
      JXL_RETURN_IF_ERROR(
197
2.88k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.88k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.5k
      for (size_t c = 0; c < 3; c++) {
200
77.8k
        for (size_t y = 0; y < kBlockDim; y++) {
201
622k
          for (size_t x = 0; x < kBlockDim; x++) {
202
553k
            weights[c * num + y * kBlockDim + x] =
203
553k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
553k
          }
205
69.2k
        }
206
8.65k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.65k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.65k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.65k
      }
210
2.88k
      break;
211
2.88k
    }
212
2.80k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.80k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.80k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.80k
      JXL_RETURN_IF_ERROR(
217
2.80k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.80k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.2k
      for (size_t c = 0; c < 3; c++) {
220
75.7k
        for (size_t y = 0; y < kBlockDim; y++) {
221
605k
          for (size_t x = 0; x < kBlockDim; x++) {
222
538k
            weights[c * num + y * kBlockDim + x] =
223
538k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
538k
          }
225
67.2k
        }
226
8.41k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.41k
      }
228
2.80k
      break;
229
2.80k
    }
230
26.3k
    case QuantEncoding::kQuantModeDCT: {
231
26.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
26.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
26.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
26.3k
      break;
235
26.3k
    }
236
26.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.31k
    case QuantEncoding::kQuantModeAFV: {
247
3.31k
      constexpr float kFreqs[] = {
248
3.31k
          0xBAD,
249
3.31k
          0xBAD,
250
3.31k
          0.8517778890324296,
251
3.31k
          5.37778436506804,
252
3.31k
          0xBAD,
253
3.31k
          0xBAD,
254
3.31k
          4.734747904497923,
255
3.31k
          5.449245381693219,
256
3.31k
          1.6598270267479331,
257
3.31k
          4,
258
3.31k
          7.275749096817861,
259
3.31k
          10.423227632456525,
260
3.31k
          2.662932286148962,
261
3.31k
          7.630657783650829,
262
3.31k
          8.962388608184032,
263
3.31k
          12.97166202570235,
264
3.31k
      };
265
266
3.31k
      float weights4x8[3 * 4 * 8];
267
3.31k
      JXL_RETURN_IF_ERROR((
268
3.31k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.31k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.31k
      float weights4x4[3 * 4 * 4];
271
3.31k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.31k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.31k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.31k
      constexpr float lo = 0.8517778890324296;
276
3.31k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
13.2k
      for (size_t c = 0; c < 3; c++) {
278
9.93k
        float bands[4];
279
9.93k
        bands[0] = encoding.afv_weights[c][5];
280
9.93k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
39.7k
        for (size_t i = 1; i < 4; i++) {
282
29.7k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
29.7k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
29.7k
        }
285
9.92k
        size_t start = c * 64;
286
168k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
168k
          weights[start + y * 8 + x] = val;
288
168k
        };
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
168k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
168k
          weights[start + y * 8 + x] = val;
288
168k
        };
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
9.92k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
9.92k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
9.92k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
9.92k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
9.92k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
9.92k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
49.6k
        for (size_t y = 0; y < 4; y++) {
300
198k
          for (size_t x = 0; x < 4; x++) {
301
158k
            if (x < 2 && y < 2) continue;
302
238k
            JXL_ASSIGN_OR_RETURN(
303
238k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
238k
            set_weight(2 * x, 2 * y, val);
305
238k
          }
306
39.7k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
49.6k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
357k
          for (size_t x = 0; x < kBlockDim; x++) {
311
317k
            if (x == 0 && y == 0) continue;
312
307k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
307k
                weights4x8[c * 32 + y * 8 + x];
314
307k
          }
315
39.7k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
49.6k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
198k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
158k
            if (x == 0 && y == 0) continue;
320
148k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
148k
                weights4x4[c * 16 + y * 4 + x];
322
148k
          }
323
39.7k
        }
324
9.92k
      }
325
3.30k
      break;
326
3.31k
    }
327
41.7k
  }
328
41.7k
  size_t prev_pos = *pos;
329
41.7k
  HWY_CAPPED(float, 64) d;
330
9.14M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
9.10M
    auto inv_val = LoadU(d, weights.data() + i);
332
9.10M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
9.10M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
23
      return JXL_FAILURE("Invalid quantization table");
335
23
    }
336
9.10M
    auto val = Div(Set(d, 1.0f), inv_val);
337
9.10M
    StoreU(val, d, table + *pos + i);
338
9.10M
    StoreU(inv_val, d, inv_table + *pos + i);
339
9.10M
  }
340
41.7k
  (*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
41.7k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
41.7k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
41.7k
  CoefficientLayout(&ys, &xs);
348
166k
  for (size_t c = 0; c < 3; c++) {
349
373k
    for (size_t y = 0; y < ys; y++) {
350
1.38M
      for (size_t x = 0; x < xs; x++) {
351
1.13M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.13M
                  x] = 0;
353
1.13M
      }
354
248k
    }
355
125k
  }
356
41.7k
  return true;
357
41.7k
}
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
41.7k
                         QuantTable kind, size_t* pos) {
167
41.7k
  constexpr size_t N = kBlockDim;
168
41.7k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
41.7k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
41.7k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
41.7k
  size_t num = wrows * wcols;
172
173
41.7k
  std::vector<float> weights(3 * num);
174
175
41.7k
  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.39k
    case QuantEncoding::kQuantModeID: {
183
3.39k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.39k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.39k
      break;
186
3.39k
    }
187
3.00k
    case QuantEncoding::kQuantModeDCT2: {
188
3.00k
      JXL_ENSURE(num == kDCTBlockSize);
189
3.00k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
3.00k
      break;
191
3.00k
    }
192
2.88k
    case QuantEncoding::kQuantModeDCT4: {
193
2.88k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.88k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.88k
      JXL_RETURN_IF_ERROR(
197
2.88k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.88k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.5k
      for (size_t c = 0; c < 3; c++) {
200
77.8k
        for (size_t y = 0; y < kBlockDim; y++) {
201
622k
          for (size_t x = 0; x < kBlockDim; x++) {
202
553k
            weights[c * num + y * kBlockDim + x] =
203
553k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
553k
          }
205
69.2k
        }
206
8.65k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.65k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.65k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.65k
      }
210
2.88k
      break;
211
2.88k
    }
212
2.80k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.80k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.80k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.80k
      JXL_RETURN_IF_ERROR(
217
2.80k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.80k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.2k
      for (size_t c = 0; c < 3; c++) {
220
75.7k
        for (size_t y = 0; y < kBlockDim; y++) {
221
605k
          for (size_t x = 0; x < kBlockDim; x++) {
222
538k
            weights[c * num + y * kBlockDim + x] =
223
538k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
538k
          }
225
67.2k
        }
226
8.41k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.41k
      }
228
2.80k
      break;
229
2.80k
    }
230
26.3k
    case QuantEncoding::kQuantModeDCT: {
231
26.3k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
26.3k
          wrows, wcols, encoding.dct_params.distance_bands,
233
26.3k
          encoding.dct_params.num_distance_bands, weights.data()));
234
26.3k
      break;
235
26.3k
    }
236
26.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.31k
    case QuantEncoding::kQuantModeAFV: {
247
3.31k
      constexpr float kFreqs[] = {
248
3.31k
          0xBAD,
249
3.31k
          0xBAD,
250
3.31k
          0.8517778890324296,
251
3.31k
          5.37778436506804,
252
3.31k
          0xBAD,
253
3.31k
          0xBAD,
254
3.31k
          4.734747904497923,
255
3.31k
          5.449245381693219,
256
3.31k
          1.6598270267479331,
257
3.31k
          4,
258
3.31k
          7.275749096817861,
259
3.31k
          10.423227632456525,
260
3.31k
          2.662932286148962,
261
3.31k
          7.630657783650829,
262
3.31k
          8.962388608184032,
263
3.31k
          12.97166202570235,
264
3.31k
      };
265
266
3.31k
      float weights4x8[3 * 4 * 8];
267
3.31k
      JXL_RETURN_IF_ERROR((
268
3.31k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.31k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.31k
      float weights4x4[3 * 4 * 4];
271
3.31k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.31k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.31k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.31k
      constexpr float lo = 0.8517778890324296;
276
3.31k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
13.2k
      for (size_t c = 0; c < 3; c++) {
278
9.93k
        float bands[4];
279
9.93k
        bands[0] = encoding.afv_weights[c][5];
280
9.93k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
39.7k
        for (size_t i = 1; i < 4; i++) {
282
29.7k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
29.7k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
29.7k
        }
285
9.92k
        size_t start = c * 64;
286
9.92k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
9.92k
          weights[start + y * 8 + x] = val;
288
9.92k
        };
289
9.92k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
9.92k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
9.92k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
9.92k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
9.92k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
9.92k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
49.6k
        for (size_t y = 0; y < 4; y++) {
300
198k
          for (size_t x = 0; x < 4; x++) {
301
158k
            if (x < 2 && y < 2) continue;
302
238k
            JXL_ASSIGN_OR_RETURN(
303
238k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
238k
            set_weight(2 * x, 2 * y, val);
305
238k
          }
306
39.7k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
49.6k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
357k
          for (size_t x = 0; x < kBlockDim; x++) {
311
317k
            if (x == 0 && y == 0) continue;
312
307k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
307k
                weights4x8[c * 32 + y * 8 + x];
314
307k
          }
315
39.7k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
49.6k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
198k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
158k
            if (x == 0 && y == 0) continue;
320
148k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
148k
                weights4x4[c * 16 + y * 4 + x];
322
148k
          }
323
39.7k
        }
324
9.92k
      }
325
3.30k
      break;
326
3.31k
    }
327
41.7k
  }
328
41.7k
  size_t prev_pos = *pos;
329
41.7k
  HWY_CAPPED(float, 64) d;
330
9.14M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
9.10M
    auto inv_val = LoadU(d, weights.data() + i);
332
9.10M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
9.10M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
23
      return JXL_FAILURE("Invalid quantization table");
335
23
    }
336
9.10M
    auto val = Div(Set(d, 1.0f), inv_val);
337
9.10M
    StoreU(val, d, table + *pos + i);
338
9.10M
    StoreU(inv_val, d, inv_table + *pos + i);
339
9.10M
  }
340
41.7k
  (*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
41.7k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
41.7k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
41.7k
  CoefficientLayout(&ys, &xs);
348
166k
  for (size_t c = 0; c < 3; c++) {
349
373k
    for (size_t y = 0; y < ys; y++) {
350
1.38M
      for (size_t x = 0; x < xs; x++) {
351
1.13M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.13M
                  x] = 0;
353
1.13M
      }
354
248k
    }
355
125k
  }
356
41.7k
  return true;
357
41.7k
}
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
199
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
374
199
  params->num_distance_bands =
375
199
      br->ReadFixedBits<DctQuantWeightParams::kLog2MaxDistanceBands>() + 1;
376
647
  for (size_t c = 0; c < 3; c++) {
377
2.70k
    for (size_t i = 0; i < params->num_distance_bands; i++) {
378
2.20k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &params->distance_bands[c][i]));
379
2.20k
    }
380
504
    if (params->distance_bands[c][0] < kAlmostZero) {
381
56
      return JXL_FAILURE("Distance band seed is too small");
382
56
    }
383
448
    params->distance_bands[c][0] *= 64.0f;
384
448
  }
385
136
  return true;
386
199
}
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.82k
              ModularFrameDecoder* modular_frame_decoder) {
392
5.82k
  size_t required_size = required_size_x * required_size_y;
393
5.82k
  required_size_x *= kBlockDim;
394
5.82k
  required_size_y *= kBlockDim;
395
5.82k
  int mode = br->ReadFixedBits<kLog2NumQuantModes>();
396
5.82k
  switch (mode) {
397
5.26k
    case QuantEncoding::kQuantModeLibrary: {
398
5.26k
      encoding->predefined = br->ReadFixedBits<kCeilLog2NumPredefinedTables>();
399
5.26k
      if (encoding->predefined >= kNumPredefinedTables) {
400
0
        return JXL_FAILURE("Invalid predefined table");
401
0
      }
402
5.26k
      break;
403
5.26k
    }
404
5.26k
    case QuantEncoding::kQuantModeID: {
405
85
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
406
232
      for (size_t c = 0; c < 3; c++) {
407
691
        for (size_t i = 0; i < 3; i++) {
408
539
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->idweights[c][i]));
409
522
          if (std::abs(encoding->idweights[c][i]) < kAlmostZero) {
410
25
            return JXL_FAILURE("ID Quantizer is too small");
411
25
          }
412
497
          encoding->idweights[c][i] *= 64;
413
497
        }
414
194
      }
415
38
      break;
416
80
    }
417
123
    case QuantEncoding::kQuantModeDCT2: {
418
123
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
419
269
      for (size_t c = 0; c < 3; c++) {
420
1.37k
        for (size_t i = 0; i < 6; i++) {
421
1.22k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->dct2weights[c][i]));
422
1.18k
          if (std::abs(encoding->dct2weights[c][i]) < kAlmostZero) {
423
47
            return JXL_FAILURE("Quantizer is too small");
424
47
          }
425
1.13k
          encoding->dct2weights[c][i] *= 64;
426
1.13k
        }
427
243
      }
428
26
      break;
429
115
    }
430
72
    case QuantEncoding::kQuantModeDCT4X8: {
431
72
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
432
236
      for (size_t c = 0; c < 3; c++) {
433
186
        JXL_RETURN_IF_ERROR(
434
186
            F16Coder::Read(br, &encoding->dct4x8multipliers[c]));
435
175
        if (std::abs(encoding->dct4x8multipliers[c]) < kAlmostZero) {
436
7
          return JXL_FAILURE("DCT4X8 multiplier is too small");
437
7
        }
438
175
      }
439
50
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
440
37
      break;
441
50
    }
442
55
    case QuantEncoding::kQuantModeDCT4: {
443
55
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
444
147
      for (size_t c = 0; c < 3; c++) {
445
331
        for (size_t i = 0; i < 2; i++) {
446
236
          JXL_RETURN_IF_ERROR(
447
236
              F16Coder::Read(br, &encoding->dct4multipliers[c][i]));
448
222
          if (std::abs(encoding->dct4multipliers[c][i]) < kAlmostZero) {
449
16
            return JXL_FAILURE("DCT4 multiplier is too small");
450
16
          }
451
222
        }
452
125
      }
453
22
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
454
16
      break;
455
22
    }
456
95
    case QuantEncoding::kQuantModeAFV: {
457
95
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
458
264
      for (size_t c = 0; c < 3; c++) {
459
1.98k
        for (size_t i = 0; i < 9; i++) {
460
1.80k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->afv_weights[c][i]));
461
1.80k
        }
462
1.19k
        for (size_t i = 0; i < 6; i++) {
463
1.02k
          encoding->afv_weights[c][i] *= 64;
464
1.02k
        }
465
171
      }
466
39
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
467
23
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params_afv_4x4));
468
20
      break;
469
23
    }
470
65
    case QuantEncoding::kQuantModeDCT: {
471
65
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
472
40
      break;
473
65
    }
474
68
    case QuantEncoding::kQuantModeRAW: {
475
      // Set mode early, to avoid mem-leak.
476
68
      encoding->mode = QuantEncoding::kQuantModeRAW;
477
68
      JXL_RETURN_IF_ERROR(ModularFrameDecoder::DecodeQuantTable(
478
68
          memory_manager, required_size_x, required_size_y, br, encoding, idx,
479
68
          modular_frame_decoder));
480
14
      break;
481
68
    }
482
14
    default:
483
0
      return JXL_FAILURE("Invalid quantization table encoding");
484
5.82k
  }
485
5.45k
  encoding->mode = static_cast<QuantEncoding::Mode>(mode);
486
5.45k
  return true;
487
5.82k
}
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.77k
                               ModularFrameDecoder* modular_frame_decoder) {
499
4.77k
  size_t all_default = br->ReadBits(1);
500
4.77k
  size_t num_tables = all_default ? 0 : static_cast<size_t>(kNumQuantTables);
501
4.77k
  encodings_.clear();
502
4.77k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
503
10.2k
  for (size_t i = 0; i < num_tables; i++) {
504
5.82k
    JXL_RETURN_IF_ERROR(jxl::Decode(memory_manager, br, &encodings_[i],
505
5.82k
                                    required_size_x[i % kNumQuantTables],
506
5.82k
                                    required_size_y[i % kNumQuantTables], i,
507
5.82k
                                    modular_frame_decoder));
508
5.82k
  }
509
4.40k
  computed_mask_ = 0;
510
4.40k
  return true;
511
4.77k
}
512
513
41.3k
Status DequantMatrices::DecodeDC(BitReader* br) {
514
41.3k
  bool all_default = static_cast<bool>(br->ReadBits(1));
515
41.3k
  if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
516
41.0k
  if (!all_default) {
517
21.3k
    for (size_t c = 0; c < 3; c++) {
518
16.0k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &dc_quant_[c]));
519
16.0k
      dc_quant_[c] *= 1.0f / 128.0f;
520
      // Negative values and nearly zero are invalid values.
521
16.0k
      if (dc_quant_[c] < kAlmostZero) {
522
59
        return JXL_FAILURE("Invalid dc_quant: coefficient is too small.");
523
59
      }
524
15.9k
      inv_dc_quant_[c] = 1.0f / dc_quant_[c];
525
15.9k
    }
526
5.36k
  }
527
40.9k
  return true;
528
41.0k
}
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.11k
const QuantEncoding* DequantMatrices::Library() {
1179
7.11k
  static const DequantMatrices::DequantLibraryInternal kDequantLibrary =
1180
7.11k
      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.11k
  return reinterpret_cast<const QuantEncoding*>(kDequantLibrary.data());
1188
7.11k
}
1189
1190
81.0k
DequantMatrices::DequantMatrices() {
1191
81.0k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
1192
81.0k
  size_t pos = 0;
1193
81.0k
  size_t offsets[kNumQuantTables * 3];
1194
1.45M
  for (size_t i = 0; i < static_cast<size_t>(kNumQuantTables); i++) {
1195
1.37M
    size_t num_blocks =
1196
1.37M
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1197
1.37M
    size_t num = num_blocks * kDCTBlockSize;
1198
5.51M
    for (size_t c = 0; c < 3; c++) {
1199
4.13M
      offsets[3 * i + c] = pos + c * num;
1200
4.13M
    }
1201
1.37M
    pos += 3 * num;
1202
1.37M
  }
1203
2.26M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1204
8.75M
    for (size_t c = 0; c < 3; c++) {
1205
6.56M
      table_offsets_[i * 3 + c] =
1206
6.56M
          offsets[static_cast<size_t>(kAcStrategyToQuantTableMap[i]) * 3 + c];
1207
6.56M
    }
1208
2.18M
  }
1209
81.0k
}
1210
1211
Status DequantMatrices::EnsureComputed(JxlMemoryManager* memory_manager,
1212
7.11k
                                       uint32_t acs_mask) {
1213
7.11k
  const QuantEncoding* library = Library();
1214
1215
7.11k
  if (!table_storage_) {
1216
7.11k
    size_t table_storage_bytes = 2 * kTotalTableSize * sizeof(float);
1217
7.11k
    JXL_ASSIGN_OR_RETURN(
1218
7.11k
        table_storage_,
1219
7.11k
        AlignedMemory::Create(memory_manager, table_storage_bytes));
1220
7.11k
    table_ = table_storage_.address<float>();
1221
7.11k
    inv_table_ = table_ + kTotalTableSize;
1222
7.11k
  }
1223
1224
7.11k
  size_t offsets[kNumQuantTables * 3 + 1];
1225
7.11k
  size_t pos = 0;
1226
128k
  for (size_t i = 0; i < kNumQuantTables; i++) {
1227
120k
    size_t num_blocks =
1228
120k
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1229
120k
    size_t num = num_blocks * kDCTBlockSize;
1230
483k
    for (size_t c = 0; c < 3; c++) {
1231
362k
      offsets[3 * i + c] = pos + c * num;
1232
362k
    }
1233
120k
    pos += 3 * num;
1234
120k
  }
1235
7.11k
  offsets[kNumQuantTables * 3] = pos;
1236
7.11k
  JXL_ENSURE(pos == kTotalTableSize);
1237
1238
7.11k
  uint32_t kind_mask = 0;
1239
199k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1240
192k
    if (acs_mask & (1u << i)) {
1241
63.5k
      kind_mask |= 1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1242
63.5k
    }
1243
192k
  }
1244
7.11k
  uint32_t computed_kind_mask = 0;
1245
199k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1246
192k
    if (computed_mask_ & (1u << i)) {
1247
0
      computed_kind_mask |=
1248
0
          1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1249
0
    }
1250
192k
  }
1251
127k
  for (size_t table = 0; table < kNumQuantTables; table++) {
1252
120k
    if ((1 << table) & computed_kind_mask) continue;
1253
120k
    if ((1 << table) & ~kind_mask) continue;
1254
41.7k
    size_t offset = offsets[table * 3];
1255
41.7k
    float* mutable_table = table_storage_.address<float>();
1256
41.7k
    if (encodings_[table].mode == QuantEncoding::kQuantModeLibrary) {
1257
41.7k
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1258
41.7k
          library[table], mutable_table, mutable_table + kTotalTableSize, table,
1259
41.7k
          QuantTable(table), &offset));
1260
41.7k
    } else {
1261
72
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1262
72
          encodings_[table], mutable_table, mutable_table + kTotalTableSize,
1263
72
          table, QuantTable(table), &offset));
1264
72
    }
1265
41.7k
    JXL_ENSURE(offset == offsets[table * 3 + 3]);
1266
41.7k
  }
1267
7.06k
  computed_mask_ |= acs_mask;
1268
1269
7.06k
  return true;
1270
7.11k
}
1271
1272
}  // namespace jxl
1273
#endif