MRPT  2.0.4
MatrixVectorBase.h
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | https://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2020, Individual contributors, see AUTHORS file |
6  | See: https://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See: https://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 #pragma once
10 
11 #include <mrpt/core/exceptions.h>
12 #include <mrpt/core/is_defined.h>
13 #include <mrpt/core/optional_ref.h>
14 #include <algorithm> // fill()
15 #include <cstddef> // size_t
16 #include <iosfwd>
17 #include <string>
18 #include <vector>
19 
20 namespace mrpt::math
21 {
22 template <class T>
23 class CVectorDynamic;
24 template <class T>
25 class CMatrixDynamic;
26 template <typename T, std::size_t ROWS, std::size_t COLS>
27 class CMatrixFixed;
28 
29 template <typename DER>
31 
32 /*! Selection of the number format in MatrixVectorBase::saveToTextFile()
33  * \ingroup mrpt_math_grp */
35 {
36  /** engineering format '%e' */
38  /** fixed floating point '%f' */
40  /** intergers '%i' */
42 };
43 
44 /** Base CRTP class for all MRPT vectors and matrices.
45  *
46  * Template methods whose implementation is not in this header file are
47  * explicitly instantiated and exported for these derived types:
48  * - CMatrixDynamic and CVectorDynamic, for `Scalar`: `float`, `double`
49  * - CMatrixFixed and CVectorFixed, for `Scalar`: `float`, `double`, and sizes
50  * from 2x2 to 6x6 and 2 to 6, respectively.
51  *
52  * \sa CMatrixFixed
53  * \ingroup mrpt_math_grp
54  */
55 template <typename Scalar, class Derived>
57 {
58  public:
59  Derived& mvbDerived() { return static_cast<Derived&>(*this); }
60  const Derived& mvbDerived() const
61  {
62  return static_cast<const Derived&>(*this);
63  }
64 
65  /** @name Initialization methods
66  * @{ */
67 
68  /*! Fill all the elements with a given value (Note: named "fillAll" since
69  * "fill" will be used by child classes) */
70  void fill(const Scalar& val)
71  {
72  std::fill(mvbDerived().begin(), mvbDerived().end(), val);
73  }
74 
75  inline void setConstant(const Scalar value) { fill(value); }
76  inline void setConstant(size_t nrows, size_t ncols, const Scalar value)
77  {
78  mvbDerived().resize(nrows, ncols);
79  fill(value);
80  }
81  inline void setConstant(size_t nrows, const Scalar value)
82  {
83  ASSERTMSG_(
84  Derived::ColsAtCompileTime == 1,
85  "setConstant(n) can be used only for vectors, not matrices");
86  setConstant(nrows, 1, value);
87  }
88 
89  static Derived Constant(const Scalar value)
90  {
91  ASSERTMSG_(
92  Derived::RowsAtCompileTime > 0 && Derived::ColsAtCompileTime > 0,
93  "Constant() without arguments can be used only for fixed-size "
94  "matrices/vectors");
95  Derived m;
96  m.fill(value);
97  return m;
98  }
99  static Derived Constant(size_t nrows, size_t ncols, const Scalar value)
100  {
101  Derived m;
102  m.setConstant(nrows, ncols, value);
103  return m;
104  }
105 
106  inline void assign(const std::size_t N, const Scalar value)
107  {
108  mvbDerived().resize(N);
109  fill(value);
110  }
111 
112  inline void setZero() { fill(0); }
113  inline void setZero(size_t nrows, size_t ncols)
114  {
115  setConstant(nrows, ncols, 0);
116  }
117  inline void setZero(size_t nrows)
118  {
119  ASSERTMSG_(
120  Derived::ColsAtCompileTime == 1,
121  "setZero(n) can be used only for vectors, not matrices");
122  setConstant(nrows, 1, 0);
123  }
124 
125  static Derived Zero() { return Constant(0); }
126  static Derived Zero(size_t nrows, size_t ncols)
127  {
128  return Constant(nrows, ncols, 0);
129  }
130 
131  /** @} */
132 
133  /** @name Operations that DO require `#include <Eigen/Dense>` in user code
134  * @{ */
135 
136  /** non-const block(): Returns an Eigen::Block reference to the block */
137  template <int BLOCK_ROWS, int BLOCK_COLS>
138  auto block(int start_row, int start_col)
139  {
140  internalAssertEigenDefined<Derived>();
141  return mvbDerived().asEigen().template block<BLOCK_ROWS, BLOCK_COLS>(
142  start_row, start_col);
143  }
144 
145  auto block(int start_row, int start_col, int BLOCK_ROWS, int BLOCK_COLS)
146  {
147  internalAssertEigenDefined<Derived>();
148  return mvbDerived().asEigen().block(
149  start_row, start_col, BLOCK_ROWS, BLOCK_COLS);
150  }
151  auto block(
152  int start_row, int start_col, int BLOCK_ROWS, int BLOCK_COLS) const
153  {
154  internalAssertEigenDefined<Derived>();
155  return mvbDerived().asEigen().block(
156  start_row, start_col, BLOCK_ROWS, BLOCK_COLS);
157  }
158 
159  auto transpose()
160  {
161  internalAssertEigenDefined<Derived>();
162  return mvbDerived().asEigen().transpose();
163  }
164  auto transpose() const
165  {
166  internalAssertEigenDefined<Derived>();
167  return mvbDerived().asEigen().transpose();
168  }
169 
170  auto array()
171  {
172  internalAssertEigenDefined<Derived>();
173  return mvbDerived().asEigen().array();
174  }
175  auto array() const
176  {
177  internalAssertEigenDefined<Derived>();
178  return mvbDerived().asEigen().array();
179  }
180 
181  auto operator-() const
182  {
183  internalAssertEigenDefined<Derived>();
184  return -mvbDerived().asEigen();
185  }
186 
187  template <typename S2, class D2>
188  auto operator+(const MatrixVectorBase<S2, D2>& m2) const
189  {
190  internalAssertEigenDefined<Derived>();
191  return mvbDerived().asEigen() + m2.mvbDerived().asEigen();
192  }
193  template <typename S2, class D2>
195  {
196  internalAssertEigenDefined<Derived>();
197  mvbDerived().asEigen() += m2.mvbDerived().asEigen();
198  }
199 
200  template <typename S2, class D2>
201  auto operator-(const MatrixVectorBase<S2, D2>& m2) const
202  {
203  internalAssertEigenDefined<Derived>();
204  return mvbDerived().asEigen() - m2.mvbDerived().asEigen();
205  }
206  template <typename S2, class D2>
208  {
209  internalAssertEigenDefined<Derived>();
210  mvbDerived().asEigen() -= m2.mvbDerived().asEigen();
211  }
212 
213  template <typename S2, class D2>
214  auto operator*(const MatrixVectorBase<S2, D2>& m2) const
215  {
216  internalAssertEigenDefined<Derived>();
217  return mvbDerived().asEigen() * m2.mvbDerived().asEigen();
218  }
219  auto operator*(const Scalar s) const
220  {
221  internalAssertEigenDefined<Derived>();
222  return mvbDerived().asEigen() * s;
223  }
224 
225  template <int N>
227  {
229  mvbDerived().asEigen().template tail<N>());
230  }
231  template <int N>
233  {
235  mvbDerived().asEigen().template head<N>());
236  }
237 
238  /** @} */
239 
240  /** @name Standalone operations (do NOT require `#include <Eigen/Dense>`)
241  * @{ */
242 
243  Scalar& coeffRef(int r, int c) { return mvbDerived()(r, c); }
244  const Scalar& coeff(int r, int c) const { return mvbDerived()(r, c); }
245 
246  /** Minimum value in the matrix/vector */
247  Scalar minCoeff() const;
248  Scalar minCoeff(std::size_t& outIndexOfMin) const;
249  Scalar minCoeff(std::size_t& rowIdx, std::size_t& colIdx) const;
250 
251  /** Maximum value in the matrix/vector */
252  Scalar maxCoeff() const;
253  Scalar maxCoeff(std::size_t& outIndexOfMax) const;
254  Scalar maxCoeff(std::size_t& rowIdx, std::size_t& colIdx) const;
255 
256  /** returns true if matrix is NxN */
257  bool isSquare() const { return mvbDerived().cols() == mvbDerived().rows(); }
258 
259  /** returns true if matrix/vector has size=0 */
260  bool empty() const
261  {
262  return mvbDerived().cols() == 0 && mvbDerived().rows() == 0;
263  }
264 
265  /** Compute the norm-infinite of a vector ($f[ ||\mathbf{v}||_\infnty $f]),
266  * ie the maximum absolute value of the elements. */
267  Scalar norm_inf() const;
268 
269  /** Compute the L2 norm of a vector/array/matrix (the Euclidean distance
270  * to the origin, taking all the elements as a single vector). \sa norm */
271  Scalar norm() const;
272 
273  void operator+=(Scalar s);
274  void operator-=(Scalar s);
275  void operator*=(Scalar s);
276 
278 
279  Derived operator+(const Derived& m2) const
280  {
281  if constexpr (
282  Derived::RowsAtCompileTime == Derived::ColsAtCompileTime ||
283  Derived::ColsAtCompileTime == 1 || Derived::ColsAtCompileTime == -1)
284  {
285  return impl_op_add(m2);
286  }
287  else
288  {
289  throw std::runtime_error(
290  "Explicit instantiation not provided for this matrix size: use "
291  "asEigen()");
292  }
293  }
294  void operator+=(const Derived& m2)
295  {
296  if constexpr (
297  Derived::RowsAtCompileTime == Derived::ColsAtCompileTime ||
298  Derived::ColsAtCompileTime == 1 || Derived::ColsAtCompileTime == -1)
299  {
300  impl_op_selfadd(m2);
301  }
302  else
303  {
304  throw std::runtime_error(
305  "Explicit instantiation not provided for this matrix size: use "
306  "asEigen()");
307  }
308  }
309  Derived operator-(const Derived& m2) const
310  {
311  if constexpr (
312  Derived::RowsAtCompileTime == Derived::ColsAtCompileTime ||
313  Derived::ColsAtCompileTime == 1 || Derived::ColsAtCompileTime == -1)
314  {
315  return impl_op_subs(m2);
316  }
317  else
318  {
319  throw std::runtime_error(
320  "Explicit instantiation not provided for this matrix size: use "
321  "asEigen()");
322  }
323  }
324  void operator-=(const Derived& m2)
325  {
326  if constexpr (
327  Derived::RowsAtCompileTime == Derived::ColsAtCompileTime ||
328  Derived::ColsAtCompileTime == 1 || Derived::ColsAtCompileTime == -1)
329  {
330  impl_op_selfsubs(m2);
331  }
332  else
333  {
334  throw std::runtime_error(
335  "Explicit instantiation not provided for this matrix size: use "
336  "asEigen()");
337  }
338  }
339  Derived operator*(const Derived& m2) const;
340 
341  private:
342  Derived impl_op_add(const Derived& m2) const;
343  void impl_op_selfadd(const Derived& m2);
344  Derived impl_op_subs(const Derived& m2) const;
345  void impl_op_selfsubs(const Derived& m2);
346 
347  public:
348  /** dot product of `this \cdot v ` */
349  Scalar dot(const CVectorDynamic<Scalar>& v) const;
351 
352  /** this = A * b , with `A` and `b` a dynamic matrix & vector */
353  void matProductOf_Ab(
355 
356  /** this = A<sup>T</sup> * b , with `A` and `b` a dynamic matrix & vector */
357  void matProductOf_Atb(
359 
360  /** Sum of all elements in matrix/vector. */
361  Scalar sum() const;
362 
363  /** Sum of the absolute value of all elements in matrix/vector. */
364  Scalar sum_abs() const;
365 
366  /** Returns a string representation of the vector/matrix, using Eigen's
367  * default settings. */
368  std::string asString() const;
369 
370  /** Reads a matrix from a string in Matlab-like format, for example:
371  * "[1 0 2; 0 4 -1]"
372  * The string must start with '[' and end with ']'. Rows are separated by
373  * semicolons ';' and columns in each row by one or more whitespaces
374  * ' ' or tabs '\t'. Commas ',' between elements are NOT allowed.
375  *
376  * This format is also used for CConfigFile::read_matrix.
377  *
378  * \return true on success. false if the string is malformed, and then the
379  * matrix will be resized to 0x0.
380  * \sa inMatlabFormat, CConfigFile::read_matrix
381  */
383  const std::string& s,
384  mrpt::optional_ref<std::ostream> dump_errors_here = std::nullopt);
385 
386  /** Exports the matrix as a string compatible with Matlab/Octave.
387  * \sa fromMatlabStringFormat()
388  */
389  std::string inMatlabFormat(const std::size_t decimal_digits = 6) const;
390 
391  /** Saves the vector/matrix to a file compatible with MATLAB/Octave
392  * text format.
393  * \param file The target filename.
394  * \param fileFormat See TMatrixTextFileFormat. The format of the numbers in
395  * the text file.
396  * \param appendMRPTHeader Insert this header to the file "% File generated
397  * by MRPT. Load with MATLAB with: VAR=load(FILENAME);"
398  * \param userHeader Additional text to be written at the head of the file.
399  * Typically MALAB comments "% This file blah blah". Final end-of-line is
400  * not needed. \sa loadFromTextFile, CMatrixDynamic::inMatlabFormat,
401  * SAVE_MATRIX
402  */
403  void saveToTextFile(
404  const std::string& file,
407  bool appendMRPTHeader = false,
408  const std::string& userHeader = std::string()) const;
409 
410  /** Loads a vector/matrix from a text file, compatible with MATLAB text
411  * format. Lines starting with '%' or '#' are interpreted as comments and
412  * ignored.
413  * \exception std::runtime_error On format error.
414  * \sa saveToTextFile, fromMatlabStringFormat
415  */
416  void loadFromTextFile(std::istream& f);
417 
418  /// \overload
419  void loadFromTextFile(const std::string& file);
420 
421  template <typename OTHERMATVEC>
422  bool operator==(const OTHERMATVEC& o) const
423  {
424  const auto& d = mvbDerived();
425  if (d.cols() != o.cols() || d.rows() != o.rows()) return false;
426  for (typename OTHERMATVEC::Index r = 0; r < d.rows(); r++)
427  for (typename OTHERMATVEC::Index c = 0; c < d.cols(); c++)
428  if (d(r, c) != o(r, c)) return false;
429  return true;
430  }
431  template <typename OTHERMATVEC>
432  bool operator!=(const OTHERMATVEC& o) const
433  {
434  return !(*this == o);
435  }
436 
437  /** @} */
438 };
439 
440 /** Issues a static_assert() error if trying to compile a method that
441  * requires Eigen headers, without including them. */
442 template <typename DER>
444 {
445  if constexpr (!mrpt::is_defined_v<typename DER::eigen_t>)
446  {
447  static_assert(
448  mrpt::is_defined_v<typename DER::eigen_t>,
449  "Using this method requires including `<Eigen/Dense>` in the "
450  "calling C++ file");
451  }
452 }
453 
454 /** Stream as text. Implemented for all matrices and vectors, except for
455  * non-square fixed-size matrices. */
456 template <
457  typename Scalar, class Derived,
458  typename = std::enable_if_t<
459  Derived::RowsAtCompileTime == Derived::ColsAtCompileTime ||
460  (Derived::ColsAtCompileTime == 1)>>
461 std::ostream& operator<<(
462  std::ostream& o, const MatrixVectorBase<Scalar, Derived>& m)
463 {
464  return o << m.asString();
465 }
466 
467 } // namespace mrpt::math
Scalar maxCoeff() const
Maximum value in the matrix/vector.
void operator-=(const Derived &m2)
Scalar norm_inf() const
Compute the norm-infinite of a vector ($f[ ||{v}||_ $f]), ie the maximum absolute value of the elemen...
void impl_op_selfsubs(const Derived &m2)
auto operator*(const MatrixVectorBase< S2, D2 > &m2) const
A compile-time fixed-size numeric matrix container.
Definition: CMatrixFixed.h:33
double Scalar
Definition: KmUtils.h:43
CMatrixFixed< Scalar, N, 1 > head() const
std::string asString() const
Returns a string representation of the vector/matrix, using Eigen&#39;s default settings.
Template for column vectors of dynamic size, compatible with Eigen.
bool empty() const
returns true if matrix/vector has size=0
Scalar norm() const
Compute the L2 norm of a vector/array/matrix (the Euclidean distance to the origin, taking all the elements as a single vector).
void fill(const Scalar &val)
engineering format &#39;e&#39;
const Derived & mvbDerived() const
bool isSquare() const
returns true if matrix is NxN
CMatrixFixed< Scalar, N, 1 > tail() const
auto operator-(const MatrixVectorBase< S2, D2 > &m2) const
std::optional< std::reference_wrapper< T > > optional_ref
Shorter name for std::optional<std::reference_wrapper<T>>
Definition: optional_ref.h:20
void operator+=(const Derived &m2)
void saveToTextFile(const std::string &file, mrpt::math::TMatrixTextFileFormat fileFormat=mrpt::math::MATRIX_FORMAT_ENG, bool appendMRPTHeader=false, const std::string &userHeader=std::string()) const
Saves the vector/matrix to a file compatible with MATLAB/Octave text format.
Derived operator-(const Derived &m2) const
void setConstant(size_t nrows, const Scalar value)
This base provides a set of functions for maths stuff.
auto block(int start_row, int start_col, int BLOCK_ROWS, int BLOCK_COLS) const
bool operator!=(const OTHERMATVEC &o) const
Scalar dot(const CVectorDynamic< Scalar > &v) const
dot product of this \cdot v
Derived operator+(const Derived &m2) const
auto block(int start_row, int start_col)
non-const block(): Returns an Eigen::Block reference to the block
static Derived Constant(size_t nrows, size_t ncols, const Scalar value)
bool operator==(const OTHERMATVEC &o) const
Derived impl_op_subs(const Derived &m2) const
void assign(const std::size_t N, const Scalar value)
int val
Definition: mrpt_jpeglib.h:957
void matProductOf_Ab(const CMatrixDynamic< Scalar > &A, const CVectorDynamic< Scalar > &b)
this = A * b , with A and b a dynamic matrix & vector
void operator+=(const MatrixVectorBase< S2, D2 > &m2)
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:108
bool fromMatlabStringFormat(const std::string &s, mrpt::optional_ref< std::ostream > dump_errors_here=std::nullopt)
Reads a matrix from a string in Matlab-like format, for example: "[1 0 2; 0 4 -1]" The string must st...
void setConstant(const Scalar value)
static Derived Zero(size_t nrows, size_t ncols)
void setZero(size_t nrows, size_t ncols)
const Scalar & coeff(int r, int c) const
Scalar sum_abs() const
Sum of the absolute value of all elements in matrix/vector.
auto operator+(const MatrixVectorBase< S2, D2 > &m2) const
fixed floating point &#39;f&#39;
const_iterator end() const
Definition: ts_hash_map.h:246
auto operator*(const Scalar s) const
const_iterator begin() const
Definition: ts_hash_map.h:240
void operator-=(const MatrixVectorBase< S2, D2 > &m2)
Scalar sum() const
Sum of all elements in matrix/vector.
Derived impl_op_add(const Derived &m2) const
void impl_op_selfadd(const Derived &m2)
std::string inMatlabFormat(const std::size_t decimal_digits=6) const
Exports the matrix as a string compatible with Matlab/Octave.
Scalar minCoeff() const
Minimum value in the matrix/vector.
auto block(int start_row, int start_col, int BLOCK_ROWS, int BLOCK_COLS)
Base CRTP class for all MRPT vectors and matrices.
void matProductOf_Atb(const CMatrixDynamic< Scalar > &A, const CVectorDynamic< Scalar > &b)
this = AT * b , with A and b a dynamic matrix & vector
This template class provides the basic functionality for a general 2D any-size, resizable container o...
intergers &#39;i&#39;
void setConstant(size_t nrows, size_t ncols, const Scalar value)
void internalAssertEigenDefined()
Issues a static_assert() error if trying to compile a method that requires Eigen headers, without including them.
static Derived Constant(const Scalar value)
Scalar & coeffRef(int r, int c)
void loadFromTextFile(std::istream &f)
Loads a vector/matrix from a text file, compatible with MATLAB text format.



Page generated by Doxygen 1.8.14 for MRPT 2.0.4 Git: 33de1d0ad Sat Jun 20 11:02:42 2020 +0200 at sáb jun 20 17:35:17 CEST 2020