Coverage Report

Created: 2025-08-12 07:37

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