00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef mrpt_math_container_ops_H
00029 #define mrpt_math_container_ops_H
00030
00031 #include <mrpt/math/math_frwds.h>
00032
00033 #include <mrpt/math/lightweight_geom_data.h>
00034
00035 #include <functional>
00036 #include <algorithm>
00037 #include <cmath>
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include <algorithm>
00053 #include <numeric>
00054 #include <functional>
00055
00056 #include <mrpt/math/CHistogram.h>
00057
00058 namespace mrpt
00059 {
00060 namespace math
00061 {
00062
00063
00064
00065
00066
00067
00068 template <class CONTAINER1,class CONTAINER2>
00069 inline RET_CONT1_ASSERT_MRPTCONTAINERS(CONTAINER1,CONTAINER2) &
00070 operator +=(CONTAINER1 &a, const CONTAINER2 &b)
00071 {
00072 ASSERT_(a.size()==b.size());
00073 typename CONTAINER1::iterator ita = a.begin();
00074 typename CONTAINER2::const_iterator itb = b.begin();
00075 const typename CONTAINER1::iterator last=a.end();
00076 while (ita!=last) { *(ita++)+=*(itb++); }
00077 return a;
00078 }
00079
00080
00081 template <class CONTAINER1,class CONTAINER2>
00082 inline RET_CONT1_ASSERT_MRPTCONTAINERS(CONTAINER1,CONTAINER2)
00083 operator +(const CONTAINER1 &a, const CONTAINER2 &b)
00084 {
00085 CONTAINER1 ret = a;
00086 ret+=b;
00087 return ret;
00088 }
00089
00090
00091 template <class CONTAINER1,class CONTAINER2>
00092 inline RET_CONT1_ASSERT_MRPTCONTAINERS(CONTAINER1,CONTAINER2) &
00093 operator -=(CONTAINER1 &a, const CONTAINER2 &b)
00094 {
00095 ASSERT_(a.size()==b.size());
00096 typename CONTAINER1::iterator ita = a.begin();
00097 typename CONTAINER2::const_iterator itb = b.begin();
00098 const typename CONTAINER1::iterator last=a.end();
00099 while (ita!=last) { *(ita++)-=*(itb++); }
00100 return a;
00101 }
00102
00103
00104 template <class CONTAINER1,class CONTAINER2>
00105 inline RET_CONT1_ASSERT_MRPTCONTAINERS(CONTAINER1,CONTAINER2)
00106 operator -(const CONTAINER1 &a, const CONTAINER2 &b)
00107 {
00108 CONTAINER1 ret = a;
00109 ret-=b;
00110 return ret;
00111 }
00112
00113
00114 template<class CONTAINER1,class CONTAINER2> CONTAINER1 ÷_elementwise(CONTAINER1 &a, const CONTAINER2 &b)
00115 {
00116 ASSERT_(a.size()==b.size());
00117 typename CONTAINER1::iterator ita = a.begin();
00118 typename CONTAINER2::const_iterator itb = b.begin();
00119 const typename CONTAINER1::iterator last=a.end();
00120 while (ita!=last) { *(ita++)/=*(itb++); }
00121 return a;
00122 }
00123
00124
00125 template <class CONTAINER>
00126 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) & operator+=(CONTAINER &c, typename CONTAINER::value_type val)
00127 {
00128 const typename CONTAINER::iterator last=c.end();
00129 for (typename CONTAINER::iterator it=c.begin();it!=last;++it) *it += val;
00130 return c;
00131 }
00132
00133
00134 template <class CONTAINER>
00135 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) operator +(CONTAINER &c, typename CONTAINER::value_type val)
00136 {
00137 CONTAINER ret = c;
00138 ret+=val;
00139 return ret;
00140 }
00141
00142
00143 template <class CONTAINER>
00144 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) & operator -= (CONTAINER &c, typename CONTAINER::value_type val)
00145 {
00146 const typename CONTAINER::iterator last=c.end();
00147 for (typename CONTAINER::iterator it=c.begin();it!=last;++it) *it -= val;
00148 return c;
00149 }
00150
00151
00152 template <class CONTAINER>
00153 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) operator -(CONTAINER &c, typename CONTAINER::value_type val)
00154 {
00155 CONTAINER ret = c;
00156 ret-=val;
00157 return ret;
00158 }
00159
00160
00161 template <class CONTAINER>
00162 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) & operator *= (CONTAINER &c, typename CONTAINER::value_type val)
00163 {
00164 const typename CONTAINER::iterator last=c.end();
00165 for (typename CONTAINER::iterator it=c.begin();it!=last;++it) *it *= val;
00166 return c;
00167 }
00168
00169
00170 template <class CONTAINER>
00171 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) operator *(const CONTAINER &c, const typename CONTAINER::value_type val)
00172 {
00173 CONTAINER ret = c;
00174 ret*=val;
00175 return ret;
00176 }
00177
00178 template <class CONTAINER>
00179 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) operator *(const typename CONTAINER::value_type val, const CONTAINER &c)
00180 {
00181 CONTAINER ret = c;
00182 ret*=val;
00183 return ret;
00184 }
00185
00186
00187 template <class CONTAINER>
00188 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) & operator /= (CONTAINER &c, typename CONTAINER::value_type val)
00189 {
00190 typename CONTAINER::value_type k = 1/val;
00191 const typename CONTAINER::iterator last=c.end();
00192 for (typename CONTAINER::iterator it=c.begin();it!=last;++it) *it *= k;
00193 return c;
00194 }
00195
00196
00197 template <class CONTAINER>
00198 inline RET_CONT_ASSERT_MRPTCONTAINER(CONTAINER) operator /(CONTAINER &c, typename CONTAINER::value_type val)
00199 {
00200 CONTAINER ret = c;
00201 ret/=val;
00202 return ret;
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 template <class CONTAINER> CONTAINER & containerFromPoseOrPoint(CONTAINER &C, const TPoint2D &p) {
00215 ASSERT_(C.size()==2)
00216 for (size_t i=0;i<2;i++) C._A(i)=p[i];
00217 return C;
00218 }
00219 template <class CONTAINER> CONTAINER & containerFromPoseOrPoint(CONTAINER &C, const TPoint3D &p) {
00220 ASSERT_(C.size()==3)
00221 for (size_t i=0;i<3;i++) C._A(i)=p[i];
00222 return C;
00223 }
00224 template <class CONTAINER> CONTAINER & containerFromPoseOrPoint(CONTAINER &C, const TPose2D &p) {
00225 ASSERT_(C.size()==3)
00226 for (size_t i=0;i<3;i++) C._A(i)=p[i];
00227 return C;
00228 }
00229 template <class CONTAINER> CONTAINER & containerFromPoseOrPoint(CONTAINER &C, const TPose3D &p) {
00230 ASSERT_(C.size()==6)
00231 for (size_t i=0;i<6;i++) C._A(i)=p[i];
00232 return C;
00233 }
00234 template <class CONTAINER> CONTAINER & containerFromPoseOrPoint(CONTAINER &C, const TPose3DQuat &p) {
00235 ASSERT_(C.size()==7)
00236 for (size_t i=0;i<7;i++) C._A(i)=p[i];
00237 return C;
00238 }
00239
00240
00241 template <class CONTAINER>
00242 size_t countNonZero(const CONTAINER &a)
00243 {
00244 typename CONTAINER::const_iterator it_a;
00245 size_t count=0;
00246 for (it_a=a.begin(); it_a!=a.end(); it_a++) if (*it_a) count++;
00247 return count;
00248 }
00249
00250
00251
00252 template <class CONTAINER>
00253 typename CONTAINER::value_type
00254 maximum(const CONTAINER &v, size_t *maxIndex)
00255 {
00256 typename CONTAINER::const_iterator maxIt = std::max_element(v.begin(),v.end());
00257 if (maxIndex) *maxIndex = std::distance(v.begin(),maxIt);
00258 return *maxIt;
00259 }
00260
00261
00262
00263
00264 template <class CONTAINER>
00265 typename CONTAINER::value_type
00266 minimum(const CONTAINER &v, size_t *minIndex)
00267 {
00268 typename CONTAINER::const_iterator minIt = std::min_element(v.begin(),v.end());
00269 if (minIndex) *minIndex = std::distance(v.begin(),minIt);
00270 return *minIt;
00271 }
00272
00273
00274
00275
00276 template <class CONTAINER>
00277 void minimum_maximum(
00278 const CONTAINER &v,
00279 typename CONTAINER::mrpt_autotype::value_type & out_min,
00280 typename CONTAINER::mrpt_autotype::value_type& out_max,
00281 size_t *minIndex,
00282 size_t *maxIndex)
00283 {
00284 const size_t N = v.size();
00285 if (N)
00286 {
00287 typename CONTAINER::const_iterator it = v.begin();
00288 size_t min_idx=0,max_idx=0;
00289 out_max = out_min = *it;
00290 size_t i;
00291 for (i=0;i<N;++it,++i)
00292 {
00293 if (*it<out_min)
00294 {
00295 out_min=*it;
00296 min_idx = i;
00297 }
00298 if (*it>out_max)
00299 {
00300 out_max=*it;
00301 max_idx = i;
00302 }
00303 }
00304 if (minIndex) *minIndex = min_idx;
00305 if (maxIndex) *maxIndex = max_idx;
00306 }
00307 else {
00308 out_min=out_max=0;
00309 if (minIndex) *minIndex = 0;
00310 if (maxIndex) *maxIndex = 0;
00311 }
00312 }
00313
00314
00315 template <class CONTAINER>
00316 typename CONTAINER::value_type
00317 norm_inf(const CONTAINER &v, size_t *maxIndex)
00318 {
00319 double M=0;
00320 int i,M_idx=-1;
00321 typename CONTAINER::const_iterator it;
00322 for (i=0, it=v.begin(); it!=v.end();it++,i++)
00323 {
00324 double it_abs = fabs( static_cast<double>(*it));
00325 if (it_abs>M || M_idx==-1)
00326 {
00327 M = it_abs;
00328 M_idx = i;
00329 }
00330 }
00331 if (maxIndex) *maxIndex = M_idx;
00332 return static_cast<typename CONTAINER::mrpt_autotype::value_type>(M);
00333 }
00334
00335
00336
00337
00338 template <class CONTAINER>
00339 typename CONTAINER::value_type
00340 squareNorm(const CONTAINER &v)
00341 {
00342 typename CONTAINER::value_type total=0;
00343 typename CONTAINER::const_iterator it;
00344 for (it=v.begin(); it!=v.end();it++)
00345 total += square(*it);
00346 return total;
00347 }
00348
00349
00350
00351 template<size_t N,class T,class U>
00352 inline T squareNorm(const U &v) {
00353 T res=0;
00354 for (size_t i=0;i<N;i++) res+=square(v[i]);
00355 return res;
00356 }
00357
00358
00359
00360 template <class CONTAINER>
00361 inline typename CONTAINER::value_type
00362 norm(const CONTAINER &v)
00363 {
00364 return ::sqrt(squareNorm(v));
00365 }
00366
00367
00368 template <class CONTAINER1,class CONTAINER2>
00369 inline typename CONTAINER1::value_type
00370 dotProduct(const CONTAINER1 &v1,const CONTAINER1 &v2)
00371 {
00372 ASSERT_(v1.size()==v2.size());
00373 const size_t N = v1.size();
00374 typename CONTAINER1::value_type res=0;
00375 typename CONTAINER1::const_iterator it1;
00376 typename CONTAINER2::const_iterator it2;
00377 size_t i;
00378 for (i=0,it1=v1.begin(),it2=v2.begin();i<N;++i,++it1,++it2) res+=(*it1)*(*it2);
00379 return res;
00380 }
00381
00382
00383 template<size_t N,class T,class U,class V>
00384 inline T dotProduct(const U &v1,const V &v2) {
00385 T res=0;
00386 for (size_t i=0;i<N;i++) res+=v1[i]*v2[i];
00387 return res;
00388 }
00389
00390
00391
00392 template <class CONTAINER>
00393 inline double
00394 mean(const CONTAINER &v)
00395 {
00396 if (v.empty())
00397 return 0;
00398 else
00399 return std::accumulate(v.begin(),v.end(), 0.0) / double(v.size());
00400 }
00401
00402
00403
00404
00405 template <class CONTAINER>
00406 inline typename CONTAINER::value_type sum(const CONTAINER &v)
00407 {
00408 return std::accumulate(v.begin(),v.end(), static_cast<typename CONTAINER::value_type>(0) );
00409 }
00410
00411
00412
00413 template <class CONTAINER,typename RET>
00414 inline RET sumRetType(const CONTAINER &v)
00415 {
00416 return std::accumulate(v.begin(),v.end(), static_cast<RET>(0) );
00417 }
00418
00419
00420
00421
00422
00423 template <class CONTAINER1,class CONTAINER2>
00424 void cumsum(const CONTAINER1 &in_data, CONTAINER2 &out_cumsum)
00425 {
00426 out_cumsum.resize(in_data.size());
00427 typename CONTAINER1::value_type last=0;
00428 const size_t N = in_data.size();
00429 typename CONTAINER1::const_iterator it1;
00430 typename CONTAINER2::iterator it2;
00431 size_t i;
00432 for (i=0,it1=in_data.begin(),it2=out_cumsum.begin();i<N;++i,++it1,++it2)
00433 last = (*it2) = last + (*it1);
00434 }
00435
00436
00437
00438 template<class CONTAINER>
00439 inline CONTAINER
00440 cumsum(const CONTAINER &in_data)
00441 {
00442 CONTAINER ret;
00443 ret.resize(in_data.size());
00444 cumsum(in_data,ret);
00445 return ret;
00446 }
00447
00448
00449
00450 template <class CONTAINER1,class CONTAINER2>
00451 size_t countCommonElements(const CONTAINER1 &a,const CONTAINER2 &b)
00452 {
00453 size_t ret=0;
00454 for (typename CONTAINER1::const_iterator it1 = a.begin();it1!=a.end();it1++)
00455 for (typename CONTAINER2::const_iterator it2 = b.begin();it2!=b.end();it2++)
00456 if ( (*it1) == (*it2) )
00457 ret++;
00458 return ret;
00459 }
00460
00461
00462
00463
00464
00465 template<class CONTAINER>
00466 std::vector<double> histogram(
00467 const CONTAINER &v,
00468 double limit_min,
00469 double limit_max,
00470 size_t number_bins,
00471 bool do_normalization,
00472 std::vector<double> *out_bin_centers
00473 )
00474 {
00475 mrpt::math::CHistogram H( limit_min, limit_max, number_bins );
00476 vector_double ret(number_bins);
00477 vector_double dummy_ret_bins;
00478 H.add(v);
00479 if (do_normalization)
00480 H.getHistogramNormalized( out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret );
00481 else H.getHistogram( out_bin_centers ? *out_bin_centers : dummy_ret_bins, ret );
00482 return ret;
00483 }
00484
00485
00486 template <class CONTAINER>
00487 void adjustRange(CONTAINER &m, const typename CONTAINER::value_type minVal,const typename CONTAINER::value_type maxVal)
00488 {
00489 if (size_t(m.size())==0) return;
00490 typename CONTAINER::value_type curMin,curMax;
00491 minimum_maximum(m,curMin,curMax);
00492 const typename CONTAINER::value_type curRan = curMax-curMin;
00493 m -= (curMin+minVal);
00494 if (curRan!=0) m *= (maxVal-minVal)/curRan;
00495 }
00496
00497
00498
00499
00500
00501
00502
00503 template <class CONTAINER1,class CONTAINER2>
00504 void Abs(const CONTAINER1 &dat_in, CONTAINER2 &dat_out) {
00505 dat_out.resize(dat_in.size());
00506 std::transform<typename CONTAINER1::const_iterator,typename CONTAINER2::iterator,typename CONTAINER1::value_type (*)(typename CONTAINER1::value_type)>
00507 (dat_in.begin(),dat_in.end(), dat_out.begin(), &::abs );
00508 }
00509
00510 template <class CONTAINER> inline CONTAINER Abs(const CONTAINER &dat_in)
00511 { CONTAINER ret; Abs(dat_in,ret); return ret; }
00512
00513
00514 template <class CONTAINER1,class CONTAINER2>
00515 void Log(const CONTAINER1 &dat_in, CONTAINER2 &dat_out) {
00516 dat_out.resize(dat_in.size());
00517 std::transform<typename CONTAINER1::const_iterator,typename CONTAINER2::iterator,typename CONTAINER1::value_type (*)(typename CONTAINER1::value_type)>
00518 (dat_in.begin(),dat_in.end(), dat_out.begin(), &::log );
00519 }
00520
00521 template <class CONTAINER> inline CONTAINER Log(const CONTAINER &dat_in)
00522 { CONTAINER ret; Log(dat_in,ret); return ret; }
00523
00524
00525 template <class CONTAINER1,class CONTAINER2>
00526 void Exp(const CONTAINER1 &dat_in, CONTAINER2 &dat_out) {
00527 dat_out.resize(dat_in.size());
00528 std::transform<typename CONTAINER1::const_iterator,typename CONTAINER2::iterator,typename CONTAINER1::value_type (*)(typename CONTAINER1::value_type)>
00529 (dat_in.begin(),dat_in.end(), dat_out.begin(), &::exp );
00530 }
00531
00532 template <class CONTAINER> inline CONTAINER Exp(const CONTAINER &dat_in)
00533 { CONTAINER ret; Exp(dat_in,ret); return ret; }
00534
00535
00536
00537 template <class CONTAINER1,class CONTAINER2>
00538 RET_TYPE_ASSERT_MRPTCONTAINER(CONTAINER1, bool)
00539 operator == (const CONTAINER1 &m1, const CONTAINER2 &m2)
00540 {
00541 if (m1.size()!=m2.size()) return false;
00542 typename CONTAINER1::const_iterator it1=m1.begin();
00543 typename CONTAINER2::const_iterator it2=m2.begin();
00544 const size_t N = m1.size();
00545 for(size_t i=0;i<N;++i, ++it1,++it2)
00546 if (*it1!=*it2)
00547 return false;
00548 return true;
00549 }
00550
00551
00552 template <class CONTAINER1,class CONTAINER2>
00553 inline RET_TYPE_ASSERT_MRPTCONTAINER(CONTAINER1, bool)
00554 operator != (const CONTAINER1 &m1, const CONTAINER2 &m2)
00555 {
00556 return !(m1 == m2);
00557 }
00558
00559
00560
00561
00562
00563
00564 template<class VECTORLIKE>
00565 double stddev(const VECTORLIKE &v, bool unbiased)
00566 {
00567 if (v.size()<2)
00568 return 0;
00569 else
00570 {
00571
00572 double vector_std=0,vector_mean = 0;
00573 for (typename VECTORLIKE::const_iterator it = v.begin();it!=v.end();++it) vector_mean += (*it);
00574 vector_mean /= static_cast<double>(v.size());
00575
00576 for (typename VECTORLIKE::const_iterator it = v.begin();it!=v.end();++it) vector_std += square((*it)-vector_mean);
00577 vector_std = sqrt(vector_std / static_cast<double>(v.size() - (unbiased ? 1:0)) );
00578 return vector_std;
00579 }
00580 }
00581
00582
00583
00584
00585
00586
00587
00588 template<class VECTOR_OF_VECTOR, class VECTORLIKE, class MATRIXLIKE>
00589 void meanAndCov(
00590 const VECTOR_OF_VECTOR &v,
00591 VECTORLIKE &out_mean,
00592 MATRIXLIKE &out_cov
00593 )
00594 {
00595 const size_t N = v.size();
00596 ASSERTMSG_(N>0,"The input vector contains no elements");
00597 const double N_inv = 1.0/N;
00598
00599 const size_t M = v[0].size();
00600 ASSERTMSG_(M>0,"The input vector contains rows of length 0");
00601
00602
00603 out_mean.assign(M,0);
00604 for (size_t i=0;i<N;i++)
00605 for (size_t j=0;j<M;j++)
00606 out_mean[j]+=v[i][j];
00607 out_mean*=N_inv;
00608
00609
00610
00611
00612 out_cov.zeros(M,M);
00613 for (size_t i=0;i<N;i++)
00614 {
00615 for (size_t j=0;j<M;j++)
00616 out_cov.get_unsafe(j,j)+=square(v[i][j]-out_mean[j]);
00617
00618 for (size_t j=0;j<M;j++)
00619 for (size_t k=j+1;k<M;k++)
00620 out_cov.get_unsafe(j,k)+=(v[i][j]-out_mean[j])*(v[i][k]-out_mean[k]);
00621 }
00622 for (size_t j=0;j<M;j++)
00623 for (size_t k=j+1;k<M;k++)
00624 out_cov.get_unsafe(k,j) = out_cov.get_unsafe(j,k);
00625 out_cov*=N_inv;
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636 template<class VECTORLIKE>
00637 void meanAndStd(
00638 const VECTORLIKE &v,
00639 double &out_mean,
00640 double &out_std,
00641 bool unbiased)
00642 {
00643 if (v.size()<2)
00644 {
00645 out_std = 0;
00646 out_mean = (v.size()==1) ? *v.begin() : 0;
00647 }
00648 else
00649 {
00650
00651 typename VECTORLIKE::const_iterator it;
00652 out_std=0,out_mean = 0;
00653 for (it = v.begin();it!=v.end();it++) out_mean += (*it);
00654 out_mean /= static_cast<double>(v.size());
00655
00656
00657 for (it = v.begin();it!=v.end();it++) out_std += mrpt::utils::square(static_cast<double>(*it)-out_mean);
00658 out_std = std::sqrt(out_std / static_cast<double>((v.size() - (unbiased ? 1:0)) ));
00659 }
00660 }
00661
00662
00663
00664
00665
00666
00667
00668 template <class CONT1,class CONT2>
00669 double ncc_vector( const CONT1 &patch1, const CONT2 &patch2 )
00670 {
00671 ASSERT_( patch1.size()==patch2.size() )
00672
00673 double numerator = 0, sum_a = 0, sum_b = 0, result, a_mean, b_mean;
00674 a_mean = patch1.mean();
00675 b_mean = patch2.mean();
00676
00677 typename CONT1::const_iterator it1;
00678 typename CONT2::const_iterator it2;
00679 const size_t N = patch1.size();
00680 size_t i;
00681 for(i=0,it1=patch1.begin(),it2=patch2.begin();i<N; ++it1, ++it2, ++i)
00682 {
00683 numerator += (*it1-a_mean)*(*it2-b_mean);
00684 sum_a += mrpt::utils::square(*it1-a_mean);
00685 sum_b += mrpt::utils::square(*it2-b_mean);
00686 }
00687 ASSERTMSG_(sum_a*sum_b!=0,"Divide by zero when normalizing.")
00688 result=numerator/sqrt(sum_a*sum_b);
00689 return result;
00690 }
00691
00692
00693
00694
00695 }
00696 }
00697
00698
00699 #endif