00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00030 #include "lin_alg.h"
00031
00032
00033
00034
00035
00036 #include <stdexcept>
00037 #include <cmath>
00038 #include "arts.h"
00039 #include "make_vector.h"
00040 #include "array.h"
00041 #include "logic.h"
00042
00044
00052 void
00053 ludcmp(MatrixView LU,
00054 ArrayOfIndex& indx,
00055 ConstMatrixView A)
00056 {
00057 Index imax = 0;
00058 const Numeric TINY=1.0e-20;
00059 Numeric big, dum, sum, temp, d;
00060
00061 LU = A;
00062 const Index dim = A.nrows();
00063 assert(is_size(A,dim,dim));
00064
00065 Vector vv(dim);
00066 d = 1.0;
00067 for (Index i=0; i<dim; i++)
00068 {
00069 indx[i]= i;
00070 big = 0.0;
00071 for (Index j=0; j<dim; j++)
00072 {
00073 if ((temp = abs(LU(i,j))) > big)
00074 big = temp;
00075 }
00076 if (big == 0.)
00077 throw runtime_error("ludcmp: Matrix is singular");
00078 vv[i] = 1.0/big;
00079 }
00080
00081 for (Index j=0; j<dim; j++)
00082 {
00083 for (Index i=0; i<j; i++)
00084 {
00085 sum = LU(i,j);
00086 for (Index k=0; k<i; k++)
00087 sum -= LU(i,k)*LU(k,j);
00088 LU(i,j) = sum;
00089 }
00090 big = 0.0;
00091 for( Index i=j; i<dim; i++)
00092 {
00093 sum = LU(i,j);
00094 for (Index k=0; k<j; k++)
00095 sum -= LU(i,k)*LU(k,j);
00096 LU(i,j) = sum;
00097 if( (dum = vv[i]*fabs(sum)) >= big)
00098 {
00099 big = dum;
00100 imax = i;
00101 }
00102 }
00103 if (j!=imax)
00104 {
00105 for(Index k=0; k<dim; k++)
00106 {
00107 dum = LU(imax,k);
00108 LU(imax,k) = LU(j,k);
00109 LU(j,k) = dum;
00110 }
00111 d = -d;
00112 vv[imax] = vv[j];
00113 indx[j] = imax;
00114 indx[imax] =j;
00115 }
00116
00117 if(LU(j,j) == 0.0) LU(j,j) = TINY;
00118
00119 if (j != dim)
00120 {
00121 dum=1.0/LU(j,j);
00122 for (Index i=j+1; i<dim; i++)
00123 LU(i,j) *=dum;
00124 }
00125 }
00126 }
00127
00128
00129
00130
00131
00133
00143 void
00144 lubacksub(VectorView x,
00145 ConstMatrixView LU,
00146 ConstVectorView b,
00147 const ArrayOfIndex& indx)
00148 {
00149 Index dim = LU.nrows();
00150
00151
00152 assert(is_size(LU, dim, dim));
00153 assert(is_size(b, dim));
00154 assert(is_size(indx, dim));
00155
00156
00157 for(Index i=0; i<dim; i++)
00158 {
00159 x[indx[i]] = b[i];
00160 }
00161
00162 for (Index i=0; i<dim; i++)
00163 {
00164 Numeric sum = x[i];
00165 for (Index j=0; j<=i-1; j++)
00166 sum -= LU(i,j)*x[j];
00167 x[i] = sum;
00168 }
00169
00170 for(Index i=dim-1; i>=0; i--)
00171 {
00172 Numeric sum = x[i];
00173 for (Index j=i+1; j<dim; j++)
00174 sum -= LU(i,j)*x[j];
00175 x[i] = sum/LU(i,i);
00176 }
00177 }
00178
00179
00181
00192 void
00193 matrix_exp(MatrixView F,
00194 ConstMatrixView A,
00195 const Index& q)
00196 {
00197 Numeric A_norm_inf, c;
00198 Numeric j;
00199 const Index n = A.ncols();
00200 Matrix D(n,n), N(n,n), X(n,n), cX(n,n,0.0), B(n,n,0.0);
00201 Vector N_col_vec(n,0.), F_col_vec(n,0.);
00202
00203
00204 assert(is_size(A,n,n));
00205 assert(is_size(F,n,n));
00206
00207 A_norm_inf = norm_inf(A);
00208
00209
00210 j = 1 + floor(1./log(2.)*log(A_norm_inf));
00211
00212 if(j<0) j=0.;
00213 Index j_index = (Index)(j);
00214
00215
00216 F = A;
00217 F /= pow(2,j);
00218
00219
00220
00221
00222 Numeric q_n = (Numeric)(q);
00223 id_mat(D);
00224 id_mat(N);
00225 id_mat(X);
00226 c = 1.;
00227
00228 for(Index k=0; k<q; k++)
00229 {
00230 Numeric k_n = (Numeric)(k+1);
00231 c *= (q_n-k_n+1)/((2*q_n-k_n+1)*k_n);
00232 mult(B,F,X);
00233 X = B;
00234 cX = X;
00235 cX *= c;
00236 N += cX;
00237 cX *= pow(-1,k_n);
00238 D += cX;
00239 }
00240
00241
00242
00243
00244
00245 ArrayOfIndex indx(n);
00246
00247 ludcmp(X, indx, D);
00248
00249 for(Index i=0; i<n; i++)
00250 {
00251 N_col_vec = N(joker,i);
00252 lubacksub(F_col_vec, X, N_col_vec, indx);
00253 F(joker,i) = F_col_vec;
00254 }
00255
00256
00257 for(Index k=0; k<j_index; k++)
00258 {
00259 mult(B,F,F);
00260 F = B;
00261 }
00262
00263 }
00264
00265
00267
00275 Numeric norm_inf(ConstMatrixView A)
00276 {
00277 Numeric norm_inf = 0;
00278
00279 for(Index j=0; j<A.nrows(); j++)
00280 {
00281 Numeric row_sum = 0;
00282
00283 for(Index i=0; i<A.ncols(); i++)
00284 row_sum += abs(A(i,j));
00285
00286 if( norm_inf < row_sum)
00287 norm_inf = row_sum;
00288 }
00289 return norm_inf;
00290 }
00291
00292
00294
00297 void
00298 id_mat(MatrixView I)
00299 {
00300
00301 const Index n = I.ncols();
00302 assert(n == I.nrows());
00303
00304 I = 0;
00305 for(Index i=0; i<n; i++)
00306 I(i,i) = 1.;
00307 }
00308
00309