Main MRPT website > C++ reference for MRPT 1.4.0
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-2016, 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
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
45namespace mrpt
46{
47 namespace math
48 {
49 /** Computes the normalized or normal histogram of a sequence of numbers given the number of bins and the limits.
50 * 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.
51 * If desired, out_bin_centers can be set to receive the bins centers.
52 */
53 template<class CONTAINER>
54 std::vector<double> histogram(
55 const CONTAINER &v,
56 double limit_min,
57 double limit_max,
58 size_t number_bins,
59 bool do_normalization = false,
60 std::vector<double> *out_bin_centers = NULL)
61 {
62 mrpt::math::CHistogram H( limit_min, limit_max, number_bins );
63 std::vector<double> ret(number_bins);
64 std::vector<double> dummy_ret_bins;
65 H.add(v);
66 if (do_normalization)
67 H.getHistogramNormalized( out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret );
68 else H.getHistogram( out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret );
69 return ret;
70 }
71
72 template <class EIGEN_CONTAINER>
73 void resizeLike(EIGEN_CONTAINER &trg, const EIGEN_CONTAINER&src) {
74 trg.resizeLike(src);
75 }
76 template <typename T>
77 void resizeLike(std::vector<T> &trg, const std::vector<T> &src) {
78 trg.resize(src.size());
79 }
80
81 /** Computes the cumulative sum of all the elements, saving the result in another container.
82 * This works for both matrices (even mixing their types) and vectores/arrays (even mixing types),
83 * and even to store the cumsum of any matrix into any vector/array, but not in opposite direction.
84 * \sa sum */
85 template <class CONTAINER1,class CONTAINER2, typename VALUE>
86 inline void cumsum_tmpl(const CONTAINER1 &in_data, CONTAINER2 &out_cumsum)
87 {
88 resizeLike(out_cumsum, in_data);
89 VALUE last=0;
90 const size_t N = in_data.size();
91 for (size_t i=0;i<N;i++)
92 last = out_cumsum[i] = last + in_data[i];
93 }
94
95 template <class CONTAINER1,class CONTAINER2>
96 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); }
97
98 /** Computes the cumulative sum of all the elements
99 * \sa sum */
100 template<class CONTAINER>
101 inline CONTAINER cumsum(const CONTAINER &in_data)
102 {
103 CONTAINER ret;
104 cumsum(in_data,ret);
105 return ret;
106 }
107
108 template <class CONTAINER> inline typename CONTAINER::Scalar norm_inf(const CONTAINER &v) { return v.norm_inf(); }
109 template <class CONTAINER> inline typename CONTAINER::Scalar norm(const CONTAINER &v) { return v.norm(); }
110 template <class CONTAINER> inline typename CONTAINER::Scalar maximum(const CONTAINER &v) { return v.maxCoeff(); }
111 template <class CONTAINER> inline typename CONTAINER::Scalar minimum(const CONTAINER &v) { return v.minimum(); }
112
113 template <typename T> inline T maximum(const std::vector<T> &v)
114 {
115 ASSERT_(!v.empty())
116 T m = v[0];
117 for (size_t i=0;i<v.size();i++) mrpt::utils::keep_max(m,v[i]);
118 return m;
119 }
120 template <typename T> inline T minimum(const std::vector<T> &v)
121 {
122 ASSERT_(!v.empty())
123 T m = v[0];
124 for (size_t i=0;i<v.size();i++) mrpt::utils::keep_min(m,v[i]);
125 return m;
126 }
127
128 /** \name Generic container element-wise operations - Miscelaneous
129 * @{
130 */
131
132 /** Accumulate the squared-norm of a vector/array/matrix into "total" (this function is compatible with std::accumulate). */
133 template <class CONTAINER, typename VALUE>
134 VALUE squareNorm_accum(const VALUE total, const CONTAINER &v) {
135 return total+v.squaredNorm();
136 }
137
138 /** Compute the square norm of anything implementing [].
139 \sa norm */
140 template<size_t N,class T,class U>
141 inline T squareNorm(const U &v) {
142 T res=0;
143 for (size_t i=0;i<N;i++) res+=square(v[i]);
144 return res;
145 }
146
147 /** v1*v2: The dot product of two containers (vectors/arrays/matrices) */
148 template <class CONTAINER1,class CONTAINER2>
149 inline typename CONTAINER1::Scalar
150 dotProduct(const CONTAINER1 &v1,const CONTAINER1 &v2)
151 {
152 return v1.dot(v2);
153 }
154
155 /** v1*v2: The dot product of any two objects supporting [] */
156 template<size_t N,class T,class U,class V>
157 inline T dotProduct(const U &v1,const V &v2) {
158 T res=0;
159 for (size_t i=0;i<N;i++) res+=v1[i]*v2[i];
160 return res;
161 }
162
163 /** Computes the sum of all the elements.
164 * \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.
165 \sa cumsum */
166 template <class CONTAINER> inline typename CONTAINER::Scalar sum(const CONTAINER &v) { return v.sum(); }
167
168 /// \overload
169 template <typename T> inline T sum(const std::vector<T> &v) { return std::accumulate(v.begin(),v.end(),T(0)); }
170
171 /** Computes the sum of all the elements, with a custom return type.
172 \sa sum, cumsum */
173 template <class CONTAINER,typename RET> inline RET sumRetType(const CONTAINER &v) { return v.template sumRetType<RET>(); }
174
175 /** Computes the mean value of a vector \return The mean, as a double number.
176 * \sa math::stddev,math::meanAndStd */
177 template <class CONTAINER>
178 inline double mean(const CONTAINER &v)
179 {
180 if (v.empty())
181 return 0;
182 else return sum(v)/static_cast<double>(v.size());
183 }
184
185 /** Return the maximum and minimum values of a std::vector */
186 template <typename T>
187 inline void minimum_maximum(const std::vector<T> &V, T&curMin,T&curMax)
188 {
189 ASSERT_(V.size()!=0)
190 const size_t N=V.size();
191 curMin=curMax=V[0];
192 for (size_t i=1;i<N;i++)
193 {
194 mrpt::utils::keep_min(curMin,V[i]);
195 mrpt::utils::keep_max(curMax,V[i]);
196 }
197 }
198
199 /** Return the maximum and minimum values of a Eigen-based vector or matrix */
200 template <class Derived>
201 inline void minimum_maximum(
202 const Eigen::MatrixBase<Derived> &V,
203 typename Eigen::MatrixBase<Derived>::Scalar &curMin,
204 typename Eigen::MatrixBase<Derived>::Scalar &curMax)
205 {
206 V.minimum_maximum(curMin,curMax);
207 }
208
209 /** Counts the number of elements that appear in both STL-like containers (comparison through the == operator)
210 * It is assumed that no repeated elements appear within each of the containers. */
211 template <class CONTAINER1,class CONTAINER2>
212 size_t countCommonElements(const CONTAINER1 &a,const CONTAINER2 &b)
213 {
214 size_t ret=0;
215 for (typename CONTAINER1::const_iterator it1 = a.begin();it1!=a.end();++it1)
216 for (typename CONTAINER2::const_iterator it2 = b.begin();it2!=b.end();++it2)
217 if ( (*it1) == (*it2) )
218 ret++;
219 return ret;
220 }
221
222 /** Adjusts the range of all the elements such as the minimum and maximum values being those supplied by the user. */
223 template <class CONTAINER>
224 void adjustRange(CONTAINER &m, const typename CONTAINER::Scalar minVal,const typename CONTAINER::Scalar maxVal)
225 {
226 if (size_t(m.size())==0) return;
227 typename CONTAINER::Scalar curMin,curMax;
228 minimum_maximum(m,curMin,curMax);
229 const typename CONTAINER::Scalar curRan = curMax-curMin;
230 m -= (curMin+minVal);
231 if (curRan!=0) m *= (maxVal-minVal)/curRan;
232 }
233
234
235 /** Computes the standard deviation of a vector
236 * \param v The set of data
237 * \param out_mean The output for the estimated mean
238 * \param out_std The output for the estimated standard deviation
239 * \param unbiased If set to true or false the std is normalized by "N-1" or "N", respectively.
240 * \sa math::mean,math::stddev
241 */
242 template<class VECTORLIKE>
244 const VECTORLIKE &v,
245 double &out_mean,
246 double &out_std,
247 bool unbiased = true)
248 {
249 if (v.size()<2)
250 {
251 out_std = 0;
252 out_mean = (v.size()==1) ? *v.begin() : 0;
253 }
254 else
255 {
256 // Compute the mean:
257 const size_t N = v.size();
258 out_mean = mrpt::math::sum(v) / static_cast<double>(N);
259 // Compute the std:
260 double vector_std=0;
261 for (size_t i=0;i<N;i++) vector_std += mrpt::utils::square( v[i]-out_mean);
262 out_std = std::sqrt(vector_std / static_cast<double>(N - (unbiased ? 1:0)) );
263 }
264 }
265
266
267 /** Computes the standard deviation of a vector
268 * \param v The set of data
269 * \param unbiased If set to true or false the std is normalized by "N-1" or "N", respectively.
270 * \sa math::mean,math::meanAndStd
271 */
272 template<class VECTORLIKE>
273 inline double stddev(const VECTORLIKE &v, bool unbiased = true)
274 {
275 double m,s;
276 meanAndStd(v,m,s,unbiased);
277 return s;
278 }
279
280 /** Computes the mean vector and covariance from a list of values given as a vector of vectors, where each row is a sample.
281 * \param v The set of data, as a vector of N vectors of M elements.
282 * \param out_mean The output M-vector for the estimated mean.
283 * \param out_cov The output MxM matrix for the estimated covariance matrix.
284 * \sa mrpt::math::meanAndCovMat, math::mean,math::stddev, math::cov
285 */
286 template<class VECTOR_OF_VECTOR, class VECTORLIKE, class MATRIXLIKE>
288 const VECTOR_OF_VECTOR &v,
289 VECTORLIKE &out_mean,
290 MATRIXLIKE &out_cov
291 )
292 {
293 const size_t N = v.size();
294 ASSERTMSG_(N>0,"The input vector contains no elements");
295 const double N_inv = 1.0/N;
296
297 const size_t M = v[0].size();
298 ASSERTMSG_(M>0,"The input vector contains rows of length 0");
299
300 // First: Compute the mean
301 out_mean.assign(M,0);
302 for (size_t i=0;i<N;i++)
303 for (size_t j=0;j<M;j++)
304 out_mean[j]+=v[i][j];
305 out_mean= out_mean * N_inv;
306
307 // Second: Compute the covariance
308 // Save only the above-diagonal part, then after averaging
309 // duplicate that part to the other half.
310 out_cov.zeros(M,M);
311 for (size_t i=0;i<N;i++)
312 {
313 for (size_t j=0;j<M;j++)
314 out_cov.get_unsafe(j,j)+=square(v[i][j]-out_mean[j]);
315
316 for (size_t j=0;j<M;j++)
317 for (size_t k=j+1;k<M;k++)
318 out_cov.get_unsafe(j,k)+=(v[i][j]-out_mean[j])*(v[i][k]-out_mean[k]);
319 }
320 for (size_t j=0;j<M;j++)
321 for (size_t k=j+1;k<M;k++)
322 out_cov.get_unsafe(k,j) = out_cov.get_unsafe(j,k);
323 out_cov= out_cov * N_inv;
324 }
325
326 /** Computes the covariance matrix from a list of values given as a vector of vectors, where each row is a sample.
327 * \param v The set of data, as a vector of N vectors of M elements.
328 * \param out_cov The output MxM matrix for the estimated covariance matrix.
329 * \tparam RETURN_MATRIX The type of the returned matrix, e.g. Eigen::MatrixXd
330 * \sa math::mean,math::stddev, math::cov, meanAndCovVec
331 */
332 template<class VECTOR_OF_VECTOR, class RETURN_MATRIX>
333 inline RETURN_MATRIX covVector( const VECTOR_OF_VECTOR &v )
334 {
336 RETURN_MATRIX C;
337 meanAndCovVec(v,m,C);
338 return C;
339 }
340
341
342 /** Normalised Cross Correlation between two vector patches
343 * The Matlab code for this is
344 * a = a - mean2(a);
345 * b = b - mean2(b);
346 * r = sum(sum(a.*b))/sqrt(sum(sum(a.*a))*sum(sum(b.*b)));
347 */
348 template <class CONT1,class CONT2>
349 double ncc_vector( const CONT1 &patch1, const CONT2 &patch2 )
350 {
351 ASSERT_( patch1.size()==patch2.size() )
352
353 double numerator = 0, sum_a = 0, sum_b = 0, result, a_mean, b_mean;
354 a_mean = patch1.mean();
355 b_mean = patch2.mean();
356
357 const size_t N = patch1.size();
358 for(size_t i=0;i<N;++i)
359 {
360 numerator += (patch1[i]-a_mean)*(patch2[i]-b_mean);
361 sum_a += mrpt::utils::square(patch1[i]-a_mean);
362 sum_b += mrpt::utils::square(patch2[i]-b_mean);
363 }
364 ASSERTMSG_(sum_a*sum_b!=0,"Divide by zero when normalizing.")
365 result=numerator/std::sqrt(sum_a*sum_b);
366 return result;
367 }
368
369 /** @} Misc ops */
370
371 } // End of math namespace
372} // End of mrpt namespace
373
374/** @} */ // end of grouping
375
376#endif
This class provides an easy way of computing histograms for unidimensional real valued variables.
Definition: CHistogram.h:36
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,...
void getHistogram(std::vector< double > &x, std::vector< double > &hits) const
Returns the list of bin centers & hit counts.
void add(const double x)
Add an element to the histogram.
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction.
Definition: types_math.h:65
EIGEN_STRONG_INLINE Scalar maximum() const
[VECTORS OR MATRICES] Finds the maximum value
EIGEN_STRONG_INLINE double mean() const
Computes the mean of the entire matrix.
EIGEN_STRONG_INLINE Scalar minimum() const
[VECTORS OR MATRICES] Finds the minimum value
EIGEN_STRONG_INLINE Scalar squareNorm() const
Compute the square norm of a vector/array/matrix (the Euclidean distance to the origin,...
EIGEN_STRONG_INLINE Scalar norm_inf() const
Compute the norm-infinite of a vector ($f[ ||\mathbf{v}||_\infnty $f]), ie the maximum absolute value...
#define ASSERT_(f)
Definition: mrpt_macros.h:261
#define ASSERTMSG_(f, __ERROR_MSG)
Definition: mrpt_macros.h:260
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,...
CONTAINER1::Scalar dotProduct(const CONTAINER1 &v1, const CONTAINER1 &v2)
v1*v2: The dot product of two containers (vectors/arrays/matrices)
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,...
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.
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...
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...
CONTAINER::Scalar norm(const CONTAINER &v)
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 ...
void resizeLike(EIGEN_CONTAINER &trg, const EIGEN_CONTAINER &src)
void cumsum_tmpl(const CONTAINER1 &in_data, CONTAINER2 &out_cumsum)
Computes the cumulative sum of all the elements, saving the result in another container.
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
RET sumRetType(const CONTAINER &v)
Computes the sum of all the elements, with a custom return type.
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
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)
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.
Definition: bits.h:145
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:113
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.
Definition: bits.h:140
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.



Page generated by Doxygen 1.9.6 for MRPT 1.4.0 SVN: at Wed Mar 22 06:08:57 UTC 2023