Coverage Report

Created: 2025-12-13 07:57

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