Main MRPT website > C++ reference for MRPT 1.9.9
matrix_ops1_unittest.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 // Note: Matrices unit tests have been split in different files since
11 // building them with eigen3 eats a lot of RAM and may be a problem while
12 // compiling in small systems.
13 
15 #include <mrpt/math/CMatrixD.h>
16 #include <mrpt/math/matrix_serialization.h> // serialization of matrices
17 #include <mrpt/math/ops_matrices.h>
20 #include <mrpt/random.h>
21 #include <gtest/gtest.h>
22 
23 using namespace mrpt;
24 using namespace mrpt::utils;
25 using namespace mrpt::math;
26 using namespace mrpt::random;
27 using namespace mrpt::utils::metaprogramming;
28 using namespace std;
29 
30 const double dat_A[] = {4, 5, 8, -2, 1, 3};
31 const double dat_B[] = {2, 6, 9, 8};
32 const double dat_Cok[] = {53, 64, -2, 32, 29, 30};
33 
34 #define CHECK_AND_RET_ERROR(_COND_, _MSG_) EXPECT_FALSE(_COND_) << _MSG_;
35 
36 TEST(Matrices, A_times_B_dyn)
37 {
38  // Dyn. size, double.
39  CMatrixDouble A(3, 2, dat_A);
40  CMatrixDouble B(2, 2, dat_B);
41  CMatrixDouble C = A * B;
42  CMatrixDouble C_ok(3, 2, dat_Cok);
43  CMatrixDouble err = C - C_ok;
44  EXPECT_NEAR(0, fabs(err.sum()), 1e-5) << "A: " << A << "B: " << B
45  << "A*B: " << C << endl;
46 }
47 
48 TEST(Matrices, A_times_B_fix)
49 {
50  // Fix. size, double.
54 
55  C = A * B;
56  Err = C - CMatrixFixedNumeric<double, 3, 2>(C_ok);
57 
58  EXPECT_NEAR(0, fabs(Err.sum()), 1e-5) << "A: " << A << "B: " << B
59  << "A*B: " << C << endl;
60 }
61 
62 TEST(Matrices, SerializeCMatrixD)
63 {
64  CMatrixDouble A(3, 2, dat_A);
66 
67  CMatrixD As = A;
68 
69  CMemoryStream membuf;
70  membuf << As;
71  membuf.Seek(0);
72  membuf >> fA;
73 
74  EXPECT_NEAR(0, fabs((CMatrixDouble(fA) - A).sum()), 1e-9);
75 
76  try
77  {
78  // Now, if we try to de-serialize into the wrong type, we should get an
79  // exception:
80  membuf.Seek(0);
82  membuf >> fB; // Wrong size!
83 
84  GTEST_FAIL() << "Exception not launched when it was expected!";
85  }
86  catch (...)
87  { // OK, exception occurred, as expected
88  }
89 }
90 
91 TEST(Matrices, EigenVal2x2dyn)
92 {
93  const double dat_C1[] = {14.6271, 5.8133, 5.8133, 16.8805};
94  CMatrixDouble C1(2, 2, dat_C1);
95 
96  Eigen::MatrixXd C1_V, C1_D;
97  C1.eigenVectors(C1_V, C1_D);
98 
99  CMatrixDouble C1_RR = C1_V * C1_D * C1_V.transpose();
100  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
101 }
102 
103 TEST(Matrices, EigenVal3x3dyn)
104 {
105  const double dat_C1[] = {8, 6, 1, 6, 9, 4, 1, 4, 10};
106  CMatrixDouble C1(3, 3, dat_C1);
107 
108  Eigen::MatrixXd C1_V, C1_D;
109  C1.eigenVectors(C1_V, C1_D);
110 
111  CMatrixDouble C1_RR = C1_V * C1_D * C1_V.transpose();
112  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
113 }
114 
115 TEST(Matrices, EigenVal2x2fix)
116 {
117  const double dat_C1[] = {14.6271, 5.8133, 5.8133, 16.8805};
118  CMatrixDouble22 C1(dat_C1);
119 
120  Eigen::Matrix2d C1_V, C1_D;
121  C1.eigenVectors(C1_V, C1_D);
122 
123  CMatrixDouble22 C1_RR = C1_V * C1_D * (~C1_V);
124  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
125 }
126 
127 TEST(Matrices, EigenVal3x3fix)
128 {
129  const double dat_C1[] = {8, 6, 1, 6, 9, 4, 1, 4, 10};
130  CMatrixDouble33 C1(dat_C1);
131 
132  CMatrixDouble33 C1_V, C1_D;
133  C1.eigenVectors(C1_V, C1_D);
134 
135  CMatrixDouble33 C1_RR = C1_V * C1_D * (~C1_V);
136  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
137 }
138 
139 #if 0 // JL: Disabled since it fails in some PPA build servers. Reported to
140  // Eigen list for possible fixes...
141 
142 // Compare the two ways of computing matrix eigenvectors: generic & for symmetric matrices:
143 TEST(Matrices,EigenVal4x4_sym_vs_generic)
144 {
145  const double dat_C1[] = {
146  13.737245,10.248641,-5.839599,11.108320,
147  10.248641,14.966139,-5.259922,11.662222,
148  -5.839599,-5.259922,9.608822,-4.342505,
149  11.108320,11.662222,-4.342505,12.121940 };
150  const CMatrixDouble44 C1(dat_C1);
151 
152  CMatrixDouble44 eigvecs_sym, eigvecs_gen, eigvals_symM, eigvals_genM;
153  CVectorDouble eigvals_sym, eigvals_gen;
154 
155  C1.eigenVectorsVec(eigvecs_gen,eigvals_gen);
156  C1.eigenVectorsSymmetricVec(eigvecs_sym,eigvals_sym);
157 
158  eigvals_symM.setZero();eigvals_symM.diagonal() = eigvals_sym;
159  eigvals_genM.setZero();eigvals_genM.diagonal() = eigvals_gen;
160 
161  EXPECT_NEAR( (C1-eigvecs_gen*eigvals_genM*(~eigvecs_gen)).array().abs().sum(),0,1e-5)
162  << endl << endl
163  << "eigvecs_gen*eigvals_gen*(~eigvecs_gen):\n" << eigvecs_gen*eigvals_genM*(~eigvecs_gen) << endl
164  << "C1:\n" << C1 << endl
165  << "eigvals_sym:\n" << eigvals_sym << endl
166  << "eigvals_gen:\n" << eigvals_gen << endl
167  << "eigvals_symM:\n" << eigvals_symM << endl
168  << "eigvals_genM:\n" << eigvals_genM << endl
169  << "eigvecs_gen:\n" << eigvecs_gen << endl
170  << "eigvecs_sym:\n" << eigvecs_sym << endl<< endl;
171 
172  EXPECT_NEAR( (C1-eigvecs_sym*eigvals_symM*(~eigvecs_sym)).array().abs().sum(),0,1e-5)
173  << endl << endl
174  << "eigvecs_sym*eigvals_sym*(~eigvecs_sym):\n" << eigvecs_sym*eigvals_symM*(~eigvecs_sym) << endl
175  << "C1:\n" << C1 << endl;
176 
177  EXPECT_NEAR( (eigvals_gen-eigvals_sym).array().abs().sum(),0,1e-5)
178  << endl << endl
179  << "eigvals_gen:\n" << eigvals_gen<< endl
180  << "eigvals_sym:\n" << eigvals_sym << endl;
181 }
182 #endif
A namespace of pseudo-random numbers genrators of diferent distributions.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
This class is a "CSerializable" wrapper for "CMatrixTemplateNumeric<double>".
Definition: CMatrixD.h:25
const double dat_A[]
uint64_t Seek(uint64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) override
Introduces a pure virtual method for moving to a specified position in the streamed resource...
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
STL namespace.
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
This CStream derived class allow using a memory buffer as a CStream.
Definition: CMemoryStream.h:27
CMatrixTemplateNumeric< double > CMatrixDouble
Declares a matrix of double numbers (non serializable).
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
TEST(Matrices, A_times_B_dyn)
A set of utility objects for metaprogramming with STL algorithms.
const double dat_Cok[]
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
This file implements matrix/vector text and binary serialization.
const double dat_B[]



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019