Main MRPT website > C++ reference for MRPT 1.9.9
ops_containers.h
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 #ifndef mrpt_math_container_ops_H
10 #define mrpt_math_container_ops_H
11 
12 #include <mrpt/math/types_math.h>
13 
14 #include <mrpt/math/lightweight_geom_data.h> // forward declarations
15 
16 #include <functional>
17 #include <algorithm>
18 #include <cmath>
19 
20 /** \addtogroup container_ops_grp Vector and matrices mathematical operations
21  * and other utilities
22  * \ingroup mrpt_math_grp
23  * @{ */
24 
25 /** \file ops_containers.h
26  * This file implements several operations that operate element-wise on
27  * individual or pairs of containers.
28  * Containers here means any of: mrpt::math::CVectorTemplace,
29  * mrpt::math::CArray, mrpt::math::CMatrixFixedNumeric,
30  * mrpt::math::CMatrixTemplate.
31  *
32  * In general, any container having a type "mrpt_autotype" self-referencing to
33  * the type itself, and a dummy struct mrpt_container<>
34  * which is only used as a way to force the compiler to assure that BOTH
35  * containers are valid ones in binary operators.
36  * This restrictions
37  * have been designed as a way to provide "polymorphism" at a template level,
38  * so the "+,-,..." operators do not
39  * generate ambiguities for ANY type, and limiting them to MRPT containers.
40  *
41  * In some cases, the containers provide specializations of some operations,
42  * for increased performance.
43  */
44 
45 #include <algorithm>
46 #include <numeric>
47 #include <functional>
48 
49 #include <mrpt/math/CHistogram.h> // Used in ::histogram()
50 
51 #include "ops_vectors.h"
52 
53 namespace mrpt
54 {
55 namespace math
56 {
57 /** Computes the normalized or normal histogram of a sequence of numbers given
58  * the number of bins and the limits.
59  * In any case this is a "linear" histogram, i.e. for matrices, all the
60  * elements are taken as if they were a plain sequence, not taking into account
61  * they were in columns or rows.
62  * If desired, out_bin_centers can be set to receive the bins centers.
63  */
64 template <class CONTAINER>
65 std::vector<double> histogram(
66  const CONTAINER& v, double limit_min, double limit_max, size_t number_bins,
67  bool do_normalization = false,
68  std::vector<double>* out_bin_centers = nullptr)
69 {
70  mrpt::math::CHistogram H(limit_min, limit_max, number_bins);
71  std::vector<double> ret(number_bins);
72  std::vector<double> dummy_ret_bins;
73  H.add(v);
74  if (do_normalization)
76  out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret);
77  else
78  H.getHistogram(
79  out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret);
80  return ret;
81 }
82 
83 template <class EIGEN_CONTAINER>
84 void resizeLike(EIGEN_CONTAINER& trg, const EIGEN_CONTAINER& src)
85 {
86  trg.resizeLike(src);
87 }
88 template <typename T>
89 void resizeLike(std::vector<T>& trg, const std::vector<T>& src)
90 {
91  trg.resize(src.size());
92 }
93 
94 /** Computes the cumulative sum of all the elements, saving the result in
95  * another container.
96  * This works for both matrices (even mixing their types) and vectores/arrays
97  * (even mixing types),
98  * and even to store the cumsum of any matrix into any vector/array, but not
99  * in opposite direction.
100  * \sa sum */
101 template <class CONTAINER1, class CONTAINER2, typename VALUE>
102 inline void cumsum_tmpl(const CONTAINER1& in_data, CONTAINER2& out_cumsum)
103 {
104  resizeLike(out_cumsum, in_data);
105  VALUE last = 0;
106  const size_t N = in_data.size();
107  for (size_t i = 0; i < N; i++) last = out_cumsum[i] = last + in_data[i];
108 }
109 
110 template <class CONTAINER1, class CONTAINER2>
111 inline void cumsum(const CONTAINER1& in_data, CONTAINER2& out_cumsum)
112 {
113  cumsum_tmpl<CONTAINER1, CONTAINER2,
115  in_data, out_cumsum);
116 }
117 
118 /** Computes the cumulative sum of all the elements
119  * \sa sum */
120 template <class CONTAINER>
121 inline CONTAINER cumsum(const CONTAINER& in_data)
122 {
123  CONTAINER ret;
124  cumsum(in_data, ret);
125  return ret;
126 }
127 
128 template <class CONTAINER>
129 inline typename CONTAINER::Scalar norm_inf(const CONTAINER& v)
130 {
131  return v.norm_inf();
132 }
133 template <class CONTAINER>
134 inline typename CONTAINER::Scalar norm(const CONTAINER& v)
135 {
136  return v.norm();
137 }
138 template <class CONTAINER>
139 inline typename CONTAINER::Scalar maximum(const CONTAINER& v)
140 {
141  return v.maxCoeff();
142 }
143 template <class CONTAINER>
144 inline typename CONTAINER::Scalar minimum(const CONTAINER& v)
145 {
146  return v.minimum();
147 }
148 
149 template <typename T>
150 inline T maximum(const std::vector<T>& v)
151 {
152  ASSERT_(!v.empty());
153  T m = v[0];
154  for (size_t i = 0; i < v.size(); i++) mrpt::keep_max(m, v[i]);
155  return m;
156 }
157 template <typename T>
158 inline T minimum(const std::vector<T>& v)
159 {
160  ASSERT_(!v.empty());
161  T m = v[0];
162  for (size_t i = 0; i < v.size(); i++) mrpt::keep_min(m, v[i]);
163  return m;
164 }
165 
166 /** \name Generic container element-wise operations - Miscelaneous
167  * @{
168  */
169 
170 /** Accumulate the squared-norm of a vector/array/matrix into "total" (this
171  * function is compatible with std::accumulate). */
172 template <class CONTAINER, typename VALUE>
173 VALUE squareNorm_accum(const VALUE total, const CONTAINER& v)
174 {
175  return total + v.squaredNorm();
176 }
177 
178 /** Compute the square norm of anything implementing [].
179  \sa norm */
180 template <size_t N, class T, class U>
181 inline T squareNorm(const U& v)
182 {
183  T res = 0;
184  for (size_t i = 0; i < N; i++) res += square(v[i]);
185  return res;
186 }
187 
188 /** v1*v2: The dot product of two containers (vectors/arrays/matrices) */
189 template <class CONTAINER1, class CONTAINER2>
191  const CONTAINER1& v1, const CONTAINER1& v2)
192 {
193  return v1.dot(v2);
194 }
195 
196 /** v1*v2: The dot product of any two objects supporting [] */
197 template <size_t N, class T, class U, class V>
198 inline T dotProduct(const U& v1, const V& v2)
199 {
200  T res = 0;
201  for (size_t i = 0; i < N; i++) res += v1[i] * v2[i];
202  return res;
203 }
204 
205 /** Computes the sum of all the elements.
206  * \note If used with containers of integer types (uint8_t, int, etc...) this
207  could overflow. In those cases, use sumRetType the second argument RET to
208  specify a larger type to hold the sum.
209  \sa cumsum */
210 template <class CONTAINER>
211 inline typename CONTAINER::Scalar sum(const CONTAINER& v)
212 {
213  return v.sum();
214 }
215 
216 /// \overload
217 template <typename T>
218 inline T sum(const std::vector<T>& v)
219 {
220  return std::accumulate(v.begin(), v.end(), T(0));
221 }
222 
223 /** Computes the sum of all the elements, with a custom return type.
224  \sa sum, cumsum */
225 template <class CONTAINER, typename RET>
226 inline RET sumRetType(const CONTAINER& v)
227 {
228  return v.template sumRetType<RET>();
229 }
230 
231 /** Computes the mean value of a vector \return The mean, as a double number.
232  * \sa math::stddev,math::meanAndStd */
233 template <class CONTAINER>
234 inline double mean(const CONTAINER& v)
235 {
236  if (v.empty())
237  return 0;
238  else
239  return sum(v) / static_cast<double>(v.size());
240 }
241 
242 /** Return the maximum and minimum values of a std::vector */
243 template <typename T>
244 inline void minimum_maximum(const std::vector<T>& V, T& curMin, T& curMax)
245 {
246  ASSERT_(V.size() != 0);
247  const size_t N = V.size();
248  curMin = curMax = V[0];
249  for (size_t i = 1; i < N; i++)
250  {
251  mrpt::keep_min(curMin, V[i]);
252  mrpt::keep_max(curMax, V[i]);
253  }
254 }
255 
256 /** Return the maximum and minimum values of a Eigen-based vector or matrix */
257 template <class Derived>
258 inline void minimum_maximum(
260  typename Eigen::MatrixBase<Derived>::Scalar& curMin,
261  typename Eigen::MatrixBase<Derived>::Scalar& curMax)
262 {
263  V.minimum_maximum(curMin, curMax);
264 }
265 
266 /** Counts the number of elements that appear in both STL-like containers
267  * (comparison through the == operator)
268  * It is assumed that no repeated elements appear within each of the
269  * containers. */
270 template <class CONTAINER1, class CONTAINER2>
271 size_t countCommonElements(const CONTAINER1& a, const CONTAINER2& b)
272 {
273  size_t ret = 0;
274  for (typename CONTAINER1::const_iterator it1 = a.begin(); it1 != a.end();
275  ++it1)
276  for (typename CONTAINER2::const_iterator it2 = b.begin();
277  it2 != b.end(); ++it2)
278  if ((*it1) == (*it2)) ret++;
279  return ret;
280 }
281 
282 /** Adjusts the range of all the elements such as the minimum and maximum values
283  * being those supplied by the user. */
284 template <class CONTAINER>
286  CONTAINER& m, const typename CONTAINER::Scalar minVal,
287  const typename CONTAINER::Scalar maxVal)
288 {
289  if (size_t(m.size()) == 0) return;
290  typename CONTAINER::Scalar curMin, curMax;
291  minimum_maximum(m, curMin, curMax);
292  const typename CONTAINER::Scalar curRan = curMax - curMin;
293  m -= (curMin + minVal);
294  if (curRan != 0) m *= (maxVal - minVal) / curRan;
295 }
296 
297 /** Computes the standard deviation of a vector
298  * \param v The set of data
299  * \param out_mean The output for the estimated mean
300  * \param out_std The output for the estimated standard deviation
301  * \param unbiased If set to true or false the std is normalized by "N-1" or
302  * "N", respectively.
303  * \sa math::mean,math::stddev
304  */
305 template <class VECTORLIKE>
307  const VECTORLIKE& v, double& out_mean, double& out_std,
308  bool unbiased = true)
309 {
310  if (v.size() < 2)
311  {
312  out_std = 0;
313  out_mean = (v.size() == 1) ? *v.begin() : 0;
314  }
315  else
316  {
317  // Compute the mean:
318  const size_t N = v.size();
319  out_mean = mrpt::math::sum(v) / static_cast<double>(N);
320  // Compute the std:
321  double vector_std = 0;
322  for (size_t i = 0; i < N; i++)
323  vector_std += mrpt::square(v[i] - out_mean);
324  out_std =
325  std::sqrt(vector_std / static_cast<double>(N - (unbiased ? 1 : 0)));
326  }
327 }
328 
329 /** Computes the standard deviation of a vector
330  * \param v The set of data
331  * \param unbiased If set to true or false the std is normalized by "N-1" or
332  * "N", respectively.
333  * \sa math::mean,math::meanAndStd
334  */
335 template <class VECTORLIKE>
336 inline double stddev(const VECTORLIKE& v, bool unbiased = true)
337 {
338  double m, s;
339  meanAndStd(v, m, s, unbiased);
340  return s;
341 }
342 
343 /** Computes the mean vector and covariance from a list of values given as a
344  * vector of vectors, where each row is a sample.
345  * \param v The set of data, as a vector of N vectors of M elements.
346  * \param out_mean The output M-vector for the estimated mean.
347  * \param out_cov The output MxM matrix for the estimated covariance matrix.
348  * \sa mrpt::math::meanAndCovMat, math::mean,math::stddev, math::cov
349  */
350 template <class VECTOR_OF_VECTOR, class VECTORLIKE, class MATRIXLIKE>
352  const VECTOR_OF_VECTOR& v, VECTORLIKE& out_mean, MATRIXLIKE& out_cov)
353 {
354  const size_t N = v.size();
355  ASSERTMSG_(N > 0, "The input vector contains no elements");
356  const double N_inv = 1.0 / N;
357 
358  const size_t M = v[0].size();
359  ASSERTMSG_(M > 0, "The input vector contains rows of length 0");
360 
361  // First: Compute the mean
362  out_mean.assign(M, 0);
363  for (size_t i = 0; i < N; i++)
364  for (size_t j = 0; j < M; j++) out_mean[j] += v[i][j];
365 
366  for (size_t j = 0; j < M; j++)
367  out_mean[j] *= N_inv;
368 
369  // Second: Compute the covariance
370  // Save only the above-diagonal part, then after averaging
371  // duplicate that part to the other half.
372  out_cov.zeros(M, M);
373  for (size_t i = 0; i < N; i++)
374  {
375  for (size_t j = 0; j < M; j++)
376  out_cov.get_unsafe(j, j) += square(v[i][j] - out_mean[j]);
377 
378  for (size_t j = 0; j < M; j++)
379  for (size_t k = j + 1; k < M; k++)
380  out_cov.get_unsafe(j, k) +=
381  (v[i][j] - out_mean[j]) * (v[i][k] - out_mean[k]);
382  }
383  for (size_t j = 0; j < M; j++)
384  for (size_t k = j + 1; k < M; k++)
385  out_cov.get_unsafe(k, j) = out_cov.get_unsafe(j, k);
386  out_cov *= N_inv;
387 }
388 
389 /** Computes the covariance matrix from a list of values given as a vector of
390  * vectors, where each row is a sample.
391  * \param v The set of data, as a vector of N vectors of M elements.
392  * \param out_cov The output MxM matrix for the estimated covariance matrix.
393  * \tparam RETURN_MATRIX The type of the returned matrix, e.g. Eigen::MatrixXd
394  * \sa math::mean,math::stddev, math::cov, meanAndCovVec
395  */
396 template <class VECTOR_OF_VECTOR, class RETURN_MATRIX>
397 inline RETURN_MATRIX covVector(const VECTOR_OF_VECTOR& v)
398 {
399  std::vector<double> m;
400  RETURN_MATRIX C;
401  meanAndCovVec(v, m, C);
402  return C;
403 }
404 
405 /** Normalised Cross Correlation between two vector patches
406  * The Matlab code for this is
407  * a = a - mean2(a);
408  * b = b - mean2(b);
409  * r = sum(sum(a.*b))/sqrt(sum(sum(a.*a))*sum(sum(b.*b)));
410  */
411 template <class CONT1, class CONT2>
412 double ncc_vector(const CONT1& patch1, const CONT2& patch2)
413 {
414  ASSERT_(patch1.size() == patch2.size());
415 
416  double numerator = 0, sum_a = 0, sum_b = 0, result, a_mean, b_mean;
417  a_mean = patch1.mean();
418  b_mean = patch2.mean();
419 
420  const size_t N = patch1.size();
421  for (size_t i = 0; i < N; ++i)
422  {
423  numerator += (patch1[i] - a_mean) * (patch2[i] - b_mean);
424  sum_a += mrpt::square(patch1[i] - a_mean);
425  sum_b += mrpt::square(patch2[i] - b_mean);
426  }
427  ASSERTMSG_(sum_a * sum_b != 0, "Divide by zero when normalizing.");
428  result = numerator / std::sqrt(sum_a * sum_b);
429  return result;
430 }
431 
432 /** @} Misc ops */
433 
434 } // namespace math
435 } // namespace mrpt
436 
437 /** @} */ // end of grouping
438 
439 #endif
void cumsum_tmpl(const CONTAINER1 &in_data, CONTAINER2 &out_cumsum)
Computes the cumulative sum of all the elements, saving the result in another container.
This class provides an easy way of computing histograms for unidimensional real valued variables...
Definition: CHistogram.h:35
double Scalar
Definition: KmUtils.h:44
size_t countCommonElements(const CONTAINER1 &a, const CONTAINER2 &b)
Counts the number of elements that appear in both STL-like containers (comparison through the == oper...
double stddev(const VECTORLIKE &v, bool unbiased=true)
Computes the standard deviation of a vector.
T squareNorm(const U &v)
Compute the square norm of anything implementing [].
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
void resizeLike(EIGEN_CONTAINER &trg, const EIGEN_CONTAINER &src)
GLdouble s
Definition: glext.h:3676
GLuint src
Definition: glext.h:7278
T square(const T x)
Inline function for the square of a number.
CONTAINER::Scalar minimum(const CONTAINER &v)
#define ASSERT_(f)
Defines an assertion mechanism.
Definition: exceptions.h:113
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
void add(const double x)
Add an element to the histogram.
Definition: CHistogram.cpp:42
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
GLubyte GLubyte b
Definition: glext.h:6279
#define ASSERTMSG_(f, __ERROR_MSG)
Defines an assertion mechanism.
Definition: exceptions.h:101
VALUE squareNorm_accum(const VALUE total, const CONTAINER &v)
Accumulate the squared-norm of a vector/array/matrix into "total" (this function is compatible with s...
CONTAINER::Scalar maximum(const CONTAINER &v)
void getHistogram(std::vector< double > &x, std::vector< double > &hits) const
Returns the list of bin centers & hit counts.
Definition: CHistogram.cpp:77
void minimum_maximum(const std::vector< T > &V, T &curMin, T &curMax)
Return the maximum and minimum values of a std::vector.
void cumsum(const CONTAINER1 &in_data, CONTAINER2 &out_cumsum)
CONTAINER::Scalar norm_inf(const CONTAINER &v)
const GLdouble * v
Definition: glext.h:3678
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
double ncc_vector(const CONT1 &patch1, const CONT2 &patch2)
Normalised Cross Correlation between two vector patches The Matlab code for this is a = a - mean2(a);...
GLfloat GLfloat v1
Definition: glext.h:4105
typename CONTAINER::value_type element_t
Definition: math_frwds.h:92
RETURN_MATRIX covVector(const VECTOR_OF_VECTOR &v)
Computes the covariance matrix from a list of values given as a vector of vectors, where each row is a sample.
RET sumRetType(const CONTAINER &v)
Computes the sum of all the elements, with a custom return type.
CONTAINER1::Scalar dotProduct(const CONTAINER1 &v1, const CONTAINER1 &v2)
v1*v2: The dot product of two containers (vectors/arrays/matrices)
std::vector< double > histogram(const CONTAINER &v, double limit_min, double limit_max, size_t number_bins, bool do_normalization=false, std::vector< double > *out_bin_centers=nullptr)
Computes the normalized or normal histogram of a sequence of numbers given the number of bins and the...
double mean(const CONTAINER &v)
Computes the mean value of a vector.
void meanAndCovVec(const VECTOR_OF_VECTOR &v, VECTORLIKE &out_mean, MATRIXLIKE &out_cov)
Computes the mean vector and covariance from a list of values given as a vector of vectors...
GLfloat GLfloat GLfloat v2
Definition: glext.h:4107
GLuint res
Definition: glext.h:7268
void adjustRange(CONTAINER &m, const typename CONTAINER::Scalar minVal, const typename CONTAINER::Scalar maxVal)
Adjusts the range of all the elements such as the minimum and maximum values being those supplied by ...
GLubyte GLubyte GLubyte a
Definition: glext.h:6279
const Scalar * const_iterator
Definition: eigen_plugins.h:27
void getHistogramNormalized(std::vector< double > &x, std::vector< double > &hits) const
Returns the list of bin centers & hit counts, normalized such as the integral of the histogram...
Definition: CHistogram.cpp:86
CONTAINER::Scalar norm(const CONTAINER &v)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ad3a9d8ae Tue May 1 23:10:22 2018 -0700 at lun oct 28 00:14:14 CET 2019