Home || Architecture || Video Search || Visual Search || Scripts || Applications || Important Messages || OGL || Src

MatPInv.h

Go to the documentation of this file.
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     //Store the singular values in a vector
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     //If No tolerance is given, the default tolerance is:
00064     //eps*max(m,n)*max(Singulars)
00065     if(tolerance <= 0)
00066         tolerance = std::max(m,n) * PixMax(Singulars) * std::numeric_limits<double>::epsilon();
00067 
00068     //Find the number of singular values above tolerance
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         //SPlus is the square matrix of reciprocals of singular values that are
00082         //above tolerance - it is assumed that the Singular value matrix is
00083         //sorted from largest to smallest singular values.
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         //We only need the first countAboveTolerance columns from V
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         //We only need the first countAboveTolerance rows from U'
00096         //Note that U is transposed:
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         //res = MatMul(V,MatMul(SPlus,UT));
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 } // namespace Matrix
00116 } // namespace Core
00117 } // namespace Impala
00118 
00119 #endif

Generated on Fri Mar 19 09:31:16 2010 for ImpalaSrc by  doxygen 1.5.1