Coverage Report

Created: 2026-03-31 06:56

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
2.93k
                         float* weights) {
50
11.7k
  for (size_t c = 0; c < 3; c++) {
51
8.79k
    size_t start = c * 64;
52
8.79k
    weights[start] = 0xBAD;
53
8.79k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
8.79k
    weights[start + 9] = dct2weights[c][1];
55
26.3k
    for (size_t y = 0; y < 2; y++) {
56
52.7k
      for (size_t x = 0; x < 2; x++) {
57
35.1k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
35.1k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
35.1k
      }
60
17.5k
    }
61
26.3k
    for (size_t y = 0; y < 2; y++) {
62
52.7k
      for (size_t x = 0; x < 2; x++) {
63
35.1k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
35.1k
      }
65
17.5k
    }
66
43.9k
    for (size_t y = 0; y < 4; y++) {
67
175k
      for (size_t x = 0; x < 4; x++) {
68
140k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
140k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
140k
      }
71
35.1k
    }
72
43.9k
    for (size_t y = 0; y < 4; y++) {
73
175k
      for (size_t x = 0; x < 4; x++) {
74
140k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
140k
      }
76
35.1k
    }
77
8.79k
  }
78
2.93k
}
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
2.93k
                         float* weights) {
50
11.7k
  for (size_t c = 0; c < 3; c++) {
51
8.79k
    size_t start = c * 64;
52
8.79k
    weights[start] = 0xBAD;
53
8.79k
    weights[start + 1] = weights[start + 8] = dct2weights[c][0];
54
8.79k
    weights[start + 9] = dct2weights[c][1];
55
26.3k
    for (size_t y = 0; y < 2; y++) {
56
52.7k
      for (size_t x = 0; x < 2; x++) {
57
35.1k
        weights[start + y * 8 + x + 2] = dct2weights[c][2];
58
35.1k
        weights[start + (y + 2) * 8 + x] = dct2weights[c][2];
59
35.1k
      }
60
17.5k
    }
61
26.3k
    for (size_t y = 0; y < 2; y++) {
62
52.7k
      for (size_t x = 0; x < 2; x++) {
63
35.1k
        weights[start + (y + 2) * 8 + x + 2] = dct2weights[c][3];
64
35.1k
      }
65
17.5k
    }
66
43.9k
    for (size_t y = 0; y < 4; y++) {
67
175k
      for (size_t x = 0; x < 4; x++) {
68
140k
        weights[start + y * 8 + x + 4] = dct2weights[c][4];
69
140k
        weights[start + (y + 4) * 8 + x] = dct2weights[c][4];
70
140k
      }
71
35.1k
    }
72
43.9k
    for (size_t y = 0; y < 4; y++) {
73
175k
      for (size_t x = 0; x < 4; x++) {
74
140k
        weights[start + (y + 4) * 8 + x + 4] = dct2weights[c][5];
75
140k
      }
76
35.1k
    }
77
8.79k
  }
78
2.93k
}
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.25k
                             float* weights) {
82
13.0k
  for (size_t c = 0; c < 3; c++) {
83
634k
    for (int i = 0; i < 64; i++) {
84
624k
      weights[64 * c + i] = idweights[c][0];
85
624k
    }
86
9.75k
    weights[64 * c + 1] = idweights[c][1];
87
9.75k
    weights[64 * c + 8] = idweights[c][1];
88
9.75k
    weights[64 * c + 9] = idweights[c][2];
89
9.75k
  }
90
3.25k
}
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.25k
                             float* weights) {
82
13.0k
  for (size_t c = 0; c < 3; c++) {
83
634k
    for (int i = 0; i < 64; i++) {
84
624k
      weights[64 * c + i] = idweights[c][0];
85
624k
    }
86
9.75k
    weights[64 * c + 1] = idweights[c][1];
87
9.75k
    weights[64 * c + 8] = idweights[c][1];
88
9.75k
    weights[64 * c + 9] = idweights[c][2];
89
9.75k
  }
90
3.25k
}
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
114k
                            size_t len) {
94
114k
  float scaled_pos = pos * (len - 1) / max;
95
114k
  size_t idx = scaled_pos;
96
114k
  JXL_ENSURE(idx + 1 < len);
97
114k
  float a = array[idx];
98
114k
  float b = array[idx + 1];
99
114k
  return a * FastPowf(b / a, scaled_pos - idx);
100
114k
}
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
114k
                            size_t len) {
94
114k
  float scaled_pos = pos * (len - 1) / max;
95
114k
  size_t idx = scaled_pos;
96
114k
  JXL_ENSURE(idx + 1 < len);
97
114k
  float a = array[idx];
98
114k
  float b = array[idx + 1];
99
114k
  return a * FastPowf(b / a, scaled_pos - idx);
100
114k
}
Unexecuted instantiation: jxl::N_SSE2::Interpolate(float, float, float const*, unsigned long)
101
102
621k
float Mult(float v) {
103
621k
  if (v > 0.0f) return 1.0f + v;
104
620k
  return 1.0f / (1.0f - v);
105
621k
}
Unexecuted instantiation: jxl::N_SSE4::Mult(float)
jxl::N_AVX2::Mult(float)
Line
Count
Source
102
621k
float Mult(float v) {
103
621k
  if (v > 0.0f) return 1.0f + v;
104
620k
  return 1.0f / (1.0f - v);
105
621k
}
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.4M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
17.4M
  HWY_CAPPED(int32_t, 4) di;
112
113
17.4M
  auto idx = ConvertTo(di, scaled_pos);
114
115
17.4M
  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.4M
  auto a = GatherIndex(DF4(), array, idx);
120
17.4M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
17.4M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
17.4M
}
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.4M
    hwy::HWY_NAMESPACE::Vec<DF4> scaled_pos, const float* array) {
111
17.4M
  HWY_CAPPED(int32_t, 4) di;
112
113
17.4M
  auto idx = ConvertTo(di, scaled_pos);
114
115
17.4M
  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.4M
  auto a = GatherIndex(DF4(), array, idx);
120
17.4M
  auto b = GatherIndex(DF4(), array + 1, idx);
121
122
17.4M
  return Mul(a, FastPowf(DF4(), Div(b, a), frac));
123
17.4M
}
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
37.6k
    size_t num_bands, float* out) {
133
150k
  for (size_t c = 0; c < 3; c++) {
134
112k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
112k
        distance_bands[c][0]};
136
112k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
705k
    for (size_t i = 1; i < num_bands; i++) {
138
592k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
592k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
592k
    }
141
112k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
112k
    float rcpcol = scale / (COLS - 1);
143
112k
    float rcprow = scale / (ROWS - 1);
144
112k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
112k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.84M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.73M
      float dy = y * rcprow;
148
1.73M
      float dy2 = dy * dy;
149
19.1M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
17.4M
        auto dx =
151
17.4M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
17.4M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
17.4M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
17.4M
                                     : InterpolateVec(scaled_distance, bands);
155
17.4M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
17.4M
      }
157
1.73M
    }
158
112k
  }
159
37.6k
  return true;
160
37.6k
}
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
37.6k
    size_t num_bands, float* out) {
133
150k
  for (size_t c = 0; c < 3; c++) {
134
112k
    float bands[DctQuantWeightParams::kMaxDistanceBands] = {
135
112k
        distance_bands[c][0]};
136
112k
    if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
137
705k
    for (size_t i = 1; i < num_bands; i++) {
138
592k
      bands[i] = bands[i - 1] * Mult(distance_bands[c][i]);
139
592k
      if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid distance bands");
140
592k
    }
141
112k
    float scale = (num_bands - 1) / (kSqrt2 + 1e-6f);
142
112k
    float rcpcol = scale / (COLS - 1);
143
112k
    float rcprow = scale / (ROWS - 1);
144
112k
    JXL_ENSURE(COLS >= Lanes(DF4()));
145
112k
    HWY_ALIGN float l0123[4] = {0, 1, 2, 3};
146
1.84M
    for (uint32_t y = 0; y < ROWS; y++) {
147
1.73M
      float dy = y * rcprow;
148
1.73M
      float dy2 = dy * dy;
149
19.1M
      for (uint32_t x = 0; x < COLS; x += Lanes(DF4())) {
150
17.4M
        auto dx =
151
17.4M
            Mul(Add(Set(DF4(), x), Load(DF4(), l0123)), Set(DF4(), rcpcol));
152
17.4M
        auto scaled_distance = Sqrt(MulAdd(dx, dx, Set(DF4(), dy2)));
153
17.4M
        auto weight = num_bands == 1 ? Set(DF4(), bands[0])
154
17.4M
                                     : InterpolateVec(scaled_distance, bands);
155
17.4M
        StoreU(weight, DF4(), out + c * COLS * ROWS + y * COLS + x);
156
17.4M
      }
157
1.73M
    }
158
112k
  }
159
37.6k
  return true;
160
37.6k
}
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
40.6k
                         QuantTable kind, size_t* pos) {
167
40.6k
  constexpr size_t N = kBlockDim;
168
40.6k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
40.6k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
40.6k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
40.6k
  size_t num = wrows * wcols;
172
173
40.6k
  std::vector<float> weights(3 * num);
174
175
40.6k
  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.25k
    case QuantEncoding::kQuantModeID: {
183
3.25k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.25k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.25k
      break;
186
3.25k
    }
187
2.93k
    case QuantEncoding::kQuantModeDCT2: {
188
2.93k
      JXL_ENSURE(num == kDCTBlockSize);
189
2.93k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
2.93k
      break;
191
2.93k
    }
192
2.83k
    case QuantEncoding::kQuantModeDCT4: {
193
2.83k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.83k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.83k
      JXL_RETURN_IF_ERROR(
197
2.83k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.83k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.3k
      for (size_t c = 0; c < 3; c++) {
200
76.4k
        for (size_t y = 0; y < kBlockDim; y++) {
201
611k
          for (size_t x = 0; x < kBlockDim; x++) {
202
543k
            weights[c * num + y * kBlockDim + x] =
203
543k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
543k
          }
205
67.9k
        }
206
8.49k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.49k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.49k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.49k
      }
210
2.83k
      break;
211
2.83k
    }
212
2.76k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.76k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.76k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.76k
      JXL_RETURN_IF_ERROR(
217
2.76k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.76k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.0k
      for (size_t c = 0; c < 3; c++) {
220
74.6k
        for (size_t y = 0; y < kBlockDim; y++) {
221
596k
          for (size_t x = 0; x < kBlockDim; x++) {
222
530k
            weights[c * num + y * kBlockDim + x] =
223
530k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
530k
          }
225
66.3k
        }
226
8.28k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.28k
      }
228
2.76k
      break;
229
2.76k
    }
230
25.6k
    case QuantEncoding::kQuantModeDCT: {
231
25.6k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
25.6k
          wrows, wcols, encoding.dct_params.distance_bands,
233
25.6k
          encoding.dct_params.num_distance_bands, weights.data()));
234
25.6k
      break;
235
25.6k
    }
236
25.6k
    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.20k
    case QuantEncoding::kQuantModeAFV: {
247
3.20k
      constexpr float kFreqs[] = {
248
3.20k
          0xBAD,
249
3.20k
          0xBAD,
250
3.20k
          0.8517778890324296,
251
3.20k
          5.37778436506804,
252
3.20k
          0xBAD,
253
3.20k
          0xBAD,
254
3.20k
          4.734747904497923,
255
3.20k
          5.449245381693219,
256
3.20k
          1.6598270267479331,
257
3.20k
          4,
258
3.20k
          7.275749096817861,
259
3.20k
          10.423227632456525,
260
3.20k
          2.662932286148962,
261
3.20k
          7.630657783650829,
262
3.20k
          8.962388608184032,
263
3.20k
          12.97166202570235,
264
3.20k
      };
265
266
3.20k
      float weights4x8[3 * 4 * 8];
267
3.20k
      JXL_RETURN_IF_ERROR((
268
3.20k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.20k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.19k
      float weights4x4[3 * 4 * 4];
271
3.19k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.19k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.19k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.19k
      constexpr float lo = 0.8517778890324296;
276
3.19k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
12.7k
      for (size_t c = 0; c < 3; c++) {
278
9.58k
        float bands[4];
279
9.58k
        bands[0] = encoding.afv_weights[c][5];
280
9.58k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
38.3k
        for (size_t i = 1; i < 4; i++) {
282
28.7k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
28.7k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
28.7k
        }
285
9.57k
        size_t start = c * 64;
286
162k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
162k
          weights[start + y * 8 + x] = val;
288
162k
        };
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
162k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
162k
          weights[start + y * 8 + x] = val;
288
162k
        };
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.57k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
9.57k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
9.57k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
9.57k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
9.57k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
9.57k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
47.8k
        for (size_t y = 0; y < 4; y++) {
300
191k
          for (size_t x = 0; x < 4; x++) {
301
153k
            if (x < 2 && y < 2) continue;
302
229k
            JXL_ASSIGN_OR_RETURN(
303
229k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
229k
            set_weight(2 * x, 2 * y, val);
305
229k
          }
306
38.2k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
47.8k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
344k
          for (size_t x = 0; x < kBlockDim; x++) {
311
306k
            if (x == 0 && y == 0) continue;
312
296k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
296k
                weights4x8[c * 32 + y * 8 + x];
314
296k
          }
315
38.2k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
47.8k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
191k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
153k
            if (x == 0 && y == 0) continue;
320
143k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
143k
                weights4x4[c * 16 + y * 4 + x];
322
143k
          }
323
38.2k
        }
324
9.57k
      }
325
3.18k
      break;
326
3.19k
    }
327
40.6k
  }
328
40.5k
  size_t prev_pos = *pos;
329
40.5k
  HWY_CAPPED(float, 64) d;
330
9.01M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
8.97M
    auto inv_val = LoadU(d, weights.data() + i);
332
8.97M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
8.97M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
21
      return JXL_FAILURE("Invalid quantization table");
335
21
    }
336
8.97M
    auto val = Div(Set(d, 1.0f), inv_val);
337
8.97M
    StoreU(val, d, table + *pos + i);
338
8.97M
    StoreU(inv_val, d, inv_table + *pos + i);
339
8.97M
  }
340
40.5k
  (*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
40.5k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
40.5k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
40.5k
  CoefficientLayout(&ys, &xs);
348
162k
  for (size_t c = 0; c < 3; c++) {
349
364k
    for (size_t y = 0; y < ys; y++) {
350
1.36M
      for (size_t x = 0; x < xs; x++) {
351
1.12M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.12M
                  x] = 0;
353
1.12M
      }
354
243k
    }
355
121k
  }
356
40.5k
  return true;
357
40.5k
}
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
40.6k
                         QuantTable kind, size_t* pos) {
167
40.6k
  constexpr size_t N = kBlockDim;
168
40.6k
  size_t quant_table_idx = static_cast<size_t>(kind);
169
40.6k
  size_t wrows = 8 * DequantMatrices::required_size_x[quant_table_idx];
170
40.6k
  size_t wcols = 8 * DequantMatrices::required_size_y[quant_table_idx];
171
40.6k
  size_t num = wrows * wcols;
172
173
40.6k
  std::vector<float> weights(3 * num);
174
175
40.6k
  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.25k
    case QuantEncoding::kQuantModeID: {
183
3.25k
      JXL_ENSURE(num == kDCTBlockSize);
184
3.25k
      GetQuantWeightsIdentity(encoding.idweights, weights.data());
185
3.25k
      break;
186
3.25k
    }
187
2.93k
    case QuantEncoding::kQuantModeDCT2: {
188
2.93k
      JXL_ENSURE(num == kDCTBlockSize);
189
2.93k
      GetQuantWeightsDCT2(encoding.dct2weights, weights.data());
190
2.93k
      break;
191
2.93k
    }
192
2.83k
    case QuantEncoding::kQuantModeDCT4: {
193
2.83k
      JXL_ENSURE(num == kDCTBlockSize);
194
2.83k
      float weights4x4[3 * 4 * 4];
195
      // Always use 4x4 GetQuantWeights for DCT4 quantization tables.
196
2.83k
      JXL_RETURN_IF_ERROR(
197
2.83k
          GetQuantWeights(4, 4, encoding.dct_params.distance_bands,
198
2.83k
                          encoding.dct_params.num_distance_bands, weights4x4));
199
11.3k
      for (size_t c = 0; c < 3; c++) {
200
76.4k
        for (size_t y = 0; y < kBlockDim; y++) {
201
611k
          for (size_t x = 0; x < kBlockDim; x++) {
202
543k
            weights[c * num + y * kBlockDim + x] =
203
543k
                weights4x4[c * 16 + (y / 2) * 4 + (x / 2)];
204
543k
          }
205
67.9k
        }
206
8.49k
        weights[c * num + 1] /= encoding.dct4multipliers[c][0];
207
8.49k
        weights[c * num + N] /= encoding.dct4multipliers[c][0];
208
8.49k
        weights[c * num + N + 1] /= encoding.dct4multipliers[c][1];
209
8.49k
      }
210
2.83k
      break;
211
2.83k
    }
212
2.76k
    case QuantEncoding::kQuantModeDCT4X8: {
213
2.76k
      JXL_ENSURE(num == kDCTBlockSize);
214
2.76k
      float weights4x8[3 * 4 * 8];
215
      // Always use 4x8 GetQuantWeights for DCT4X8 quantization tables.
216
2.76k
      JXL_RETURN_IF_ERROR(
217
2.76k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
218
2.76k
                          encoding.dct_params.num_distance_bands, weights4x8));
219
11.0k
      for (size_t c = 0; c < 3; c++) {
220
74.6k
        for (size_t y = 0; y < kBlockDim; y++) {
221
596k
          for (size_t x = 0; x < kBlockDim; x++) {
222
530k
            weights[c * num + y * kBlockDim + x] =
223
530k
                weights4x8[c * 32 + (y / 2) * 8 + x];
224
530k
          }
225
66.3k
        }
226
8.28k
        weights[c * num + N] /= encoding.dct4x8multipliers[c];
227
8.28k
      }
228
2.76k
      break;
229
2.76k
    }
230
25.6k
    case QuantEncoding::kQuantModeDCT: {
231
25.6k
      JXL_RETURN_IF_ERROR(GetQuantWeights(
232
25.6k
          wrows, wcols, encoding.dct_params.distance_bands,
233
25.6k
          encoding.dct_params.num_distance_bands, weights.data()));
234
25.6k
      break;
235
25.6k
    }
236
25.6k
    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.20k
    case QuantEncoding::kQuantModeAFV: {
247
3.20k
      constexpr float kFreqs[] = {
248
3.20k
          0xBAD,
249
3.20k
          0xBAD,
250
3.20k
          0.8517778890324296,
251
3.20k
          5.37778436506804,
252
3.20k
          0xBAD,
253
3.20k
          0xBAD,
254
3.20k
          4.734747904497923,
255
3.20k
          5.449245381693219,
256
3.20k
          1.6598270267479331,
257
3.20k
          4,
258
3.20k
          7.275749096817861,
259
3.20k
          10.423227632456525,
260
3.20k
          2.662932286148962,
261
3.20k
          7.630657783650829,
262
3.20k
          8.962388608184032,
263
3.20k
          12.97166202570235,
264
3.20k
      };
265
266
3.20k
      float weights4x8[3 * 4 * 8];
267
3.20k
      JXL_RETURN_IF_ERROR((
268
3.20k
          GetQuantWeights(4, 8, encoding.dct_params.distance_bands,
269
3.20k
                          encoding.dct_params.num_distance_bands, weights4x8)));
270
3.19k
      float weights4x4[3 * 4 * 4];
271
3.19k
      JXL_RETURN_IF_ERROR((GetQuantWeights(
272
3.19k
          4, 4, encoding.dct_params_afv_4x4.distance_bands,
273
3.19k
          encoding.dct_params_afv_4x4.num_distance_bands, weights4x4)));
274
275
3.19k
      constexpr float lo = 0.8517778890324296;
276
3.19k
      constexpr float hi = 12.97166202570235f - lo + 1e-6f;
277
12.7k
      for (size_t c = 0; c < 3; c++) {
278
9.58k
        float bands[4];
279
9.58k
        bands[0] = encoding.afv_weights[c][5];
280
9.58k
        if (bands[0] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
281
38.3k
        for (size_t i = 1; i < 4; i++) {
282
28.7k
          bands[i] = bands[i - 1] * Mult(encoding.afv_weights[c][i + 5]);
283
28.7k
          if (bands[i] < kAlmostZero) return JXL_FAILURE("Invalid AFV bands");
284
28.7k
        }
285
9.57k
        size_t start = c * 64;
286
9.57k
        auto set_weight = [&start, &weights](size_t x, size_t y, float val) {
287
9.57k
          weights[start + y * 8 + x] = val;
288
9.57k
        };
289
9.57k
        weights[start] = 1;  // Not used, but causes MSAN error otherwise.
290
        // Weights for (0, 1) and (1, 0).
291
9.57k
        set_weight(0, 1, encoding.afv_weights[c][0]);
292
9.57k
        set_weight(1, 0, encoding.afv_weights[c][1]);
293
        // AFV special weights for 3-pixel corner.
294
9.57k
        set_weight(0, 2, encoding.afv_weights[c][2]);
295
9.57k
        set_weight(2, 0, encoding.afv_weights[c][3]);
296
9.57k
        set_weight(2, 2, encoding.afv_weights[c][4]);
297
298
        // All other AFV weights.
299
47.8k
        for (size_t y = 0; y < 4; y++) {
300
191k
          for (size_t x = 0; x < 4; x++) {
301
153k
            if (x < 2 && y < 2) continue;
302
229k
            JXL_ASSIGN_OR_RETURN(
303
229k
                float val, Interpolate(kFreqs[y * 4 + x] - lo, hi, bands, 4));
304
229k
            set_weight(2 * x, 2 * y, val);
305
229k
          }
306
38.2k
        }
307
308
        // Put 4x8 weights in odd rows, except (1, 0).
309
47.8k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
310
344k
          for (size_t x = 0; x < kBlockDim; x++) {
311
306k
            if (x == 0 && y == 0) continue;
312
296k
            weights[c * num + (2 * y + 1) * kBlockDim + x] =
313
296k
                weights4x8[c * 32 + y * 8 + x];
314
296k
          }
315
38.2k
        }
316
        // Put 4x4 weights in even rows / odd columns, except (0, 1).
317
47.8k
        for (size_t y = 0; y < kBlockDim / 2; y++) {
318
191k
          for (size_t x = 0; x < kBlockDim / 2; x++) {
319
153k
            if (x == 0 && y == 0) continue;
320
143k
            weights[c * num + (2 * y) * kBlockDim + 2 * x + 1] =
321
143k
                weights4x4[c * 16 + y * 4 + x];
322
143k
          }
323
38.2k
        }
324
9.57k
      }
325
3.18k
      break;
326
3.19k
    }
327
40.6k
  }
328
40.5k
  size_t prev_pos = *pos;
329
40.5k
  HWY_CAPPED(float, 64) d;
330
9.01M
  for (size_t i = 0; i < num * 3; i += Lanes(d)) {
331
8.97M
    auto inv_val = LoadU(d, weights.data() + i);
332
8.97M
    if (JXL_UNLIKELY(!AllFalse(d, Ge(inv_val, Set(d, 1.0f / kAlmostZero))) ||
333
8.97M
                     !AllFalse(d, Lt(inv_val, Set(d, kAlmostZero))))) {
334
21
      return JXL_FAILURE("Invalid quantization table");
335
21
    }
336
8.97M
    auto val = Div(Set(d, 1.0f), inv_val);
337
8.97M
    StoreU(val, d, table + *pos + i);
338
8.97M
    StoreU(inv_val, d, inv_table + *pos + i);
339
8.97M
  }
340
40.5k
  (*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
40.5k
  size_t xs = DequantMatrices::required_size_x[quant_table_idx];
346
40.5k
  size_t ys = DequantMatrices::required_size_y[quant_table_idx];
347
40.5k
  CoefficientLayout(&ys, &xs);
348
162k
  for (size_t c = 0; c < 3; c++) {
349
364k
    for (size_t y = 0; y < ys; y++) {
350
1.36M
      for (size_t x = 0; x < xs; x++) {
351
1.12M
        inv_table[prev_pos + c * ys * xs * kDCTBlockSize + y * kBlockDim * xs +
352
1.12M
                  x] = 0;
353
1.12M
      }
354
243k
    }
355
121k
  }
356
40.5k
  return true;
357
40.5k
}
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
197
Status DecodeDctParams(BitReader* br, DctQuantWeightParams* params) {
374
197
  params->num_distance_bands =
375
197
      br->ReadFixedBits<DctQuantWeightParams::kLog2MaxDistanceBands>() + 1;
376
630
  for (size_t c = 0; c < 3; c++) {
377
2.67k
    for (size_t i = 0; i < params->num_distance_bands; i++) {
378
2.18k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &params->distance_bands[c][i]));
379
2.18k
    }
380
491
    if (params->distance_bands[c][0] < kAlmostZero) {
381
58
      return JXL_FAILURE("Distance band seed is too small");
382
58
    }
383
433
    params->distance_bands[c][0] *= 64.0f;
384
433
  }
385
131
  return true;
386
197
}
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.30k
              ModularFrameDecoder* modular_frame_decoder) {
392
5.30k
  size_t required_size = required_size_x * required_size_y;
393
5.30k
  required_size_x *= kBlockDim;
394
5.30k
  required_size_y *= kBlockDim;
395
5.30k
  int mode = br->ReadFixedBits<kLog2NumQuantModes>();
396
5.30k
  switch (mode) {
397
4.76k
    case QuantEncoding::kQuantModeLibrary: {
398
4.76k
      encoding->predefined = br->ReadFixedBits<kCeilLog2NumPredefinedTables>();
399
4.76k
      if (encoding->predefined >= kNumPredefinedTables) {
400
0
        return JXL_FAILURE("Invalid predefined table");
401
0
      }
402
4.76k
      break;
403
4.76k
    }
404
4.76k
    case QuantEncoding::kQuantModeID: {
405
85
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
406
214
      for (size_t c = 0; c < 3; c++) {
407
635
        for (size_t i = 0; i < 3; i++) {
408
499
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->idweights[c][i]));
409
481
          if (std::abs(encoding->idweights[c][i]) < kAlmostZero) {
410
28
            return JXL_FAILURE("ID Quantizer is too small");
411
28
          }
412
453
          encoding->idweights[c][i] *= 64;
413
453
        }
414
182
      }
415
32
      break;
416
78
    }
417
113
    case QuantEncoding::kQuantModeDCT2: {
418
113
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
419
251
      for (size_t c = 0; c < 3; c++) {
420
1.28k
        for (size_t i = 0; i < 6; i++) {
421
1.14k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->dct2weights[c][i]));
422
1.10k
          if (std::abs(encoding->dct2weights[c][i]) < kAlmostZero) {
423
47
            return JXL_FAILURE("Quantizer is too small");
424
47
          }
425
1.05k
          encoding->dct2weights[c][i] *= 64;
426
1.05k
        }
427
229
      }
428
22
      break;
429
108
    }
430
68
    case QuantEncoding::kQuantModeDCT4X8: {
431
68
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
432
212
      for (size_t c = 0; c < 3; c++) {
433
167
        JXL_RETURN_IF_ERROR(
434
167
            F16Coder::Read(br, &encoding->dct4x8multipliers[c]));
435
158
        if (std::abs(encoding->dct4x8multipliers[c]) < kAlmostZero) {
436
7
          return JXL_FAILURE("DCT4X8 multiplier is too small");
437
7
        }
438
158
      }
439
45
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
440
34
      break;
441
45
    }
442
50
    case QuantEncoding::kQuantModeDCT4: {
443
50
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
444
133
      for (size_t c = 0; c < 3; c++) {
445
298
        for (size_t i = 0; i < 2; i++) {
446
212
          JXL_RETURN_IF_ERROR(
447
212
              F16Coder::Read(br, &encoding->dct4multipliers[c][i]));
448
201
          if (std::abs(encoding->dct4multipliers[c][i]) < kAlmostZero) {
449
16
            return JXL_FAILURE("DCT4 multiplier is too small");
450
16
          }
451
201
        }
452
113
      }
453
20
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
454
14
      break;
455
20
    }
456
98
    case QuantEncoding::kQuantModeAFV: {
457
98
      if (required_size != 1) return JXL_FAILURE("Invalid mode");
458
276
      for (size_t c = 0; c < 3; c++) {
459
2.07k
        for (size_t i = 0; i < 9; i++) {
460
1.89k
          JXL_RETURN_IF_ERROR(F16Coder::Read(br, &encoding->afv_weights[c][i]));
461
1.89k
        }
462
1.26k
        for (size_t i = 0; i < 6; i++) {
463
1.08k
          encoding->afv_weights[c][i] *= 64;
464
1.08k
        }
465
180
      }
466
42
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
467
24
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params_afv_4x4));
468
20
      break;
469
24
    }
470
66
    case QuantEncoding::kQuantModeDCT: {
471
66
      JXL_RETURN_IF_ERROR(DecodeDctParams(br, &encoding->dct_params));
472
39
      break;
473
66
    }
474
59
    case QuantEncoding::kQuantModeRAW: {
475
      // Set mode early, to avoid mem-leak.
476
59
      encoding->mode = QuantEncoding::kQuantModeRAW;
477
59
      JXL_RETURN_IF_ERROR(ModularFrameDecoder::DecodeQuantTable(
478
59
          memory_manager, required_size_x, required_size_y, br, encoding, idx,
479
59
          modular_frame_decoder));
480
9
      break;
481
59
    }
482
9
    default:
483
0
      return JXL_FAILURE("Invalid quantization table encoding");
484
5.30k
  }
485
4.93k
  encoding->mode = static_cast<QuantEncoding::Mode>(mode);
486
4.93k
  return true;
487
5.30k
}
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.30k
                               ModularFrameDecoder* modular_frame_decoder) {
499
4.30k
  size_t all_default = br->ReadBits(1);
500
4.30k
  size_t num_tables = all_default ? 0 : static_cast<size_t>(kNumQuantTables);
501
4.30k
  encodings_.clear();
502
4.30k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
503
9.24k
  for (size_t i = 0; i < num_tables; i++) {
504
5.30k
    JXL_RETURN_IF_ERROR(jxl::Decode(memory_manager, br, &encodings_[i],
505
5.30k
                                    required_size_x[i % kNumQuantTables],
506
5.30k
                                    required_size_y[i % kNumQuantTables], i,
507
5.30k
                                    modular_frame_decoder));
508
5.30k
  }
509
3.93k
  computed_mask_ = 0;
510
3.93k
  return true;
511
4.30k
}
512
513
38.4k
Status DequantMatrices::DecodeDC(BitReader* br) {
514
38.4k
  bool all_default = static_cast<bool>(br->ReadBits(1));
515
38.4k
  if (!br->AllReadsWithinBounds()) return JXL_FAILURE("EOS during DecodeDC");
516
38.1k
  if (!all_default) {
517
21.1k
    for (size_t c = 0; c < 3; c++) {
518
15.9k
      JXL_RETURN_IF_ERROR(F16Coder::Read(br, &dc_quant_[c]));
519
15.9k
      dc_quant_[c] *= 1.0f / 128.0f;
520
      // Negative values and nearly zero are invalid values.
521
15.9k
      if (dc_quant_[c] < kAlmostZero) {
522
57
        return JXL_FAILURE("Invalid dc_quant: coefficient is too small.");
523
57
      }
524
15.8k
      inv_dc_quant_[c] = 1.0f / dc_quant_[c];
525
15.8k
    }
526
5.33k
  }
527
38.0k
  return true;
528
38.1k
}
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
6.62k
const QuantEncoding* DequantMatrices::Library() {
1179
6.62k
  static const DequantMatrices::DequantLibraryInternal kDequantLibrary =
1180
6.62k
      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
6.62k
  return reinterpret_cast<const QuantEncoding*>(kDequantLibrary.data());
1188
6.62k
}
1189
1190
86.7k
DequantMatrices::DequantMatrices() {
1191
86.7k
  encodings_.resize(kNumQuantTables, QuantEncoding::Library<0>());
1192
86.7k
  size_t pos = 0;
1193
86.7k
  size_t offsets[kNumQuantTables * 3];
1194
1.56M
  for (size_t i = 0; i < static_cast<size_t>(kNumQuantTables); i++) {
1195
1.47M
    size_t num_blocks =
1196
1.47M
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1197
1.47M
    size_t num = num_blocks * kDCTBlockSize;
1198
5.90M
    for (size_t c = 0; c < 3; c++) {
1199
4.42M
      offsets[3 * i + c] = pos + c * num;
1200
4.42M
    }
1201
1.47M
    pos += 3 * num;
1202
1.47M
  }
1203
2.42M
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1204
9.37M
    for (size_t c = 0; c < 3; c++) {
1205
7.02M
      table_offsets_[i * 3 + c] =
1206
7.02M
          offsets[static_cast<size_t>(kAcStrategyToQuantTableMap[i]) * 3 + c];
1207
7.02M
    }
1208
2.34M
  }
1209
86.7k
}
1210
1211
Status DequantMatrices::EnsureComputed(JxlMemoryManager* memory_manager,
1212
6.62k
                                       uint32_t acs_mask) {
1213
6.62k
  const QuantEncoding* library = Library();
1214
1215
6.62k
  if (!table_storage_) {
1216
6.62k
    size_t table_storage_bytes = 2 * kTotalTableSize * sizeof(float);
1217
6.62k
    JXL_ASSIGN_OR_RETURN(
1218
6.62k
        table_storage_,
1219
6.62k
        AlignedMemory::Create(memory_manager, table_storage_bytes));
1220
6.62k
    table_ = table_storage_.address<float>();
1221
6.62k
    inv_table_ = table_ + kTotalTableSize;
1222
6.62k
  }
1223
1224
6.62k
  size_t offsets[kNumQuantTables * 3 + 1];
1225
6.62k
  size_t pos = 0;
1226
119k
  for (size_t i = 0; i < kNumQuantTables; i++) {
1227
112k
    size_t num_blocks =
1228
112k
        static_cast<size_t>(required_size_x[i]) * required_size_y[i];
1229
112k
    size_t num = num_blocks * kDCTBlockSize;
1230
450k
    for (size_t c = 0; c < 3; c++) {
1231
337k
      offsets[3 * i + c] = pos + c * num;
1232
337k
    }
1233
112k
    pos += 3 * num;
1234
112k
  }
1235
6.62k
  offsets[kNumQuantTables * 3] = pos;
1236
6.62k
  JXL_ENSURE(pos == kTotalTableSize);
1237
1238
6.62k
  uint32_t kind_mask = 0;
1239
185k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1240
178k
    if (acs_mask & (1u << i)) {
1241
62.1k
      kind_mask |= 1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1242
62.1k
    }
1243
178k
  }
1244
6.62k
  uint32_t computed_kind_mask = 0;
1245
185k
  for (size_t i = 0; i < AcStrategy::kNumValidStrategies; i++) {
1246
178k
    if (computed_mask_ & (1u << i)) {
1247
0
      computed_kind_mask |=
1248
0
          1u << static_cast<uint32_t>(kAcStrategyToQuantTableMap[i]);
1249
0
    }
1250
178k
  }
1251
118k
  for (size_t table = 0; table < kNumQuantTables; table++) {
1252
111k
    if ((1 << table) & computed_kind_mask) continue;
1253
111k
    if ((1 << table) & ~kind_mask) continue;
1254
40.6k
    size_t offset = offsets[table * 3];
1255
40.6k
    float* mutable_table = table_storage_.address<float>();
1256
40.6k
    if (encodings_[table].mode == QuantEncoding::kQuantModeLibrary) {
1257
40.5k
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1258
40.5k
          library[table], mutable_table, mutable_table + kTotalTableSize, table,
1259
40.5k
          QuantTable(table), &offset));
1260
40.5k
    } else {
1261
61
      JXL_RETURN_IF_ERROR(HWY_DYNAMIC_DISPATCH(ComputeQuantTable)(
1262
61
          encodings_[table], mutable_table, mutable_table + kTotalTableSize,
1263
61
          table, QuantTable(table), &offset));
1264
61
    }
1265
40.5k
    JXL_ENSURE(offset == offsets[table * 3 + 3]);
1266
40.5k
  }
1267
6.57k
  computed_mask_ |= acs_mask;
1268
1269
6.57k
  return true;
1270
6.62k
}
1271
1272
}  // namespace jxl
1273
#endif