Coverage Report

Created: 2026-02-14 07:11

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