Coverage Report

Created: 2026-11-12 07:35

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