// 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. #ifndef LIB_JXL_MATRIX_OPS_H_ #define LIB_JXL_MATRIX_OPS_H_ // 3x3 matrix operations. #include #include // abs #include #include "lib/jxl/base/status.h" namespace jxl { typedef std::array Vector3; typedef std::array Vector3d; typedef std::array Matrix3x3; typedef std::array Matrix3x3d; // Computes C = A * B, where A, B, C are 3x3 matrices. template void Mul3x3Matrix(const Matrix& a, const Matrix& b, Matrix& c) { for (size_t x = 0; x < 3; x++) { alignas(16) Vector3d temp{b[0][x], b[1][x], b[2][x]}; // transpose for (size_t y = 0; y < 3; y++) { c[y][x] = a[y][0] * temp[0] + a[y][1] * temp[1] + a[y][2] * temp[2]; } } } // Computes C = A * B, where A is 3x3 matrix and B is vector. template void Mul3x3Vector(const Matrix& a, const Vector& b, Vector& c) { for (size_t y = 0; y < 3; y++) { double e = 0; for (size_t x = 0; x < 3; x++) { e += a[y][x] * b[x]; } c[y] = e; } } // Inverts a 3x3 matrix in place. template Status Inv3x3Matrix(Matrix& matrix) { // Intermediate computation is done in double precision. Matrix3x3d temp; temp[0][0] = static_cast(matrix[1][1]) * matrix[2][2] - static_cast(matrix[1][2]) * matrix[2][1]; temp[0][1] = static_cast(matrix[0][2]) * matrix[2][1] - static_cast(matrix[0][1]) * matrix[2][2]; temp[0][2] = static_cast(matrix[0][1]) * matrix[1][2] - static_cast(matrix[0][2]) * matrix[1][1]; temp[1][0] = static_cast(matrix[1][2]) * matrix[2][0] - static_cast(matrix[1][0]) * matrix[2][2]; temp[1][1] = static_cast(matrix[0][0]) * matrix[2][2] - static_cast(matrix[0][2]) * matrix[2][0]; temp[1][2] = static_cast(matrix[0][2]) * matrix[1][0] - static_cast(matrix[0][0]) * matrix[1][2]; temp[2][0] = static_cast(matrix[1][0]) * matrix[2][1] - static_cast(matrix[1][1]) * matrix[2][0]; temp[2][1] = static_cast(matrix[0][1]) * matrix[2][0] - static_cast(matrix[0][0]) * matrix[2][1]; temp[2][2] = static_cast(matrix[0][0]) * matrix[1][1] - static_cast(matrix[0][1]) * matrix[1][0]; double det = matrix[0][0] * temp[0][0] + matrix[0][1] * temp[1][0] + matrix[0][2] * temp[2][0]; if (std::abs(det) < 1e-10) { return JXL_FAILURE("Matrix determinant is too close to 0"); } double idet = 1.0 / det; for (size_t j = 0; j < 3; j++) { for (size_t i = 0; i < 3; i++) { matrix[j][i] = temp[j][i] * idet; } } return true; } } // namespace jxl #endif // LIB_JXL_MATRIX_OPS_H_