// Copyright (c) the JPEG XL Project Authors. All rights reserved. // // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file.
usesuper::*; use jxl_simd::{test_all_instruction_sets, ScalarDescriptor, SimdDescriptor}; use rand::Rng; use rand::SeedableRng; use rand_chacha::ChaCha12Rng; use test_log::test;
use std::f64::consts::FRAC_1_SQRT_2; use std::f64::consts::PI; use std::f64::consts::SQRT_2;
#[inline(always)] fn alpha(u: usize) -> f64 { if u == 0 {
FRAC_1_SQRT_2
} else { 1.0
}
}
pubfn dct1d(input_matrix: &[Vec<f64>]) -> Vec<Vec<f64>> { let num_rows = input_matrix.len();
// Precompute the DCT matrix (size: n_rows x n_rows) letmut dct_coeff_matrix = vec![vec![0.0f64; num_rows]; num_rows]; for (u_freq, row) in dct_coeff_matrix.iter_mut().enumerate() { let alpha_u_val = alpha(u_freq); for (y_spatial, coeff) in row.iter_mut().enumerate() {
*coeff = alpha_u_val
* ((y_spatial as f64 + 0.5) * u_freq as f64 * PI / num_rows as f64).cos()
* scale;
}
}
// Perform the DCT calculation column by column for x_col_idx in0..num_cols { for u_freq_idx in0..num_rows { letmut sum = 0.0; for (y_spatial_idx, col) in input_matrix.iter().enumerate() { // This access `input_matrix[y_spatial_idx][x_col_idx]` assumes the input_matrix // is rectangular. If not, it might panic here.
sum += dct_coeff_matrix[u_freq_idx][y_spatial_idx] * col[x_col_idx];
}
output_matrix[u_freq_idx][x_col_idx] = sum;
}
}
output_matrix
}
pubfn idct1d(input_matrix: &[Vec<f64>]) -> Vec<Vec<f64>> { let num_rows = input_matrix.len();
// Precompute the DCT matrix (size: num_rows x num_rows) letmut dct_coeff_matrix = vec![vec![0.0f64; num_rows]; num_rows]; for (u_freq, row) in dct_coeff_matrix.iter_mut().enumerate() { let alpha_u_val = alpha(u_freq); for (y_def_idx, coeff) in row.iter_mut().enumerate() {
*coeff = alpha_u_val
* ((y_def_idx as f64 + 0.5) * u_freq as f64 * PI / num_rows as f64).cos()
* scale;
}
}
// Perform the IDCT calculation column by column for x_col_idx in0..num_cols { for (y_row_idx, row) in output_matrix.iter_mut().enumerate() { letmut sum = 0.0; for (u_freq_idx, col) in input_matrix.iter().enumerate() { // This access input_coeffs_matrix[u_freq_idx][x_col_idx] assumes input_coeffs_matrix // is rectangular. If not, it might panic here.
sum += dct_coeff_matrix[u_freq_idx][y_row_idx] * col[x_col_idx];
}
row[x_col_idx] = sum;
}
}
output_matrix
}
fn transpose_f64(matrix: &[Vec<f64>]) -> Vec<Vec<f64>> { if matrix.is_empty() { return Vec::new();
} let num_rows = matrix.len(); let num_cols = matrix[0].len(); letmut transposed = vec![vec![0.0; num_rows]; num_cols]; for i in0..num_rows { for j in0..num_cols {
transposed[j][i] = matrix[i][j];
}
}
transposed
}
pubfn slow_idct2d(input: &[Vec<f64>]) -> Vec<Vec<f64>> { let rows = input.len(); let cols = input[0].len(); let idct1 = if rows < cols { let transposed = transpose_f64(input);
idct1d(&transposed)
} else { let input: Vec<_> = input.iter().flat_map(|x| x.iter()).copied().collect(); let input: Vec<_> = input.chunks_exact(rows).map(|x| x.to_vec()).collect();
idct1d(&input)
}; let transposed1 = transpose_f64(&idct1);
idct1d(&transposed1)
}
pubfn scales(n: usize) -> Vec<f64> {
(0..n)
.map(|i| {
(i as f64 / (16 * n) as f64 * PI).cos()
* (i as f64 / (8 * n) as f64 * PI).cos()
* (i as f64 / (4 * n) as f64 * PI).cos()
* n as f64
})
.collect()
}
pubfn slow_reinterpreting_dct2d(input: &[Vec<f64>]) -> Vec<Vec<f64>> { let rows = input.len(); let cols = input[0].len(); let dct1 = dct1d(input); let tdct1 = transpose_f64(&dct1); let dct2 = dct1d(&tdct1); letmut res = if rows < cols {
transpose_f64(&dct2)
} else {
dct2
};
let row_scales = scales(rows); let col_scales = scales(cols); if rows < cols { for y in0..rows { for x in0..cols {
res[y][x] /= row_scales[y] * col_scales[x];
}
}
} else { for y in0..cols { for x in0..rows {
res[y][x] /= row_scales[x] * col_scales[y];
}
}
}
res
}
let on = slow_output.len(); let om = slow_output[0].len();
for r in0..on { for c in0..om {
check_close(output[r * om * 8 + c] as f64, slow_output[r][c], $tol);
}
}
}
test_all_instruction_sets!($test_name);
};
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.