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-2018, 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>
19 #include <mrpt/io/CMemoryStream.h>
20 #include <mrpt/random.h>
21 #include <gtest/gtest.h>
22 
23 using namespace mrpt;
24 using namespace mrpt::math;
25 using namespace mrpt::random;
26 using namespace std;
27 
28 const double dat_A[] = {4, 5, 8, -2, 1, 3};
29 const double dat_B[] = {2, 6, 9, 8};
30 const double dat_Cok[] = {53, 64, -2, 32, 29, 30};
31 
32 #define CHECK_AND_RET_ERROR(_COND_, _MSG_) EXPECT_FALSE(_COND_) << _MSG_;
33 
34 TEST(Matrices, A_times_B_dyn)
35 {
36  // Dyn. size, double.
37  CMatrixDouble A(3, 2, dat_A);
38  CMatrixDouble B(2, 2, dat_B);
39  CMatrixDouble C = A * B;
40  CMatrixDouble C_ok(3, 2, dat_Cok);
41  CMatrixDouble err = C - C_ok;
42  EXPECT_NEAR(0, fabs(err.sum()), 1e-5) << "A: " << A << "B: " << B
43  << "A*B: " << C << endl;
44 }
45 
46 TEST(Matrices, A_times_B_fix)
47 {
48  // Fix. size, double.
52 
53  C = A * B;
54  Err = C - CMatrixFixedNumeric<double, 3, 2>(C_ok);
55 
56  EXPECT_NEAR(0, fabs(Err.sum()), 1e-5) << "A: " << A << "B: " << B
57  << "A*B: " << C << endl;
58 }
59 
60 TEST(Matrices, SerializeCMatrixD)
61 {
62  CMatrixDouble A(3, 2, dat_A);
64 
65  CMatrixD As = A;
66 
68  auto arch = mrpt::serialization::archiveFrom(membuf);
69  arch << As;
70  membuf.Seek(0);
71  arch >> fA;
72 
73  EXPECT_NEAR(0, fabs((CMatrixDouble(fA) - A).sum()), 1e-9);
74 
75  try
76  {
77  // Now, if we try to de-serialize into the wrong type, we should get an
78  // exception:
79  membuf.Seek(0);
81  arch >> fB; // Wrong size!
82 
83  GTEST_FAIL() << "Exception not launched when it was expected!";
84  }
85  catch (...)
86  { // OK, exception occurred, as expected
87  }
88 }
89 
90 TEST(Matrices, EigenVal2x2dyn)
91 {
92  const double dat_C1[] = {14.6271, 5.8133, 5.8133, 16.8805};
93  CMatrixDouble C1(2, 2, dat_C1);
94 
95  Eigen::MatrixXd C1_V, C1_D;
96  C1.eigenVectors(C1_V, C1_D);
97 
98  CMatrixDouble C1_RR = C1_V * C1_D * C1_V.transpose();
99  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
100 }
101 
102 TEST(Matrices, EigenVal3x3dyn)
103 {
104  const double dat_C1[] = {8, 6, 1, 6, 9, 4, 1, 4, 10};
105  CMatrixDouble C1(3, 3, dat_C1);
106 
107  Eigen::MatrixXd C1_V, C1_D;
108  C1.eigenVectors(C1_V, C1_D);
109 
110  CMatrixDouble C1_RR = C1_V * C1_D * C1_V.transpose();
111  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
112 }
113 
114 TEST(Matrices, EigenVal2x2fix)
115 {
116  const double dat_C1[] = {14.6271, 5.8133, 5.8133, 16.8805};
117  CMatrixDouble22 C1(dat_C1);
118 
119  Eigen::Matrix2d C1_V, C1_D;
120  C1.eigenVectors(C1_V, C1_D);
121 
122  CMatrixDouble22 C1_RR = C1_V * C1_D * C1_V.transpose();
123  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
124 }
125 
126 TEST(Matrices, EigenVal3x3fix)
127 {
128  const double dat_C1[] = {8, 6, 1, 6, 9, 4, 1, 4, 10};
129  CMatrixDouble33 C1(dat_C1);
130 
131  CMatrixDouble33 C1_V, C1_D;
132  C1.eigenVectors(C1_V, C1_D);
133 
134  CMatrixDouble33 C1_RR = C1_V * C1_D * C1_V.transpose();
135  EXPECT_NEAR((C1_RR - C1).array().abs().sum(), 0, 1e-4);
136 }
137 
138 #if 0 // JL: Disabled since it fails in some PPA build servers. Reported to
139  // Eigen list for possible fixes...
140 
141 // Compare the two ways of computing matrix eigenvectors: generic & for symmetric matrices:
142 TEST(Matrices,EigenVal4x4_sym_vs_generic)
143 {
144  const double dat_C1[] = {
145  13.737245,10.248641,-5.839599,11.108320,
146  10.248641,14.966139,-5.259922,11.662222,
147  -5.839599,-5.259922,9.608822,-4.342505,
148  11.108320,11.662222,-4.342505,12.121940 };
149  const CMatrixDouble44 C1(dat_C1);
150 
151  CMatrixDouble44 eigvecs_sym, eigvecs_gen, eigvals_symM, eigvals_genM;
152  CVectorDouble eigvals_sym, eigvals_gen;
153 
154  C1.eigenVectorsVec(eigvecs_gen,eigvals_gen);
155  C1.eigenVectorsSymmetricVec(eigvecs_sym,eigvals_sym);
156 
157  eigvals_symM.setZero();eigvals_symM.diagonal() = eigvals_sym;
158  eigvals_genM.setZero();eigvals_genM.diagonal() = eigvals_gen;
159 
160  EXPECT_NEAR( (C1-eigvecs_gen*eigvals_genM*(~eigvecs_gen)).array().abs().sum(),0,1e-5)
161  << endl << endl
162  << "eigvecs_gen*eigvals_gen*(~eigvecs_gen):\n" << eigvecs_gen*eigvals_genM*(~eigvecs_gen) << endl
163  << "C1:\n" << C1 << endl
164  << "eigvals_sym:\n" << eigvals_sym << endl
165  << "eigvals_gen:\n" << eigvals_gen << endl
166  << "eigvals_symM:\n" << eigvals_symM << endl
167  << "eigvals_genM:\n" << eigvals_genM << endl
168  << "eigvecs_gen:\n" << eigvecs_gen << endl
169  << "eigvecs_sym:\n" << eigvecs_sym << endl<< endl;
170 
171  EXPECT_NEAR( (C1-eigvecs_sym*eigvals_symM*(~eigvecs_sym)).array().abs().sum(),0,1e-5)
172  << endl << endl
173  << "eigvecs_sym*eigvals_sym*(~eigvecs_sym):\n" << eigvecs_sym*eigvals_symM*(~eigvecs_sym) << endl
174  << "C1:\n" << C1 << endl;
175 
176  EXPECT_NEAR( (eigvals_gen-eigvals_sym).array().abs().sum(),0,1e-5)
177  << endl << endl
178  << "eigvals_gen:\n" << eigvals_gen<< endl
179  << "eigvals_sym:\n" << eigvals_sym << endl;
180 }
181 #endif
A namespace of pseudo-random numbers generators of diferent distributions.
This class is a "CSerializable" wrapper for "CMatrixTemplateNumeric<double>".
Definition: CMatrixD.h:22
const double dat_A[]
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:44
STL namespace.
CArchiveStreamBase< STREAM > archiveFrom(STREAM &s)
Helper function to create a templatized wrapper CArchive object for a: MRPT&#39;s CStream, std::istream, std::ostream, std::stringstream
Definition: CArchive.h:555
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
This CStream derived class allow using a memory buffer as a CStream.
CMatrixTemplateNumeric< double > CMatrixDouble
Declares a matrix of double numbers (non serializable).
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
uint64_t Seek(int64_t Offset, CStream::TSeekOrigin Origin=sFromBeginning) override
Introduces a pure virtual method for moving to a specified position in the streamed resource...
TEST(Matrices, A_times_B_dyn)
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: 7d5e6d718 Fri Aug 24 01:51:28 2018 +0200 at lun nov 2 08:35:50 CET 2020