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



Page generated by Doxygen 1.8.6 for MRPT 1.5.6 Git: 4c65e84 Tue Apr 24 08:18:17 2018 +0200 at mar abr 24 08:26:17 CEST 2018