Main MRPT website > C++ reference
MRPT logo
eigen_plugins_impl.h
Go to the documentation of this file.
1 /* +---------------------------------------------------------------------------+
2  | The Mobile Robot Programming Toolkit (MRPT) C++ library |
3  | |
4  | http://www.mrpt.org/ |
5  | |
6  | Copyright (C) 2005-2012 University of Malaga |
7  | |
8  | This software was written by the Machine Perception and Intelligent |
9  | Robotics Lab, University of Malaga (Spain). |
10  | Contact: Jose-Luis Blanco <jlblanco@ctima.uma.es> |
11  | |
12  | This file is part of the MRPT project. |
13  | |
14  | MRPT is free software: you can redistribute it and/or modify |
15  | it under the terms of the GNU General Public License as published by |
16  | the Free Software Foundation, either version 3 of the License, or |
17  | (at your option) any later version. |
18  | |
19  | MRPT is distributed in the hope that it will be useful, |
20  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
21  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
22  | GNU General Public License for more details. |
23  | |
24  | You should have received a copy of the GNU General Public License |
25  | along with MRPT. If not, see <http://www.gnu.org/licenses/>. |
26  | |
27  +---------------------------------------------------------------------------+ */
28 
29 #ifndef MRPT_EIGEN_PLUGINS_IMPL_H
30 #define MRPT_EIGEN_PLUGINS_IMPL_H
31 
32 // -------------------------------------------------------------------------
33 // This file implements some templates which had to be left only declared
34 // in the "plug-in" headers "eigen_plugins.h" within Eigen::MatrixBase<>
35 // -------------------------------------------------------------------------
36 
37 namespace internal_mrpt
38 {
39  // Generic version for all kind of matrices:
40  template<int R, int C>
42  {
43  template <typename S, int Opt, int MaxR, int MaxC>
44  static inline void doit(Eigen::Matrix<S,R,C,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
45  {
46  ::mrpt::math::detail::TAuxResizer<Eigen::Matrix<S,R,C,Opt,MaxR,MaxC>,Eigen::Matrix<S,R,C,Opt,MaxR,MaxC>::SizeAtCompileTime>::internal_resize(mat,new_rows,new_cols);
47  //mat.derived().conservativeResize(new_rows,new_cols);
48  }
49  };
50  // Specialization for column matrices:
51  template<int R>
52  struct MatOrVecResizer<R,1>
53  {
54  template <typename S, int Opt, int MaxR, int MaxC>
55  static inline void doit(Eigen::Matrix<S,R,1,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
56  {
57  ::mrpt::math::detail::TAuxResizer<Eigen::Matrix<S,R,1,Opt,MaxR,MaxC>,Eigen::Matrix<S,R,1,Opt,MaxR,MaxC>::SizeAtCompileTime>::internal_resize(mat,new_rows);
58  //mat.derived().conservativeResize(new_rows);
59  }
60  };
61  // Specialization for row matrices:
62  template<int C>
63  struct MatOrVecResizer<1,C>
64  {
65  template <typename S, int Opt, int MaxR, int MaxC>
66  static inline void doit(Eigen::Matrix<S,1,C,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
67  {
68  ::mrpt::math::detail::TAuxResizer<Eigen::Matrix<S,1,C,Opt,MaxR,MaxC>,Eigen::Matrix<S,1,C,Opt,MaxR,MaxC>::SizeAtCompileTime>::internal_resize(mat,new_cols);
69  //mat.derived().conservativeResize(new_cols);
70  }
71  };
72  template<>
73  struct MatOrVecResizer<1,1>
74  {
75  template <typename S, int Opt, int MaxR, int MaxC>
76  static inline void doit(Eigen::Matrix<S,1,1,Opt,MaxR,MaxC> &mat, size_t new_rows,size_t new_cols)
77  {
78  ::mrpt::math::detail::TAuxResizer<Eigen::Matrix<S,1,1,Opt,MaxR,MaxC>,Eigen::Matrix<S,1,1,Opt,MaxR,MaxC>::SizeAtCompileTime>::internal_resize(mat,new_cols);
79  //mat.derived().conservativeResize(new_cols);
80  }
81  };
82 }
83 
84 /** Compute the eigenvectors and eigenvalues, both returned as matrices: eigenvectors are the columns, and eigenvalues
85  */
86 template <class Derived>
87 template <class MATRIX1,class MATRIX2>
88 EIGEN_STRONG_INLINE void Eigen::MatrixBase<Derived>::eigenVectors( MATRIX1 & eVecs, MATRIX2 & eVals ) const
89 {
90  Matrix<Scalar,Dynamic,1> evals;
91  eigenVectorsVec(eVecs,evals);
92  eVals.resize(evals.size(),evals.size());
93  eVals.setZero();
94  eVals.diagonal()=evals;
95 }
96 
97 /** Compute the eigenvectors and eigenvalues, both returned as matrices: eigenvectors are the columns, and eigenvalues
98  */
99 template <class Derived>
100 template <class MATRIX1,class VECTOR1>
101 EIGEN_STRONG_INLINE void Eigen::MatrixBase<Derived>::eigenVectorsVec( MATRIX1 & eVecs, VECTOR1 & eVals ) const
102 {
103  Eigen::EigenSolver< Derived > es(*this, true);
104  eVecs = es.eigenvectors().real(); // Keep only the real part of complex matrix
105  eVals = es.eigenvalues().real(); // Keep only the real part of complex matrix
106 
107  // Sort by ascending eigenvalues:
108  std::vector<std::pair<Scalar,Index> > D;
109  D.reserve(eVals.size());
110  for (Index i=0;i<eVals.size();i++)
111  D.push_back(std::make_pair<Scalar,Index>(eVals.coeff(i,0),i));
112  std::sort(D.begin(),D.end());
113  MATRIX1 sortedEigs;
114  sortedEigs.resizeLike(eVecs);
115  for (int i=0;i<eVals.size();i++)
116  {
117  eVals.coeffRef(i,0)=D[i].first;
118  sortedEigs.col(i)=eVecs.col(D[i].second);
119  }
120  eVecs = sortedEigs;
121 }
122 
123 /** Compute the eigenvectors and eigenvalues, both returned as matrices: eigenvectors are the columns, and eigenvalues
124  */
125 template <class Derived>
126 template <class MATRIX1,class MATRIX2>
127 EIGEN_STRONG_INLINE void Eigen::MatrixBase<Derived>::eigenVectorsSymmetric( MATRIX1 & eVecs, MATRIX2 & eVals ) const
128 {
129  Matrix<Scalar,Dynamic,1> evals;
130  eigenVectorsSymmetricVec(eVecs,evals);
131  eVals.resize(evals.size(),evals.size());
132  eVals.setZero();
133  eVals.diagonal()=evals;
134 }
135 
136 /** Compute the eigenvectors and eigenvalues, both returned as matrices: eigenvectors are the columns, and eigenvalues
137  */
138 template <class Derived>
139 template <class MATRIX1,class VECTOR1>
140 EIGEN_STRONG_INLINE void Eigen::MatrixBase<Derived>::eigenVectorsSymmetricVec( MATRIX1 & eVecs, VECTOR1 & eVals ) const
141 {
142  // This solver returns the eigenvectors already sorted.
143  Eigen::SelfAdjointEigenSolver<Derived> eigensolver(*this);
144  eVecs = eigensolver.eigenvectors();
145  eVals = eigensolver.eigenvalues();
146 }
147 
148 
149 template <class Derived>
150 bool Eigen::MatrixBase<Derived>::fromMatlabStringFormat(const std::string &s, bool dumpErrorMsgToStdErr)
151 {
152  // Start with a (0,0) matrix:
153  if ( Derived::RowsAtCompileTime==Eigen::Dynamic)
154  (*this) = Derived();
155 
156  // Look for starting "[".
157  size_t ini = s.find_first_not_of(" \t\r\n");
158  if (ini==std::string::npos || s[ini]!='[') { return false; }
159 
160  size_t end = s.find_last_not_of(" \t\r\n");
161  if (end==std::string::npos || s[end]!=']') return false;
162 
163  if (ini>end) return false;
164 
165  std::vector<Scalar> lstElements;
166 
167  size_t i = ini+1;
168  size_t nRow = 0;
169 
170  while (i<end)
171  {
172  // Extract one row:
173  size_t end_row = s.find_first_of(";]",i);
174  if (end_row==std::string::npos) { return false; }
175 
176  // We have one row in s[ i : (end_row-1) ]
177  std::stringstream ss(s.substr(i, end_row-i ));
178  lstElements.clear();
179  try
180  {
181  while (!ss.eof())
182  {
183  Scalar val;
184  ss >> val;
185  if (ss.bad() || ss.fail()) break;
186  lstElements.push_back(val);
187  }
188  } catch (...) { } // end of line
189 
190  // Empty row? Only for the first row, then this is an empty matrix:
191  if (lstElements.empty())
192  {
193  if (nRow>0)
194  return false;
195  else
196  {
197  // Else, this may be an empty matrix... if there is no next row, we'll return with a (0,0) matrix
198  if ( Derived::RowsAtCompileTime==Eigen::Dynamic )
199  (*this) = Derived();
200  }
201  }
202  else
203  {
204  const size_t N = lstElements.size();
205 
206  // Check valid width: All rows must have the same width
207  if ((nRow>0 && size_t(cols())!=N) ||
208  (nRow==0 && Derived::ColsAtCompileTime!=Eigen::Dynamic && Derived::ColsAtCompileTime!=int(N)) )
209  {
210  if (dumpErrorMsgToStdErr)
211  std::cerr << "[fromMatlabStringFormat] Row " << nRow+1 << " has invalid number of columns.\n";
212  return false;
213  }
214 
215  // Append to the matrix:
216  if ( Derived::RowsAtCompileTime==Eigen::Dynamic || Derived::ColsAtCompileTime==Eigen::Dynamic )
218  else if (Derived::RowsAtCompileTime!=Eigen::Dynamic && int(nRow)>=Derived::RowsAtCompileTime)
219  {
220  if (dumpErrorMsgToStdErr)
221  std::cerr << "[fromMatlabStringFormat] Read more rows than the capacity of the fixed sized matrix.\n";
222  return false;
223  }
224 
225  for (size_t q=0;q<N;q++)
226  coeffRef(nRow,q) = lstElements[q];
227 
228  // Go for the next row:
229  nRow++;
230  }
231 
232  i = end_row+1;
233  }
234  // For fixed sized matrices, check size:
235  if (Derived::RowsAtCompileTime!=Eigen::Dynamic && int(nRow)!=Derived::RowsAtCompileTime)
236  {
237  if (dumpErrorMsgToStdErr)
238  std::cerr << "[fromMatlabStringFormat] Read less rows than the capacity of the fixed sized matrix.\n";
239  return false;
240  }
241  return true; // Ok
242 }
243 
244 template <class Derived>
245 std::string Eigen::MatrixBase<Derived>::inMatlabFormat(const size_t decimal_digits) const
246 {
247  std::stringstream s;
248  s << "[" << std::scientific;
249  s.precision(decimal_digits);
250  for (Index i=0;i<rows();i++)
251  {
252  for (Index j=0;j<cols();j++)
253  s << coeff(i,j) << " ";
254  if (i<rows()-1) s << ";";
255  }
256  s << "]";
257  return s.str();
258 }
259 
260 template <class Derived>
262  const std::string &file,
264  bool appendMRPTHeader,
265  const std::string &userHeader
266  ) const
267 {
268  FILE *f= ::fopen(file.c_str(),"wt");
269  if (!f)
270  throw std::runtime_error(std::string("saveToTextFile: Error opening file ")+file+std::string("' for writing a matrix as text."));
271 
272  if (!userHeader.empty())
273  fprintf(f,"%s",userHeader.c_str() );
274 
275  if (appendMRPTHeader)
276  {
277  time_t rawtime;
278  ::time(&rawtime);
279  struct tm * timeinfo = ::localtime(&rawtime);
280 
281  fprintf(f,"%% File generated with MRPT %s at %s\n%%-----------------------------------------------------------------\n",
283  asctime(timeinfo) );
284  }
285 
286  for (Index i=0; i < rows(); i++)
287  {
288  for (Index j=0; j < cols(); j++)
289  {
290  switch(fileFormat)
291  {
292  case mrpt::math::MATRIX_FORMAT_ENG: ::fprintf(f,"%.16e",static_cast<double>(coeff(i,j))); break;
293  case mrpt::math::MATRIX_FORMAT_FIXED: ::fprintf(f,"%.16f",static_cast<double>(coeff(i,j))); break;
294  case mrpt::math::MATRIX_FORMAT_INT: ::fprintf(f,"%i",static_cast<int>(coeff(i,j))); break;
295  default:
296  throw std::runtime_error("Unsupported value for the parameter 'fileFormat'!");
297  };
298  // Separating blank space
299  if (j<(cols()-1)) ::fprintf(f," ");
300  }
301  ::fprintf(f,"\n");
302  }
303  ::fclose(f);
304 }
305 
306 
307 template <class Derived>
308 void Eigen::MatrixBase<Derived>::loadFromTextFile(const std::string &file)
309 {
310  std::ifstream f(file.c_str());
311  if (f.fail()) throw std::runtime_error(std::string("loadFromTextFile: can't open file:") + file);
312  loadFromTextFile(f);
313 }
314 
315 template <class Derived>
317 {
318  // This matrix is NROWS x NCOLS
319  std::string str;
320  std::vector<double> fil(512);
321  size_t nRows = 0;
322  while ( !f.eof() )
323  {
324  std::getline(f,str);
325  if (str.size() && str[0]!='#' && str[0]!='%')
326  {
327  // Parse row to floats:
328  const char *ptr = str.c_str();
329  char *ptrEnd = NULL;
330  size_t i=0;
331  // Process each number in this row:
332  while ( ptr[0] && ptr!=ptrEnd )
333  {
334  // Find next number: (non white-space character):
335  while (ptr[0] && (ptr[0]==' ' || ptr[0]=='\t' || ptr[0]=='\r' || ptr[0]=='\n'))
336  ptr++;
337  if (fil.size()<=i) fil.resize(fil.size()+512);
338  // Convert to "double":
339  fil[i] = strtod(ptr,&ptrEnd);
340  // A valid conversion has been done?
341  if (ptr!=ptrEnd)
342  {
343  i++; // Yes
344  ptr = ptrEnd;
345  ptrEnd = NULL;
346  }
347  }; // end while procesing this row
348 
349  // "i": # of columns:
350  if ((Derived::ColsAtCompileTime!=Eigen::Dynamic && Index(i)!=Derived::ColsAtCompileTime) )
351  throw std::runtime_error("loadFromTextFile: The matrix in the text file does not match fixed matrix size");
352  if (Derived::ColsAtCompileTime==Eigen::Dynamic && nRows>0 && Index(i)!=cols() )
353  throw std::runtime_error("loadFromTextFile: The matrix in the text file does not have the same number of columns in all rows");
354 
355  // Append to the matrix:
356  if ( Derived::RowsAtCompileTime==Eigen::Dynamic || Derived::ColsAtCompileTime==Eigen::Dynamic )
358  else if (Derived::RowsAtCompileTime!=Eigen::Dynamic && int(nRows)>=Derived::RowsAtCompileTime)
359  throw std::runtime_error("loadFromTextFile: Read more rows than the capacity of the fixed sized matrix.");
360 
361  for (size_t q=0;q<i;q++)
362  coeffRef(nRows,q) = Scalar(fil[q]);
363 
364  nRows++;
365  } // end if fgets
366  } // end while not feof
367 
368  // Report error as exception
369  if (!nRows)
370  throw std::runtime_error("loadFromTextFile: Error loading from text file");
371 }
372 
373 
374 #endif // guard define



Page generated by Doxygen 1.8.3 for MRPT 0.9.6 SVN: at Fri Feb 15 22:05:02 EST 2013