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_matrix_ops_H
00029 #define mrpt_math_matrix_ops_H
00030
00031 #include <mrpt/math/math_frwds.h>
00032
00033 #include <mrpt/math/CMatrix.h>
00034 #include <mrpt/math/CMatrixD.h>
00035
00036 #include <mrpt/math/CMatrixTemplateNumeric.h>
00037 #include <mrpt/math/CMatrixFixedNumeric.h>
00038 #include <mrpt/math/CVectorTemplate.h>
00039
00040 #include <mrpt/math/ops_containers.h>
00041 #include <mrpt/math/ops_matrices_eigen.h>
00042 #include <mrpt/math/matrices_metaprogramming.h>
00043
00044
00045
00046
00047
00048
00049
00050 namespace mrpt
00051 {
00052 namespace math
00053 {
00054
00055 template <size_t NROWS,size_t NCOLS>
00056 mrpt::utils::CStream &operator>>(mrpt::utils::CStream &in, CMatrixFixedNumeric<float,NROWS,NCOLS> & M) {
00057 CMatrix aux;
00058 in >> aux;
00059 M = aux;
00060 return in;
00061 }
00062
00063 template <size_t NROWS,size_t NCOLS>
00064 mrpt::utils::CStream &operator>>(mrpt::utils::CStream &in, CMatrixFixedNumeric<double,NROWS,NCOLS> & M) {
00065 CMatrixD aux;
00066 in >> aux;
00067 M = aux;
00068 return in;
00069 }
00070
00071
00072 template <size_t NROWS,size_t NCOLS>
00073 mrpt::utils::CStream &operator<<(mrpt::utils::CStream &out,const CMatrixFixedNumeric<float,NROWS,NCOLS> & M) {
00074 CMatrix aux = CMatrixFloat(M);
00075 out << aux;
00076 return out;
00077 }
00078
00079 template <size_t NROWS,size_t NCOLS>
00080 mrpt::utils::CStream &operator<<(mrpt::utils::CStream &out,const CMatrixFixedNumeric<double,NROWS,NCOLS> & M) {
00081 CMatrixD aux = CMatrixDouble(M);
00082 out << aux;
00083 return out;
00084 }
00085
00086
00087 template <class T,size_t NROWS, size_t NCOLS>
00088 bool operator == (const CMatrixFixedNumeric<T,NROWS,NCOLS>& M1, const CMatrixFixedNumeric<T,NROWS,NCOLS>& M2)
00089 {
00090 for (size_t i=0; i < NROWS; i++)
00091 for (size_t j=0; j < NCOLS; j++)
00092 if (M1.get_unsafe(i,j)!=M2.get_unsafe(i,j))
00093 return false;
00094 return true;
00095 }
00096
00097
00098
00099
00100 template <class MATRIX>
00101 RET_TYPE_ASSERT_MRPTMATRIX(MATRIX, std::ostream)&
00102 operator << (std::ostream& ostrm, const MATRIX& m)
00103 {
00104 ostrm << std::setprecision(4);
00105 for (size_t i=0; i < m.getRowCount(); i++)
00106 {
00107 for (size_t j=0; j < m.getColCount(); j++)
00108 ostrm << std::setw(13) << m(i,j);
00109 ostrm << std::endl;
00110 }
00111 return ostrm;
00112 }
00113
00114
00115
00116
00117
00118 namespace detail
00119 {
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 template<class MATRIX1,class MATRIX2>
00131 bool chol(const MATRIX1 &in, MATRIX2 &out)
00132 {
00133 typedef typename MATRIX1::value_type T;
00134 const size_t N=in.getRowCount();
00135 if (in.getColCount()!=in.getRowCount()) throw std::logic_error("Error in Cholesky factorization. Matrix is not square");
00136 out.setSize(N,N);
00137 {
00138 T coef=in.get_unsafe(0,0);
00139 if (coef<=0) return false;
00140 else out.get_unsafe(0,0)=(coef=sqrt(coef));
00141 for (size_t j=1;j<N;++j) out.get_unsafe(0,j)=in.get_unsafe(0,j)/coef;
00142 }
00143 T sum;
00144 for (size_t i=1;i<N;++i) {
00145 out.set_unsafe(i,0,0);
00146 {
00147 sum=in.get_unsafe(i,i);
00148 for (size_t k=i-1;k<N;--k) sum-=square(out.get_unsafe(k,i));
00149 if (sum<=0) return false;
00150 else out.get_unsafe(i,i)=sqrt(sum);
00151 }
00152 for (size_t j=i+1;j<N;++j) {
00153 sum=in.get_unsafe(i,j);
00154 for (size_t k=i-1;k<N;--k) sum-=out.get_unsafe(k,i)*out.get_unsafe(k,j);
00155 out.get_unsafe(i,j)=sum/out.get_unsafe(i,i);
00156 out.get_unsafe(j,i)=0;
00157 }
00158 }
00159 return true;
00160 }
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 template <class MAT>
00171 void saveMatrixToTextFile(
00172 const MAT &theMatrix,
00173 const std::string &file,
00174 TMatrixTextFileFormat fileFormat,
00175 bool appendMRPTHeader,
00176 const std::string &userHeader
00177 )
00178 {
00179 using namespace mrpt::system;
00180
00181 MRPT_START;
00182
00183 FILE *f=os::fopen(file.c_str(),"wt");
00184 if (!f)
00185 THROW_EXCEPTION_CUSTOM_MSG1("saveToTextFile: Error opening file '%s' for writing a matrix as text.", file.c_str());
00186
00187 if (!userHeader.empty())
00188 fprintf(f,"%s",userHeader.c_str() );
00189
00190 if (appendMRPTHeader)
00191 fprintf(f,"%% File generated with MRPT %s at %s\n%%-----------------------------------------------------------------\n",
00192 mrpt::system::MRPT_getVersion().c_str(),
00193 mrpt::system::dateTimeLocalToString( mrpt::system::now() ).c_str() );
00194
00195 for (size_t i=0; i < theMatrix.getRowCount(); i++)
00196 {
00197 for (size_t j=0; j < theMatrix.getColCount(); j++)
00198 {
00199 switch(fileFormat)
00200 {
00201 case MATRIX_FORMAT_ENG: os::fprintf(f,"%.16e",static_cast<double>(theMatrix(i,j))); break;
00202 case MATRIX_FORMAT_FIXED: os::fprintf(f,"%.16f",static_cast<double>(theMatrix(i,j))); break;
00203 case MATRIX_FORMAT_INT: os::fprintf(f,"%i",static_cast<int>(theMatrix(i,j))); break;
00204 default:
00205 THROW_EXCEPTION("Unsupported value for the parameter 'fileFormat'!");
00206 };
00207
00208 if (j<(theMatrix.getColCount()-1)) os::fprintf(f," ");
00209 }
00210 os::fprintf(f,"\n");
00211 }
00212 os::fclose(f);
00213 MRPT_END;
00214 }
00215
00216
00217
00218
00219 template<class MATRIX1>
00220 typename MATRIX1::value_type trace(const MATRIX1 &m)
00221 {
00222 if (!m.IsSquare()) throw std::logic_error("Error in trace: matrix is not square");
00223 const size_t N = size(m,1);
00224 typename MATRIX1::value_type ret=0;
00225 for (size_t i=0;i<N;i++)
00226 ret+=m.get_unsafe(i,i);
00227 return ret;
00228 }
00229
00230
00231 template<class MATRIX1, class OTHERVECTOR1,class OTHERVECTOR2>
00232 void multiply_Ab(const MATRIX1 &m, const OTHERVECTOR1 &vIn,OTHERVECTOR2 &vOut,bool accumToOutput ) {
00233 MRPT_START
00234 size_t N=m.getRowCount();
00235 size_t M=m.getColCount();
00236 ASSERT_(vIn.size()==M)
00237 vOut.resize(N);
00238 if (!accumToOutput) for (size_t i=0;i<N;++i) vOut[i]=typename OTHERVECTOR2::value_type(0);
00239 for (size_t i=0;i<N;++i) {
00240 typename MATRIX1::value_type &accum=vOut[i];
00241 for (size_t j=0;j<M;++j) accum+=m.get_unsafe(i,j)*vIn[j];
00242 }
00243 MRPT_END
00244 }
00245
00246
00247 template<class MATRIX1, class OTHERVECTOR1,class OTHERVECTOR2>
00248 void multiply_Atb(const MATRIX1 &m, const OTHERVECTOR1 &vIn,OTHERVECTOR2 &vOut,bool accumToOutput ) {
00249 MRPT_START
00250 size_t N=m.getColCount();
00251 size_t M=m.getRowCount();
00252 ASSERT_(vIn.size()==M)
00253 vOut.resize(N);
00254 if (!accumToOutput) for (size_t i=0;i<N;++i) vOut[i]=typename OTHERVECTOR2::value_type(0);
00255 for (size_t i=0;i<N;++i) {
00256 typename MATRIX1::value_type &accum=vOut[i];
00257 for (size_t j=0;j<M;++j) accum+=m.get_unsafe(j,i)*vIn[j];
00258 }
00259 MRPT_END
00260 }
00261
00262
00263 template <class MATRIX1,class MATRIX2>
00264 void multiply_AAt( const MATRIX1& m1, MATRIX2& RESULT )
00265 {
00266 typedef typename MATRIX2::value_type T;
00267 const size_t M1R = m1.getRowCount();
00268 const size_t M1C = m1.getColCount();
00269 RESULT.setSize(M1R,M1R);
00270
00271
00272 if ((void*)&m1==(void*)&RESULT)
00273 {
00274
00275 std::vector<T> temp(M1R*M1R);
00276
00277 T *ptr = &temp[0];
00278 size_t i;
00279 for (i=0; i < M1R; i++)
00280 {
00281 for (size_t j=i; j < M1R; j++)
00282 {
00283 T accum = 0;
00284 for (size_t k=0; k < M1C; k++)
00285 accum += m1.get_unsafe(i,k) * m1.get_unsafe(j,k);
00286 *(ptr++) = accum;
00287 }
00288 }
00289
00290 ptr = &temp[0];
00291 for (i=0; i < M1R; i++)
00292 for (size_t j=i; j < M1R; j++)
00293 RESULT.get_unsafe(i,j) = RESULT.get_unsafe(j,i) = *(ptr++);
00294 }
00295 else
00296 {
00297
00298 for (size_t i=0; i < M1R; i++)
00299 for (size_t j=i; j < M1R; j++)
00300 {
00301 T accum = 0;
00302 for (size_t k=0; k < M1C; k++)
00303 accum += m1.get_unsafe(i,k) * m1.get_unsafe(j,k);
00304 RESULT.get_unsafe(i,j) = RESULT.get_unsafe(j,i) = accum;
00305 }
00306 }
00307 }
00308
00309
00310 template <class MATRIX1,class MATRIX2>
00311 void multiply_AtA( const MATRIX1& m1, MATRIX2& RESULT )
00312 {
00313 typedef typename MATRIX2::value_type T;
00314 const size_t M1R = m1.getRowCount();
00315 const size_t M1C = m1.getColCount();
00316 RESULT.setSize(M1C,M1C);
00317
00318
00319 if ((void*)&m1==(void*)&RESULT)
00320 {
00321
00322 std::vector<T> temp(M1C*M1C);
00323
00324 T *ptr = &temp[0];
00325 size_t i;
00326 for (i=0; i < M1C; i++)
00327 {
00328 for (size_t j=i; j < M1C; j++)
00329 {
00330 T accum = 0;
00331 for (size_t k=0; k < M1R; k++)
00332 accum += m1.get_unsafe(i,k) * m1.get_unsafe(j,k);
00333 *(ptr++) = accum;
00334 }
00335 }
00336
00337 ptr = &temp[0];
00338 for (i=0; i < M1C; i++)
00339 for (size_t j=i; j < M1C; j++)
00340 RESULT.get_unsafe(i,j) = RESULT.get_unsafe(j,i) = *(ptr++);
00341 }
00342 else
00343 {
00344
00345 for (size_t i=0; i < M1C; i++)
00346 {
00347 for (size_t j=i; j < M1C; j++)
00348 {
00349 T accum = 0;
00350 for (size_t k=0; k < M1R; k++)
00351 accum += m1.get_unsafe(k,i) * m1.get_unsafe(k,j);
00352 RESULT.get_unsafe(i,j) = RESULT.get_unsafe(j,i) = accum;
00353 }
00354 }
00355 }
00356 }
00357
00358
00359 template <class MATRIX1,class MATRIX2,class MATRIXRES>
00360 void multiply_AB(const MATRIX1& m1,const MATRIX2& m2, MATRIXRES& RESULT )
00361 {
00362 MRPT_START
00363
00364 typedef typename MATRIXRES::value_type T;
00365
00366 const size_t NROWS = m1.getRowCount();
00367 const size_t NCOLS = m2.getColCount();
00368 const size_t M1C = m1.getColCount();
00369 ASSERTMSG_(M1C==m2.getRowCount(),format("Invalid matrix sizes in multiplication: %ux%u * %ux%u",(unsigned int)NROWS,(unsigned int)M1C,(unsigned int)m2.getRowCount(),(unsigned int)NCOLS ));
00370
00371 RESULT.setSize(NROWS,NCOLS);
00372
00373
00374 if ( (void*)(&m1)==(void*)(&RESULT) || (void*)(&m2)==(void*)&RESULT)
00375 {
00376
00377 std::vector<T> temp(NROWS*NCOLS);
00378 size_t out_idx = 0;
00379 for (size_t i=0; i < NROWS; i++)
00380 {
00381 for (size_t j=0; j < NCOLS; j++)
00382 {
00383 T accum = 0;
00384 for (size_t k=0; k < M1C; k++)
00385 accum += m1.get_unsafe(i,k) * m2.get_unsafe(k,j);
00386 temp[out_idx++] = accum;
00387 }
00388 }
00389
00390
00391 T* ptr = &temp[0];
00392 for (size_t i=0; i < NROWS; i++)
00393 for (size_t j=0; j < NCOLS; j++)
00394 RESULT.get_unsafe(i,j)= *(ptr++);
00395 }
00396 else
00397 {
00398
00399 for (size_t i=0; i < NROWS; i++)
00400 {
00401 for (size_t j=0; j < NCOLS; j++)
00402 {
00403 T accum = 0;
00404 for (size_t k=0; k < M1C; k++)
00405 accum += m1.get_unsafe(i,k) * m2.get_unsafe(k,j);
00406 RESULT.get_unsafe(i,j)=accum;
00407 }
00408 }
00409 }
00410
00411 MRPT_END
00412 }
00413
00414
00415
00416 template <typename MAT_H, typename MAT_C, typename MAT_R>
00417 void multiply_HCHt(
00418 const MAT_H &H,
00419 const MAT_C &C,
00420 MAT_R &R,
00421 bool accumResultInOutput,
00422 bool allow_submatrix_mult)
00423 {
00424 MRPT_START
00425
00426 ASSERTMSG_( (void*)&C != (void*)&H, "C and H must be different matrices." )
00427 ASSERTMSG_( (void*)&R != (void*)&H, "R and H must be different matrices." )
00428 ASSERTMSG_( (void*)&C != (void*)&R, "C and R must be different matrices.")
00429 ASSERT_(C.IsSquare())
00430
00431 if (allow_submatrix_mult)
00432 ASSERT_(C.getRowCount()>=H.getColCount())
00433 else ASSERT_(C.getRowCount()==H.getColCount())
00434
00435 const size_t N=H.getRowCount();
00436 const size_t M=H.getColCount();
00437
00438 R.setSize(N,N);
00439
00440
00441 MAT_TYPE_PRODUCT_OF(MAT_H,MAT_C) R_;
00442 R_.setSize(N,M);
00443
00444
00445 for (size_t i=0;i<N;i++)
00446 for (size_t j=0;j<M;j++)
00447 {
00448 typename MAT_H::value_type sumAccum = 0;
00449 for (size_t l=0;l<M;l++)
00450 sumAccum += H.get_unsafe(i,l) * C.get_unsafe(l,j);
00451 R_.get_unsafe(i,j) = sumAccum;
00452 }
00453
00454
00455 for (size_t i=0;i<N;i++)
00456 for (size_t j=i;j<N;j++)
00457 {
00458 typename MAT_H::value_type sumAccum = accumResultInOutput ? R.get_unsafe(i,j) : 0;
00459 for (size_t l=0;l<M;l++)
00460 sumAccum += R_.get_unsafe(i,l) * H.get_unsafe(j,l);
00461 R.get_unsafe(i,j) = R.get_unsafe(j,i) = sumAccum;
00462 }
00463 MRPT_END
00464 }
00465
00466
00467 template <typename VECTOR_H, typename MAT_C>
00468 typename MAT_C::value_type
00469 multiply_HCHt_scalar(const VECTOR_H &H, const MAT_C &C)
00470 {
00471 MRPT_START
00472 ASSERT_( C.IsSquare() )
00473
00474 const size_t M = H.size();
00475
00476
00477 ASSERT_( size(C,1)==M );
00478
00479 typename VECTOR_H::value_type sumAccum = 0;
00480 typename VECTOR_H::const_iterator itL=H.begin();
00481 for (size_t l=0;l<M; ++l, ++itL)
00482 {
00483 typename VECTOR_H::value_type sumAccumInner = 0;
00484 typename VECTOR_H::const_iterator it;
00485 size_t k;
00486 for (k=0,it=H.begin();it!=H.end();++it,++k)
00487 sumAccumInner += *it * C.get_unsafe(k,l);
00488 sumAccum += sumAccumInner * (*itL);
00489 }
00490 return sumAccum;
00491 MRPT_END
00492 }
00493
00494
00495 template <typename MAT_H, typename MAT_C, typename MAT_R>
00496 void multiply_HtCH(
00497 const MAT_H &H,
00498 const MAT_C &C,
00499 MAT_R &R,
00500 bool accumResultInOutput,
00501 bool allow_submatrix_mult)
00502 {
00503 MRPT_START
00504
00505 ASSERTMSG_( (void*)&C != (void*)&H, "C and H must be different matrices." )
00506 ASSERTMSG_( (void*)&R != (void*)&H, "R and H must be different matrices." )
00507 ASSERTMSG_( (void*)&C != (void*)&R, "C and R must be different matrices.")
00508 ASSERT_(C.IsSquare())
00509
00510 if (allow_submatrix_mult)
00511 ASSERT_(C.getRowCount()>=H.getRowCount())
00512 else ASSERT_(C.getRowCount()==H.getRowCount())
00513
00514 R.setSize( H.getColCount(), H.getColCount());
00515
00516 MAT_H R_;
00517
00518 const size_t M=H.getRowCount();
00519 const size_t N=H.getColCount();
00520
00521
00522 for (size_t i=0;i<N;i++)
00523 for (size_t j=0;j<M;j++)
00524 {
00525 typename MAT_H::value_type sumAccum = 0;
00526 for (size_t l=0;l<M;l++)
00527 sumAccum += H.get_unsafe(l,i) * C.get_unsafe(l,j);
00528 R_.get_unsafe(i,j) = sumAccum;
00529 }
00530
00531
00532 for (size_t i=0;i<N;i++)
00533 for (size_t j=i;j<N;j++)
00534 {
00535 typename MAT_H::value_type sumAccum = accumResultInOutput ? R.get_unsafe(i,j) : 0;
00536 for (size_t l=0;l<M;l++)
00537 sumAccum += R_.get_unsafe(i,l) * H.get_unsafe(l,j);
00538 R.get_unsafe(i,j) = R.get_unsafe(j,i) = sumAccum;
00539 }
00540 MRPT_END
00541 }
00542
00543
00544
00545
00546 template <class MAT_X,class MAT_A,class MAT_OUT>
00547 void multiply_subMatrix (
00548 const MAT_X &X,
00549 const MAT_A &A,
00550 MAT_OUT &outResult,
00551 const size_t A_cols_offset,
00552 const size_t A_rows_offset,
00553 const size_t A_col_count)
00554 {
00555 MRPT_START
00556
00557 const size_t N = X.getRowCount();
00558 const size_t M = A_col_count;
00559 #if defined(_DEBUG) || (MRPT_ALWAYS_CHECKS_DEBUG_MATRICES)
00560 ASSERT_( A.getColCount() >= A_col_count + A_cols_offset );
00561 ASSERT_( A.getRowCount() >= N + A_rows_offset );
00562 #endif
00563 outResult.setSize(N,M);
00564 for (size_t i=0; i < N; i++)
00565 for (size_t j=0; j < M; j++)
00566 {
00567 typename MAT_OUT::value_type tmp = 0;
00568 for (size_t k=0; k < X.getColCount(); k++)
00569 tmp += X.get_unsafe(i,k) * A.get_unsafe(k+A_rows_offset,j+A_cols_offset);
00570 outResult.get_unsafe(i,j) = tmp;
00571 }
00572 MRPT_END
00573 }
00574
00575
00576 template <class MAT_A,class MAT_B,class MAT_C,class MAT_OUT>
00577 void multiply_ABC(const MAT_A &A, const MAT_B &B, const MAT_C &C, MAT_OUT & RES)
00578 {
00579 const size_t NROWS = A.getRowCount();
00580 const size_t N1 = B.getRowCount();
00581 const size_t N2 = B.getColCount();
00582 const size_t NCOLS = C.getColCount();
00583 ASSERT_( A.getColCount()==B.getRowCount() && B.getColCount()==C.getRowCount() )
00584
00585 RES.zeros();
00586 for (size_t i=0;i<NROWS;i++)
00587 for (size_t l=0;l<N2;l++)
00588 {
00589 typename MAT_OUT::value_type sumAccumInner = 0;
00590 for (size_t k=0;k<N1;k++)
00591 sumAccumInner += A.get_unsafe(i,k) * B.get_unsafe(k,l);
00592 for (size_t j=0;j<NCOLS;j++)
00593 RES.get_unsafe(i,j) += sumAccumInner * C.get_unsafe(l,j);
00594 }
00595 }
00596
00597
00598 template <class MAT_A,class MAT_B,class MAT_C,class MAT_OUT>
00599 void multiply_ABCt(const MAT_A &A, const MAT_B &B, const MAT_C &C, MAT_OUT & RES)
00600 {
00601 const size_t NROWS = A.getRowCount();
00602 const size_t N1 = B.getRowCount();
00603 const size_t N2 = B.getColCount();
00604 const size_t NCOLS = C.getRowCount();
00605 ASSERT_( A.getColCount()==B.getRowCount() && B.getColCount()==C.getColCount() )
00606
00607 RES.zeros();
00608 for (size_t i=0;i<NROWS;i++)
00609 for (size_t l=0;l<N2;l++)
00610 {
00611 typename MAT_OUT::value_type sumAccumInner = 0;
00612 for (size_t k=0;k<N1;k++)
00613 sumAccumInner += A.get_unsafe(i,k) * B.get_unsafe(k,l);
00614 for (size_t j=0;j<NCOLS;j++)
00615 RES.get_unsafe(i,j) += sumAccumInner * C.get_unsafe(j,l);
00616 }
00617 }
00618
00619 template <class MAT_A,class MAT_B,class MAT_OUT>
00620 void multiply_ABt(const MAT_A &m1,const MAT_B &m2, MAT_OUT &out)
00621 {
00622 MRPT_START
00623 typedef typename MAT_OUT::value_type T;
00624 const size_t M1R = m1.getRowCount();
00625 const size_t M1C = m1.getColCount();
00626 const size_t M2C = m2.getRowCount();
00627
00628 ASSERTMSG_(m1.getColCount() == m2.getColCount(),"multiply_ABt: Inconsistent matrix sizes in multiplication!")
00629
00630
00631 if ((void*)&m1==(void*)&out|| (void*)&m2==(void*)&out)
00632 {
00633
00634 std::vector<T> temp(M1R*M2C);
00635
00636 T *ptr = &temp[0];
00637 for (size_t i=0; i < M1R; i++)
00638 for (size_t j=0; j < M2C; j++)
00639 {
00640 T accum = 0;
00641 for (size_t k=0; k < M1C; k++)
00642 accum += m1.get_unsafe(i,k) * m2.get_unsafe(j,k);
00643 *(ptr++) = accum;
00644 }
00645
00646 out.setSize(M1R,M2C);
00647 ptr = &temp[0];
00648 for (size_t i=0; i < M1R; i++)
00649 for (size_t j=0; j < M2C; j++)
00650 out.set_unsafe(i,j, *(ptr++) );
00651 }
00652 else
00653 {
00654
00655 out.setSize( M1R,M2C );
00656 for (size_t i=0; i < M1R; i++)
00657 for (size_t j=0; j < M2C; j++)
00658 {
00659 T accum = 0;
00660 for (size_t k=0; k < M1C; k++)
00661 accum += m1.get_unsafe(i,k) * m2.get_unsafe(j,k);
00662 out.set_unsafe(i,j,accum);
00663 }
00664 }
00665 MRPT_END
00666 }
00667
00668 template <class MAT_A,class MAT_B,class MAT_OUT>
00669 void multiply_result_is_symmetric(const MAT_A &m1,const MAT_B &m2, MAT_OUT &out)
00670 {
00671 MRPT_START
00672 typedef typename MAT_OUT::value_type T;
00673 const size_t M1R = m1.getRowCount();
00674 const size_t M1C = m1.getColCount();
00675 const size_t M2C = m2.getColCount();
00676
00677 ASSERTMSG_(m1.getColCount() == m2.getRowCount(),"multiply_result_is_symmetric: Inconsistent matrix sizes in multiplication!")
00678
00679
00680 if ((void*)&m1==(void*)&out || (void*)&m2==(void*)&out)
00681 {
00682
00683 std::vector<T> temp(M1R*M2C);
00684 T *ptr = &temp[0];
00685 for (size_t i=0; i < M1R; i++)
00686 for (size_t j=i; j < M2C; j++)
00687 {
00688 T accum = 0;
00689 for (size_t k=0; k < M1C; k++)
00690 accum += m1.get_unsafe(i,k) * m2.get_unsafe(k,j);
00691 *(ptr++) = accum;
00692 }
00693
00694
00695 out.setSize(M1R,M2C);
00696 ptr = &temp[0];
00697 for (size_t i=0; i < M1R; i++)
00698 for (size_t j=i; j < M1C; j++)
00699 out.get_unsafe(i,j) = out.get_unsafe(j,i) = *(ptr++);
00700 }
00701 else
00702 {
00703
00704 out.setSize( M1R,M2C );
00705 for (size_t i=0; i < M1R; i++)
00706 for (size_t j=i; j < M2C; j++)
00707 {
00708 T accum = 0;
00709 for (size_t k=0; k < M1C; k++)
00710 accum += m1.get_unsafe(i,k) * m2.get_unsafe(k,j);
00711 out.set_unsafe(i,j,accum);
00712 }
00713 for (size_t i=0; i < M1R; i++)
00714 for (size_t j=0; j<i; j++)
00715 out.get_unsafe(j,i) = out.get_unsafe(i,j);
00716 }
00717 MRPT_END
00718 }
00719
00720
00721
00722 template <typename T,size_t NROWS,size_t NCOLS>
00723 void fixedToDynMatrix( const CMatrixFixedNumeric<T,NROWS,NCOLS> &SRC, CMatrixTemplateNumeric<T> &DST)
00724 {
00725 DST.resize(NROWS,NCOLS);
00726 for (size_t r=0;r<NROWS;r++)
00727 ::memcpy(DST.get_unsafe_row(r), &SRC.m_Val[0]+r*NCOLS,sizeof(T)*NCOLS);
00728 }
00729
00730
00731 template <typename T,size_t NROWS,size_t NCOLS>
00732 void insertMatrixFixTransposeIntoDyn(
00733 CMatrixTemplate<T> &M,
00734 const size_t nRow,
00735 const size_t nCol,
00736 const CMatrixFixedNumeric<T,NROWS,NCOLS> &in)
00737 {
00738 ASSERTMSG_( (nRow+NCOLS <= M.getRowCount() ) && (nCol+NROWS<= M.getColCount()), "insertMatrix: Row or Col index out of bounds")
00739 for (size_t c=0;c<NCOLS;c++)
00740 for (size_t r=0;r<NROWS;r++)
00741 M.get_unsafe(nRow+c,nCol+r) = in.get_unsafe(r,c);
00742 }
00743
00744
00745 template <typename T,size_t NROWS,size_t NCOLS>
00746 void insertMatrixFixIntoDyn(
00747 CMatrixTemplate<T> &M,
00748 const size_t nRow,
00749 const size_t nCol,
00750 const CMatrixFixedNumeric<T,NROWS,NCOLS> &in)
00751 {
00752 ASSERTMSG_( (nRow+NROWS <= M.getRowCount() ) && (nCol+NCOLS <= M.getColCount()), "insertMatrix: Row or Col index out of bounds")
00753 for (size_t r=0;r<NROWS;r++)
00754 ::memcpy( M.get_unsafe_row(r+nRow)+nCol, &in.m_Val[0]+r*NCOLS, NCOLS*sizeof(T));
00755 }
00756
00757
00758 template <typename T,size_t NROWS,size_t NCOLS>
00759 void extractFixMatrixFromDynMatrix(
00760 const CMatrixTemplate<T> &M,
00761 const size_t nRow,
00762 const size_t nCol,
00763 CMatrixFixedNumeric<T,NROWS,NCOLS> &outMat)
00764 {
00765 ASSERTMSG_( (nRow+NROWS <= M.getRowCount() ) && (nCol+NCOLS <= M.getColCount()), "extractMatrix: Row or Col index out of bounds")
00766 for (size_t r=0;r<NROWS;r++)
00767 ::memcpy( &outMat.m_Val[0]+r*NCOLS, M.get_unsafe_row(r+nRow)+nCol, sizeof(T)*NCOLS );
00768 }
00769
00770
00771
00772
00773
00774 template <class MATRIXIN,class MATRIXOUT>
00775 inline void invMatrix_special_2x2( const MATRIXIN &M, MATRIXOUT &out_inv )
00776 {
00777 typedef typename MATRIXIN::value_type T;
00778
00779
00780
00781 const T det = M.det();
00782 ASSERTMSG_(det!=0,"Singular matrix")
00783 const T det_inv = 1.0 / det;
00784 out_inv.setSize(2,2);
00785 out_inv._E(1,1) = M._E(2,2) * det_inv;
00786 out_inv._E(1,2) = -M._E(1,2) * det_inv;
00787 out_inv._E(2,1) = -M._E(2,1) * det_inv;
00788 out_inv._E(2,2) = M._E(1,1) * det_inv;
00789 }
00790 template <class MATRIXIN,class MATRIXOUT>
00791 inline void invMatrix_special_3x3( const MATRIXIN &M, MATRIXOUT &out_inv )
00792 {
00793 typedef typename MATRIXIN::value_type T;
00794
00795
00796
00797 const T det = M.det();
00798 ASSERTMSG_(det!=0,"Singular matrix")
00799 const T det_inv = 1.0 / det;
00800 out_inv.setSize(3,3);
00801 out_inv._E(1,1) = (M._E(3,3)*M._E(2,2)-M._E(3,2)*M._E(2,3) ) * det_inv;
00802 out_inv._E(1,2) = (-M._E(3,3)*M._E(1,2)+M._E(3,2)*M._E(1,3) )* det_inv;
00803 out_inv._E(1,3) = (M._E(2,3)*M._E(1,2)-M._E(2,2)*M._E(1,3) )* det_inv;
00804 out_inv._E(2,1) = (-M._E(3,3)*M._E(2,1)+M._E(3,1)*M._E(2,3))* det_inv;
00805 out_inv._E(2,2) = (M._E(3,3)*M._E(1,1)-M._E(3,1)*M._E(1,3))* det_inv;
00806 out_inv._E(2,3) = (-M._E(2,3)*M._E(1,1)+M._E(2,1)*M._E(1,3))* det_inv;
00807 out_inv._E(3,1) = (M._E(3,2)*M._E(2,1)-M._E(3,1)*M._E(2,2))* det_inv;
00808 out_inv._E(3,2) = (-M._E(3,2)*M._E(1,1)+M._E(3,1)*M._E(1,2))* det_inv;
00809 out_inv._E(3,3) = (M._E(2,2)*M._E(1,1)-M._E(2,1)*M._E(1,2))* det_inv;
00810 }
00811
00812
00813 template <> inline void invMatrix<CMatrixFixedNumeric<float,2,2>,CMatrixFixedNumeric<float,2,2> >( const CMatrixFixedNumeric<float,2,2> &M, CMatrixFixedNumeric<float,2,2> &out_inv ) { invMatrix_special_2x2(M,out_inv); }
00814 template <> inline void invMatrix_destroySrc<CMatrixFixedNumeric<float,2,2>,CMatrixFixedNumeric<float,2,2> >( CMatrixFixedNumeric<float,2,2> &M, CMatrixFixedNumeric<float,2,2> &out_inv ) { invMatrix_special_2x2(M,out_inv); }
00815 template <> inline void invMatrix<CMatrixFixedNumeric<double,2,2>,CMatrixFixedNumeric<double,2,2> >( const CMatrixFixedNumeric<double,2,2> &M, CMatrixFixedNumeric<double,2,2> &out_inv ) { invMatrix_special_2x2(M,out_inv); }
00816 template <> inline void invMatrix_destroySrc<CMatrixFixedNumeric<double,2,2>,CMatrixFixedNumeric<double,2,2> >( CMatrixFixedNumeric<double,2,2> &M, CMatrixFixedNumeric<double,2,2> &out_inv ) { invMatrix_special_2x2(M,out_inv); }
00817 template <> inline void invMatrix<CMatrixFixedNumeric<float,3,3>,CMatrixFixedNumeric<float,3,3> >( const CMatrixFixedNumeric<float,3,3> &M, CMatrixFixedNumeric<float,3,3> &out_inv ) { invMatrix_special_3x3(M,out_inv); }
00818 template <> inline void invMatrix_destroySrc<CMatrixFixedNumeric<float,3,3>,CMatrixFixedNumeric<float,3,3> >( CMatrixFixedNumeric<float,3,3> &M, CMatrixFixedNumeric<float,3,3> &out_inv ) { invMatrix_special_3x3(M,out_inv); }
00819 template <> inline void invMatrix<CMatrixFixedNumeric<double,3,3>,CMatrixFixedNumeric<double,3,3> >( const CMatrixFixedNumeric<double,3,3> &M, CMatrixFixedNumeric<double,3,3> &out_inv ) { invMatrix_special_3x3(M,out_inv); }
00820 template <> inline void invMatrix_destroySrc<CMatrixFixedNumeric<double,3,3>,CMatrixFixedNumeric<double,3,3> >( CMatrixFixedNumeric<double,3,3> &M, CMatrixFixedNumeric<double,3,3> &out_inv ) { invMatrix_special_3x3(M,out_inv); }
00821
00822 template <class MATRIXIN,class MATRIXOUT>
00823 inline void invMatrix( const MATRIXIN &M, MATRIXOUT &out_inv )
00824 {
00825 MAT_TYPE_SAMESIZE_OF(MATRIXIN) temp;
00826 temp.assignMatrix(M);
00827 invMatrix_destroySrc(temp,out_inv);
00828 }
00829
00830 template <class MATRIXIN,class MATRIXOUT>
00831 inline void invMatrix_destroySrc( MATRIXIN &M, MATRIXOUT &out_inv )
00832 {
00833 #if 0
00834 out_inv.setIdentity(M.getRowCount());
00835 mrpt::math::detail::fastLeftDivideSquare(out_inv,M);
00836 return;
00837 #else
00838 typedef typename MATRIXIN::value_type T;
00839 ASSERTMSG_(M.IsSquare(),"Inversion of non-square matrix")
00840
00841 const size_t NROWS = M.getRowCount();
00842 if (NROWS==3) return invMatrix_special_3x3(M,out_inv);
00843 else if (NROWS==2) return invMatrix_special_2x2(M,out_inv);
00844
00845
00846 T a1,a2;
00847 out_inv.setSize(NROWS,NROWS);
00848 out_inv.unit();
00849 for (size_t k=0; k < NROWS; k++)
00850 {
00851 int indx = M.pivot(k);
00852 if (indx == -1)
00853 THROW_EXCEPTION( "Inversion of a singular matrix");
00854
00855 if (indx != 0)
00856 out_inv.swapRows(k,indx);
00857
00858 a1 = M.get_unsafe(k,k);
00859 ASSERTDEB_(a1!=0)
00860 const T a1_i = 1/a1;
00861 for (size_t j=0; j < NROWS; j++)
00862 {
00863 M.get_unsafe(k,j) *= a1_i;
00864 out_inv.get_unsafe(k,j) *= a1_i;
00865 }
00866 for (size_t i=0; i < NROWS; i++)
00867 {
00868 if (i != k)
00869 {
00870 a2 = M.get_unsafe(i,k);
00871 for (size_t j=0; j < NROWS; j++)
00872 {
00873 M.get_unsafe(i,j) -= a2 * M.get_unsafe(k,j);
00874 out_inv.get_unsafe(i,j) -= a2 * out_inv.get_unsafe(k,j);
00875 }
00876 }
00877 }
00878 }
00879 #endif
00880 }
00881
00882
00883
00884
00885
00886
00887
00888 template <class MATRIX> inline typename MATRIX::value_type
00889 detMatrix_special_2x2(const MATRIX &M)
00890 {
00891 return M._E(1,1)*M._E(2,2) - M._E(1,2)*M._E(2,1);
00892 }
00893 template <class MATRIX> inline typename MATRIX::value_type
00894 detMatrix_special_3x3(const MATRIX &M)
00895 {
00896 return M._E(1,1)*(M._E(3,3)*M._E(2,2)-M._E(3,2)*M._E(2,3))-
00897 M._E(2,1)*(M._E(3,3)*M._E(1,2)-M._E(3,2)*M._E(1,3))+
00898 M._E(3,1)*(M._E(2,3)*M._E(1,2)-M._E(2,2)*M._E(1,3));
00899 }
00900 template <class MATRIX> typename MATRIX::value_type
00901 detMatrix_special_4x4(const MATRIX &M)
00902 {
00903 typedef typename MATRIX::value_type T;
00904 const T D1 = M._E(1+1,1+1)*(M._E(3+1,3+1)*M._E(2+1,2+1)-M._E(3+1,2+1)*M._E(2+1,3+1))-
00905 M._E(2+1,1+1)*(M._E(3+1,3+1)*M._E(1+1,2+1)-M._E(3+1,2+1)*M._E(1+1,3+1))+
00906 M._E(3+1,1+1)*(M._E(2+1,3+1)*M._E(1+1,2+1)-M._E(2+1,2+1)*M._E(1+1,3+1));
00907 const T D2 = M._E(1+1,1)*(M._E(3+1,3+1)*M._E(2+1,2+1)-M._E(3+1,2+1)*M._E(2+1,3+1))-
00908 M._E(2+1,1)*(M._E(3+1,3+1)*M._E(1+1,2+1)-M._E(3+1,2+1)*M._E(1+1,3+1))+
00909 M._E(3+1,1)*(M._E(2+1,3+1)*M._E(1+1,2+1)-M._E(2+1,2+1)*M._E(1+1,3+1));
00910 const T D3 = M._E(1+1,1)*(M._E(3+1,3+1)*M._E(2+1,2)-M._E(3+1,2)*M._E(2+1,3+1))-
00911 M._E(2+1,1)*(M._E(3+1,3+1)*M._E(1+1,2)-M._E(3+1,2)*M._E(1+1,3+1))+
00912 M._E(3+1,1)*(M._E(2+1,3+1)*M._E(1+1,2)-M._E(2+1,2)*M._E(1+1,3+1));
00913 const T D4 = M._E(1+1,1)*(M._E(3+1,3)*M._E(2+1,2)-M._E(3+1,2)*M._E(2+1,3))-
00914 M._E(2+1,1)*(M._E(3+1,3)*M._E(1+1,2)-M._E(3+1,2)*M._E(1+1,3))+
00915 M._E(3+1,1)*(M._E(2+1,3)*M._E(1+1,2)-M._E(2+1,2)*M._E(1+1,3));
00916 return M._E(1,1)*D1 - M._E(1,2)*D2 + M._E(1,3)*D3 - M._E(1,4)*D4;
00917 }
00918
00919
00920 template <> inline float detMatrix<CMatrixFixedNumeric<float,2,2> >(const CMatrixFixedNumeric<float,2,2> &M) { return detMatrix_special_2x2(M); }
00921 template <> inline double detMatrix<CMatrixFixedNumeric<double,2,2> >(const CMatrixFixedNumeric<double,2,2> &M) { return detMatrix_special_2x2(M); }
00922 template <> inline float detMatrix<CMatrixFixedNumeric<float,3,3> >(const CMatrixFixedNumeric<float,3,3> &M) { return detMatrix_special_3x3(M); }
00923 template <> inline double detMatrix<CMatrixFixedNumeric<double,3,3> >(const CMatrixFixedNumeric<double,3,3> &M) { return detMatrix_special_3x3(M); }
00924 template <> inline float detMatrix<CMatrixFixedNumeric<float,4,4> >(const CMatrixFixedNumeric<float,4,4> &M) { return detMatrix_special_4x4(M); }
00925 template <> inline double detMatrix<CMatrixFixedNumeric<double,4,4> >(const CMatrixFixedNumeric<double,4,4> &M) { return detMatrix_special_4x4(M); }
00926
00927 template <class MATRIX> RET_ELEMENT_ASSERT_MRPTCONTAINER(MATRIX)
00928 detMatrix(const MATRIX& M)
00929 {
00930 typedef typename MATRIX::value_type T;
00931 ASSERTMSG_(M.IsSquare(),"Inversion of non-square matrix")
00932
00933 const size_t NROWS = M.getRowCount();
00934 if (NROWS==3) return detMatrix_special_3x3(M);
00935 else if (NROWS==2) return detMatrix_special_2x2(M);
00936
00937 MAT_TYPE_SAMESIZE_OF(MATRIX) temp;
00938 temp.assignMatrix(M);
00939 T detVal = T(1);
00940 for (size_t k=0; k < NROWS; k++)
00941 {
00942 int indx = temp.pivot(k);
00943 if (indx == -1) return 0;
00944 if (indx != 0) detVal = - detVal;
00945 const T temp_kk = temp.get_unsafe(k,k);
00946 const T temp_kk_inv = T(1)/temp_kk;
00947 detVal = detVal * temp_kk;
00948 for (size_t i=k+1; i < NROWS; i++)
00949 {
00950 T piv = temp.get_unsafe(i,k)*temp_kk_inv;
00951 for (size_t j=k+1; j < NROWS; j++)
00952 temp.get_unsafe(i,j) -= piv * temp.get_unsafe(k,j);
00953 }
00954 }
00955 return detVal;
00956 }
00957
00958
00959
00960
00961 template <class MATRIX>
00962 int matrix_pivot(MATRIX &M, const size_t row)
00963 {
00964 typedef typename MATRIX::value_type T;
00965 size_t k = row;
00966 const size_t NROWS = M.getRowCount();
00967 T temp, amax = -1;
00968 for (size_t i=row; i < NROWS; i++)
00969 if ( (temp = std::abs( M.get_unsafe(i,row))) > amax && temp != 0)
00970 {
00971 amax = temp;
00972 k = i;
00973 }
00974 if (M.get_unsafe(k,row) == T(0)) return -1;
00975 if (k != row)
00976 {
00977 M.swapRows(k,row);
00978 return static_cast<int>( k );
00979 }
00980 return 0;
00981 }
00982
00983
00984 }
00985
00986
00987 template <class MAT1,class MAT2>
00988 inline typename MAT1::value_type multiply_HCHt_scalar(const MAT1 &H, const MAT2 &C) {
00989 return detail::multiply_HCHt_scalar(H,C);
00990 }
00991
00992
00993 template <class T>
00994 inline CMatrixTemplateNumeric<T> operator / (const CMatrixTemplateNumeric<T>& m1, const CMatrixTemplateNumeric<T>& m2)
00995 {
00996 return (m1 * !m2);
00997 }
00998
00999
01000 template <class T>
01001 inline CMatrixTemplateNumeric<T> operator ^ (const CMatrixTemplateNumeric<T>& m, const unsigned int pow)
01002 {
01003 CMatrixTemplateNumeric<T> temp(m);
01004 temp ^= pow;
01005 return temp;
01006 }
01007
01008
01009 template <class MAT>
01010 inline MAT_TYPE_TRANSPOSE_OF(MAT)
01011 operator ~ (const MAT& m)
01012 {
01013 const size_t R=m.getRowCount();
01014 const size_t C=m.getColCount();
01015 MAT_TYPE_TRANSPOSE_OF(MAT) temp; temp.setSize(C,R);
01016 for (size_t i=0;i<R;i++)
01017 for (size_t j=0;j<C;j++)
01018 temp.get_unsafe(j,i) = m.get_unsafe(i,j);
01019 return temp;
01020 }
01021
01022
01023 template <class MATRIX>
01024 inline RET_MAT_ASSERT_MRPTMATRIX(MATRIX)
01025 operator !(const MATRIX &m) {
01026 RET_MAT_ASSERT_MRPTMATRIX(MATRIX) ret(UNINITIALIZED_MATRIX);
01027 m.inv(ret);
01028 return ret;
01029 }
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043 template <class MAT1,class MAT2>
01044 inline MAT_TYPE_PRODUCT_OF(MAT1,MAT2)
01045 operator * ( const MAT1 &A,
01046 const MAT2 &B )
01047 {
01048 MAT_TYPE_PRODUCT_OF(MAT1,MAT2) RES(UNINITIALIZED_MATRIX);
01049 detail::multiply_AB(A,B, RES);
01050 return RES;
01051 }
01052
01053
01054
01055
01056
01057
01058
01059 template<class MAT_IN, class MAT_OUT>
01060 void meanAndCov(
01061 const MAT_IN &v,
01062 vector_double &out_mean,
01063 MAT_OUT &out_cov
01064 )
01065 {
01066 const size_t N = v.getRowCount();
01067 ASSERTMSG_(N>0,"The input matrix contains no elements");
01068 const double N_inv = 1.0/N;
01069
01070 const size_t M = v.getColCount();
01071 ASSERTMSG_(M>0,"The input matrix contains rows of length 0");
01072
01073
01074 out_mean.assign(M,0);
01075 for (size_t i=0;i<N;i++)
01076 for (size_t j=0;j<M;j++)
01077 out_mean[j]+=v.get_unsafe(i,j);
01078 out_mean*=N_inv;
01079
01080
01081
01082
01083 out_cov.zeros(M,M);
01084 for (size_t i=0;i<N;i++)
01085 {
01086 for (size_t j=0;j<M;j++)
01087 out_cov.get_unsafe(j,j)+=square(v.get_unsafe(i,j)-out_mean[j]);
01088
01089 for (size_t j=0;j<M;j++)
01090 for (size_t k=j+1;k<M;k++)
01091 out_cov.get_unsafe(j,k)+=(v.get_unsafe(i,j)-out_mean[j])*(v.get_unsafe(i,k)-out_mean[k]);
01092 }
01093 for (size_t j=0;j<M;j++)
01094 for (size_t k=j+1;k<M;k++)
01095 out_cov.get_unsafe(k,j) = out_cov.get_unsafe(j,k);
01096 out_cov*=N_inv;
01097 }
01098
01099
01100
01101
01102
01103
01104 template<class MATRIX>
01105 inline MAT_TYPE_COVARIANCE_OF(MATRIX) cov( const MATRIX &v )
01106 {
01107 vector_double m;
01108 MAT_TYPE_COVARIANCE_OF(MATRIX) C;
01109 meanAndCov(v,m,C);
01110 return C;
01111 }
01112
01113
01114
01115 #define SAVE_MATRIX(M) \
01116 M.saveToTextFile(mrpt::format("%s.txt",#M));
01117
01118
01119
01120 namespace detail {
01121
01122
01123
01124 template<typename T> class VicinityTraits<CMatrixTemplate<T> > {
01125 public:
01126 inline static void initialize(CMatrixTemplate<T> &mat,size_t N) {
01127 mat.setSize(N,N,true);
01128 }
01129 inline static void insertInContainer(CMatrixTemplate<T> &mat,size_t r,size_t c,const T &t) {
01130 mat.get_unsafe(r,c)=t;
01131 }
01132 };
01133
01134
01135
01136 template<typename T> class VicinityTraits<std::vector<T> > {
01137 public:
01138 inline static void initialize(std::vector<T> &vec,size_t N) {
01139 vec.reserve(N*N);
01140 }
01141 inline static void insertInContainer(std::vector<T> &vec,size_t,size_t,const T &t) {
01142 vec.push_back(t);
01143 }
01144 };
01145
01146
01147
01148
01149
01150
01151
01152
01153 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,4> {
01154 public:
01155 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01156 mat.ASSERT_ENOUGHROOM<1>(r,c);
01157 ReturnType res;
01158 VicinityTraits<ReturnType>::initialize(res,3);
01159 VicinityTraits<ReturnType>::insertInContainer(res,0,1,mat.get_unsafe(r-1,c));
01160 VicinityTraits<ReturnType>::insertInContainer(res,1,0,mat.get_unsafe(r,c-1));
01161 VicinityTraits<ReturnType>::insertInContainer(res,1,2,mat.get_unsafe(r,c+1));
01162 VicinityTraits<ReturnType>::insertInContainer(res,2,1,mat.get_unsafe(r+1,c));
01163 return res;
01164 }
01165 };
01166
01167
01168
01169
01170
01171
01172
01173
01174 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,5> {
01175 public:
01176 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01177 mat.ASSERT_ENOUGHROOM<1>(r,c);
01178 ReturnType res;
01179 VicinityTraits<ReturnType>::initialize(res,3);
01180 VicinityTraits<ReturnType>::insertInContainer(res,0,1,mat.get_unsafe(r-1,c));
01181 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,1,i+1,mat.get_unsafe(r,c+i));
01182 VicinityTraits<ReturnType>::insertInContainer(res,2,1,mat.get_unsafe(r+1,c));
01183 return res;
01184 }
01185 };
01186
01187
01188
01189
01190
01191
01192
01193
01194 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,8> {
01195 public:
01196 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01197 mat.ASSERT_ENOUGHROOM<1>(r,c);
01198 ReturnType res;
01199 VicinityTraits<ReturnType>::initialize(res,3);
01200 for (int i=-1;i<=1;++i) for (int j=-1;j<=1;++j) if (i||j) VicinityTraits<ReturnType>::insertInContainer(res,i+1,j+1,mat.get_unsafe(r+i,c+j));
01201 return res;
01202 }
01203 };
01204
01205
01206
01207
01208
01209
01210
01211
01212 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,9> {
01213 public:
01214 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01215 mat.ASSERT_ENOUGHROOM<1>(r,c);
01216 ReturnType res;
01217 VicinityTraits<ReturnType>::initialize(res,3);
01218 for (int i=-1;i<=1;++i) for (int j=-1;j<=1;++j) VicinityTraits<ReturnType>::insertInContainer(res,i+1,j+1,mat.get_unsafe(r+i,c+j));
01219 return res;
01220 }
01221 };
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,12> {
01233 public:
01234 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01235 mat.ASSERT_ENOUGHROOM<2>(r,c);
01236 ReturnType res;
01237 VicinityTraits<ReturnType>::initialize(res,5);
01238 VicinityTraits<ReturnType>::insertInContainer(res,0,2,mat.get_unsafe(r-2,c));
01239 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,1,i+2,mat.get_unsafe(r-1,c+i));
01240 for (int i=-2;i<=2;++i) if (i) VicinityTraits<ReturnType>::insertInContainer(res,2,i+2,mat.get_unsafe(r,c+i));
01241 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,3,i+2,mat.get_unsafe(r+1,c+i));
01242 VicinityTraits<ReturnType>::insertInContainer(res,4,2,mat.get_unsafe(r+2,c));
01243 return res;
01244 }
01245 };
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,13> {
01257 public:
01258 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01259 mat.ASSERT_ENOUGHROOM<2>(r,c);
01260 ReturnType res;
01261 VicinityTraits<ReturnType>::initialize(res,5);
01262 VicinityTraits<ReturnType>::insertInContainer(res,0,2,mat.get_unsafe(r-2,c));
01263 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,1,i+2,mat.get_unsafe(r-1,c+i));
01264 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,2,i+2,mat.get_unsafe(r,c+i));
01265 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,3,i+2,mat.get_unsafe(r+1,c+i));
01266 VicinityTraits<ReturnType>::insertInContainer(res,4,2,mat.get_unsafe(r+2,c));
01267 return res;
01268 }
01269 };
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,20> {
01281 public:
01282 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01283 mat.ASSERT_ENOUGHROOM<2>(r,c);
01284 ReturnType res;
01285 VicinityTraits<ReturnType>::initialize(res,5);
01286 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,0,i+2,mat.get_unsafe(r-2,c+i));
01287 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,1,i+2,mat.get_unsafe(r-1,c+i));
01288 for (int i=-2;i<=2;++i) if (i) VicinityTraits<ReturnType>::insertInContainer(res,2,i+2,mat.get_unsafe(r,c+i));
01289 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,3,i+2,mat.get_unsafe(r+1,c+i));
01290 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,4,i+2,mat.get_unsafe(r+2,c+i));
01291 return res;
01292 }
01293 };
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,21> {
01305 public:
01306 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01307 mat.ASSERT_ENOUGHROOM<2>(r,c);
01308 ReturnType res;
01309 VicinityTraits<ReturnType>::initialize(res,5);
01310 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,0,i+2,mat.get_unsafe(r-2,c+i));
01311 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,1,i+2,mat.get_unsafe(r-1,c+i));
01312 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,2,i+2,mat.get_unsafe(r,c+i));
01313 for (int i=-2;i<=2;++i) VicinityTraits<ReturnType>::insertInContainer(res,3,i+2,mat.get_unsafe(r+1,c+i));
01314 for (int i=-1;i<=1;++i) VicinityTraits<ReturnType>::insertInContainer(res,4,i+2,mat.get_unsafe(r+2,c+i));
01315 return res;
01316 }
01317 };
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,24> {
01329 public:
01330 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01331 mat.ASSERT_ENOUGHROOM<2>(r,c);
01332 ReturnType res;
01333 VicinityTraits<ReturnType>::initialize(res,5);
01334 for (int i=-2;i<=2;++i) for (int j=-2;j<=2;++j) if (i||j) VicinityTraits<ReturnType>::insertInContainer(res,i+2,j+2,mat.get_unsafe(r+i,c+j));
01335 return res;
01336 }
01337 };
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348 template<typename MatrixType,typename T,typename ReturnType> struct getVicinity<MatrixType,T,ReturnType,25> {
01349 public:
01350 static ReturnType get(size_t r,size_t c,const MatrixType &mat) {
01351 mat.ASSERT_ENOUGHROOM<2>(r,c);
01352 ReturnType res;
01353 VicinityTraits<ReturnType>::initialize(res,5);
01354 for (int i=-2;i<=2;++i) for (int j=-2;j<=2;++j) VicinityTraits<ReturnType>::insertInContainer(res,i+2,j+2,mat.get_unsafe(r+i,c+j));
01355 return res;
01356 }
01357 };
01358
01359 template<typename MatrixType> size_t rank(const MatrixType &m,typename MatrixType::value_type eps) {
01360 size_t N=m.getRowCount();
01361 ASSERT_(m.getColCount()==N);
01362 MAT_TYPE_SAMESIZE_OF(MatrixType) tmp;
01363 tmp.assignMatrix(m);
01364 CArbitrarySubmatrixView<MatrixType> mat(tmp,0,N,0,N);
01365 size_t res=0;
01366 while (mat.getRowCount()!=0&&mat.getColCount()!=0) {
01367 size_t row=0;
01368 if (std::abs(mat(0,0)<=eps)) {
01369 for (size_t i=1;i<mat.getColCount();++i) if (std::abs(mat(i,0))>eps) {
01370 row=i;
01371 break;
01372 }
01373 if (row==0) {
01374 mat.deleteColumn(0);
01375 continue;
01376 }
01377 }
01378 size_t pRow=mat.getProxyRow(row);
01379 for (size_t i=0;i<mat.getRowCount();++i) {
01380 if (i==row) continue;
01381 size_t pRowAlt=mat.getProxyRow(i);
01382 typename MatrixType::value_type prop=mat.getWithRowProxied(pRowAlt,0)/mat.getWithRowProxied(pRow,0);
01383 for (size_t j=1;j<mat.getColCount();++j) mat.getWithRowProxied(pRowAlt,j)-=prop*mat.getWithRowProxied(pRow,j);
01384 }
01385 res++;
01386 mat.deleteColumn(0);
01387 mat.deleteRow(row);
01388 }
01389 return res;
01390 }
01391
01392 template<typename JA> void pivotUntilIdentity(JointAccessor<JA> &joint) {
01393 size_t N=joint.size();
01394
01395 for (size_t i=0;i<N-1;++i) {
01396
01397 joint.ensureSuitablePos(i);
01398 for (size_t j=i+1;j<N;++j) joint.substractRowAsNeeded(i,j);
01399 joint.unitarizeReducedRow(i);
01400 }
01401 joint.ensureAndUnitarizeLast();
01402
01403
01404 for (size_t i=N-1;i>0;--i) for (int j=i-1;j>=0;--j) joint.substractWhenReduced(i,j);
01405 }
01406
01407
01408 template <typename MAT1,typename MAT2,typename MAT3> inline void leftDivideSquare(const MAT1 &C,const MAT2 &A,MAT3 &RES) {
01409 MAT_TYPE_SAMESIZE_OF(MAT2) tmp;
01410 tmp.assignMatrix(A);
01411 RES.assignMatrix(C);
01412 fastLeftDivideSquare(RES,tmp);
01413 }
01414
01415
01416 template <typename MAT1,typename MAT2,typename MAT3> inline void rightDivideSquare(const MAT1 &C,const MAT2 &B, MAT3 &RES) {
01417 MAT_TYPE_SAMESIZE_OF(MAT2) tmp;
01418 tmp.assignMatrix(B);
01419 RES.assignMatrix(C);
01420 fastRightDivideSquare(RES,tmp);
01421 }
01422
01423
01424 template<typename MAT1,typename MAT2> inline void fastLeftDivideSquare(MAT1 &inout_CB,MAT2 &willBeDestroyed_A) {
01425 JointHorizontalAccessor<MAT2,MAT1> jha=JointHorizontalAccessor<MAT2,MAT1>(willBeDestroyed_A,inout_CB);
01426 JointAccessor<JointHorizontalAccessor<MAT2,MAT1> > ja=JointAccessor<JointHorizontalAccessor<MAT2,MAT1> >(jha);
01427 pivotUntilIdentity(ja);
01428 }
01429
01430
01431 template<typename MAT1,typename MAT2> inline void fastRightDivideSquare(MAT1 &inout_CA,MAT2 &willBeDestroyed_B) {
01432 JointVerticalAccessor<MAT2,MAT1> jva=JointVerticalAccessor<MAT2,MAT1>(willBeDestroyed_B,inout_CA);
01433 JointAccessor<JointVerticalAccessor<MAT2,MAT1> > ja=JointAccessor<JointVerticalAccessor<MAT2,MAT1> >(jva);
01434 pivotUntilIdentity(ja);
01435 }
01436
01437 }
01438
01439 }
01440 }
01441
01442
01443 #endif