12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath> 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <limits> 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/geometry/matrix3_f.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gfx { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, Constructors) { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F zeros = Matrix3F::Zeros(); 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F ones = Matrix3F::Ones(); 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F identity = Matrix3F::Identity(); 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F product_ones = Matrix3F::FromOuterProduct( 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(1.0f, 1.0f, 1.0f)); 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F product_zeros = Matrix3F::FromOuterProduct( 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF(1.0f, 1.0f, 1.0f), Vector3dF(0.0f, 0.0f, 0.0f)); 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(ones, product_ones); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(zeros, product_zeros); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < 3; ++i) { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int j = 0; j < 3; ++j) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(i == j ? 1.0f : 0.0f, identity.get(i, j)); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, DataAccess) { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F matrix = Matrix3F::Ones(); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F identity = Matrix3F::Identity(); 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), identity.get_column(1)); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(2.0f, 5.0f, 8.0f), matrix.get_column(2)); 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set_column(0, Vector3dF(0.1f, 0.2f, 0.3f)); 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(0.1f, 0.2f, 0.3f), matrix.get_column(0)); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0.1f, matrix.get(0, 0)); 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(5.0f, matrix.get(1, 2)); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, Determinant) { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(1.0f, Matrix3F::Identity().Determinant()); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0.0f, Matrix3F::Zeros().Determinant()); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0.0f, Matrix3F::Ones().Determinant()); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now for something non-trivial... 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F matrix = Matrix3F::Zeros(); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(0, 5, 6, 8, 7, 0, 1, 9, 0); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(390.0f, matrix.Determinant()); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(2, 0, 3 * matrix.get(0, 0)); 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(2, 1, 3 * matrix.get(0, 1)); 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(2, 2, 3 * matrix.get(0, 2)); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, matrix.Determinant()); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(0.57f, 0.205f, 0.942f, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.314f, 0.845f, 0.826f, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.131f, 0.025f, 0.962f); 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_NEAR(0.3149f, matrix.Determinant(), 0.0001f); 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, Inverse) { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F identity = Matrix3F::Identity(); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F inv_identity = identity.Inverse(); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(identity, inv_identity); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F singular = Matrix3F::Zeros(); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) singular.set(1.0f, 3.0f, 4.0f, 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2.0f, 11.0f, 5.0f, 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.5f, 1.5f, 2.0f); 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(0, singular.Determinant()); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Matrix3F::Zeros(), singular.Inverse()); 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F regular = Matrix3F::Zeros(); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) regular.set(0.57f, 0.205f, 0.942f, 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.314f, 0.845f, 0.826f, 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.131f, 0.025f, 0.962f); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F inv_regular = regular.Inverse(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) regular.set(2.51540616f, -0.55138018f, -1.98968043f, 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -0.61552266f, 1.34920184f, -0.55573636f, 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) -0.32653861f, 0.04002158f, 1.32488726f); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(regular.IsNear(inv_regular, 0.00001f)); 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, EigenvectorsIdentity) { 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This block tests the trivial case of eigenvalues of the identity matrix. 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F identity = Matrix3F::Identity(); 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF eigenvals = identity.SolveEigenproblem(NULL); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(1.0f, 1.0f, 1.0f), eigenvals); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, EigenvectorsDiagonal) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This block tests the another trivial case of eigenvalues of a diagonal 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // matrix. Here we expect values to be sorted. 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F matrix = Matrix3F::Zeros(); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(0, 0, 1.0f); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(1, 1, -2.5f); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(2, 2, 3.14f); 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F eigenvectors = Matrix3F::Zeros(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(3.14f, 1.0f, -2.5f), eigenvals); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(0.0f, 0.0f, 1.0f), eigenvectors.get_column(0)); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(1.0f, 0.0f, 0.0f), eigenvectors.get_column(1)); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(0.0f, 1.0f, 0.0f), eigenvectors.get_column(2)); 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, EigenvectorsNiceNotPositive) { 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This block tests computation of eigenvectors of a matrix where nice 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // round values are expected. 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F matrix = Matrix3F::Zeros(); 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is not a positive-definite matrix but eigenvalues and the first 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // eigenvector should nonetheless be computed correctly. 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(3, 2, 4, 2, 0, 2, 4, 2, 3); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F eigenvectors = Matrix3F::Zeros(); 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_EQ(Vector3dF(8.0f, -1.0f, -1.0f), eigenvals); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF expected_principal(0.66666667f, 0.33333333f, 0.66666667f); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_NEAR(0.0f, 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (expected_principal - eigenvectors.get_column(0)).Length(), 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.000001f); 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST(Matrix3fTest, EigenvectorsPositiveDefinite) { 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This block tests computation of eigenvectors of a matrix where output 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is not as nice as above, but it actually meets the definition. 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F matrix = Matrix3F::Zeros(); 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F eigenvectors = Matrix3F::Zeros(); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Matrix3F expected_eigenvectors = Matrix3F::Zeros(); 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) matrix.set(1, -1, 2, -1, 4, 5, 2, 5, 0); 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF eigenvals = matrix.SolveEigenproblem(&eigenvectors); 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Vector3dF expected_eigv(7.3996266f, 1.91197255f, -4.31159915f); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expected_eigv -= eigenvals; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_NEAR(0, expected_eigv.LengthSquared(), 0.00001f); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expected_eigenvectors.set(0.04926317f, -0.92135662f, -0.38558414f, 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.82134249f, 0.25703273f, -0.50924521f, 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0.56830419f, -0.2916096f, 0.76941158f); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EXPECT_TRUE(expected_eigenvectors.IsNear(eigenvectors, 0.00001f)); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 149