00001 #ifndef Impala_Core_Matrix_MatInverse_h
00002 #define Impala_Core_Matrix_MatInverse_h
00003
00004 #include "Core/Matrix/MatFunc.h"
00005 #include "Core/Matrix/MatSet.h"
00006 #include <iostream>
00007 #include <math.h>
00008
00009 namespace Impala
00010 {
00011 namespace Core
00012 {
00013 namespace Matrix
00014 {
00015
00016
00017 static const double Matrix_EPS = 1e-12;
00018
00019 template<class C>
00020 inline int
00021 Ludcmp(C* a, int n, short *indx, double *d)
00022 {
00023 double *vv = new double [n];
00024
00025 *d=1.0;
00026 int i, j, k;
00027 for ( i=0;i<n;i++)
00028 {
00029 double big=0.0;
00030 for (j=0;j<n;j++)
00031 {
00032 double temp = fabs(a[i*n+j]);
00033 if (temp > big)
00034 big=temp;
00035 }
00036 if (big == 0.0)
00037 return(0);
00038 vv[i]=1.0/big;
00039 }
00040 for (j=0;j<n;j++)
00041 {
00042 for (i=0;i<j;i++)
00043 {
00044 double sum=a[i*n+j];
00045 for (k=0;k<i;k++)
00046 sum -= a[i*n+k]*a[k*n+j];
00047 a[i*n+j]=sum;
00048 }
00049 double big=0.0;
00050 int imax = 0;
00051 for (i=j;i<n;i++)
00052 {
00053 double sum=a[i*n+j];
00054 for (k=0;k<j;k++)
00055 sum -= a[i*n+k]*a[k*n+j];
00056 a[i*n+j]=sum;
00057
00058 double dum = vv[i]*fabs(sum);
00059 if ( dum >= big)
00060 {
00061 big=dum;
00062 imax=i;
00063 }
00064 }
00065 if (j != imax)
00066 {
00067 for (k=0;k<n;k++)
00068 {
00069 double dum=a[imax*n+k];
00070 a[imax*n+k]=a[j*n+k];
00071 a[j*n+k]=dum;
00072 }
00073 *d = -(*d);
00074 vv[imax]=vv[j];
00075 }
00076 indx[j]=imax;
00077 if (a[j*n+j] == 0.0)
00078 a[j*n+j]=Matrix_EPS;
00079 if (j != n-1)
00080 {
00081 double dum=1.0/a[j*n+j];
00082 for (i=j+1;i<n;i++)
00083 a[i*n+j] *= dum;
00084 }
00085 }
00086 delete [] vv;
00087
00088 return(1);
00089 }
00090
00091 template<class C>
00092 inline void
00093 Lubksb(C* a, int n, short *indx, double *b)
00094 {
00095 int ii = -1;
00096
00097 int i;
00098 for (i=0;i<n;i++)
00099 {
00100 int ip=indx[i];
00101 double sum=b[ip];
00102 b[ip]=b[i];
00103 if (ii>=0)
00104 for (int j=ii;j<=i-1;j++)
00105 sum -= a[i*n+j]*b[j];
00106 else if (sum) ii=i;
00107 b[i]=sum;
00108 }
00109 for (i=n-1;i>=0;i--)
00110 {
00111 double sum=b[i];
00112 for (int j=i+1;j<n;j++)
00113 sum -= a[i*n+j]*b[j];
00114 b[i]=sum/a[i*n+i];
00115 }
00116 }
00117
00118 template<class ArrayT>
00119 inline ArrayT*
00120 MatInverse(ArrayT* a)
00121 {
00122 if (MatNrCol(a) != MatNrRow(a))
00123 {
00124 std::cerr << "MatInverse: matrix is not square!" << std::endl;
00125 return 0;
00126 }
00127
00128 int size = MatNrRow(a);
00129 ArrayT* m = MatCreate<ArrayT>(size, size);
00130 ArrayT* tmp = MatCreate<ArrayT>(MatNrRow(a), MatNrCol(a));
00131 MatSet(tmp, a);
00132 short* idx = new short[size];
00133 double d;
00134 if (!Ludcmp(MatE(tmp, 0, 0), size, idx, &d))
00135 {
00136 std::cerr << "MatInverse: singular matrix can't be inverted." << std::endl;
00137 delete [] idx;
00138 return 0;
00139 }
00140
00141 double* res = new double[size];
00142 for (int j=0 ; j<size ; j++)
00143 {
00144 for (int i=0 ; i<size; i++)
00145 res[i] = 0.0;
00146 res[j] = 1.0;
00147 Lubksb(MatE(tmp, 0, 0), size, idx, res);
00148 for (int k=0 ; k<size ; k++)
00149 *MatE(m, k, j) = res[k];
00150 }
00151
00152 delete [] res;
00153 delete [] idx;
00154 delete tmp;
00155
00156 return m;
00157 }
00158
00159 }
00160 }
00161 }
00162
00163 #endif