MOOS 0.2375
|
00001 //$$ newmat8.cpp Advanced LU transform, scalar functions 00002 00003 // Copyright (C) 1991,2,3,4,8: R B Davies 00004 00005 #define WANT_MATH 00006 00007 #include "include.h" 00008 00009 #include "newmat.h" 00010 #include "newmatrc.h" 00011 #include "precisio.h" 00012 00013 #ifdef use_namespace 00014 namespace NEWMAT { 00015 #endif 00016 00017 00018 #ifdef DO_REPORT 00019 #define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; } 00020 #else 00021 #define REPORT {} 00022 #endif 00023 00024 00025 /************************** LU transformation ****************************/ 00026 00027 void CroutMatrix::ludcmp() 00028 // LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer 00029 // product" version). 00030 // This replaces the code derived from Numerical Recipes in C in previous 00031 // versions of newmat and being row oriented runs much faster with large 00032 // matrices. 00033 { 00034 REPORT 00035 Tracer trace( "Crout(ludcmp)" ); sing = false; 00036 Real* akk = store; // runs down diagonal 00037 00038 Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k; 00039 00040 for (k = 1; k < nrows; k++) 00041 { 00042 ai += nrows; const Real trybig = fabs(*ai); 00043 if (big < trybig) { big = trybig; mu = k; } 00044 } 00045 00046 00047 if (nrows) for (k = 0;;) 00048 { 00049 /* 00050 int mu1; 00051 { 00052 Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i; 00053 00054 for (i = k+1; i < nrows; i++) 00055 { 00056 ai += nrows; const Real trybig = fabs(*ai); 00057 if (big < trybig) { big = trybig; mu1 = i; } 00058 } 00059 } 00060 if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl; 00061 */ 00062 00063 indx[k] = mu; 00064 00065 if (mu != k) //row swap 00066 { 00067 Real* a1 = store + nrows * k; Real* a2 = store + nrows * mu; d = !d; 00068 int j = nrows; 00069 while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; } 00070 } 00071 00072 Real diag = *akk; big = 0; mu = k + 1; 00073 if (diag != 0) 00074 { 00075 ai = akk; int i = nrows - k - 1; 00076 while (i--) 00077 { 00078 ai += nrows; Real* al = ai; Real mult = *al / diag; *al = mult; 00079 int l = nrows - k - 1; Real* aj = akk; 00080 // work out the next pivot as part of this loop 00081 // this saves a column operation 00082 if (l-- != 0) 00083 { 00084 *(++al) -= (mult * *(++aj)); 00085 const Real trybig = fabs(*al); 00086 if (big < trybig) { big = trybig; mu = nrows - i - 1; } 00087 while (l--) *(++al) -= (mult * *(++aj)); 00088 } 00089 } 00090 } 00091 else sing = true; 00092 if (++k == nrows) break; // so next line won't overflow 00093 akk += nrows + 1; 00094 } 00095 } 00096 00097 void CroutMatrix::lubksb(Real* B, int mini) 00098 { 00099 REPORT 00100 // this has been adapted from Numerical Recipes in C. The code has been 00101 // substantially streamlined, so I do not think much of the original 00102 // copyright remains. However there is not much opportunity for 00103 // variation in the code, so it is still similar to the NR code. 00104 // I follow the NR code in skipping over initial zeros in the B vector. 00105 00106 Tracer trace("Crout(lubksb)"); 00107 if (sing) Throw(SingularException(*this)); 00108 int i, j, ii = nrows; // ii initialised : B might be all zeros 00109 00110 00111 // scan for first non-zero in B 00112 for (i = 0; i < nrows; i++) 00113 { 00114 int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp; 00115 if (temp != 0.0) { ii = i; break; } 00116 } 00117 00118 Real* bi; Real* ai; 00119 i = ii + 1; 00120 00121 if (i < nrows) 00122 { 00123 bi = B + ii; ai = store + ii + i * nrows; 00124 for (;;) 00125 { 00126 int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i]; 00127 Real* aij = ai; Real* bj = bi; j = i - ii; 00128 while (j--) sum -= *aij++ * *bj++; 00129 B[i] = sum; 00130 if (++i == nrows) break; 00131 ai += nrows; 00132 } 00133 } 00134 00135 ai = store + nrows * nrows; 00136 00137 for (i = nrows - 1; i >= mini; i--) 00138 { 00139 Real* bj = B+i; ai -= nrows; Real* ajx = ai+i; 00140 Real sum = *bj; Real diag = *ajx; 00141 j = nrows - i; while(--j) sum -= *(++ajx) * *(++bj); 00142 B[i] = sum / diag; 00143 } 00144 } 00145 00146 /****************************** scalar functions ****************************/ 00147 00148 inline Real square(Real x) { return x*x; } 00149 00150 Real GeneralMatrix::SumSquare() const 00151 { 00152 REPORT 00153 Real sum = 0.0; int i = storage; Real* s = store; 00154 while (i--) sum += square(*s++); 00155 ((GeneralMatrix&)*this).tDelete(); return sum; 00156 } 00157 00158 Real GeneralMatrix::SumAbsoluteValue() const 00159 { 00160 REPORT 00161 Real sum = 0.0; int i = storage; Real* s = store; 00162 while (i--) sum += fabs(*s++); 00163 ((GeneralMatrix&)*this).tDelete(); return sum; 00164 } 00165 00166 Real GeneralMatrix::Sum() const 00167 { 00168 REPORT 00169 Real sum = 0.0; int i = storage; Real* s = store; 00170 while (i--) sum += *s++; 00171 ((GeneralMatrix&)*this).tDelete(); return sum; 00172 } 00173 00174 // maxima and minima 00175 00176 // There are three sets of routines 00177 // MaximumAbsoluteValue, MinimumAbsoluteValue, Maximum, Minimum 00178 // ... these find just the maxima and minima 00179 // MaximumAbsoluteValue1, MinimumAbsoluteValue1, Maximum1, Minimum1 00180 // ... these find the maxima and minima and their locations in a 00181 // one dimensional object 00182 // MaximumAbsoluteValue2, MinimumAbsoluteValue2, Maximum2, Minimum2 00183 // ... these find the maxima and minima and their locations in a 00184 // two dimensional object 00185 00186 // If the matrix has no values throw an exception 00187 00188 // If we do not want the location find the maximum or minimum on the 00189 // array stored by GeneralMatrix 00190 // This won't work for BandMatrices. We call ClearCorner for 00191 // MaximumAbsoluteValue but for the others use the AbsoluteMinimumValue2 00192 // version and discard the location. 00193 00194 // For one dimensional objects, when we want the location of the 00195 // maximum or minimum, work with the array stored by GeneralMatrix 00196 00197 // For two dimensional objects where we want the location of the maximum or 00198 // minimum proceed as follows: 00199 00200 // For rectangular matrices use the array stored by GeneralMatrix and 00201 // deduce the location from the location in the GeneralMatrix 00202 00203 // For other two dimensional matrices use the Matrix Row routine to find the 00204 // maximum or minimum for each row. 00205 00206 static void NullMatrixError(const GeneralMatrix* gm) 00207 { 00208 ((GeneralMatrix&)*gm).tDelete(); 00209 Throw(ProgramException("Maximum or minimum of null matrix")); 00210 } 00211 00212 Real GeneralMatrix::MaximumAbsoluteValue() const 00213 { 00214 REPORT 00215 if (storage == 0) NullMatrixError(this); 00216 Real maxval = 0.0; int l = storage; Real* s = store; 00217 while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; } 00218 ((GeneralMatrix&)*this).tDelete(); return maxval; 00219 } 00220 00221 Real GeneralMatrix::MaximumAbsoluteValue1(int& i) const 00222 { 00223 REPORT 00224 if (storage == 0) NullMatrixError(this); 00225 Real maxval = 0.0; int l = storage; Real* s = store; int li = storage; 00226 while (l--) 00227 { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; } } 00228 i = storage - li; 00229 ((GeneralMatrix&)*this).tDelete(); return maxval; 00230 } 00231 00232 Real GeneralMatrix::MinimumAbsoluteValue() const 00233 { 00234 REPORT 00235 if (storage == 0) NullMatrixError(this); 00236 int l = storage - 1; Real* s = store; Real minval = fabs(*s++); 00237 while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; } 00238 ((GeneralMatrix&)*this).tDelete(); return minval; 00239 } 00240 00241 Real GeneralMatrix::MinimumAbsoluteValue1(int& i) const 00242 { 00243 REPORT 00244 if (storage == 0) NullMatrixError(this); 00245 int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l; 00246 while (l--) 00247 { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; } } 00248 i = storage - li; 00249 ((GeneralMatrix&)*this).tDelete(); return minval; 00250 } 00251 00252 Real GeneralMatrix::Maximum() const 00253 { 00254 REPORT 00255 if (storage == 0) NullMatrixError(this); 00256 int l = storage - 1; Real* s = store; Real maxval = *s++; 00257 while (l--) { Real a = *s++; if (maxval < a) maxval = a; } 00258 ((GeneralMatrix&)*this).tDelete(); return maxval; 00259 } 00260 00261 Real GeneralMatrix::Maximum1(int& i) const 00262 { 00263 REPORT 00264 if (storage == 0) NullMatrixError(this); 00265 int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l; 00266 while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } } 00267 i = storage - li; 00268 ((GeneralMatrix&)*this).tDelete(); return maxval; 00269 } 00270 00271 Real GeneralMatrix::Minimum() const 00272 { 00273 REPORT 00274 if (storage == 0) NullMatrixError(this); 00275 int l = storage - 1; Real* s = store; Real minval = *s++; 00276 while (l--) { Real a = *s++; if (minval > a) minval = a; } 00277 ((GeneralMatrix&)*this).tDelete(); return minval; 00278 } 00279 00280 Real GeneralMatrix::Minimum1(int& i) const 00281 { 00282 REPORT 00283 if (storage == 0) NullMatrixError(this); 00284 int l = storage - 1; Real* s = store; Real minval = *s++; int li = l; 00285 while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } } 00286 i = storage - li; 00287 ((GeneralMatrix&)*this).tDelete(); return minval; 00288 } 00289 00290 Real GeneralMatrix::MaximumAbsoluteValue2(int& i, int& j) const 00291 { 00292 REPORT 00293 if (storage == 0) NullMatrixError(this); 00294 Real maxval = 0.0; int nr = Nrows(); 00295 MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); 00296 for (int r = 1; r <= nr; r++) 00297 { 00298 int c; maxval = mr.MaximumAbsoluteValue1(maxval, c); 00299 if (c > 0) { i = r; j = c; } 00300 mr.Next(); 00301 } 00302 ((GeneralMatrix&)*this).tDelete(); return maxval; 00303 } 00304 00305 Real GeneralMatrix::MinimumAbsoluteValue2(int& i, int& j) const 00306 { 00307 REPORT 00308 if (storage == 0) NullMatrixError(this); 00309 Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); 00310 MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); 00311 for (int r = 1; r <= nr; r++) 00312 { 00313 int c; minval = mr.MinimumAbsoluteValue1(minval, c); 00314 if (c > 0) { i = r; j = c; } 00315 mr.Next(); 00316 } 00317 ((GeneralMatrix&)*this).tDelete(); return minval; 00318 } 00319 00320 Real GeneralMatrix::Maximum2(int& i, int& j) const 00321 { 00322 REPORT 00323 if (storage == 0) NullMatrixError(this); 00324 Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows(); 00325 MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); 00326 for (int r = 1; r <= nr; r++) 00327 { 00328 int c; maxval = mr.Maximum1(maxval, c); 00329 if (c > 0) { i = r; j = c; } 00330 mr.Next(); 00331 } 00332 ((GeneralMatrix&)*this).tDelete(); return maxval; 00333 } 00334 00335 Real GeneralMatrix::Minimum2(int& i, int& j) const 00336 { 00337 REPORT 00338 if (storage == 0) NullMatrixError(this); 00339 Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); 00340 MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); 00341 for (int r = 1; r <= nr; r++) 00342 { 00343 int c; minval = mr.Minimum1(minval, c); 00344 if (c > 0) { i = r; j = c; } 00345 mr.Next(); 00346 } 00347 ((GeneralMatrix&)*this).tDelete(); return minval; 00348 } 00349 00350 Real Matrix::MaximumAbsoluteValue2(int& i, int& j) const 00351 { 00352 REPORT 00353 int k; Real m = GeneralMatrix::MaximumAbsoluteValue1(k); k--; 00354 i = k / Ncols(); j = k - i * Ncols(); i++; j++; 00355 return m; 00356 } 00357 00358 Real Matrix::MinimumAbsoluteValue2(int& i, int& j) const 00359 { 00360 REPORT 00361 int k; Real m = GeneralMatrix::MinimumAbsoluteValue1(k); k--; 00362 i = k / Ncols(); j = k - i * Ncols(); i++; j++; 00363 return m; 00364 } 00365 00366 Real Matrix::Maximum2(int& i, int& j) const 00367 { 00368 REPORT 00369 int k; Real m = GeneralMatrix::Maximum1(k); k--; 00370 i = k / Ncols(); j = k - i * Ncols(); i++; j++; 00371 return m; 00372 } 00373 00374 Real Matrix::Minimum2(int& i, int& j) const 00375 { 00376 REPORT 00377 int k; Real m = GeneralMatrix::Minimum1(k); k--; 00378 i = k / Ncols(); j = k - i * Ncols(); i++; j++; 00379 return m; 00380 } 00381 00382 Real SymmetricMatrix::SumSquare() const 00383 { 00384 REPORT 00385 Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; 00386 for (int i = 0; i<nr; i++) 00387 { 00388 int j = i; 00389 while (j--) sum2 += square(*s++); 00390 sum1 += square(*s++); 00391 } 00392 ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; 00393 } 00394 00395 Real SymmetricMatrix::SumAbsoluteValue() const 00396 { 00397 REPORT 00398 Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; 00399 for (int i = 0; i<nr; i++) 00400 { 00401 int j = i; 00402 while (j--) sum2 += fabs(*s++); 00403 sum1 += fabs(*s++); 00404 } 00405 ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; 00406 } 00407 00408 Real IdentityMatrix::SumAbsoluteValue() const 00409 { REPORT return fabs(Trace()); } // no need to do tDelete? 00410 00411 Real SymmetricMatrix::Sum() const 00412 { 00413 REPORT 00414 Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; 00415 for (int i = 0; i<nr; i++) 00416 { 00417 int j = i; 00418 while (j--) sum2 += *s++; 00419 sum1 += *s++; 00420 } 00421 ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; 00422 } 00423 00424 Real IdentityMatrix::SumSquare() const 00425 { 00426 Real sum = *store * *store * nrows; 00427 ((GeneralMatrix&)*this).tDelete(); return sum; 00428 } 00429 00430 00431 Real BaseMatrix::SumSquare() const 00432 { 00433 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00434 Real s = gm->SumSquare(); return s; 00435 } 00436 00437 Real BaseMatrix::NormFrobenius() const 00438 { REPORT return sqrt(SumSquare()); } 00439 00440 Real BaseMatrix::SumAbsoluteValue() const 00441 { 00442 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00443 Real s = gm->SumAbsoluteValue(); return s; 00444 } 00445 00446 Real BaseMatrix::Sum() const 00447 { 00448 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00449 Real s = gm->Sum(); return s; 00450 } 00451 00452 Real BaseMatrix::MaximumAbsoluteValue() const 00453 { 00454 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00455 Real s = gm->MaximumAbsoluteValue(); return s; 00456 } 00457 00458 Real BaseMatrix::MaximumAbsoluteValue1(int& i) const 00459 { 00460 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00461 Real s = gm->MaximumAbsoluteValue1(i); return s; 00462 } 00463 00464 Real BaseMatrix::MaximumAbsoluteValue2(int& i, int& j) const 00465 { 00466 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00467 Real s = gm->MaximumAbsoluteValue2(i, j); return s; 00468 } 00469 00470 Real BaseMatrix::MinimumAbsoluteValue() const 00471 { 00472 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00473 Real s = gm->MinimumAbsoluteValue(); return s; 00474 } 00475 00476 Real BaseMatrix::MinimumAbsoluteValue1(int& i) const 00477 { 00478 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00479 Real s = gm->MinimumAbsoluteValue1(i); return s; 00480 } 00481 00482 Real BaseMatrix::MinimumAbsoluteValue2(int& i, int& j) const 00483 { 00484 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00485 Real s = gm->MinimumAbsoluteValue2(i, j); return s; 00486 } 00487 00488 Real BaseMatrix::Maximum() const 00489 { 00490 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00491 Real s = gm->Maximum(); return s; 00492 } 00493 00494 Real BaseMatrix::Maximum1(int& i) const 00495 { 00496 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00497 Real s = gm->Maximum1(i); return s; 00498 } 00499 00500 Real BaseMatrix::Maximum2(int& i, int& j) const 00501 { 00502 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00503 Real s = gm->Maximum2(i, j); return s; 00504 } 00505 00506 Real BaseMatrix::Minimum() const 00507 { 00508 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00509 Real s = gm->Minimum(); return s; 00510 } 00511 00512 Real BaseMatrix::Minimum1(int& i) const 00513 { 00514 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00515 Real s = gm->Minimum1(i); return s; 00516 } 00517 00518 Real BaseMatrix::Minimum2(int& i, int& j) const 00519 { 00520 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00521 Real s = gm->Minimum2(i, j); return s; 00522 } 00523 00524 Real DotProduct(const Matrix& A, const Matrix& B) 00525 { 00526 REPORT 00527 int n = A.storage; 00528 if (n != B.storage) Throw(IncompatibleDimensionsException(A,B)); 00529 Real sum = 0.0; Real* a = A.store; Real* b = B.store; 00530 while (n--) sum += *a++ * *b++; 00531 return sum; 00532 } 00533 00534 Real Matrix::Trace() const 00535 { 00536 REPORT 00537 Tracer trace("Trace"); 00538 int i = nrows; int d = i+1; 00539 if (i != ncols) Throw(NotSquareException(*this)); 00540 Real sum = 0.0; Real* s = store; 00541 // while (i--) { sum += *s; s += d; } 00542 if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; } 00543 ((GeneralMatrix&)*this).tDelete(); return sum; 00544 } 00545 00546 Real DiagonalMatrix::Trace() const 00547 { 00548 REPORT 00549 int i = nrows; Real sum = 0.0; Real* s = store; 00550 while (i--) sum += *s++; 00551 ((GeneralMatrix&)*this).tDelete(); return sum; 00552 } 00553 00554 Real SymmetricMatrix::Trace() const 00555 { 00556 REPORT 00557 int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; 00558 // while (i--) { sum += *s; s += j++; } 00559 if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } 00560 ((GeneralMatrix&)*this).tDelete(); return sum; 00561 } 00562 00563 Real LowerTriangularMatrix::Trace() const 00564 { 00565 REPORT 00566 int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; 00567 // while (i--) { sum += *s; s += j++; } 00568 if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } 00569 ((GeneralMatrix&)*this).tDelete(); return sum; 00570 } 00571 00572 Real UpperTriangularMatrix::Trace() const 00573 { 00574 REPORT 00575 int i = nrows; Real sum = 0.0; Real* s = store; 00576 while (i) { sum += *s; s += i--; } // won t cause a problem 00577 ((GeneralMatrix&)*this).tDelete(); return sum; 00578 } 00579 00580 Real BandMatrix::Trace() const 00581 { 00582 REPORT 00583 int i = nrows; int w = lower+upper+1; 00584 Real sum = 0.0; Real* s = store+lower; 00585 // while (i--) { sum += *s; s += w; } 00586 if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } 00587 ((GeneralMatrix&)*this).tDelete(); return sum; 00588 } 00589 00590 Real SymmetricBandMatrix::Trace() const 00591 { 00592 REPORT 00593 int i = nrows; int w = lower+1; 00594 Real sum = 0.0; Real* s = store+lower; 00595 // while (i--) { sum += *s; s += w; } 00596 if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } 00597 ((GeneralMatrix&)*this).tDelete(); return sum; 00598 } 00599 00600 Real IdentityMatrix::Trace() const 00601 { 00602 Real sum = *store * nrows; 00603 ((GeneralMatrix&)*this).tDelete(); return sum; 00604 } 00605 00606 00607 Real BaseMatrix::Trace() const 00608 { 00609 REPORT 00610 MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK(); 00611 GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag); 00612 Real sum = gm->Trace(); return sum; 00613 } 00614 00615 void LogAndSign::operator*=(Real x) 00616 { 00617 if (x > 0.0) { log_value += log(x); } 00618 else if (x < 0.0) { log_value += log(-x); sign = -sign; } 00619 else sign = 0; 00620 } 00621 00622 void LogAndSign::PowEq(int k) 00623 { 00624 if (sign) 00625 { 00626 log_value *= k; 00627 if ( (k & 1) == 0 ) sign = 1; 00628 } 00629 } 00630 00631 Real LogAndSign::Value() const 00632 { 00633 Tracer et("LogAndSign::Value"); 00634 if (log_value >= FloatingPointPrecision::LnMaximum()) 00635 Throw(OverflowException("Overflow in exponential")); 00636 return sign * exp(log_value); 00637 } 00638 00639 LogAndSign::LogAndSign(Real f) 00640 { 00641 if (f == 0.0) { log_value = 0.0; sign = 0; return; } 00642 else if (f < 0.0) { sign = -1; f = -f; } 00643 else sign = 1; 00644 log_value = log(f); 00645 } 00646 00647 LogAndSign DiagonalMatrix::LogDeterminant() const 00648 { 00649 REPORT 00650 int i = nrows; LogAndSign sum; Real* s = store; 00651 while (i--) sum *= *s++; 00652 ((GeneralMatrix&)*this).tDelete(); return sum; 00653 } 00654 00655 LogAndSign LowerTriangularMatrix::LogDeterminant() const 00656 { 00657 REPORT 00658 int i = nrows; LogAndSign sum; Real* s = store; int j = 2; 00659 // while (i--) { sum *= *s; s += j++; } 00660 if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; } 00661 ((GeneralMatrix&)*this).tDelete(); return sum; 00662 } 00663 00664 LogAndSign UpperTriangularMatrix::LogDeterminant() const 00665 { 00666 REPORT 00667 int i = nrows; LogAndSign sum; Real* s = store; 00668 while (i) { sum *= *s; s += i--; } 00669 ((GeneralMatrix&)*this).tDelete(); return sum; 00670 } 00671 00672 LogAndSign IdentityMatrix::LogDeterminant() const 00673 { 00674 REPORT 00675 int i = nrows; LogAndSign sum; 00676 if (i > 0) { sum = *store; sum.PowEq(i); } 00677 ((GeneralMatrix&)*this).tDelete(); return sum; 00678 } 00679 00680 LogAndSign BaseMatrix::LogDeterminant() const 00681 { 00682 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00683 LogAndSign sum = gm->LogDeterminant(); return sum; 00684 } 00685 00686 LogAndSign GeneralMatrix::LogDeterminant() const 00687 { 00688 REPORT 00689 Tracer tr("LogDeterminant"); 00690 if (nrows != ncols) Throw(NotSquareException(*this)); 00691 CroutMatrix C(*this); return C.LogDeterminant(); 00692 } 00693 00694 LogAndSign CroutMatrix::LogDeterminant() const 00695 { 00696 REPORT 00697 if (sing) return 0.0; 00698 int i = nrows; int dd = i+1; LogAndSign sum; Real* s = store; 00699 if (i) for(;;) 00700 { 00701 sum *= *s; 00702 if (!(--i)) break; 00703 s += dd; 00704 } 00705 if (!d) sum.ChangeSign(); return sum; 00706 00707 } 00708 00709 Real BaseMatrix::Determinant() const 00710 { 00711 REPORT 00712 Tracer tr("Determinant"); 00713 REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); 00714 LogAndSign ld = gm->LogDeterminant(); 00715 return ld.Value(); 00716 } 00717 00718 00719 00720 00721 00722 LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm) 00723 : gm( ( ((BaseMatrix&)bm).Evaluate() )->MakeSolver() ) 00724 { 00725 if (gm==&bm) { REPORT gm = gm->Image(); } 00726 // want a copy if *gm is actually bm 00727 else { REPORT gm->Protect(); } 00728 } 00729 00730 00731 #ifdef use_namespace 00732 } 00733 #endif 00734