00001 #ifndef Impala_Core_Matrix_MatPseudoInverse_h
00002 #define Impala_Core_Matrix_MatPseudoInverse_h
00003
00004 #include "Core/Matrix/MatFunc.h"
00005
00006 namespace Impala
00007 {
00008 namespace Core
00009 {
00010 namespace Matrix
00011 {
00012
00013 template<class ArrayT>
00014 inline ArrayT*
00015 MatPseudoInverse(ArrayT* a, double tolerance)
00016 {
00017 int m = MatNrRow(a);
00018 int n = MatNrCol(a);
00019 if(n > m)
00020 return MatPseudoInverse(MatTranspose(a), tolerance);
00021
00022 Matrix* u=0;
00023 Matrix* s=0;
00024 Matrix* v=0;
00025 MatSvd(a, 0, u, s, v);
00026 if(m > 1)
00027 s = diag(S);
00028 else if (m == 1)
00029 s = S(1);
00030 else s = 0;
00031
00032 if(tolerance <= 0)
00033 tolerance = max(m,n) * max(s) * eps;
00034
00035 int i;
00036 int countAboveTolerance = 0;
00037 for(i=0 ; i< ; ++i)
00038 if(s[i] > tolerance)
00039 ++countAboveTolerance;
00040 Matrix* x = new Matrix(n, m);
00041 if (countAboveTolerance == 0)
00042 SetVal(x, 0);
00043 else
00044 {
00045
00046 matrix s2(countAboveTolerance,countAboveTolerance);
00047 SetVal(s, 0);
00048 for(i=0 ; i<countAboveTolerance ; ++i)
00049 s2.Value(i,i) = s[i];
00050
00051 v.Resize(m,countAboveTolerance);
00052 u.Resize(countAboveTolerance,n);
00053 x = MatMul(v,MatMul(s,u));
00054 }
00055
00056 return x;
00057 }
00058
00059 }
00060 }
00061 }
00062
00063 #endif