enc_linalg_test.cc (2519B)
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 6 #include "lib/jxl/enc_linalg.h" 7 8 #include <cstddef> 9 10 #include "lib/jxl/base/random.h" 11 #include "lib/jxl/testing.h" 12 13 namespace jxl { 14 namespace { 15 16 Matrix2x2 Diagonal(const Vector2& d) { return {{{d[0], 0.0}, {0.0, d[1]}}}; } 17 18 Matrix2x2 Identity() { return Diagonal({1.0, 1.0}); } 19 20 Matrix2x2 MatMul(const Matrix2x2& A, const Matrix2x2& B) { 21 Matrix2x2 out; 22 for (size_t y = 0; y < 2; ++y) { 23 for (size_t x = 0; x < 2; ++x) { 24 out[y][x] = A[0][x] * B[y][0] + A[1][x] * B[y][1]; 25 } 26 } 27 return out; 28 } 29 30 Matrix2x2 Transpose(const Matrix2x2& A) { 31 return {{{A[0][0], A[1][0]}, {A[0][1], A[1][1]}}}; 32 } 33 34 Matrix2x2 RandomSymmetricMatrix(Rng& rng, const double vmin, 35 const double vmax) { 36 Matrix2x2 A; 37 A[0][0] = rng.UniformF(vmin, vmax); 38 A[0][1] = A[1][0] = rng.UniformF(vmin, vmax); 39 A[1][1] = rng.UniformF(vmin, vmax); 40 return A; 41 } 42 43 void VerifyMatrixEqual(const Matrix2x2& A, const Matrix2x2& B, 44 const double eps) { 45 for (size_t y = 0; y < 2; ++y) { 46 for (size_t x = 0; x < 2; ++x) { 47 ASSERT_NEAR(A[y][x], B[y][x], eps); 48 } 49 } 50 } 51 52 void VerifyOrthogonal(const Matrix2x2& A, const double eps) { 53 VerifyMatrixEqual(Identity(), MatMul(Transpose(A), A), eps); 54 } 55 56 TEST(LinAlgTest, ConvertToDiagonal) { 57 { 58 Matrix2x2 I = Identity(); 59 Matrix2x2 U; 60 Vector2 d; 61 ConvertToDiagonal(I, d, U); 62 VerifyMatrixEqual(I, U, 1e-15); 63 for (size_t k = 0; k < 2; ++k) { 64 ASSERT_NEAR(d[k], 1.0, 1e-15); 65 } 66 } 67 { 68 Matrix2x2 A = Identity(); 69 A[0][1] = A[1][0] = 2.0; 70 Matrix2x2 U; 71 Vector2 d; 72 ConvertToDiagonal(A, d, U); 73 VerifyOrthogonal(U, 1e-12); 74 VerifyMatrixEqual(A, MatMul(U, MatMul(Diagonal(d), Transpose(U))), 1e-12); 75 } 76 { 77 Matrix2x2 A; 78 A[0] = {0.000208649, 1.13687e-12}; 79 A[1] = {1.13687e-12, 0.000208649}; 80 Matrix2x2 U; 81 Vector2 d; 82 ConvertToDiagonal(A, d, U); 83 VerifyOrthogonal(U, 1e-12); 84 VerifyMatrixEqual(A, MatMul(U, MatMul(Diagonal(d), Transpose(U))), 1e-11); 85 } 86 Rng rng(0); 87 for (size_t i = 0; i < 1000000; ++i) { 88 Matrix2x2 A = RandomSymmetricMatrix(rng, -1.0, 1.0); 89 Matrix2x2 U; 90 Vector2 d; 91 ConvertToDiagonal(A, d, U); 92 VerifyOrthogonal(U, 1e-12); 93 VerifyMatrixEqual(A, MatMul(U, MatMul(Diagonal(d), Transpose(U))), 5e-10); 94 } 95 } 96 97 } // namespace 98 } // namespace jxl