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_H
00029 #define MRPT_MATH_H
00030
00031 #include <mrpt/utils/utils_defs.h>
00032 #include <mrpt/math/CMatrixTemplateNumeric.h>
00033 #include <mrpt/math/CMatrixFixedNumeric.h>
00034 #include <mrpt/math/CVectorTemplate.h>
00035 #include <mrpt/math/CHistogram.h>
00036
00037 #include <mrpt/math/ops_vectors.h>
00038 #include <mrpt/math/ops_matrices.h>
00039
00040 #include <numeric>
00041 #include <cmath>
00042
00043
00044
00045
00046 namespace mrpt
00047 {
00048
00049
00050 namespace math
00051 {
00052 using namespace mrpt::utils;
00053
00054
00055
00056
00057
00058 bool MRPTDLLIMPEXP loadVector( utils::CFileStream &f, std::vector<int> &d);
00059
00060
00061
00062
00063
00064 bool MRPTDLLIMPEXP loadVector( utils::CFileStream &f, std::vector<double> &d);
00065
00066
00067
00068 bool MRPTDLLIMPEXP isNaN(float f) MRPT_NO_THROWS;
00069
00070
00071 bool MRPTDLLIMPEXP isNaN(double f) MRPT_NO_THROWS;
00072
00073
00074 bool MRPTDLLIMPEXP isFinite(float f) MRPT_NO_THROWS;
00075
00076
00077 bool MRPTDLLIMPEXP isFinite(double f) MRPT_NO_THROWS;
00078
00079 #ifdef HAVE_LONG_DOUBLE
00080
00081 bool MRPTDLLIMPEXP isNaN(long double f) MRPT_NO_THROWS;
00082
00083
00084 bool MRPTDLLIMPEXP isFinite(long double f) MRPT_NO_THROWS;
00085 #endif
00086
00087
00088
00089 template<typename T,typename K>
00090 void linspace(T first,T last, size_t count, std::vector<K> &out_vector)
00091 {
00092 if (count<2)
00093 {
00094 out_vector.assign(1,last);
00095 return;
00096 }
00097 else
00098 {
00099 out_vector.resize(count);
00100 const T incr = (last-first)/T(count-1);
00101 T c = first;
00102 for (size_t i=0;i<count;i++,c+=incr)
00103 out_vector[i] = K(c);
00104 }
00105 }
00106
00107
00108
00109 template<class T>
00110 inline std::vector<T> linspace(T first,T last, size_t count)
00111 {
00112 std::vector<T> ret;
00113 mrpt::math::linspace(first,last,count,ret);
00114 return ret;
00115 }
00116
00117
00118 template<class T,T STEP>
00119 inline std::vector<T> sequence(T first,size_t length)
00120 {
00121 std::vector<T> ret(length);
00122 if (!length) return ret;
00123 size_t i=0;
00124 while (length--) { ret[i++]=first; first+=STEP; }
00125 return ret;
00126 }
00127
00128
00129 template<class T>
00130 std::vector<T> ones(size_t count)
00131 {
00132 return std::vector<T>(count,1);
00133 }
00134
00135
00136 template<class T>
00137 std::vector<T> zeros(size_t count)
00138 {
00139 return std::vector<T>(count,0);
00140 }
00141
00142
00143
00144
00145 template<class T>
00146 void normalize(const std::vector<T> &v, std::vector<T> &out_v)
00147 {
00148 T total=0;
00149 typename std::vector<T>::const_iterator it;
00150 for (it=v.begin(); it!=v.end();it++)
00151 total += square(*it);
00152 total = ::sqrt(total);
00153 if (total)
00154 {
00155 out_v.resize(v.size());
00156 typename std::vector<T>::iterator q;
00157 for (it=v.begin(),q=out_v.begin(); q!=out_v.end();it++,q++)
00158 *q = *it / total;
00159 }
00160 else out_v.assign(v.size(),0);
00161 }
00162
00163
00164
00165
00166
00167
00168
00169 template<class VECTOR_OF_VECTOR, class VECTORLIKE, class MATRIXLIKE>
00170 void meanAndCovVector(
00171 const VECTOR_OF_VECTOR &v,
00172 VECTORLIKE &out_mean,
00173 MATRIXLIKE &out_cov
00174 )
00175 {
00176 const size_t N = v.size();
00177 ASSERTMSG_(N>0,"The input vector contains no elements");
00178 const double N_inv = 1.0/N;
00179
00180 const size_t M = v[0].size();
00181 ASSERTMSG_(M>0,"The input vector contains rows of length 0");
00182
00183
00184 out_mean.assign(M,0);
00185 for (size_t i=0;i<N;i++)
00186 for (size_t j=0;j<M;j++)
00187 out_mean[j]+=v[i][j];
00188 out_mean*=N_inv;
00189
00190
00191
00192
00193 out_cov.zeros(M,M);
00194 for (size_t i=0;i<N;i++)
00195 {
00196 for (size_t j=0;j<M;j++)
00197 out_cov.get_unsafe(j,j)+=square(v[i][j]-out_mean[j]);
00198
00199 for (size_t j=0;j<M;j++)
00200 for (size_t k=j+1;k<M;k++)
00201 out_cov.get_unsafe(j,k)+=(v[i][j]-out_mean[j])*(v[i][k]-out_mean[k]);
00202 }
00203 for (size_t j=0;j<M;j++)
00204 for (size_t k=j+1;k<M;k++)
00205 out_cov.get_unsafe(k,j) = out_cov.get_unsafe(j,k);
00206 out_cov*=N_inv;
00207 }
00208
00209
00210
00211
00212
00213
00214 template<class VECTOR_OF_VECTOR>
00215 inline CMatrixDouble covVector( const VECTOR_OF_VECTOR &v )
00216 {
00217 vector_double m;
00218 CMatrixDouble C;
00219 meanAndCovVector(v,m,C);
00220 return C;
00221 }
00222
00223
00224
00225
00226
00227
00228 template<typename T,size_t N,typename U>
00229 void covariancesAndMean(const std::vector<T> &elements,CMatrixTemplateNumeric<U> &covariances,U (&means)[N]) {
00230 size_t nElms=elements.size();
00231 for (size_t i=0;i<N;i++) {
00232 means[i]=0;
00233 for (size_t j=0;j<nElms;j++) means[i]+=elements[j][i];
00234 means[i]/=nElms;
00235 }
00236 covariances.resize(N,N);
00237 for (size_t i=0;i<N;i++) for (size_t j=0;j<=i;j++) {
00238 U elem=0;
00239 for (size_t k=0;k<nElms;k++) elem+=(elements[k][i]-means[i])*(elements[k][j]-means[j]);
00240 elem/=nElms;
00241 covariances.get_unsafe(i,j) = elem;
00242 if (i!=j) covariances.get_unsafe(j,i)=elem;
00243 }
00244 }
00245
00246
00247
00248
00249
00250 template<typename T,size_t N,typename U>
00251 void covariancesAndMean(const std::vector<T> &elements,CMatrixFixedNumeric<U,N,N> &covariances,U (&means)[N]) {
00252 size_t nElms=elements.size();
00253 for (size_t i=0;i<N;i++) {
00254 means[i]=0;
00255 for (size_t j=0;j<nElms;j++) means[i]+=elements[j][i];
00256 means[i]/=nElms;
00257 }
00258 for (size_t i=0;i<N;i++) for (size_t j=0;j<=i;j++) {
00259 U elem=0;
00260 for (size_t k=0;k<nElms;k++) elem+=(elements[k][i]-means[i])*(elements[k][j]-means[j]);
00261 elem/=nElms;
00262 covariances.get_unsafe(i,j) = elem;
00263 if (i!=j) covariances.get_unsafe(j,i)=elem;
00264 }
00265 }
00266
00267
00268
00269
00270
00271 template<typename T,size_t N,typename U>
00272 void covariancesAndMean(const std::vector<T> &elements,CMatrixFixedNumeric<U,N,N> &covariances,std::vector<U> &means ) {
00273 means.resize(N);
00274 size_t nElms=elements.size();
00275 for (size_t i=0;i<N;i++) {
00276 means[i]=0;
00277 for (size_t j=0;j<nElms;j++) means[i]+=elements[j][i];
00278 means[i]/=nElms;
00279 }
00280 for (size_t i=0;i<N;i++) for (size_t j=0;j<=i;j++) {
00281 U elem=0;
00282 for (size_t k=0;k<nElms;k++) elem+=(elements[k][i]-means[i])*(elements[k][j]-means[j]);
00283 elem/=nElms;
00284 covariances.get_unsafe(i,j) = elem;
00285 if (i!=j) covariances.get_unsafe(j,i)=elem;
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 template<class VECTORLIKE1,class VECTORLIKE2>
00299 void weightedHistogram(
00300 const VECTORLIKE1 &values,
00301 const VECTORLIKE1 &weights,
00302 float binWidth,
00303 VECTORLIKE2 &out_binCenters,
00304 VECTORLIKE2 &out_binValues )
00305 {
00306 MRPT_START;
00307 typedef typename VECTORLIKE1::value_type TNum;
00308
00309 ASSERT_( values.size() == weights.size() );
00310 ASSERT_( binWidth > 0 );
00311 TNum minBin = minimum( values );
00312 unsigned int nBins = static_cast<unsigned>(ceil((maximum( values )-minBin) / binWidth));
00313
00314
00315 out_binCenters.resize(nBins);
00316 out_binValues.clear(); out_binValues.resize(nBins,0);
00317 TNum halfBin = TNum(0.5)*binWidth;;
00318 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
00319 for (unsigned int i=0;i<nBins;i++)
00320 {
00321 binBorders[i+1] = binBorders[i]+binWidth;
00322 out_binCenters[i] = binBorders[i]+halfBin;
00323 }
00324
00325
00326 TNum totalSum = 0;
00327 typename VECTORLIKE1::const_iterator itVal, itW;
00328 for (itVal = values.begin(), itW = weights.begin(); itVal!=values.end(); ++itVal, ++itW )
00329 {
00330 int idx = round(((*itVal)-minBin)/binWidth);
00331 if (idx>=int(nBins)) idx=nBins-1;
00332 ASSERTDEB_(idx>=0);
00333 out_binValues[idx] += *itW;
00334 totalSum+= *itW;
00335 }
00336
00337 if (totalSum)
00338 out_binValues /= totalSum;
00339
00340
00341 MRPT_END;
00342 }
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352 template<class VECTORLIKE1,class VECTORLIKE2>
00353 void weightedHistogramLog(
00354 const VECTORLIKE1 &values,
00355 const VECTORLIKE1 &log_weights,
00356 float binWidth,
00357 VECTORLIKE2 &out_binCenters,
00358 VECTORLIKE2 &out_binValues )
00359 {
00360 MRPT_START;
00361 typedef typename VECTORLIKE1::value_type TNum;
00362
00363 ASSERT_( values.size() == log_weights.size() );
00364 ASSERT_( binWidth > 0 );
00365 TNum minBin = minimum( values );
00366 unsigned int nBins = static_cast<unsigned>(ceil((maximum( values )-minBin) / binWidth));
00367
00368
00369 out_binCenters.resize(nBins);
00370 out_binValues.clear(); out_binValues.resize(nBins,0);
00371 TNum halfBin = TNum(0.5)*binWidth;;
00372 VECTORLIKE2 binBorders(nBins+1,minBin-halfBin);
00373 for (unsigned int i=0;i<nBins;i++)
00374 {
00375 binBorders[i+1] = binBorders[i]+binWidth;
00376 out_binCenters[i] = binBorders[i]+halfBin;
00377 }
00378
00379
00380 const TNum max_log_weight = maximum(log_weights);
00381 TNum totalSum = 0;
00382 typename VECTORLIKE1::const_iterator itVal, itW;
00383 for (itVal = values.begin(), itW = log_weights.begin(); itVal!=values.end(); ++itVal, ++itW )
00384 {
00385 int idx = round(((*itVal)-minBin)/binWidth);
00386 if (idx>=int(nBins)) idx=nBins-1;
00387 ASSERTDEB_(idx>=0);
00388 const TNum w = exp(*itW-max_log_weight);
00389 out_binValues[idx] += w;
00390 totalSum+= w;
00391 }
00392
00393 if (totalSum)
00394 out_binValues /= totalSum;
00395
00396 MRPT_END;
00397 }
00398
00399
00400
00401
00402 uint64_t MRPTDLLIMPEXP factorial64(unsigned int n);
00403
00404
00405
00406 double MRPTDLLIMPEXP factorial(unsigned int n);
00407
00408
00409
00410
00411
00412
00413 template <class T>
00414 void wrapTo2PiInPlace(T &a)
00415 {
00416 bool was_neg = a<0;
00417 a = fmod(a, static_cast<T>(M_2PI) );
00418 if (was_neg) a+=static_cast<T>(M_2PI);
00419 }
00420
00421
00422
00423
00424
00425 template <class T>
00426 T wrapTo2Pi(T a)
00427 {
00428 wrapTo2PiInPlace(a);
00429 return a;
00430 }
00431
00432
00433
00434
00435
00436 template <class T>
00437 T wrapToPi(T a)
00438 {
00439 return wrapTo2Pi( a + static_cast<T>(M_PI) )-static_cast<T>(M_PI);
00440 }
00441
00442
00443
00444
00445
00446 template <class T>
00447 void wrapToPiInPlace(T &a)
00448 {
00449 a = wrapToPi(a);
00450 }
00451
00452
00453
00454 template <class T>
00455 T round2up(T val)
00456 {
00457 T n = 1;
00458 while (n < val)
00459 {
00460 n <<= 1;
00461 if (n<=1)
00462 THROW_EXCEPTION("Overflow!");
00463 }
00464 return n;
00465 }
00466
00467
00468
00469
00470 template <class T>
00471 T round_10power(T val, int power10)
00472 {
00473 long double F = ::pow((long double)10.0,-(long double)power10);
00474 long int t = round_long( val * F );
00475 return T(t/F);
00476 }
00477
00478
00479
00480
00481 template<class T>
00482 double correlate_matrix(const CMatrixTemplateNumeric<T> &a1, const CMatrixTemplateNumeric<T> &a2)
00483 {
00484 if ((a1.getColCount()!=a2.getColCount())|(a1.getRowCount()!=a2.getRowCount()))
00485 THROW_EXCEPTION("Correlation Error!, images with no same size");
00486
00487 int i,j;
00488 T x1,x2;
00489 T syy=0, sxy=0, sxx=0, m1=0, m2=0 ,n=a1.getRowCount()*a2.getColCount();
00490
00491
00492 for (i=0;i<a1.getRowCount();i++)
00493 {
00494 for (j=0;j<a1.getColCount();j++)
00495 {
00496 m1 += a1(i,j);
00497 m2 += a2(i,j);
00498 }
00499 }
00500 m1 /= n;
00501 m2 /= n;
00502
00503 for (i=0;i<a1.getRowCount();i++)
00504 {
00505 for (j=0;j<a1.getColCount();j++)
00506 {
00507 x1 = a1(i,j) - m1;
00508 x2 = a2(i,j) - m2;
00509 sxx += x1*x1;
00510 syy += x2*x2;
00511 sxy += x1*x2;
00512 }
00513 }
00514
00515 return sxy / sqrt(sxx * syy);
00516 }
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 template<class T>
00532 void MRPTDLLIMPEXP qr_decomposition(
00533 CMatrixTemplateNumeric<T> &A,
00534 CMatrixTemplateNumeric<T> &R,
00535 CMatrixTemplateNumeric<T> &Q,
00536 CVectorTemplate<T> &c,
00537 int &sing);
00538
00539
00540
00541
00542
00543 template<class T>
00544 void MRPTDLLIMPEXP UpdateCholesky(
00545 CMatrixTemplateNumeric<T> &chol,
00546 CVectorTemplate<T> &r1Modification);
00547
00548
00549
00550
00551
00552
00553
00554 void MRPTDLLIMPEXP computeEigenValues2x2(
00555 const CMatrixFloat &in_matrix,
00556 float &min_eigenvalue,
00557 float &max_eigenvalue );
00558
00559
00560
00561
00562
00563
00564
00565
00566 double MRPTDLLIMPEXP averageLogLikelihood( const vector_double &logLikelihoods );
00567
00568
00569
00570 double MRPTDLLIMPEXP averageWrap2Pi(const vector_double &angles );
00571
00572
00573
00574
00575
00576
00577
00578
00579 double MRPTDLLIMPEXP averageLogLikelihood(
00580 const vector_double &logWeights,
00581 const vector_double &logLikelihoods );
00582
00583
00584
00585
00586
00587
00588
00589
00590 std::string MRPTDLLIMPEXP MATLAB_plotCovariance2D(
00591 const CMatrixFloat &cov22,
00592 const CVectorFloat &mean,
00593 const float &stdCount,
00594 const std::string &style = std::string("b"),
00595 const size_t &nEllipsePoints = 30 );
00596
00597
00598
00599
00600
00601
00602
00603
00604 std::string MRPTDLLIMPEXP MATLAB_plotCovariance2D(
00605 const CMatrixDouble &cov22,
00606 const CVectorDouble &mean,
00607 const float &stdCount,
00608 const std::string &style = std::string("b"),
00609 const size_t &nEllipsePoints = 30 );
00610
00611
00612
00613
00614
00615
00616
00617 template <class MATRIXLIKE1,class MATRIXLIKE2> RET_VOID_ASSERT_MRPTMATRICES(MATRIXLIKE1,MATRIXLIKE2)
00618 homogeneousMatrixInverse(const MATRIXLIKE1 &M, MATRIXLIKE2 &out_inverse_M)
00619 {
00620 MRPT_START;
00621 ASSERT_( M.IsSquare() && size(M,1)==4);
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634 out_inverse_M.setSize(4,4);
00635
00636
00637 out_inverse_M.set_unsafe(0,0, M.get_unsafe(0,0));
00638 out_inverse_M.set_unsafe(0,1, M.get_unsafe(1,0));
00639 out_inverse_M.set_unsafe(0,2, M.get_unsafe(2,0));
00640
00641 out_inverse_M.set_unsafe(1,0, M.get_unsafe(0,1));
00642 out_inverse_M.set_unsafe(1,1, M.get_unsafe(1,1));
00643 out_inverse_M.set_unsafe(1,2, M.get_unsafe(2,1));
00644
00645 out_inverse_M.set_unsafe(2,0, M.get_unsafe(0,2));
00646 out_inverse_M.set_unsafe(2,1, M.get_unsafe(1,2));
00647 out_inverse_M.set_unsafe(2,2, M.get_unsafe(2,2));
00648
00649 const double tx = -M.get_unsafe(0,3);
00650 const double ty = -M.get_unsafe(1,3);
00651 const double tz = -M.get_unsafe(2,3);
00652
00653 const double tx_ = tx*M.get_unsafe(0,0)+ty*M.get_unsafe(1,0)+tz*M.get_unsafe(2,0);
00654 const double ty_ = tx*M.get_unsafe(0,1)+ty*M.get_unsafe(1,1)+tz*M.get_unsafe(2,1);
00655 const double tz_ = tx*M.get_unsafe(0,2)+ty*M.get_unsafe(1,2)+tz*M.get_unsafe(2,2);
00656
00657 out_inverse_M.set_unsafe(0,3, tx_ );
00658 out_inverse_M.set_unsafe(1,3, ty_ );
00659 out_inverse_M.set_unsafe(2,3, tz_ );
00660 out_inverse_M.set_unsafe(3,3, 1);
00661
00662 MRPT_END;
00663 }
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 template <class VECTORLIKE,class VECTORLIKE2, class VECTORLIKE3, class MATRIXLIKE, class USERPARAM >
00674 void estimateJacobian(
00675 const VECTORLIKE &x,
00676 void (*functor) (const VECTORLIKE &x,const USERPARAM &y, VECTORLIKE3 &out),
00677 const VECTORLIKE2 &increments,
00678 const USERPARAM &userParam,
00679 MATRIXLIKE &out_Jacobian )
00680 {
00681 MRPT_START
00682 ASSERT_(x.size()>0 && increments.size() == x.size());
00683
00684 size_t m = 0;
00685 const size_t n = x.size();
00686
00687 for (size_t j=0;j<n;j++) { ASSERT_( increments[j]>0 ) }
00688
00689 VECTORLIKE3 f_minus, f_plus;
00690 VECTORLIKE x_mod(x);
00691
00692
00693 for (size_t j=0;j<n;j++)
00694 {
00695
00696 x_mod[j]=x[j]+increments[j];
00697 functor(x_mod,userParam, f_plus);
00698
00699 x_mod[j]=x[j]-increments[j];
00700 functor(x_mod,userParam, f_minus);
00701
00702 x_mod[j]=x[j];
00703 const double Ax_2_inv = 0.5/increments[j];
00704
00705
00706 if (j==0)
00707 {
00708 m = f_plus.size();
00709 out_Jacobian.setSize(m,n);
00710 }
00711
00712 for (size_t i=0;i<m;i++)
00713 out_Jacobian.get_unsafe(i,j) = Ax_2_inv* (f_plus[i]-f_minus[i]);
00714
00715 }
00716
00717 MRPT_END
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727 template <class T>
00728 T interpolate(
00729 const T &x,
00730 const std::vector<T> &ys,
00731 const T &x0,
00732 const T &x1 )
00733 {
00734 MRPT_START
00735 ASSERT_(x1>x0); ASSERT_(!ys.empty());
00736 const size_t N = ys.size();
00737 if (x<=x0) return ys[0];
00738 if (x>=x1) return ys[N-1];
00739 const T Ax = (x1-x0)/T(N);
00740 const size_t i = int( (x-x0)/Ax );
00741 if (i>=N-1) return ys[N-1];
00742 const T Ay = ys[i+1]-ys[i];
00743 return ys[i] + (x-(x0+i*Ax))*Ay/Ax;
00744 MRPT_END
00745 }
00746
00747
00748
00749
00750
00751 double MRPTDLLIMPEXP interpolate2points(const double x, const double x0, const double y0, const double x1, const double y1, bool wrap2pi = false);
00752
00753
00754
00755
00756
00757 double MRPTDLLIMPEXP spline(const double t, const std::vector<double> &x, const std::vector<double> &y, bool wrap2pi = false);
00758
00759
00760
00761
00762
00763
00764
00765 template <typename NUMTYPE,class VECTORLIKE>
00766 NUMTYPE leastSquareLinearFit(const NUMTYPE t, const VECTORLIKE &x, const VECTORLIKE &y, bool wrap2pi = false)
00767 {
00768 MRPT_START
00769
00770
00771 ASSERT_(x.size()==y.size());
00772 ASSERT_(x.size()>1);
00773
00774 const size_t N = x.size();
00775
00776 typedef typename VECTORLIKE::value_type NUM;
00777
00778
00779 const NUM x_min = mrpt::math::minimum(x);
00780 CMatrixTemplateNumeric<NUM> Xt(2,N);
00781 for (size_t i=0;i<N;i++)
00782 {
00783 Xt.set_unsafe(0,i, 1);
00784 Xt.set_unsafe(1,i, x[i]-x_min);
00785 }
00786
00787 CMatrixTemplateNumeric<NUM> XtX;
00788 XtX.multiply_AAt(Xt);
00789
00790 CMatrixTemplateNumeric<NUM> XtXinv;
00791 XtX.inv_fast(XtXinv);
00792
00793 CMatrixTemplateNumeric<NUM> XtXinvXt;
00794 XtXinvXt.multiply(XtXinv,Xt);
00795
00796 VECTORLIKE B;
00797 XtXinvXt.multiply_Ab(y,B);
00798
00799 ASSERT_(B.size()==2)
00800
00801 NUM ret = B[0] + B[1]*(t-x_min);
00802
00803
00804 if (!wrap2pi)
00805 return ret;
00806 else return mrpt::math::wrapToPi(ret);
00807
00808 MRPT_END
00809 }
00810
00811
00812
00813
00814
00815 template <class VECTORLIKE1,class VECTORLIKE2,class VECTORLIKE3>
00816 void leastSquareLinearFit(
00817 const VECTORLIKE1 &ts,
00818 VECTORLIKE2 &outs,
00819 const VECTORLIKE3 &x,
00820 const VECTORLIKE3 &y,
00821 bool wrap2pi = false)
00822 {
00823 MRPT_START
00824
00825
00826 ASSERT_(x.size()==y.size());
00827 ASSERT_(x.size()>1);
00828
00829 const size_t N = x.size();
00830
00831
00832 typedef typename VECTORLIKE3::value_type NUM;
00833 const NUM x_min = mrpt::math::minimum(x);
00834 CMatrixTemplateNumeric<NUM> Xt(2,N);
00835 for (size_t i=0;i<N;i++)
00836 {
00837 Xt.set_unsafe(0,i, 1);
00838 Xt.set_unsafe(1,i, x[i]-x_min);
00839 }
00840
00841 CMatrixTemplateNumeric<NUM> XtX;
00842 XtX.multiply_AAt(Xt);
00843
00844 CMatrixTemplateNumeric<NUM> XtXinv;
00845 XtX.inv_fast(XtXinv);
00846
00847 CMatrixTemplateNumeric<NUM> XtXinvXt;
00848 XtXinvXt.multiply(XtXinv,Xt);
00849
00850 VECTORLIKE3 B;
00851 XtXinvXt.multiply_Ab(y,B);
00852
00853 ASSERT_(B.size()==2)
00854
00855 outs.resize(ts.size());
00856 if (!wrap2pi)
00857 for (size_t k=0;k<ts.size();k++)
00858 outs[k] = B[0] + B[1]*(ts[k]-x_min);
00859 else
00860 for (size_t k=0;k<ts.size();k++)
00861 outs[k] = mrpt::math::wrapToPi( B[0] + B[1]*(ts[k]-x_min) );
00862
00863 MRPT_END
00864 }
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877 template <typename T, typename At, size_t N>
00878 std::vector<T>& loadVector( std::vector<T> &v, At (&theArray)[N] )
00879 {
00880 MRPT_COMPILE_TIME_ASSERT(N!=0)
00881 v.resize(N);
00882 for (size_t i=0; i < N; i++)
00883 v[i] = static_cast<T>(theArray[i]);
00884 return v;
00885 }
00886
00887
00888
00889
00890
00891 void unwrap2PiSequence(vector_double &x);
00892
00893
00894
00895
00896
00897
00898
00899 template<class VECTORLIKE1,class VECTORLIKE2,class MAT>
00900 typename VECTORLIKE1::value_type mahalanobisDistance2(
00901 const VECTORLIKE1 &X,
00902 const VECTORLIKE2 &MU,
00903 const MAT &COV )
00904 {
00905 MRPT_START
00906 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00907 ASSERT_( !X.empty() );
00908 ASSERT_( X.size()==MU.size() );
00909 ASSERT_( X.size()==size(COV,1) && COV.IsSquare() );
00910 #endif
00911 const size_t N = X.size();
00912 std::vector<typename VECTORLIKE1::value_type> X_MU(N);
00913 for (size_t i=0;i<N;i++) X_MU[i]=X[i]-MU[i];
00914 return detail::multiply_HCHt_scalar(X_MU, COV.inv() );
00915 MRPT_END
00916 }
00917
00918
00919
00920
00921
00922 template<class VECTORLIKE1,class VECTORLIKE2,class MAT>
00923 inline typename VECTORLIKE1::value_type mahalanobisDistance(
00924 const VECTORLIKE1 &X,
00925 const VECTORLIKE2 &MU,
00926 const MAT &COV )
00927 {
00928 return std::sqrt( mahalanobisDistance2(X,MU,COV) );
00929 }
00930
00931
00932
00933
00934
00935 template<class VECTORLIKE,class MAT1,class MAT2,class MAT3>
00936 typename VECTORLIKE::value_type
00937 mahalanobisDistance2(
00938 const VECTORLIKE &mean_diffs,
00939 const MAT1 &COV1,
00940 const MAT2 &COV2,
00941 const MAT3 &CROSS_COV12 )
00942 {
00943 MRPT_START
00944 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00945 ASSERT_( !mean_diffs.empty() );
00946 ASSERT_( mean_diffs.size()==size(COV1,1));
00947 ASSERT_( COV1.IsSquare() && COV2.IsSquare() );
00948 ASSERT_( size(COV1,1)==size(COV2,1));
00949 #endif
00950 const size_t N = size(COV1,1);
00951 MAT1 COV = COV1;
00952 COV+=COV2;
00953 COV.substract_An(CROSS_COV12,2);
00954 MAT1 COV_inv;
00955 COV.inv_fast(COV_inv);
00956 return detail::multiply_HCHt_scalar(mean_diffs,COV_inv);
00957 MRPT_END
00958 }
00959
00960
00961
00962
00963 template<class VECTORLIKE,class MAT1,class MAT2,class MAT3> inline typename VECTORLIKE::value_type
00964 mahalanobisDistance(
00965 const VECTORLIKE &mean_diffs,
00966 const MAT1 &COV1,
00967 const MAT2 &COV2,
00968 const MAT3 &CROSS_COV12 )
00969 {
00970 return std::sqrt( mahalanobisDistance( mean_diffs, COV1,COV2,CROSS_COV12 ));
00971 }
00972
00973
00974
00975
00976 template<class VECTORLIKE,class MATRIXLIKE>
00977 inline typename MATRIXLIKE::value_type
00978 mahalanobisDistance2(const VECTORLIKE &delta_mu,const MATRIXLIKE &cov)
00979 {
00980 ASSERTDEB_(cov.IsSquare())
00981 ASSERTDEB_(cov.getColCount()==delta_mu.size())
00982 MATRIXLIKE C_inv;
00983 cov.inv(C_inv);
00984 return detail::multiply_HCHt_scalar(delta_mu,C_inv);
00985 }
00986
00987
00988
00989
00990 template<class VECTORLIKE,class MATRIXLIKE>
00991 inline typename MATRIXLIKE::value_type
00992 mahalanobisDistance(const VECTORLIKE &delta_mu,const MATRIXLIKE &cov)
00993 {
00994 return std::sqrt(mahalanobisDistance2(delta_mu,cov));
00995 }
00996
00997
00998
00999
01000 template <typename T>
01001 T productIntegralTwoGaussians(
01002 const std::vector<T> &mean_diffs,
01003 const CMatrixTemplateNumeric<T> &COV1,
01004 const CMatrixTemplateNumeric<T> &COV2
01005 )
01006 {
01007 const size_t vector_dim = mean_diffs.size();
01008 ASSERT_(vector_dim>=1)
01009
01010 CMatrixTemplateNumeric<T> C = COV1;
01011 C+= COV2;
01012 const T cov_det = C.det();
01013 CMatrixTemplateNumeric<T> C_inv;
01014 C.inv_fast(C_inv);
01015
01016 return std::pow( M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))
01017 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
01018 }
01019
01020
01021
01022
01023 template <typename T, size_t DIM>
01024 T productIntegralTwoGaussians(
01025 const std::vector<T> &mean_diffs,
01026 const CMatrixFixedNumeric<T,DIM,DIM> &COV1,
01027 const CMatrixFixedNumeric<T,DIM,DIM> &COV2
01028 )
01029 {
01030 ASSERT_(mean_diffs.size()==DIM);
01031
01032 CMatrixFixedNumeric<T,DIM,DIM> C = COV1;
01033 C+= COV2;
01034 const T cov_det = C.det();
01035 CMatrixFixedNumeric<T,DIM,DIM> C_inv(UNINITIALIZED_MATRIX);
01036 C.inv_fast(C_inv);
01037
01038 return std::pow( M_2PI, -0.5*DIM ) * (1.0/std::sqrt( cov_det ))
01039 * exp( -0.5 * mean_diffs.multiply_HCHt_scalar(C_inv) );
01040 }
01041
01042
01043
01044
01045 template <typename T, class VECLIKE,class MATLIKE1, class MATLIKE2>
01046 void productIntegralAndMahalanobisTwoGaussians(
01047 const VECLIKE &mean_diffs,
01048 const MATLIKE1 &COV1,
01049 const MATLIKE2 &COV2,
01050 T &maha2_out,
01051 T &intprod_out,
01052 const MATLIKE1 *CROSS_COV12=NULL
01053 )
01054 {
01055 const size_t vector_dim = mean_diffs.size();
01056 ASSERT_(vector_dim>=1)
01057
01058 MATLIKE1 C = COV1;
01059 C+= COV2;
01060 if (CROSS_COV12) { C-=*CROSS_COV12; C-=*CROSS_COV12; }
01061 const T cov_det = C.det();
01062 MATLIKE1 C_inv;
01063 C.inv_fast(C_inv);
01064
01065 maha2_out = mean_diffs.multiply_HCHt_scalar(C_inv);
01066 intprod_out = std::pow( M_2PI, -0.5*vector_dim ) * (1.0/std::sqrt( cov_det ))*exp(-0.5*maha2_out);
01067 }
01068
01069
01070
01071
01072 template <typename T, class VECLIKE,class MATRIXLIKE>
01073 void mahalanobisDistance2AndLogPDF(
01074 const VECLIKE &diff_mean,
01075 const MATRIXLIKE &cov,
01076 T &maha2_out,
01077 T &log_pdf_out)
01078 {
01079 MRPT_START
01080 ASSERTDEB_(cov.IsSquare())
01081 ASSERTDEB_(cov.getColCount()==diff_mean.size())
01082 MATRIXLIKE C_inv;
01083 cov.inv(C_inv);
01084 maha2_out = multiply_HCHt_scalar(diff_mean,C_inv);
01085 log_pdf_out = static_cast<typename MATRIXLIKE::value_type>(-0.5)* (
01086 maha2_out+
01087 static_cast<typename MATRIXLIKE::value_type>(cov.getColCount())*::log(static_cast<typename MATRIXLIKE::value_type>(M_2PI))+
01088 ::log(cov.det())
01089 );
01090 MRPT_END
01091 }
01092
01093
01094
01095
01096 template <typename T, class VECLIKE,class MATRIXLIKE>
01097 inline void mahalanobisDistance2AndPDF(
01098 const VECLIKE &diff_mean,
01099 const MATRIXLIKE &cov,
01100 T &maha2_out,
01101 T &pdf_out)
01102 {
01103 mahalanobisDistance2AndLogPDF(diff_mean,cov,maha2_out,pdf_out);
01104 pdf_out = std::exp(pdf_out);
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 template <size_t N, typename T>
01119 std::vector<T> make_vector(const T val1, ...)
01120 {
01121 MRPT_COMPILE_TIME_ASSERT( N>0 )
01122 std::vector<T> ret;
01123 ret.reserve(N);
01124
01125 ret.push_back(val1);
01126
01127 va_list args;
01128 va_start(args,val1);
01129 for (size_t i=0;i<N-1;i++)
01130 ret.push_back( va_arg(args,T) );
01131
01132 va_end(args);
01133 return ret;
01134 }
01135
01136 }
01137
01138 }
01139
01140 #endif