Homepage Demos Overview Downloads Tutorials Reference
Credits

newmat8.cpp

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

newmat11b
Generated Tue Oct 19 14:18:14 2004 by Doxygen 1.3.9.1