00001 #ifndef Impala_Core_Matrix_MatKLM_h
00002 #define Impala_Core_Matrix_MatKLM_h
00003
00004 #include "Core/Matrix/MatCovariance.h"
00005
00006 namespace Impala
00007 {
00008 namespace Core
00009 {
00010 namespace Matrix
00011 {
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 template<class MatrixT, class VectorT>
00023 void
00024 Tred2(MatrixT* a, VectorT* d, VectorT* e)
00025 {
00026 int i,j,k,l;
00027 double scale,hh,h,g,f;
00028
00029 int n = VecNrElem(d);
00030
00031 for (i=n-1; i>0; i--)
00032 {
00033 l = i-1;
00034 h = scale = 0.0;
00035 if (l>0)
00036 {
00037 for (k=0; k<=l; k++)
00038 scale += fabs(*MatE(a, i, k));
00039 if (scale == 0.0)
00040 *VecE(e, i) = *MatE(a, i, l);
00041 else
00042 {
00043 for (k=0; k<=l; k++)
00044 {
00045 *MatE(a, i, k) /= scale;
00046 h += *MatE(a, i, k) * *MatE(a, i, k);
00047 }
00048 f = *MatE(a, i, l);
00049 g = (f >=0.0 ? -sqrt(h) : sqrt(h));
00050 *VecE(e, i) = scale*g;
00051 h -= f*g;
00052 *MatE(a, i, l) = f-g;
00053 f = 0.0;
00054 for (j=0; j<=l; j++)
00055 {
00056 *MatE(a, j, i) = *MatE(a, i, j)/h;
00057 g = 0.0;
00058 for (k=0; k<=j; k++)
00059 g += *MatE(a, j, k) * *MatE(a, i, k);
00060 for (k=j+1; k<=l; k++)
00061 g += *MatE(a, k, j) * *MatE(a, i, k);
00062 *VecE(e, j) = g/h;
00063 f += *VecE(e, j) * *MatE(a, i, j);
00064 }
00065 hh = f/(h+h);
00066 for (j=0; j<=l; j++)
00067 {
00068 f = *MatE(a, i, j);
00069 *VecE(e, j) = g = *VecE(e, j)-hh*f;
00070 for (k=0; k<=j; k++)
00071 *MatE(a, j, k) -= (f * *VecE(e, k)
00072 + g * *MatE(a, i, k));
00073 }
00074 }
00075 }
00076 else
00077 *VecE(e, i) = *MatE(a, i, l);
00078 *VecE(d, i) = h;
00079 }
00080
00081 *VecE(d, 0) = 0.0;
00082 *VecE(e, 0) = 0.0;
00083
00084 for (i=0; i<n; i++)
00085 {
00086 l = i-1;
00087 if (*VecE(d, i))
00088 {
00089 for (j=0; j<=l; j++)
00090 {
00091 g = 0.0;
00092 for (k=0; k<=l; k++)
00093 g += *MatE(a, i, k) * *MatE(a, k, j);
00094 for (k=0; k<=l; k++)
00095 *MatE(a, k, j) -= g * *MatE(a, k, i);
00096 }
00097 }
00098 *VecE(d, i) = *MatE(a, i, i);
00099 *MatE(a, i, i) = 1.0;
00100 for (j=0; j<=l; j++)
00101 *MatE(a, j, i) = *MatE(a, i, j) = 0.0;
00102 }
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 template<class MatrixT, class VectorT>
00121 void
00122 Tqli(VectorT* d, VectorT* e, MatrixT* z)
00123 {
00124
00125 int m,l,iter,i,k;
00126 double s,r,p,g,f,dd,c,b;
00127
00128 int n = VecNrElem(e);
00129
00130 for (i=1; i<n; i++)
00131 *VecE(e, i-1) = *VecE(e, i);
00132 *VecE(e, n-1) = 0.0;
00133
00134
00135 for (l=0; l<n; l++)
00136 {
00137 iter=0;
00138 do {
00139 for (m=l; m<n-1; m++)
00140 {
00141 dd = fabs(*VecE(d, m)) + fabs(*VecE(d, m+1));
00142 if ( (fabs(*VecE(e, m)) + dd) == dd)
00143 break;
00144 }
00145 if (m != l)
00146 {
00147 if (iter++ == 30)
00148 std::cout << "Tqli: Too many iterations" << std::endl;
00149 g = (*VecE(d, l+1) - *VecE(d, l)) / (2.0 * *VecE(e, l));
00150 r = sqrt(g*g + 1.0);
00151 g = *VecE(d, m) - *VecE(d, l) + *VecE(e, l)/(g+SIGN(r,g));
00152 s = c = 1.0;
00153 p = 0.0;
00154 for (i=m-1; i>=l; i--)
00155 {
00156 f = s * *VecE(e, i);
00157 b = c * *VecE(e, i);
00158 *VecE(e, i+1) = (r=sqrt(f*f+g*g));
00159 if (r == 0.0)
00160 {
00161 *VecE(d, i+1) -= p;
00162 *VecE(e, m) = 0.0;
00163 break;
00164 }
00165 s = f/r;
00166 c = g/r;
00167 g = *VecE(d, i+1)-p;
00168 r = (*VecE(d, i)-g)*s + 2.0*c*b;
00169 *VecE(d, i+1) = g+(p=s*r);
00170 g = c*r-b;
00171
00172 for (k=0; k<n; k++)
00173 {
00174 f = *MatE(z, k, i+1);
00175 *MatE(z, k, i+1) = s * *MatE(z, k, i) + c*f;
00176 *MatE(z, k, i) = c * *MatE(z, k, i) - s*f;
00177 }
00178 }
00179 if (r==0.0 && i>=l)
00180 continue;
00181 *VecE(d, l) -= p;
00182 *VecE(e, l) = g;
00183 *VecE(e, m) = 0.0;
00184 }
00185 } while (m != l);
00186 }
00187
00188
00189 int j;
00190 for (i=0; i<n-1; i++)
00191 {
00192 p = *VecE(d, k=i);
00193 for (j=i+1; j<n; j++)
00194 if (*VecE(d, j) >= p)
00195 p = *VecE(d, k=j);
00196 if (k!=i)
00197 {
00198 *VecE(d, k) = *VecE(d, i);
00199 *VecE(d, i) = p;
00200
00201 for (j=0; j<n; j++)
00202 {
00203 p = *MatE(z, j, i);
00204 *MatE(z, j, i) = *MatE(z, j, k);
00205 *MatE(z, j, k) = p;
00206 }
00207 }
00208 }
00209 }
00210
00211
00212
00213
00214
00215 template<class ArrayT>
00216 inline ArrayT*
00217 MatKLM(ArrayT* m, int newDim)
00218 {
00219 typedef ArrayT Mat;
00220 typedef ArrayT Vec;
00221
00222 int nr = MatNrRow(m);
00223 int nc = MatNrCol(m);
00224
00225 if (newDim<1 || newDim>nc)
00226 {
00227 std::cout << "MatKLM: new dimensionality invalid, set to 1..." << std::endl;
00228 newDim = 1;
00229 }
00230
00231 Mat* newfvec = MatCreate<Mat>(nr, newDim);
00232 Mat* a = MatCovariance(m, (Mat*) 0);
00233 Vec* d = VecCreate<Vec>(nc);
00234 Vec* e = VecCreate<Vec>(nc);
00235
00236 Tred2(a, d, e);
00237 Tqli(d, e, a);
00238
00239
00240
00241 for (int k=0; k<nr; k++)
00242 {
00243 for (int i=0; i<newDim; i++)
00244 {
00245 double vl = 0.0;
00246 for (int j=0; j<nc; j++)
00247 vl += *MatE(m, k, j) * *MatE(a, j, i);
00248 *MatE(newfvec, k, i) = vl;
00249 }
00250 }
00251 delete a;
00252 delete d;
00253 delete e;
00254 return newfvec;
00255 }
00256
00257 }
00258 }
00259 }
00260
00261 #endif