00001 #ifndef Impala_Core_Matrix_MatPInv_h
00002 #define Impala_Core_Matrix_MatPInv_h
00003
00004 #include "Core/Matrix/MatFunc.h"
00005 #include "Core/Matrix/Vecs.h"
00006 #include "Core/Matrix/MatMul.h"
00007 #include "Core/Matrix/VecFunc.h"
00008 #include "Core/Matrix/MatSVD.h"
00009 #include "Core/Matrix/MatTranspose.h"
00010 #include "Core/Array/PixMax.h"
00011 #include "Core/Array/SetVal.h"
00012 #include "Core/Array/SetPart.h"
00013
00014 namespace Impala
00015 {
00016 namespace Core
00017 {
00018 namespace Matrix
00019 {
00020
00021 template<class ArrayT>
00022 inline ArrayT*
00023 MatPInv(ArrayT* a, double tolerance=-1)
00024 {
00025 int m = MatNrRow(a);
00026 int n = MatNrCol(a);
00027
00028 if(n > m)
00029 return MatTranspose(MatPInv(MatTranspose(a), tolerance));
00030
00031 Mat* u=0;
00032 Mat* s=0;
00033 Mat* v=0;
00034
00035 MatSVD(a, u, s, v);
00036 Mat* res= MatPInv(a,u,s,v,tolerance);
00037
00038 delete u;
00039 delete s;
00040 delete v;
00041
00042 return res;
00043 }
00044
00045 template<class ArrayT>
00046 inline ArrayT*
00047 MatPInv(ArrayT* a,ArrayT* u,ArrayT* s,ArrayT* v, double tolerance=-1){
00048
00049 Mat* res;
00050 VecScalarReal64* Singulars;
00051
00052 int m = MatNrRow(a);
00053 int n = MatNrCol(a);
00054
00055 int ssize = std::min(s->H(),s->W());
00056
00057
00058 Singulars = VecCreate<VecScalarReal64>(ssize);
00059 SetVal(Singulars,0);
00060 for(int i=0; i<ssize;i++)
00061 Singulars->SetValue(s->Value(i,i),i,0);
00062
00063
00064
00065 if(tolerance <= 0)
00066 tolerance = std::max(m,n) * PixMax(Singulars) * std::numeric_limits<double>::epsilon();
00067
00068
00069 int countAboveTolerance = 0;
00070 for(int i=0 ; i<ssize ; ++i)
00071 if(Singulars->Value(i,0) > tolerance)
00072 ++countAboveTolerance;
00073
00074 if (countAboveTolerance == 0)
00075 {
00076 res = MatCreate<Mat>(n,m);
00077 SetVal(res, 0);
00078 }
00079 else
00080 {
00081
00082
00083
00084 Mat* SPlus = MatCreate<Mat>(countAboveTolerance,countAboveTolerance);
00085 SetVal(SPlus, 0);
00086 for(int i=0 ; i<countAboveTolerance ; ++i)
00087 SPlus->SetValue(1/Singulars->Value(i,0),i,i);
00088
00089
00090 Mat* V =MatCreate<Mat>(n,countAboveTolerance);
00091 for(int i=0;i<countAboveTolerance;i++)
00092 for(int j=0;j<n;j++)
00093 V->SetValue(v->Value(i,j),i,j);
00094
00095
00096
00097 Mat* UT =MatCreate<Mat>(countAboveTolerance,m);
00098 for(int i=0;i<countAboveTolerance;i++)
00099 for(int j=0;j<m;j++)
00100 UT->SetValue(u->Value(i,j),j,i);
00101
00102 Mat* SPlus_X_UT = MatMul(SPlus,UT);
00103 res = MatMul(V,SPlus_X_UT);
00104
00105 delete V;
00106 delete SPlus;
00107 delete SPlus_X_UT;
00108 delete UT;
00109 }
00110
00111 delete Singulars;
00112 return res;
00113 }
00114
00115 }
00116 }
00117 }
00118
00119 #endif