1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <cmath>
#include <limits>
#include "base/basictypes.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/matrix3_f.h"
namespace gfx {
namespace {
TEST(Matrix3fTest, Constructors) {
Matrix3F zeros = Matrix3F::Zeros();
Matrix3F ones = Matrix3F::Ones();
Matrix3F identity = Matrix3F::Identity();
Matrix3F product_ones = Matrix3F::FromOuterProduct(
Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(1.0f, 1.0f, 1.0f));
Matrix3F product_zeros = Matrix3F::FromOuterProduct(
Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(0.0f, 0.0f, 0.0f));
EXPECT_EQ(ones, product_ones);
EXPECT_EQ(zeros, product_zeros);
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j)
EXPECT_EQ(i == j ? 1.0f : 0.0f, identity.get(i, j));
}
}
TEST(Matrix3fTest, DataAccess) {
Matrix3F matrix = Matrix3F::Ones();
Matrix3F identity = Matrix3F::Identity();
EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), identity.get_column(1));
matrix.set(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f);
EXPECT_EQ(Vector3dF(2.0f, 5.0f, 8.0f), matrix.get_column(2));
matrix.set_column(0, Vector3dF(0.1f, 0.2f, 0.3f));
EXPECT_EQ(Vector3dF(0.1f, 0.2f, 0.3f), matrix.get_column(0));
EXPECT_EQ(0.1f, matrix.get(0, 0));
EXPECT_EQ(5.0f, matrix.get(1, 2));
}
TEST(Matrix3fTest, Determinant) {
EXPECT_EQ(1.0f, Matrix3F::Identity().Determinant());
EXPECT_EQ(0.0f, Matrix3F::Zeros().Determinant());
EXPECT_EQ(0.0f, Matrix3F::Ones().Determinant());
// Now for something non-trivial...
Matrix3F matrix = Matrix3F::Zeros();
matrix.set(0, 5, 6, 8, 7, 0, 1, 9, 0);
EXPECT_EQ(390.0f, matrix.Determinant());
matrix.set(2, 0, 3 * matrix.get(0, 0));
matrix.set(2, 1, 3 * matrix.get(0, 1));
matrix.set(2, 2, 3 * matrix.get(0, 2));
EXPECT_EQ(0, matrix.Determinant());
matrix.set(0.57f, 0.205f, 0.942f,
0.314f, 0.845f, 0.826f,
0.131f, 0.025f, 0.962f);
EXPECT_NEAR(0.3149f, matrix.Determinant(), 0.0001f);
}
TEST(Matrix3fTest, Inverse) {
Matrix3F identity = Matrix3F::Identity();
Matrix3F inv_identity = identity.Inverse();
EXPECT_EQ(identity, inv_identity);
Matrix3F singular = Matrix3F::Zeros();
singular.set(1.0f, 3.0f, 4.0f,
2.0f, 11.0f, 5.0f,
0.5f, 1.5f, 2.0f);
EXPECT_EQ(0, singular.Determinant());
EXPECT_EQ(Matrix3F::Zeros(), singular.Inverse());
Matrix3F regular = Matrix3F::Zeros();
regular.set(0.57f, 0.205f, 0.942f,
0.314f, 0.845f, 0.826f,
0.131f, 0.025f, 0.962f);
Matrix3F inv_regular = regular.Inverse();
regular.set(2.51540616f, -0.55138018f, -1.98968043f,
-0.61552266f, 1.34920184f, -0.55573636f,
-0.32653861f, 0.04002158f, 1.32488726f);
EXPECT_TRUE(regular.IsNear(inv_regular, 0.00001f));
}
TEST(Matrix3fTest, EigenvectorsIdentity) {
// This block tests the trivial case of eigenvalues of the identity matrix.
Matrix3F identity = Matrix3F::Identity();
Vector3dF eigenvals = identity.SolveEigenproblem(NULL);
EXPECT_EQ(Vector3dF(1.0f, 1.0f, 1.0f), eigenvals);
}
TEST(Matrix3fTest, EigenvectorsDiagonal) {
// This block tests the another trivial case of eigenvalues of a diagonal
// matrix. Here we expect values to be sorted.
Matrix3F matrix = Matrix3F::Zeros();
matrix.set(0, 0, 1.0f);
matrix.set(1, 1, -2.5f);
matrix.set(2, 2, 3.14f);
Matrix3F eigenvectors = Matrix3F::Zeros();
Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
EXPECT_EQ(Vector3dF(3.14f, 1.0f, -2.5f), eigenvals);
EXPECT_EQ(Vector3dF(0.0f, 0.0f, 1.0f), eigenvectors.get_column(0));
EXPECT_EQ(Vector3dF(1.0f, 0.0f, 0.0f), eigenvectors.get_column(1));
EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), eigenvectors.get_column(2));
}
TEST(Matrix3fTest, EigenvectorsNiceNotPositive) {
// This block tests computation of eigenvectors of a matrix where nice
// round values are expected.
Matrix3F matrix = Matrix3F::Zeros();
// This is not a positive-definite matrix but eigenvalues and the first
// eigenvector should nonetheless be computed correctly.
matrix.set(3, 2, 4, 2, 0, 2, 4, 2, 3);
Matrix3F eigenvectors = Matrix3F::Zeros();
Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
EXPECT_EQ(Vector3dF(8.0f, -1.0f, -1.0f), eigenvals);
Vector3dF expected_principal(0.66666667f, 0.33333333f, 0.66666667f);
EXPECT_NEAR(0.0f,
(expected_principal - eigenvectors.get_column(0)).Length(),
0.000001f);
}
TEST(Matrix3fTest, EigenvectorsPositiveDefinite) {
// This block tests computation of eigenvectors of a matrix where output
// is not as nice as above, but it actually meets the definition.
Matrix3F matrix = Matrix3F::Zeros();
Matrix3F eigenvectors = Matrix3F::Zeros();
Matrix3F expected_eigenvectors = Matrix3F::Zeros();
matrix.set(1, -1, 2, -1, 4, 5, 2, 5, 0);
Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors);
Vector3dF expected_eigv(7.3996266f, 1.91197255f, -4.31159915f);
expected_eigv -= eigenvals;
EXPECT_NEAR(0, expected_eigv.LengthSquared(), 0.00001f);
expected_eigenvectors.set(0.04926317f, -0.92135662f, -0.38558414f,
0.82134249f, 0.25703273f, -0.50924521f,
0.56830419f, -0.2916096f, 0.76941158f);
EXPECT_TRUE(expected_eigenvectors.IsNear(eigenvectors, 0.00001f));
}
}
}
|