00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00044 #ifndef lu_mat_CXX
00045 #define lu_mat_CXX "lu_mat.cxx"
00046 static char *lu_mat_template_rcs_id = lu_mat_CXX "$Revision$";
00047 #endif
00048
00049 #ifndef lu_mat_INCLUDED
00050 #include "lu_mat.h"
00051 #endif
00052
00053
00054
00055 #ifndef __GNUC__
00056
00057
00058
00059 extern MEM_POOL LNO_local_pool;
00060
00061 template <class T>
00062 LU_MAT<T>& LU_MAT<T>::operator =(const LU_MAT<T>& a)
00063 {
00064 if (_cpvt_sz < a._cpvt_sz) {
00065 if (_cpvt)
00066 CXX_DELETE_ARRAY(_cpvt, _pool);
00067 _cpvt = CXX_NEW_ARRAY(BOOL, a._cpvt_sz, _pool);
00068 _cpvt_sz = a._cpvt_sz;
00069 }
00070 for (INT i = 0; i < a._cpvt_sz; i++)
00071 _cpvt[i] = a._cpvt[i];
00072
00073 if (_interch_sz < a._interch_sz) {
00074 if (_interch)
00075 CXX_DELETE_ARRAY(_interch, _pool);
00076 _interch = CXX_NEW_ARRAY(mINT32, a._interch_sz, _pool);
00077 _interch_sz = a._interch_sz;
00078 }
00079 for (i = 0; i < a._interch_sz; i++)
00080 _interch[i] = a._interch[i];
00081
00082 _lu = a._lu;
00083
00084 return *this;
00085 }
00086
00087 template<class T>
00088 LU_MAT<T>::LU_MAT(MEM_POOL* pool) :
00089 _pool(pool),
00090 _lu(0,0,pool),
00091 _interch(NULL),
00092 _cpvt(NULL),
00093 _interch_sz(0),
00094 _cpvt_sz(0)
00095 {
00096 }
00097
00098 template<class T>
00099 LU_MAT<T>::LU_MAT(const LU_MAT<T>& a, MEM_POOL* pool) :
00100 _pool(pool),
00101 _lu(0,0,pool),
00102 _interch(NULL),
00103 _cpvt(NULL),
00104 _interch_sz(0),
00105 _cpvt_sz(0)
00106 {
00107 *this = a;
00108 }
00109
00110 template<class T>
00111 LU_MAT<T>::LU_MAT(const LU_MAT<T>& a) :
00112 _pool(a.pool),
00113 _lu(0,0,pool),
00114 _interch(NULL),
00115 _cpvt(NULL),
00116 _interch_sz(0),
00117 _cpvt_sz(0)
00118 {
00119 *this = a;
00120 }
00121
00122
00123 template<class T>
00124 LU_MAT<T>::LU_MAT(const MAT<T>& m, MEM_POOL* pool) :
00125 _pool(pool),
00126 _lu(m.Rows(), 0, pool),
00127 _interch(CXX_NEW_ARRAY(mINT32, m.Rows(), pool)),
00128 _cpvt(CXX_NEW_ARRAY(BOOL, m.Cols(), pool)),
00129 _interch_sz(m.Rows()),
00130 _cpvt_sz(m.Cols())
00131 {
00132 T* tmpc = CXX_NEW_ARRAY(T, m.Rows(), &LNO_local_pool);
00133
00134
00135 for (INT r = 0; r < m.Rows(); r++)
00136 _interch[r] = r;
00137
00138 for (INT c = 0; c < m.Cols(); c++)
00139 _cpvt[c] = FALSE;
00140
00141 for (c = 0; c < m.Cols(); c++) {
00142 for (r = 0; r < m.Rows(); r++)
00143 tmpc[r] = m(r,c);
00144 Cfactor_And_Insert(tmpc, FALSE);
00145 }
00146
00147 CXX_DELETE_ARRAY(tmpc, &LNO_local_pool);
00148 }
00149
00150 template <class T>
00151 BOOL LU_MAT<T>::Particular_Solution(const T* in, T* x) const
00152 {
00153 T* inx = CXX_NEW_ARRAY(T, _lu.Rows(), &LNO_local_pool);
00154 for (INT i = 0; i < _lu.Rows(); i++)
00155 inx[i] = in[i];
00156 L_Mul(inx);
00157 BOOL ok = U_Solve(inx, x) ? TRUE : FALSE;
00158 CXX_DELETE_ARRAY(inx, &LNO_local_pool);
00159 return ok;
00160 }
00161
00162 template<class T>
00163 LU_MAT<T>::~LU_MAT()
00164 {
00165 if (_interch)
00166 CXX_DELETE_ARRAY(_interch, _pool);
00167 if (_cpvt)
00168 CXX_DELETE_ARRAY(_cpvt, _pool);
00169 }
00170
00171 template<class T>
00172 MAT<T> LU_MAT<T>::Inv() const
00173 {
00174 INT n = _lu.Rows();
00175
00176 MAT<T> rval(n, n, 0);
00177
00178 T* tmpc = CXX_NEW_ARRAY(T, n, &LNO_local_pool);
00179 T* tmpr = CXX_NEW_ARRAY(T, n, &LNO_local_pool);
00180
00181 FmtAssert(_lu.Rows() == _lu.Cols(), ("inv(): Matrix is not square"));
00182
00183 for (INT c = 0; c < n; c++)
00184 FmtAssert(_cpvt[c], ("inv(): matrix apparently singular"));
00185
00186 for (INT r = 0; r < n; r++) {
00187 for (INT rr = 0; rr < n; rr++)
00188 tmpc[rr] = T(r == rr);
00189 L_Mul(tmpc);
00190 T* ok = U_Solve(tmpc, tmpr);
00191 FmtAssert(ok, ("LU_MAT<T>::Inv(): U_Solve failed"));
00192 rval.D_Update_Col(r, tmpr);
00193 }
00194
00195 CXX_DELETE_ARRAY(tmpr, &LNO_local_pool);
00196 CXX_DELETE_ARRAY(tmpc, &LNO_local_pool);
00197
00198 return rval;
00199 }
00200
00201 template<class T>
00202 MAT<T> LU_MAT<T>::Unfactor() const
00203 {
00204 MAT<T> l = _lu.L();
00205 MAT<T> u = _lu.U();
00206 INT r = _lu.Rows();
00207
00208 for (INT i = r - 1; i >= 0; i--) {
00209 if(_interch[i] != i) {
00210 Is_True(_interch[i] > i, ("Unfactor problem"));
00211 for (INT j = 0; j < r; j++) {
00212 T tmp = l(i,j);
00213 l(i,j) = l(_interch[i],j);
00214 l(_interch[i],j) = tmp;
00215 }
00216 }
00217 }
00218
00219 return l*u;
00220 }
00221
00222 template<class T>
00223 MAT<T> LU_MAT<T>::TUnfactor() const
00224 {
00225 MAT<T> lut = _lu.Trans();
00226 MAT<T> l = lut.L();
00227 MAT<T> u = lut.U();
00228 INT r = lut.Rows();
00229 INT c = lut.Cols();
00230
00231 for (INT i = r - 1; i >= 0; i--) {
00232 if(_interch[i] != i) {
00233 Is_True(_interch[i] > i, ("Unfactor problem"));
00234 for (INT j = 0; j < r; j++) {
00235 T tmp = l(i,j);
00236 l(i,j) = l(_interch[i],j);
00237 l(_interch[i],j) = tmp;
00238 }
00239 }
00240 }
00241
00242 return l*u;
00243 }
00244
00245
00246
00247 template<class T>
00248 T* LU_MAT<T>::U_Solve(const T* in, T* out, INT free) const
00249 {
00250 INT rows = _lu.Rows();
00251 INT cols = _lu.Cols();
00252
00253 INT zrow = 0;
00254 for (INT c = 0; c < cols; c++)
00255 zrow += _cpvt[c];
00256
00257 for (INT r = zrow; r < rows; r++)
00258 if (in[r] != T(0))
00259 return NULL;
00260
00261
00262
00263 r = zrow - 1;
00264 for (c = cols-1; c >= 0; c--) {
00265 if (_cpvt[c]) {
00266 T t = in[r];
00267 for (INT cc = c+1; cc < cols; cc++)
00268 t -= _lu(r,cc) * out[cc];
00269 out[c] = t/_lu(r,c);
00270 r--;
00271 }
00272 else {
00273 out[c] = T(c == free);
00274 }
00275 }
00276
00277 return out;
00278 }
00279
00280 template<class T>
00281 void LU_MAT<T>::L_Mul(T* f) const
00282 {
00283 INT rows = _lu.Rows();
00284 INT cols = _lu.Cols();
00285
00286
00287
00288 for (INT r = 0; r < rows; r++) {
00289 INT rr = _interch[r];
00290 if (r != rr) {
00291 T t = f[rr];
00292 f[rr] = f[r];
00293 f[r] = t;
00294 }
00295 }
00296
00297
00298
00299 for (INT c = 0; c < cols; c++)
00300 for (r = c+1; r < rows; r++)
00301 f[r] -= f[c] * _lu(r,c);
00302 }
00303
00304 template<class T>
00305 INT LU_MAT<T>::Cfactor(T* col, INT rpvt) const
00306 {
00307 INT nrpvt;
00308
00309 INT rows = _lu.Rows();
00310 INT cols = _lu.Cols();
00311
00312 L_Mul(col);
00313
00314 if (rpvt == rows)
00315 return rows;
00316
00317 if (Exact_Arithmetic()) {
00318
00319 for (nrpvt = rpvt; nrpvt < rows; nrpvt++)
00320 if (col[nrpvt] != T(0))
00321 break;
00322 if (nrpvt == rows)
00323 nrpvt = rpvt;
00324 }
00325 else {
00326
00327 T mx = T(0);
00328 INT imx = -1;
00329 for (nrpvt = rpvt; nrpvt < rows; nrpvt++) {
00330 T x = col[nrpvt] < 0 ? -col[nrpvt] : col[nrpvt];
00331 if (x > mx) {
00332 mx = x;
00333 imx = nrpvt;
00334 }
00335 }
00336 if (imx == -1)
00337 nrpvt = rpvt;
00338 else
00339 nrpvt = imx;
00340 }
00341
00342 if (nrpvt != rpvt) {
00343 T t = col[rpvt];
00344 col[rpvt] = col[nrpvt];
00345 col[nrpvt] = t;
00346 }
00347
00348 if (col[rpvt] != T(0)) {
00349 for (INT r = rpvt+1; r < rows; r++)
00350 col[r] /= col[rpvt];
00351 }
00352
00353 return nrpvt;
00354 }
00355
00356 template<class T>
00357 BOOL LU_MAT<T>::Cfactor_And_Insert(T* w, INT insert_only_nonzero_piv)
00358 {
00359 INT c = _lu.Cols();
00360 INT r = _lu.Rows();
00361 INT curpivrow = 0;
00362
00363 for (INT i = 0; i < c; i++)
00364 curpivrow += Is_Pivot(i);
00365 if(curpivrow == r && insert_only_nonzero_piv) {
00366 return FALSE;
00367 }
00368
00369 Is_True(curpivrow <= r, ("Cfactor_And_Insert: %d <= %d", curpivrow, r));
00370 INT rrr = Cfactor(w, curpivrow);
00371
00372 Is_True((curpivrow <= rrr && rrr < r) || (rrr == r && curpivrow == rrr),
00373 ("Problem in Cfactor_And_Insert"));
00374
00375 if (insert_only_nonzero_piv && w[curpivrow] == T(0)) {
00376 return FALSE;
00377 }
00378
00379 if(curpivrow < r) {
00380 _interch[curpivrow] = rrr;
00381 if(rrr != curpivrow)
00382 _lu.D_Swap_Rows(rrr, curpivrow);
00383 if (_cpvt_sz <= c) {
00384 BOOL* newpivots = CXX_NEW_ARRAY(BOOL, c+2, _pool);
00385 _cpvt_sz = c+2;
00386 for (INT i = 0; i < c; i++)
00387 newpivots[i] = _cpvt[i];
00388 CXX_DELETE_ARRAY(_cpvt, _pool);
00389 _cpvt = newpivots;
00390 }
00391 _cpvt[c] = w[curpivrow] != 0;
00392 }
00393 else
00394 _cpvt[c] = FALSE;
00395
00396
00397 if (curpivrow == c) {
00398 _lu.D_Add_Col(w);
00399 } else {
00400 for (INT i = curpivrow + 1; i < r; i++)
00401 _lu(i,curpivrow) = w[i];
00402 for (i = curpivrow + 1; i < r; i++)
00403 w[i] = T(0);
00404 _lu.D_Add_Col(w);
00405 }
00406
00407 return TRUE;
00408 }
00409
00410 template<class T>
00411 void LU_MAT<T>::Print(FILE*f) const
00412 {
00413 fprintf(f, "LU matrix output (%d x %d)\n", _lu.Rows(), _lu.Cols());
00414 _lu.Print(f);
00415
00416 fprintf(f, "interchange vector:");
00417 for (INT r = 0; r < _lu.Rows(); r++)
00418 fprintf(f, " %d", _interch[r]);
00419
00420 fprintf(f, " column pivots: ");
00421 for (INT c = 0; c < _lu.Cols(); c++)
00422 fprintf(f, "%s", _cpvt[c] ? "T" : "F");
00423 fprintf(f, "\n");
00424 }
00425
00426 #endif
00427