Fix row/col des matrices

This commit is contained in:
FyloZ 2024-01-29 13:59:46 -05:00
parent 9a93c8e529
commit 92d337fcc6
Signed by: william
GPG Key ID: 835378AE9AF4AE97
2 changed files with 466 additions and 413 deletions

View File

@ -64,9 +64,9 @@ namespace gti320 {
this->resize(submatrix->rows(), submatrix->cols()); this->resize(submatrix->rows(), submatrix->cols());
} }
for (int i = 0; i < this->rows(); i++) { for (int col = 0; col < this->cols(); col++) {
for (int j = 0; j < this->cols(); j++) { for (int row = 0; row < this->rows(); row++) {
this(i, j) = submatrix(i, j); this(col, row) = submatrix(col, row);
} }
} }
return *this; return *this;
@ -109,9 +109,9 @@ namespace gti320 {
template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage> template<typename _OtherScalar, int _OtherRows, int _OtherCols, int _OtherStorage>
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const { Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const {
auto transposed = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->cols(), this->rows()); auto transposed = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->cols(), this->rows());
for (int i = 0; i < this->rows(); i++) { for (int col = 0; col < this->cols(); col++) {
for (int j = 0; j < this->cols(); j++) { for (int row = 0; row < this->rows(); row++) {
transposed(j, i) = (*this)(i, j); transposed(row, col) = (*this)(col, row);
} }
} }
return transposed; return transposed;
@ -170,9 +170,9 @@ namespace gti320 {
this->resize(submatrix->rows(), submatrix->cols()); this->resize(submatrix->rows(), submatrix->cols());
} }
for (int j = 0; j < this->cols(); j++) { for (int row = 0; row < this->rows(); row++) {
for (int i = 0; i < this->rows(); i++) { for (int col = 0; col < this->cols(); col++) {
this(i, j) = submatrix(i, j); this(col, row) = submatrix(col, row);
} }
} }
return *this; return *this;
@ -182,7 +182,7 @@ namespace gti320 {
* Accesseur à une entrée de la matrice (lecture seule) * Accesseur à une entrée de la matrice (lecture seule)
*/ */
_Scalar operator()(int i, int j) const { _Scalar operator()(int i, int j) const {
int index = j * this->cols() + i; int index = i + j * this->cols();
return this->m_storage.data()[index]; return this->m_storage.data()[index];
} }
@ -190,7 +190,7 @@ namespace gti320 {
* Accesseur à une entrée de la matrice (lecture ou écriture) * Accesseur à une entrée de la matrice (lecture ou écriture)
*/ */
_Scalar &operator()(int i, int j) { _Scalar &operator()(int i, int j) {
int index = j * this->cols() + i; int index = i + j * this->cols();
return this->m_storage.data()[index]; return this->m_storage.data()[index];
} }
@ -215,9 +215,9 @@ namespace gti320 {
Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage> transpose() const { Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage> transpose() const {
auto t = Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage>(this->cols(), this->rows()); auto t = Matrix<_Scalar, _RowsAtCompile, _ColsAtCompile, ColumnStorage>(this->cols(), this->rows());
for (int i = 0; i < this->rows(); i++) { for (int row = 0; row < this->rows(); row++) {
for (int j = 0; j < this->cols(); j++) { for (int col = 0; col < this->cols(); col++) {
t(j, i) = (*this)(i, j); t(row, col) = (*this)(col, row);
} }
} }
@ -308,9 +308,9 @@ namespace gti320 {
assert(this->rows() == matrix.rows()); assert(this->rows() == matrix.rows());
assert(this->cols() == matrix.cols()); assert(this->cols() == matrix.cols());
for (int i = 0; i < this->rows(); i++) { for (int col = 0; col < this->cols(); col++) {
for (int j = 0; j < this->cols(); j++) { for (int row = 0; row < this->rows(); row++) {
(*this)(i, j) = matrix(i, j); (*this)(col, row) = matrix(col, row);
} }
} }
@ -349,6 +349,7 @@ namespace gti320 {
int full_i = this->m_i + i; int full_i = this->m_i + i;
int full_j = this->m_j + j; int full_j = this->m_j + j;
return this->m_matrix(full_i, full_j); return this->m_matrix(full_i, full_j);
} }
@ -359,9 +360,9 @@ namespace gti320 {
Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const { Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage> transpose() const {
auto t = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->rows(), this->cols()); auto t = Matrix<_OtherScalar, _OtherRows, _OtherCols, _OtherStorage>(this->rows(), this->cols());
for (int i = 0; i < this->rows(); i++) { for (int col = 0; col < this->cols(); col++) {
for (int j = 0; j < this->cols(); j++) { for (int row = 0; row < this->rows(); row++) {
t(j, i) = (*this)(i, j); t(row, col) = (*this)(col, row);
} }
} }

View File

@ -23,108 +23,106 @@ using namespace gti320;
* Multiplication matrice * vecteur, utilisant une implémentation naive * Multiplication matrice * vecteur, utilisant une implémentation naive
*/ */
template<typename _Scalar> template<typename _Scalar>
static inline Vector<_Scalar, Dynamic> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Vector<_Scalar, Dynamic>& v) static inline Vector<_Scalar, Dynamic>
{ naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> &A, const Vector<_Scalar, Dynamic> &v) {
assert(A.cols() == v.rows()); assert(A.cols() == v.rows());
Vector<_Scalar, Dynamic> b(A.rows()); Vector<_Scalar, Dynamic> b(A.rows());
assert(b.rows() == A.rows()); assert(b.rows() == A.rows());
for (int i = 0; i < A.rows(); ++i) { for (int i = 0; i < A.rows(); ++i) {
b(i) = 0.0; b(i) = 0.0;
for (int j = 0; j < A.cols(); ++j) { for (int j = 0; j < A.cols(); ++j) {
b(i) += A(i, j) * v(j); b(i) += A(i, j) * v(j);
} }
} }
return b; return b;
} }
/** /**
* Addition matrice + matrice, utilisant une implémentation naive * Addition matrice + matrice, utilisant une implémentation naive
*/ */
template<typename _Scalar> template<typename _Scalar>
static inline Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> naiveMatrixAddition(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& A, const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>& B) static inline Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage>
{ naiveMatrixAddition(const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> &A,
assert(A.cols() == B.cols() && A.rows() == B.rows()); const Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> &B) {
assert(A.cols() == B.cols() && A.rows() == B.rows());
Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> C(A.rows(), A.cols()); Matrix<_Scalar, Dynamic, Dynamic, ColumnStorage> C(A.rows(), A.cols());
assert(C.rows() == A.rows() && C.cols() == A.cols()); assert(C.rows() == A.rows() && C.cols() == A.cols());
for (int i = 0; i < C.rows(); ++i) { for (int i = 0; i < C.rows(); ++i) {
for (int j = 0; j < C.cols(); ++j) { for (int j = 0; j < C.cols(); ++j) {
C(i, j) = A(i, j) + B(i, j); C(i, j) = A(i, j) + B(i, j);
} }
} }
return C; return C;
} }
/** /**
* Multiplication matrice * matrice, utilisant une implémentation naive. * Multiplication matrice * matrice, utilisant une implémentation naive.
*/ */
template<typename _Scalar, int _Storage> template<typename _Scalar, int _Storage>
static inline Matrix<_Scalar, Dynamic, Dynamic, _Storage> naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& A, const Matrix<_Scalar, Dynamic, Dynamic, _Storage>& B) static inline Matrix<_Scalar, Dynamic, Dynamic, _Storage>
{ naiveMatrixMult(const Matrix<_Scalar, Dynamic, Dynamic, _Storage> &A,
assert(A.cols() == B.rows()); const Matrix<_Scalar, Dynamic, Dynamic, _Storage> &B) {
Matrix<_Scalar, Dynamic, Dynamic> product(A.rows(), B.cols()); assert(A.cols() == B.rows());
for (int i = 0; i < A.rows(); ++i) Matrix<_Scalar, Dynamic, Dynamic> product(A.rows(), B.cols());
{ for (int i = 0; i < A.rows(); ++i) {
for (int j = 0; j < B.cols(); ++j) for (int j = 0; j < B.cols(); ++j) {
{ for (int k = 0; k < A.cols(); ++k) {
for (int k = 0; k < A.cols(); ++k) product(i, j) += A(i, k) * B(k, j);
{ }
product(i, j) += A(i, k) * B(k, j); }
} }
} return product;
}
return product;
} }
// Test les matrice avec redimensionnement dynamique // Test les matrice avec redimensionnement dynamique
TEST(TestLabo1, DynamicMatrixTests) TEST(TestLabo1, DynamicMatrixTests) {
{ // Crée une matrice à taille dynamique
// Crée une matrice à taille dynamique // (note : les valeurs par défaut du patron de la classe `Matrix` mettent le
// (note : les valeurs par défaut du patron de la classe `Matrix` mettent le // le nombre de ligne et de colonnes à `Dynamic`)
// le nombre de ligne et de colonnes à `Dynamic`) Matrix<double> M(3, 5);
Matrix<double> M(3, 5); EXPECT_EQ(M.cols(), 5);
EXPECT_EQ(M.cols(), 5); EXPECT_EQ(M.rows(), 3);
EXPECT_EQ(M.rows(), 3);
// Redimensionne la matrice // Redimensionne la matrice
M.resize(100, 1000); M.resize(100, 1000);
EXPECT_EQ(M.cols(), 1000); EXPECT_EQ(M.cols(), 1000);
EXPECT_EQ(M.rows(), 100); EXPECT_EQ(M.rows(), 100);
// Test - stockage par colonnes // Test - stockage par colonnes
Matrix<double, Dynamic, Dynamic, ColumnStorage> ColM(100, 100); Matrix<double, Dynamic, Dynamic, ColumnStorage> ColM(100, 100);
ColM.setZero(); ColM.setZero();
ColM(0, 0) = 1.0; ColM(0, 0) = 1.0;
ColM(99, 99) = 99.0; ColM(99, 99) = 99.0;
ColM(10, 33) = 5.0; ColM(10, 33) = 5.0;
EXPECT_EQ(ColM(0, 0), 1.0); EXPECT_EQ(ColM(0, 0), 1.0);
EXPECT_EQ(ColM(10, 33), 5.0); EXPECT_EQ(ColM(10, 33), 5.0);
EXPECT_EQ(ColM(99, 99), 99.0); EXPECT_EQ(ColM(99, 99), 99.0);
// Test - stockage par lignes // Test - stockage par lignes
Matrix<double, Dynamic, Dynamic, RowStorage> RowM(5, 4); Matrix<double, Dynamic, Dynamic, RowStorage> RowM(5, 4);
RowM.setZero(); RowM.setZero();
RowM(0, 0) = 2.1; RowM(0, 0) = 2.1;
RowM(3, 3) = -0.2; RowM(3, 3) = -0.2;
RowM(4, 3) = 1.2; RowM(4, 3) = 1.2;
EXPECT_EQ(RowM.rows(), 5); EXPECT_EQ(RowM.rows(), 5);
EXPECT_EQ(RowM.cols(), 4); EXPECT_EQ(RowM.cols(), 4);
EXPECT_DOUBLE_EQ(RowM(0, 0), 2.1); EXPECT_DOUBLE_EQ(RowM(0, 0), 2.1);
EXPECT_DOUBLE_EQ(RowM(3, 3), -0.2); EXPECT_DOUBLE_EQ(RowM(3, 3), -0.2);
EXPECT_DOUBLE_EQ(RowM(4, 3), 1.2); EXPECT_DOUBLE_EQ(RowM(4, 3), 1.2);
EXPECT_DOUBLE_EQ(RowM(3, 2), 0.0); EXPECT_DOUBLE_EQ(RowM(3, 2), 0.0);
// Transposée // Transposée
const auto RowMT = RowM.transpose(); const auto RowMT = RowM.transpose();
EXPECT_EQ(RowMT.rows(), 4); EXPECT_EQ(RowMT.rows(), 4);
EXPECT_EQ(RowMT.cols(), 5); EXPECT_EQ(RowMT.cols(), 5);
EXPECT_DOUBLE_EQ(RowMT(0, 0), 2.1); EXPECT_DOUBLE_EQ(RowMT(0, 0), 2.1);
EXPECT_DOUBLE_EQ(RowMT(3, 3), -0.2); EXPECT_DOUBLE_EQ(RowMT(3, 3), -0.2);
EXPECT_DOUBLE_EQ(RowMT(3, 4), 1.2); EXPECT_DOUBLE_EQ(RowMT(3, 4), 1.2);
EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0); EXPECT_DOUBLE_EQ(RowMT(2, 3), 0.0);
} }
@ -132,324 +130,382 @@ TEST(TestLabo1, DynamicMatrixTests)
/** /**
* Test pour les vecteurs à taille dynamique * Test pour les vecteurs à taille dynamique
*/ */
TEST(TestLabo1, DynamicVectorSizeTest) TEST(TestLabo1, DynamicVectorSizeTest) {
{ Vector<double> v(5);
Vector<double> v(5); v.setZero();
v.setZero();
EXPECT_EQ(v.rows(), 5); EXPECT_EQ(v.rows(), 5);
v.resize(3); v.resize(3);
EXPECT_EQ(v.rows(), 3); EXPECT_EQ(v.rows(), 3);
v(0) = 1.0; v(0) = 1.0;
v(1) = 2.0; v(1) = 2.0;
v(2) = 3.0; v(2) = 3.0;
EXPECT_DOUBLE_EQ(v.norm(), 3.7416573867739413855837487323165); EXPECT_DOUBLE_EQ(v.norm(), 3.7416573867739413855837487323165);
Vector<double, Dynamic> v2(3); Vector<double, Dynamic> v2(3);
v2.setZero(); v2.setZero();
v2(1) = 2.0; v2(1) = 2.0;
EXPECT_DOUBLE_EQ(v2.dot(v), 4.0); EXPECT_DOUBLE_EQ(v2.dot(v), 4.0);
EXPECT_DOUBLE_EQ(v2(0), 0.0); EXPECT_DOUBLE_EQ(v2(0), 0.0);
EXPECT_DOUBLE_EQ(v2(1), 2.0); EXPECT_DOUBLE_EQ(v2(1), 2.0);
EXPECT_DOUBLE_EQ(v2(2), 0.0); EXPECT_DOUBLE_EQ(v2(2), 0.0);
} }
/** /**
* Test pour les matrice à taille fixe * Test pour les matrice à taille fixe
*/ */
TEST(TestLabo1, Matrix4x4SizeTest) TEST(TestLabo1, Matrix4x4SizeTest) {
{ Matrix4d M;
Matrix4d M; M.setZero();
M.setZero();
EXPECT_EQ(M.cols(), 4); EXPECT_EQ(M.cols(), 4);
EXPECT_EQ(M.rows(), 4); EXPECT_EQ(M.rows(), 4);
} }
/** /**
* Test pour les opérateurs d'arithmétique matricielle. * Test pour les opérateurs d'arithmétique matricielle.
*/ */
TEST(TestLabo1, MatrixMatrixOperators) TEST(TestLabo1, MatrixMatrixOperators) {
{ // Opérations arithmétiques avec matrices à taille dynamique
// Opérations arithmétiques avec matrices à taille dynamique
// {
// // Test : matrice identité
// Matrix<double> A(6, 6);
// A.setIdentity();
// EXPECT_DOUBLE_EQ(A(0, 0), 1.0);
// EXPECT_DOUBLE_EQ(A(1, 1), 1.0);
// EXPECT_DOUBLE_EQ(A(2, 2), 1.0);
// EXPECT_DOUBLE_EQ(A(3, 3), 1.0);
// EXPECT_DOUBLE_EQ(A(4, 4), 1.0);
// EXPECT_DOUBLE_EQ(A(5, 5), 1.0);
// EXPECT_DOUBLE_EQ(A(0, 1), 0.0);
// EXPECT_DOUBLE_EQ(A(1, 0), 0.0);
//
// // Test : produit scalaire * matrice
// const double alpha = 2.5;
// Matrix<double> B = alpha * A;
// EXPECT_DOUBLE_EQ(B(0, 0), alpha);
// EXPECT_DOUBLE_EQ(B(1, 1), alpha);
// EXPECT_DOUBLE_EQ(B(2, 2), alpha);
// EXPECT_DOUBLE_EQ(B(3, 3), alpha);
// EXPECT_DOUBLE_EQ(B(4, 4), alpha);
// EXPECT_DOUBLE_EQ(B(5, 5), alpha);
// EXPECT_DOUBLE_EQ(B(0, 1), 0.0);
// EXPECT_DOUBLE_EQ(B(1, 0), 0.0);
//
// // Test : produit matrice * matrice
// Matrix<double> C = A * B;
// EXPECT_DOUBLE_EQ(C(0, 0), A(0, 0) * B(0, 0));
// EXPECT_DOUBLE_EQ(C(1, 1), A(1, 1) * B(1, 1));
// EXPECT_DOUBLE_EQ(C(2, 2), A(2, 2) * B(2, 2));
// EXPECT_DOUBLE_EQ(C(3, 3), A(3, 3) * B(3, 3));
// EXPECT_DOUBLE_EQ(C(4, 4), A(4, 4) * B(4, 4));
// EXPECT_DOUBLE_EQ(C(5, 5), A(5, 5) * B(5, 5));
// EXPECT_DOUBLE_EQ(C(0, 1), 0.0);
// EXPECT_DOUBLE_EQ(C(2, 3), 0.0);
//
// // Test : addition matrice * matrice
// Matrix<double> A_plus_B = A + B;
// EXPECT_DOUBLE_EQ(A_plus_B(0, 0), A(0, 0) + B(0, 0));
// EXPECT_DOUBLE_EQ(A_plus_B(1, 1), A(1, 1) + B(1, 1));
// EXPECT_DOUBLE_EQ(A_plus_B(2, 2), A(2, 2) + B(2, 2));
// EXPECT_DOUBLE_EQ(A_plus_B(3, 3), A(3, 3) + B(3, 3));
// EXPECT_DOUBLE_EQ(A_plus_B(4, 4), A(4, 4) + B(4, 4));
// EXPECT_DOUBLE_EQ(A_plus_B(5, 5), A(5, 5) + B(5, 5));
// EXPECT_DOUBLE_EQ(A_plus_B(0, 1), 0.0);
// EXPECT_DOUBLE_EQ(A_plus_B(2, 3), 0.0);
// }
// Opérations arithmétique avec matrices à stockage par lignes et par
// colonnes.
{ {
// Création d'un matrice à stockage par lignes // Test : matrice identité
Matrix<double, Dynamic, Dynamic, RowStorage> A(5, 5); Matrix<double> A(6, 6);
A(0, 0) = 0.8147; A(0, 1) = 0.0975; A(0, 2) = 0.1576; A(0, 3) = 0.1419; A(0, 4) = 0.6557; A.setIdentity();
A(1, 0) = 0.9058; A(1, 1) = 0.2785; A(1, 2) = 0.9706; A(1, 3) = 0.4218; A(1, 4) = 0.0357; EXPECT_DOUBLE_EQ(A(0, 0), 1.0);
A(2, 0) = 0.1270; A(2, 1) = 0.5469; A(2, 2) = 0.9572; A(2, 3) = 0.9157; A(2, 4) = 0.8491; EXPECT_DOUBLE_EQ(A(1, 1), 1.0);
A(3, 0) = 0.9134; A(3, 1) = 0.9575; A(3, 2) = 0.4854; A(3, 3) = 0.7922; A(3, 4) = 0.9340; EXPECT_DOUBLE_EQ(A(2, 2), 1.0);
A(4, 0) = 0.6324; A(4, 1) = 0.9649; A(4, 2) = 0.8003; A(4, 3) = 0.9595; A(4, 4) = 0.6787; EXPECT_DOUBLE_EQ(A(3, 3), 1.0);
EXPECT_DOUBLE_EQ(A(4, 4), 1.0);
EXPECT_DOUBLE_EQ(A(5, 5), 1.0);
EXPECT_DOUBLE_EQ(A(0, 1), 0.0);
EXPECT_DOUBLE_EQ(A(1, 0), 0.0);
// Test : transposée (le résultat est une matrice à stockage par // Test : produit scalaire * matrice
// colonnes) const double alpha = 2.5;
Matrix<double, Dynamic, Dynamic, ColumnStorage> B = A.transpose(); Matrix<double> B = alpha * A;
EXPECT_DOUBLE_EQ(B(0, 0), alpha);
EXPECT_DOUBLE_EQ(B(1, 1), alpha);
EXPECT_DOUBLE_EQ(B(2, 2), alpha);
EXPECT_DOUBLE_EQ(B(3, 3), alpha);
EXPECT_DOUBLE_EQ(B(4, 4), alpha);
EXPECT_DOUBLE_EQ(B(5, 5), alpha);
EXPECT_DOUBLE_EQ(B(0, 1), 0.0);
EXPECT_DOUBLE_EQ(B(1, 0), 0.0);
// Test : multiplication matrix(ligne) * matrice(colonne) // Test : produit matrice * matrice
// Note : teste seulement la première et la dernière colonne Matrix<double> C = A * B;
const auto C = A * B; EXPECT_DOUBLE_EQ(C(0, 0), A(0, 0) * B(0, 0));
EXPECT_NEAR(C(0, 0), 1.14815820000000, 1e-3); EXPECT_NEAR(C(0, 4), 1.31659795000000, 1e-3); EXPECT_DOUBLE_EQ(C(1, 1), A(1, 1) * B(1, 1));
EXPECT_NEAR(C(1, 0), 1.00133748000000, 1e-3); EXPECT_NEAR(C(1, 4), 2.04727044000000, 1e-3); EXPECT_DOUBLE_EQ(C(2, 2), A(2, 2) * B(2, 2));
EXPECT_NEAR(C(2, 0), 0.99433707000000, 1e-3); EXPECT_NEAR(C(2, 4), 2.82896409000000, 1e-3); EXPECT_DOUBLE_EQ(C(3, 3), A(3, 3) * B(3, 3));
EXPECT_NEAR(C(3, 0), 1.63883925000000, 1e-3); EXPECT_NEAR(C(3, 4), 3.28401323000000, 1e-3); EXPECT_DOUBLE_EQ(C(4, 4), A(4, 4) * B(4, 4));
EXPECT_NEAR(C(4, 0), 1.31659795000000, 1e-3); EXPECT_NEAR(C(4, 4), 3.35271580000000, 1e-3); EXPECT_DOUBLE_EQ(C(5, 5), A(5, 5) * B(5, 5));
EXPECT_DOUBLE_EQ(C(0, 1), 0.0);
EXPECT_DOUBLE_EQ(C(2, 3), 0.0);
// Test : multiplication matrice(colonne) * matrice(ligne)
// Note : teste seulement la première et la dernière colonne
const auto C2 = B * A;
EXPECT_NEAR(C2(0, 0), 2.73456805000000, 1e-3); EXPECT_NEAR(C2(0, 4), 1.95669703000000, 1e-3);
EXPECT_NEAR(C2(1, 0), 1.88593811000000, 1e-3); EXPECT_NEAR(C2(1, 4), 2.08742862000000, 1e-3);
EXPECT_NEAR(C2(2, 0), 2.07860468000000, 1e-3); EXPECT_NEAR(C2(2, 4), 1.94727447000000, 1e-3);
EXPECT_NEAR(C2(3, 0), 1.94434955000000, 1e-3); EXPECT_NEAR(C2(3, 4), 2.27675041000000, 1e-3);
EXPECT_NEAR(C2(4, 0), 1.95669703000000, 1e-3); EXPECT_NEAR(C2(4, 4), 2.48517748000000, 1e-3);
// Test : addition matrice(ligne) + matrice(ligne)
// Note : teste seulement la première et la dernière colonne
const auto A_plus_A = A + A;
EXPECT_DOUBLE_EQ(A_plus_A(0, 0), A(0, 0) + A(0, 0)); EXPECT_DOUBLE_EQ(A_plus_A(0, 4), A(0, 4) + A(0, 4));
EXPECT_DOUBLE_EQ(A_plus_A(1, 0), A(1, 0) + A(1, 0)); EXPECT_DOUBLE_EQ(A_plus_A(1, 4), A(1, 4) + A(1, 4));
EXPECT_DOUBLE_EQ(A_plus_A(2, 0), A(2, 0) + A(2, 0)); EXPECT_DOUBLE_EQ(A_plus_A(2, 4), A(2, 4) + A(2, 4));
EXPECT_DOUBLE_EQ(A_plus_A(3, 0), A(3, 0) + A(3, 0)); EXPECT_DOUBLE_EQ(A_plus_A(3, 4), A(3, 4) + A(3, 4));
EXPECT_DOUBLE_EQ(A_plus_A(4, 0), A(4, 0) + A(4, 0)); EXPECT_DOUBLE_EQ(A_plus_A(4, 4), A(4, 4) + A(4, 4));
// Test : addition matrice(colonne) + matrice(colonne)
// Note : teste seulement la première et la dernière colonne
const auto B_plus_B = B + B;
EXPECT_DOUBLE_EQ(B_plus_B(0, 0), B(0, 0) + B(0, 0)); EXPECT_DOUBLE_EQ(B_plus_B(0, 4), B(0, 4) + B(0, 4));
EXPECT_DOUBLE_EQ(B_plus_B(1, 0), B(1, 0) + B(1, 0)); EXPECT_DOUBLE_EQ(B_plus_B(1, 4), B(1, 4) + B(1, 4));
EXPECT_DOUBLE_EQ(B_plus_B(2, 0), B(2, 0) + B(2, 0)); EXPECT_DOUBLE_EQ(B_plus_B(2, 4), B(2, 4) + B(2, 4));
EXPECT_DOUBLE_EQ(B_plus_B(3, 0), B(3, 0) + B(3, 0)); EXPECT_DOUBLE_EQ(B_plus_B(3, 4), B(3, 4) + B(3, 4));
EXPECT_DOUBLE_EQ(B_plus_B(4, 0), B(4, 0) + B(4, 0)); EXPECT_DOUBLE_EQ(B_plus_B(4, 4), B(4, 4) + B(4, 4));
// Test : addition matrice * matrice
Matrix<double> A_plus_B = A + B;
EXPECT_DOUBLE_EQ(A_plus_B(0, 0), A(0, 0) + B(0, 0));
EXPECT_DOUBLE_EQ(A_plus_B(1, 1), A(1, 1) + B(1, 1));
EXPECT_DOUBLE_EQ(A_plus_B(2, 2), A(2, 2) + B(2, 2));
EXPECT_DOUBLE_EQ(A_plus_B(3, 3), A(3, 3) + B(3, 3));
EXPECT_DOUBLE_EQ(A_plus_B(4, 4), A(4, 4) + B(4, 4));
EXPECT_DOUBLE_EQ(A_plus_B(5, 5), A(5, 5) + B(5, 5));
EXPECT_DOUBLE_EQ(A_plus_B(0, 1), 0.0);
EXPECT_DOUBLE_EQ(A_plus_B(2, 3), 0.0);
} }
// Opérations arithmétique avec matrices à stockage par lignes et par
// colonnes.
{
// Création d'un matrice à stockage par lignes
Matrix<double, Dynamic, Dynamic, RowStorage> A(5, 5);
A(0, 0) = 0.8147;
A(0, 1) = 0.0975;
A(0, 2) = 0.1576;
A(0, 3) = 0.1419;
A(0, 4) = 0.6557;
A(1, 0) = 0.9058;
A(1, 1) = 0.2785;
A(1, 2) = 0.9706;
A(1, 3) = 0.4218;
A(1, 4) = 0.0357;
A(2, 0) = 0.1270;
A(2, 1) = 0.5469;
A(2, 2) = 0.9572;
A(2, 3) = 0.9157;
A(2, 4) = 0.8491;
A(3, 0) = 0.9134;
A(3, 1) = 0.9575;
A(3, 2) = 0.4854;
A(3, 3) = 0.7922;
A(3, 4) = 0.9340;
A(4, 0) = 0.6324;
A(4, 1) = 0.9649;
A(4, 2) = 0.8003;
A(4, 3) = 0.9595;
A(4, 4) = 0.6787;
// Test : transposée (le résultat est une matrice à stockage par
// colonnes)
Matrix<double, Dynamic, Dynamic, ColumnStorage> B = A.transpose();
// Test : multiplication matrix(ligne) * matrice(colonne)
// Note : teste seulement la première et la dernière colonne
const auto C = A * B;
EXPECT_NEAR(C(0, 0), 1.14815820000000, 1e-3);
EXPECT_NEAR(C(0, 4), 1.31659795000000, 1e-3);
EXPECT_NEAR(C(1, 0), 1.00133748000000, 1e-3);
EXPECT_NEAR(C(1, 4), 2.04727044000000, 1e-3);
EXPECT_NEAR(C(2, 0), 0.99433707000000, 1e-3);
EXPECT_NEAR(C(2, 4), 2.82896409000000, 1e-3);
EXPECT_NEAR(C(3, 0), 1.63883925000000, 1e-3);
EXPECT_NEAR(C(3, 4), 3.28401323000000, 1e-3);
EXPECT_NEAR(C(4, 0), 1.31659795000000, 1e-3);
EXPECT_NEAR(C(4, 4), 3.35271580000000, 1e-3);
// Test : multiplication matrice(colonne) * matrice(ligne)
// Note : teste seulement la première et la dernière colonne
const auto C2 = B * A;
EXPECT_NEAR(C2(0, 0), 2.73456805000000, 1e-3);
EXPECT_NEAR(C2(0, 4), 1.95669703000000, 1e-3);
EXPECT_NEAR(C2(1, 0), 1.88593811000000, 1e-3);
EXPECT_NEAR(C2(1, 4), 2.08742862000000, 1e-3);
EXPECT_NEAR(C2(2, 0), 2.07860468000000, 1e-3);
EXPECT_NEAR(C2(2, 4), 1.94727447000000, 1e-3);
EXPECT_NEAR(C2(3, 0), 1.94434955000000, 1e-3);
EXPECT_NEAR(C2(3, 4), 2.27675041000000, 1e-3);
EXPECT_NEAR(C2(4, 0), 1.95669703000000, 1e-3);
EXPECT_NEAR(C2(4, 4), 2.48517748000000, 1e-3);
// Test : addition matrice(ligne) + matrice(ligne)
// Note : teste seulement la première et la dernière colonne
const auto A_plus_A = A + A;
EXPECT_DOUBLE_EQ(A_plus_A(0, 0), A(0, 0) + A(0, 0));
EXPECT_DOUBLE_EQ(A_plus_A(0, 4), A(0, 4) + A(0, 4));
EXPECT_DOUBLE_EQ(A_plus_A(1, 0), A(1, 0) + A(1, 0));
EXPECT_DOUBLE_EQ(A_plus_A(1, 4), A(1, 4) + A(1, 4));
EXPECT_DOUBLE_EQ(A_plus_A(2, 0), A(2, 0) + A(2, 0));
EXPECT_DOUBLE_EQ(A_plus_A(2, 4), A(2, 4) + A(2, 4));
EXPECT_DOUBLE_EQ(A_plus_A(3, 0), A(3, 0) + A(3, 0));
EXPECT_DOUBLE_EQ(A_plus_A(3, 4), A(3, 4) + A(3, 4));
EXPECT_DOUBLE_EQ(A_plus_A(4, 0), A(4, 0) + A(4, 0));
EXPECT_DOUBLE_EQ(A_plus_A(4, 4), A(4, 4) + A(4, 4));
// Test : addition matrice(colonne) + matrice(colonne)
// Note : teste seulement la première et la dernière colonne
const auto B_plus_B = B + B;
EXPECT_DOUBLE_EQ(B_plus_B(0, 0), B(0, 0) + B(0, 0));
EXPECT_DOUBLE_EQ(B_plus_B(0, 4), B(0, 4) + B(0, 4));
EXPECT_DOUBLE_EQ(B_plus_B(1, 0), B(1, 0) + B(1, 0));
EXPECT_DOUBLE_EQ(B_plus_B(1, 4), B(1, 4) + B(1, 4));
EXPECT_DOUBLE_EQ(B_plus_B(2, 0), B(2, 0) + B(2, 0));
EXPECT_DOUBLE_EQ(B_plus_B(2, 4), B(2, 4) + B(2, 4));
EXPECT_DOUBLE_EQ(B_plus_B(3, 0), B(3, 0) + B(3, 0));
EXPECT_DOUBLE_EQ(B_plus_B(3, 4), B(3, 4) + B(3, 4));
EXPECT_DOUBLE_EQ(B_plus_B(4, 0), B(4, 0) + B(4, 0));
EXPECT_DOUBLE_EQ(B_plus_B(4, 4), B(4, 4) + B(4, 4));
}
} }
/** /**
* Test pour la multiplication matrice * vecteur * Test pour la multiplication matrice * vecteur
*/ */
TEST(TestLabo1, MatrixVectorOperators) TEST(TestLabo1, MatrixVectorOperators) {
{ // Vecteur à taille dynamique
// Vecteur à taille dynamique Vector<double> v(5);
Vector<double> v(5); v(0) = 1.0;
v(0) = 1.0; v(1) = 2.0;
v(1) = 2.0; v(2) = 4.0;
v(2) = 4.0; v(3) = 8.0;
v(3) = 8.0; v(4) = 16.0;
v(4) = 16.0;
// Test : multiplication par la matrice identité // Test : multiplication par la matrice identité
{ {
Matrix<double> M(5, 5); Matrix<double> M(5, 5);
M.setIdentity(); M.setIdentity();
const auto b = M * v; const auto b = M * v;
EXPECT_DOUBLE_EQ(b(0), 1.0); EXPECT_DOUBLE_EQ(b(0), 1.0);
EXPECT_DOUBLE_EQ(b(1), 2.0); EXPECT_DOUBLE_EQ(b(1), 2.0);
EXPECT_DOUBLE_EQ(b(2), 4.0); EXPECT_DOUBLE_EQ(b(2), 4.0);
EXPECT_DOUBLE_EQ(b(3), 8.0); EXPECT_DOUBLE_EQ(b(3), 8.0);
EXPECT_DOUBLE_EQ(b(4), 16.0); EXPECT_DOUBLE_EQ(b(4), 16.0);
} }
// Test : multiplication par une matrice à taille dynamique avec stockage par ligne. // Test : multiplication par une matrice à taille dynamique avec stockage par ligne.
{ {
Matrix<double, Dynamic, Dynamic, RowStorage> M(5, 5); Matrix<double, Dynamic, Dynamic, RowStorage> M(5, 5);
M.setIdentity(); M.setIdentity();
M = 2.0 * M; M = 2.0 * M;
Vector<double> b2 = M * v; Vector<double> b2 = M * v;
EXPECT_DOUBLE_EQ(b2(0), 2.0); EXPECT_DOUBLE_EQ(b2(0), 2.0);
EXPECT_DOUBLE_EQ(b2(1), 4.0); EXPECT_DOUBLE_EQ(b2(1), 4.0);
EXPECT_DOUBLE_EQ(b2(2), 8.0); EXPECT_DOUBLE_EQ(b2(2), 8.0);
EXPECT_DOUBLE_EQ(b2(3), 16.0); EXPECT_DOUBLE_EQ(b2(3), 16.0);
EXPECT_DOUBLE_EQ(b2(4), 32.0); EXPECT_DOUBLE_EQ(b2(4), 32.0);
} }
} }
/** /**
* Opérateurs d'arithmétique vectorielle * Opérateurs d'arithmétique vectorielle
*/ */
TEST(TestLabo1, VectorOperators) TEST(TestLabo1, VectorOperators) {
{ Vector<double> v(5);
Vector<double> v(5); v(0) = 0.1;
v(0) = 0.1; v(1) = 0.2;
v(1) = 0.2; v(2) = 0.4;
v(2) = 0.4; v(3) = 0.8;
v(3) = 0.8; v(4) = 1.6;
v(4) = 1.6;
// Test : multiplication scalaire * vecteur // Test : multiplication scalaire * vecteur
const double alpha = 4.0; const double alpha = 4.0;
const auto v2 = alpha * v; const auto v2 = alpha * v;
EXPECT_DOUBLE_EQ(v2(0), alpha * v(0)); EXPECT_DOUBLE_EQ(v2(0), alpha * v(0));
EXPECT_DOUBLE_EQ(v2(1), alpha * v(1)); EXPECT_DOUBLE_EQ(v2(1), alpha * v(1));
EXPECT_DOUBLE_EQ(v2(2), alpha * v(2)); EXPECT_DOUBLE_EQ(v2(2), alpha * v(2));
EXPECT_DOUBLE_EQ(v2(3), alpha * v(3)); EXPECT_DOUBLE_EQ(v2(3), alpha * v(3));
EXPECT_DOUBLE_EQ(v2(4), alpha * v(4)); EXPECT_DOUBLE_EQ(v2(4), alpha * v(4));
// Test : addition vecteur + vecteur // Test : addition vecteur + vecteur
const auto v3 = v + v2; const auto v3 = v + v2;
EXPECT_DOUBLE_EQ(v3(0), v(0) + v2(0)); EXPECT_DOUBLE_EQ(v3(0), v(0) + v2(0));
EXPECT_DOUBLE_EQ(v3(1), v(1) + v2(1)); EXPECT_DOUBLE_EQ(v3(1), v(1) + v2(1));
EXPECT_DOUBLE_EQ(v3(2), v(2) + v2(2)); EXPECT_DOUBLE_EQ(v3(2), v(2) + v2(2));
EXPECT_DOUBLE_EQ(v3(3), v(3) + v2(3)); EXPECT_DOUBLE_EQ(v3(3), v(3) + v2(3));
EXPECT_DOUBLE_EQ(v3(4), v(4) + v2(4)); EXPECT_DOUBLE_EQ(v3(4), v(4) + v2(4));
} }
/** /**
* Mathématiques 3D * Mathématiques 3D
*/ */
TEST(TestLabo1, Math3D) TEST(TestLabo1, Math3D) {
{ // Test : norme d'un vecteur de dimension 3
// Test : norme d'un vecteur de dimension 3 Vector3d v;
Vector3d v; v.setZero();
v.setZero(); v(1) = 2.0;
v(1) = 2.0; EXPECT_EQ(v.rows(), 3);
EXPECT_EQ(v.rows(), 3); EXPECT_EQ(v.cols(), 1);
EXPECT_EQ(v.cols(), 1); EXPECT_DOUBLE_EQ(v(0), 0.0);
EXPECT_DOUBLE_EQ(v(0), 0.0); EXPECT_DOUBLE_EQ(v(1), 2.0);
EXPECT_DOUBLE_EQ(v(1), 2.0); EXPECT_DOUBLE_EQ(v(2), 0.0);
EXPECT_DOUBLE_EQ(v(2), 0.0); EXPECT_DOUBLE_EQ(v.norm(), 2.0);
EXPECT_DOUBLE_EQ(v.norm(), 2.0);
// Test : calcul de la norme d'un deuxième vecteur 3D // Test : calcul de la norme d'un deuxième vecteur 3D
Vector3d v2; Vector3d v2;
v2(0) = 4.0; v2(0) = 4.0;
v2(1) = 2.0; v2(1) = 2.0;
v2(2) = 5.0; v2(2) = 5.0;
EXPECT_EQ(v2.rows(), 3); EXPECT_EQ(v2.rows(), 3);
EXPECT_EQ(v2.cols(), 1); EXPECT_EQ(v2.cols(), 1);
EXPECT_DOUBLE_EQ(v2(0), 4.0); EXPECT_DOUBLE_EQ(v2(0), 4.0);
EXPECT_DOUBLE_EQ(v2(1), 2.0); EXPECT_DOUBLE_EQ(v2(1), 2.0);
EXPECT_DOUBLE_EQ(v2(2), 5.0); EXPECT_DOUBLE_EQ(v2(2), 5.0);
EXPECT_DOUBLE_EQ(v2.norm(), 6.7082039324993690892275210061938); EXPECT_DOUBLE_EQ(v2.norm(), 6.7082039324993690892275210061938);
// Test : produit scalaire // Test : produit scalaire
EXPECT_DOUBLE_EQ(v.dot(v2), 4.0); EXPECT_DOUBLE_EQ(v.dot(v2), 4.0);
// Test : matrice identité 4x4 // Test : matrice identité 4x4
Matrix4d M; Matrix4d M;
M.setIdentity(); M.setIdentity();
EXPECT_DOUBLE_EQ(M(0, 0), 1.0); EXPECT_DOUBLE_EQ(M(0, 0), 1.0);
EXPECT_DOUBLE_EQ(M(0, 1), 0.0); EXPECT_DOUBLE_EQ(M(0, 1), 0.0);
EXPECT_DOUBLE_EQ(M(0, 2), 0.0); EXPECT_DOUBLE_EQ(M(0, 2), 0.0);
EXPECT_DOUBLE_EQ(M(1, 1), 1.0); EXPECT_DOUBLE_EQ(M(1, 1), 1.0);
EXPECT_DOUBLE_EQ(M(1, 0), 0.0); EXPECT_DOUBLE_EQ(M(1, 0), 0.0);
EXPECT_DOUBLE_EQ(M(1, 2), 0.0); EXPECT_DOUBLE_EQ(M(1, 2), 0.0);
EXPECT_DOUBLE_EQ(M(2, 0), 0.0); EXPECT_DOUBLE_EQ(M(2, 0), 0.0);
EXPECT_DOUBLE_EQ(M(2, 1), 0.0); EXPECT_DOUBLE_EQ(M(2, 1), 0.0);
EXPECT_DOUBLE_EQ(M(2, 2), 1.0); EXPECT_DOUBLE_EQ(M(2, 2), 1.0);
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des x // Test : création d'une matrice de rotation de 45 degrés autour de l'axe des x
const auto Rx = makeRotation<double>(M_PI / 4.0, 0, 0); const auto Rx = makeRotation<double>(M_PI / 4.0, 0, 0);
EXPECT_NEAR(Rx(0, 0), 1, 1e-3); EXPECT_NEAR(Rx(0, 1), 0, 1e-3); EXPECT_NEAR(Rx(0, 2), 0, 1e-3); EXPECT_NEAR(Rx(0, 0), 1, 1e-3);
EXPECT_NEAR(Rx(1, 0), 0, 1e-3); EXPECT_NEAR(Rx(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(1, 2), -0.7071, 1e-3); EXPECT_NEAR(Rx(0, 1), 0, 1e-3);
EXPECT_NEAR(Rx(2, 0), 0, 1e-3); EXPECT_NEAR(Rx(2, 1), 0.7071, 1e-3); EXPECT_NEAR(Rx(2, 2), 0.7071, 1e-3); EXPECT_NEAR(Rx(0, 2), 0, 1e-3);
EXPECT_NEAR(Rx(1, 0), 0, 1e-3);
EXPECT_NEAR(Rx(1, 1), 0.7071, 1e-3);
EXPECT_NEAR(Rx(1, 2), -0.7071, 1e-3);
EXPECT_NEAR(Rx(2, 0), 0, 1e-3);
EXPECT_NEAR(Rx(2, 1), 0.7071, 1e-3);
EXPECT_NEAR(Rx(2, 2), 0.7071, 1e-3);
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des y // Test : création d'une matrice de rotation de 45 degrés autour de l'axe des y
const auto Ry = makeRotation<double>(0, M_PI / 4.0, 0); const auto Ry = makeRotation<double>(0, M_PI / 4.0, 0);
EXPECT_NEAR(Ry(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Ry(0, 1), 0, 1e-3); EXPECT_NEAR(Ry(0, 2), 0.7071, 1e-3); EXPECT_NEAR(Ry(0, 0), 0.7071, 1e-3);
EXPECT_NEAR(Ry(1, 0), 0, 1e-3); EXPECT_NEAR(Ry(1, 1), 1, 1e-3); EXPECT_NEAR(Ry(1, 2), 0, 1e-3); EXPECT_NEAR(Ry(0, 1), 0, 1e-3);
EXPECT_NEAR(Ry(2, 0), -0.7071, 1e-3); EXPECT_NEAR(Ry(2, 1), 0, 1e-3); EXPECT_NEAR(Ry(2, 2), 0.7071, 1e-3); EXPECT_NEAR(Ry(0, 2), 0.7071, 1e-3);
EXPECT_NEAR(Ry(1, 0), 0, 1e-3);
EXPECT_NEAR(Ry(1, 1), 1, 1e-3);
EXPECT_NEAR(Ry(1, 2), 0, 1e-3);
EXPECT_NEAR(Ry(2, 0), -0.7071, 1e-3);
EXPECT_NEAR(Ry(2, 1), 0, 1e-3);
EXPECT_NEAR(Ry(2, 2), 0.7071, 1e-3);
// Test : création d'une matrice de rotation de 45 degrés autour de l'axe des z // Test : création d'une matrice de rotation de 45 degrés autour de l'axe des z
const auto Rz = makeRotation<double>(0, 0, M_PI / 4.0); const auto Rz = makeRotation<double>(0, 0, M_PI / 4.0);
EXPECT_NEAR(Rz(0, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(0, 1), -0.7071, 1e-3); EXPECT_NEAR(Rz(0, 2), 0, 1e-3); EXPECT_NEAR(Rz(0, 0), 0.7071, 1e-3);
EXPECT_NEAR(Rz(1, 0), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 1), 0.7071, 1e-3); EXPECT_NEAR(Rz(1, 2), 0, 1e-3); EXPECT_NEAR(Rz(0, 1), -0.7071, 1e-3);
EXPECT_NEAR(Rz(2, 0), 0, 1e-3); EXPECT_NEAR(Rz(2, 1), 0, 1e-3); EXPECT_NEAR(Rz(2, 2), 1, 1e-3); EXPECT_NEAR(Rz(0, 2), 0, 1e-3);
EXPECT_NEAR(Rz(1, 0), 0.7071, 1e-3);
EXPECT_NEAR(Rz(1, 1), 0.7071, 1e-3);
EXPECT_NEAR(Rz(1, 2), 0, 1e-3);
EXPECT_NEAR(Rz(2, 0), 0, 1e-3);
EXPECT_NEAR(Rz(2, 1), 0, 1e-3);
EXPECT_NEAR(Rz(2, 2), 1, 1e-3);
// Test : création d'une matrice de rotation quelconque. // Test : création d'une matrice de rotation quelconque.
const auto Rxyz = makeRotation<double>(M_PI / 3.0, -M_PI / 6.0, M_PI / 4.0); const auto Rxyz = makeRotation<double>(M_PI / 3.0, -M_PI / 6.0, M_PI / 4.0);
EXPECT_NEAR(Rxyz(0, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(0, 1), -0.6597, 1e-3); EXPECT_NEAR(Rxyz(0, 2), 0.4356, 1e-3); EXPECT_NEAR(Rxyz(0, 0), 0.6124, 1e-3);
EXPECT_NEAR(Rxyz(1, 0), 0.6124, 1e-3); EXPECT_NEAR(Rxyz(1, 1), 0.0474, 1e-3); EXPECT_NEAR(Rxyz(1, 2), -0.7891, 1e-3); EXPECT_NEAR(Rxyz(0, 1), -0.6597, 1e-3);
EXPECT_NEAR(Rxyz(2, 0), 0.5, 1e-3); EXPECT_NEAR(Rxyz(2, 1), 0.75, 1e-3); EXPECT_NEAR(Rxyz(2, 2), 0.4330, 1e-3); EXPECT_NEAR(Rxyz(0, 2), 0.4356, 1e-3);
EXPECT_NEAR(Rxyz(1, 0), 0.6124, 1e-3);
EXPECT_NEAR(Rxyz(1, 1), 0.0474, 1e-3);
EXPECT_NEAR(Rxyz(1, 2), -0.7891, 1e-3);
EXPECT_NEAR(Rxyz(2, 0), 0.5, 1e-3);
EXPECT_NEAR(Rxyz(2, 1), 0.75, 1e-3);
EXPECT_NEAR(Rxyz(2, 2), 0.4330, 1e-3);
// Test : création d'une transformation homogène via la sous-matrice 3x3 en // Test : création d'une transformation homogène via la sous-matrice 3x3 en
// utilisant la fonction `block` // utilisant la fonction `block`
M.block(0, 0, 3, 3) = Rxyz; M.block(0, 0, 3, 3) = Rxyz;
M(0, 3) = -0.1; M(0, 3) = -0.1;
M(1, 3) = 1.0; M(1, 3) = 1.0;
M(2, 3) = 2.1; M(2, 3) = 2.1;
// Test : calcule l'inverse de la matrice M et vérifie que M^(-1) * M * v = v // Test : calcule l'inverse de la matrice M et vérifie que M^(-1) * M * v = v
const Matrix4d Minv = M.inverse(); const Matrix4d Minv = M.inverse();
const Vector3d v3 = Minv * (M * v2); const Vector3d v3 = Minv * (M * v2);
EXPECT_DOUBLE_EQ(v3(0), v2(0)); EXPECT_DOUBLE_EQ(v3(0), v2(0));
EXPECT_DOUBLE_EQ(v3(1), v2(1)); EXPECT_DOUBLE_EQ(v3(1), v2(1));
EXPECT_DOUBLE_EQ(v3(2), v2(2)); EXPECT_DOUBLE_EQ(v3(2), v2(2));
// Test : translation d'un vecteur 3D effectuée avec une matrice 4x4 en coordonnées homogènes // Test : translation d'un vecteur 3D effectuée avec une matrice 4x4 en coordonnées homogènes
Matrix4d T; Matrix4d T;
T.setIdentity(); T.setIdentity();
T(0, 3) = 1.2; T(0, 3) = 1.2;
T(1, 3) = 2.5; T(1, 3) = 2.5;
T(2, 3) = -4.0; T(2, 3) = -4.0;
const Vector3d t = T * v3; const Vector3d t = T * v3;
EXPECT_DOUBLE_EQ(t(0), v3(0) + 1.2); EXPECT_DOUBLE_EQ(t(0), v3(0) + 1.2);
EXPECT_DOUBLE_EQ(t(1), v3(1) + 2.5); EXPECT_DOUBLE_EQ(t(1), v3(1) + 2.5);
EXPECT_DOUBLE_EQ(t(2), v3(2) - 4.0); EXPECT_DOUBLE_EQ(t(2), v3(2) - 4.0);
// Test : inverse d'un matrice de rotation // Test : inverse d'un matrice de rotation
const Matrix3d Rinv = Rxyz.inverse(); const Matrix3d Rinv = Rxyz.inverse();
const Matrix3d RT = Rxyz.transpose<double, 3, 3, ColumnStorage>(); const Matrix3d RT = Rxyz.transpose<double, 3, 3, ColumnStorage>();
EXPECT_DOUBLE_EQ(Rinv(0, 0), RT(0, 0)); EXPECT_DOUBLE_EQ(Rinv(0, 0), RT(0, 0));
EXPECT_DOUBLE_EQ(Rinv(1, 1), RT(1, 1)); EXPECT_DOUBLE_EQ(Rinv(1, 1), RT(1, 1));
EXPECT_DOUBLE_EQ(Rinv(0, 2), RT(0, 2)); EXPECT_DOUBLE_EQ(Rinv(0, 2), RT(0, 2));
} }
@ -458,55 +514,52 @@ TEST(TestLabo1, Math3D)
* Test des performance de la multiplication matrice * vecteur * Test des performance de la multiplication matrice * vecteur
* pour de grandes dimensions. * pour de grandes dimensions.
*/ */
TEST(TestLabo1, PerformanceMatrixVector) TEST(TestLabo1, PerformanceMatrixVector) {
{ Matrix<double> A(16384, 16384); // grande matrice avec stockage colonne
Matrix<double> A(16384, 16384); // grande matrice avec stockage colonne Vector<double> v(16384); // grand vecteur
Vector<double> v(16384); // grand vecteur
using namespace std::chrono; using namespace std::chrono;
// Test : multiplication avec l'algorithme naif. // Test : multiplication avec l'algorithme naif.
high_resolution_clock::time_point t = high_resolution_clock::now(); high_resolution_clock::time_point t = high_resolution_clock::now();
naiveMatrixMult(A, v); naiveMatrixMult(A, v);
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t); const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
// Test : multiplication avec l'implémentation spécifique pour les matrices avec // Test : multiplication avec l'implémentation spécifique pour les matrices avec
// stockage par colonnes. // stockage par colonnes.
t = high_resolution_clock::now(); t = high_resolution_clock::now();
A* v; A * v;
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t); const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
EXPECT_TRUE(optimal_t < 0.4 * naive_t) EXPECT_TRUE(optimal_t < 0.4 * naive_t)
<< "Naive time: " << duration_cast<std::chrono::milliseconds>(naive_t).count() << " ms, " << "Naive time: " << duration_cast<std::chrono::milliseconds>(naive_t).count() << " ms, "
<< "optimized time: " << duration_cast<std::chrono::milliseconds>(optimal_t).count() << " ms"; << "optimized time: " << duration_cast<std::chrono::milliseconds>(optimal_t).count() << " ms";
} }
/** /**
* Test des performances de l'addition matrice + matrice * Test des performances de l'addition matrice + matrice
* pour de grandes dimensions. * pour de grandes dimensions.
*/ */
TEST(TestLabo1, PerformanceLargeMatrixMatrix) TEST(TestLabo1, PerformanceLargeMatrixMatrix) {
{ // deux grandes matrices à stockage par colonnes
// deux grandes matrices à stockage par colonnes Matrix<double> A(16384, 16384);
Matrix<double> A(16384, 16384); Matrix<double> B(16384, 16384);
Matrix<double> B(16384, 16384);
using namespace std::chrono; using namespace std::chrono;
high_resolution_clock::time_point t = high_resolution_clock::now(); high_resolution_clock::time_point t = high_resolution_clock::now();
// Test : addition avec l'algorithme naif // Test : addition avec l'algorithme naif
naiveMatrixAddition(A, B); naiveMatrixAddition(A, B);
const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t); const duration<double> naive_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
// Test : addition avec l'implémentation spécifique pour les matrices à // Test : addition avec l'implémentation spécifique pour les matrices à
// stockage par colonnes. // stockage par colonnes.
t = high_resolution_clock::now(); t = high_resolution_clock::now();
A + B; A + B;
const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t); const duration<double> optimal_t = duration_cast<duration<double>>(high_resolution_clock::now() - t);
EXPECT_TRUE(optimal_t < 0.4 * naive_t); EXPECT_TRUE(optimal_t < 0.4 * naive_t);
} }
TEST(TestLabo1, Supplementaires) TEST(TestLabo1, Supplementaires) {
{
// === Stockage === // === Stockage ===
// Test 1: Set zero // Test 1: Set zero
DenseStorage<int, Dynamic> S1(10); DenseStorage<int, Dynamic> S1(10);
@ -534,18 +587,18 @@ TEST(TestLabo1, Supplementaires)
EXPECT_EQ(S1.data()[5], S3.data()[5]); EXPECT_EQ(S1.data()[5], S3.data()[5]);
EXPECT_EQ(S1.data()[7], S3.data()[7]); EXPECT_EQ(S1.data()[7], S3.data()[7]);
// === Matrices === // === Matrices ===
// Test 5: Identité // Test 5: Identité
Matrix<int, -1, -1, ColumnStorage> MC(4, 6); Matrix<int, -1, -1, ColumnStorage> MC(4, 6);
MC.setIdentity(); MC.setIdentity();
for (int i = 0; i < MC.rows(); i++) { for (int col = 0; col < MC.cols(); col++) {
for (int j = 0; j < MC.cols(); j++) { for (int row = 0; row < MC.rows(); row++) {
int expected = 0; int expected = 0;
if (i == j) { if (row == col) {
expected = 1; expected = 1;
} }
EXPECT_EQ(MC(i, j), expected); EXPECT_EQ(MC(col, row), expected);
} }
} }
@ -560,17 +613,17 @@ TEST(TestLabo1, Supplementaires)
MC(3, 2) = 8; MC(3, 2) = 8;
MC(3, 3) = 9; MC(3, 3) = 9;
SubMatrix<int, -1, -1, ColumnStorage> s = MC.block(1, 1, 3, 3); SubMatrix<int, -1, -1, ColumnStorage> s = MC.block(1, 1, 3, 3);
for (int i = 0; i < s.rows(); i++) { for (int col = 0; col < s.cols(); col++) {
for (int j = 0; j < s.cols(); j++) { for (int row = 0; row < s.rows(); row++) {
EXPECT_EQ(s(i, j), MC(i + 1, j + 1)); EXPECT_EQ(s(col, row), MC(col + 1, row + 1));
} }
} }
// Test 7: Transposée d'une sous-matrice // Test 7: Transposée d'une sous-matrice
const Matrix<int, -1, -1, ColumnStorage> t = s.transpose<int, -1, -1, ColumnStorage>(); const Matrix<int, -1, -1, ColumnStorage> t = s.transpose<int, -1, -1, ColumnStorage>();
for (int i = 0; i < t.rows(); i++) { for (int col = 0; col < t.cols(); col++) {
for (int j = 0; j < t.cols(); j++) { for (int row = 0; row < t.rows(); row++) {
EXPECT_EQ(t(j, i), s(i, j)); EXPECT_EQ(t(col, row), s(row, col));
} }
} }
@ -599,10 +652,9 @@ TEST(TestLabo1, Supplementaires)
EXPECT_EQ(V1(12), V2(12)); EXPECT_EQ(V1(12), V2(12));
} }
int main(int argc, char** argv) int main(int argc, char **argv) {
{ ::testing::InitGoogleTest(&argc, argv);
::testing::InitGoogleTest(&argc, argv); const int ret = RUN_ALL_TESTS();
const int ret = RUN_ALL_TESTS();
return ret; return ret;
} }