| 1 | //$$ newmat8.cpp         Advanced LU transform, scalar functions | 
|---|
| 2 |  | 
|---|
| 3 | // Copyright (C) 1991,2,3,4,8: R B Davies | 
|---|
| 4 |  | 
|---|
| 5 | #define WANT_MATH | 
|---|
| 6 |  | 
|---|
| 7 | #include "include.h" | 
|---|
| 8 |  | 
|---|
| 9 | #include "newmat.h" | 
|---|
| 10 | #include "newmatrc.h" | 
|---|
| 11 | #include "precisio.h" | 
|---|
| 12 |  | 
|---|
| 13 | #ifdef use_namespace | 
|---|
| 14 | namespace NEWMAT { | 
|---|
| 15 | #endif | 
|---|
| 16 |  | 
|---|
| 17 |  | 
|---|
| 18 | #ifdef DO_REPORT | 
|---|
| 19 | #define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; } | 
|---|
| 20 | #else | 
|---|
| 21 | #define REPORT {} | 
|---|
| 22 | #endif | 
|---|
| 23 |  | 
|---|
| 24 |  | 
|---|
| 25 | /************************** LU transformation ****************************/ | 
|---|
| 26 |  | 
|---|
| 27 | void CroutMatrix::ludcmp() | 
|---|
| 28 | // LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer | 
|---|
| 29 | // product" version). | 
|---|
| 30 | // This replaces the code derived from Numerical Recipes in C in previous | 
|---|
| 31 | // versions of newmat and being row oriented runs much faster with large | 
|---|
| 32 | // matrices. | 
|---|
| 33 | { | 
|---|
| 34 |    REPORT | 
|---|
| 35 |    Tracer trace( "Crout(ludcmp)" ); sing = false; | 
|---|
| 36 |    Real* akk = store;                    // runs down diagonal | 
|---|
| 37 |  | 
|---|
| 38 |    Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k; | 
|---|
| 39 |  | 
|---|
| 40 |    for (k = 1; k < nrows; k++) | 
|---|
| 41 |    { | 
|---|
| 42 |       ai += nrows; const Real trybig = fabs(*ai); | 
|---|
| 43 |       if (big < trybig) { big = trybig; mu = k; } | 
|---|
| 44 |    } | 
|---|
| 45 |  | 
|---|
| 46 |  | 
|---|
| 47 |    if (nrows) for (k = 0;;) | 
|---|
| 48 |    { | 
|---|
| 49 |       /* | 
|---|
| 50 |       int mu1; | 
|---|
| 51 |       { | 
|---|
| 52 |          Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i; | 
|---|
| 53 |  | 
|---|
| 54 |          for (i = k+1; i < nrows; i++) | 
|---|
| 55 |          { | 
|---|
| 56 |             ai += nrows; const Real trybig = fabs(*ai); | 
|---|
| 57 |             if (big < trybig) { big = trybig; mu1 = i; } | 
|---|
| 58 |          } | 
|---|
| 59 |       } | 
|---|
| 60 |       if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl; | 
|---|
| 61 |       */ | 
|---|
| 62 |  | 
|---|
| 63 |       indx[k] = mu; | 
|---|
| 64 |  | 
|---|
| 65 |       if (mu != k)                       //row swap | 
|---|
| 66 |       { | 
|---|
| 67 |          Real* a1 = store + nrows * k; Real* a2 = store + nrows * mu; d = !d; | 
|---|
| 68 |          int j = nrows; | 
|---|
| 69 |          while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; } | 
|---|
| 70 |       } | 
|---|
| 71 |  | 
|---|
| 72 |       Real diag = *akk; big = 0; mu = k + 1; | 
|---|
| 73 |       if (diag != 0) | 
|---|
| 74 |       { | 
|---|
| 75 |          ai = akk; int i = nrows - k - 1; | 
|---|
| 76 |          while (i--) | 
|---|
| 77 |          { | 
|---|
| 78 |             ai += nrows; Real* al = ai; Real mult = *al / diag; *al = mult; | 
|---|
| 79 |             int l = nrows - k - 1; Real* aj = akk; | 
|---|
| 80 |             // work out the next pivot as part of this loop | 
|---|
| 81 |             // this saves a column operation | 
|---|
| 82 |             if (l-- != 0) | 
|---|
| 83 |             { | 
|---|
| 84 |                *(++al) -= (mult * *(++aj)); | 
|---|
| 85 |                const Real trybig = fabs(*al); | 
|---|
| 86 |                if (big < trybig) { big = trybig; mu = nrows - i - 1; } | 
|---|
| 87 |                while (l--) *(++al) -= (mult * *(++aj)); | 
|---|
| 88 |             } | 
|---|
| 89 |          } | 
|---|
| 90 |       } | 
|---|
| 91 |       else sing = true; | 
|---|
| 92 |       if (++k == nrows) break;          // so next line won't overflow | 
|---|
| 93 |       akk += nrows + 1; | 
|---|
| 94 |    } | 
|---|
| 95 | } | 
|---|
| 96 |  | 
|---|
| 97 | void CroutMatrix::lubksb(Real* B, int mini) | 
|---|
| 98 | { | 
|---|
| 99 |    REPORT | 
|---|
| 100 |    // this has been adapted from Numerical Recipes in C. The code has been | 
|---|
| 101 |    // substantially streamlined, so I do not think much of the original | 
|---|
| 102 |    // copyright remains. However there is not much opportunity for | 
|---|
| 103 |    // variation in the code, so it is still similar to the NR code. | 
|---|
| 104 |    // I follow the NR code in skipping over initial zeros in the B vector. | 
|---|
| 105 |  | 
|---|
| 106 |    Tracer trace("Crout(lubksb)"); | 
|---|
| 107 |    if (sing) Throw(SingularException(*this)); | 
|---|
| 108 |    int i, j, ii = nrows;            // ii initialised : B might be all zeros | 
|---|
| 109 |  | 
|---|
| 110 |  | 
|---|
| 111 |    // scan for first non-zero in B | 
|---|
| 112 |    for (i = 0; i < nrows; i++) | 
|---|
| 113 |    { | 
|---|
| 114 |       int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp; | 
|---|
| 115 |       if (temp != 0.0) { ii = i; break; } | 
|---|
| 116 |    } | 
|---|
| 117 |  | 
|---|
| 118 |    Real* bi; Real* ai; | 
|---|
| 119 |    i = ii + 1; | 
|---|
| 120 |  | 
|---|
| 121 |    if (i < nrows) | 
|---|
| 122 |    { | 
|---|
| 123 |       bi = B + ii; ai = store + ii + i * nrows; | 
|---|
| 124 |       for (;;) | 
|---|
| 125 |       { | 
|---|
| 126 |          int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i]; | 
|---|
| 127 |          Real* aij = ai; Real* bj = bi; j = i - ii; | 
|---|
| 128 |          while (j--) sum -= *aij++ * *bj++; | 
|---|
| 129 |          B[i] = sum; | 
|---|
| 130 |          if (++i == nrows) break; | 
|---|
| 131 |          ai += nrows; | 
|---|
| 132 |       } | 
|---|
| 133 |    } | 
|---|
| 134 |  | 
|---|
| 135 |    ai = store + nrows * nrows; | 
|---|
| 136 |  | 
|---|
| 137 |    for (i = nrows - 1; i >= mini; i--) | 
|---|
| 138 |    { | 
|---|
| 139 |       Real* bj = B+i; ai -= nrows; Real* ajx = ai+i; | 
|---|
| 140 |       Real sum = *bj; Real diag = *ajx; | 
|---|
| 141 |       j = nrows - i; while(--j) sum -= *(++ajx) * *(++bj); | 
|---|
| 142 |       B[i] = sum / diag; | 
|---|
| 143 |    } | 
|---|
| 144 | } | 
|---|
| 145 |  | 
|---|
| 146 | /****************************** scalar functions ****************************/ | 
|---|
| 147 |  | 
|---|
| 148 | inline Real square(Real x) { return x*x; } | 
|---|
| 149 |  | 
|---|
| 150 | Real GeneralMatrix::SumSquare() const | 
|---|
| 151 | { | 
|---|
| 152 |    REPORT | 
|---|
| 153 |    Real sum = 0.0; int i = storage; Real* s = store; | 
|---|
| 154 |    while (i--) sum += square(*s++); | 
|---|
| 155 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 156 | } | 
|---|
| 157 |  | 
|---|
| 158 | Real GeneralMatrix::SumAbsoluteValue() const | 
|---|
| 159 | { | 
|---|
| 160 |    REPORT | 
|---|
| 161 |    Real sum = 0.0; int i = storage; Real* s = store; | 
|---|
| 162 |    while (i--) sum += fabs(*s++); | 
|---|
| 163 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 164 | } | 
|---|
| 165 |  | 
|---|
| 166 | Real GeneralMatrix::Sum() const | 
|---|
| 167 | { | 
|---|
| 168 |    REPORT | 
|---|
| 169 |    Real sum = 0.0; int i = storage; Real* s = store; | 
|---|
| 170 |    while (i--) sum += *s++; | 
|---|
| 171 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 172 | } | 
|---|
| 173 |  | 
|---|
| 174 | // maxima and minima | 
|---|
| 175 |  | 
|---|
| 176 | // There are three sets of routines | 
|---|
| 177 | // MaximumAbsoluteValue, MinimumAbsoluteValue, Maximum, Minimum | 
|---|
| 178 | // ... these find just the maxima and minima | 
|---|
| 179 | // MaximumAbsoluteValue1, MinimumAbsoluteValue1, Maximum1, Minimum1 | 
|---|
| 180 | // ... these find the maxima and minima and their locations in a | 
|---|
| 181 | //     one dimensional object | 
|---|
| 182 | // MaximumAbsoluteValue2, MinimumAbsoluteValue2, Maximum2, Minimum2 | 
|---|
| 183 | // ... these find the maxima and minima and their locations in a | 
|---|
| 184 | //     two dimensional object | 
|---|
| 185 |  | 
|---|
| 186 | // If the matrix has no values throw an exception | 
|---|
| 187 |  | 
|---|
| 188 | // If we do not want the location find the maximum or minimum on the | 
|---|
| 189 | // array stored by GeneralMatrix | 
|---|
| 190 | // This won't work for BandMatrices. We call ClearCorner for | 
|---|
| 191 | // MaximumAbsoluteValue but for the others use the AbsoluteMinimumValue2 | 
|---|
| 192 | // version and discard the location. | 
|---|
| 193 |  | 
|---|
| 194 | // For one dimensional objects, when we want the location of the | 
|---|
| 195 | // maximum or minimum, work with the array stored by GeneralMatrix | 
|---|
| 196 |  | 
|---|
| 197 | // For two dimensional objects where we want the location of the maximum or | 
|---|
| 198 | // minimum proceed as follows: | 
|---|
| 199 |  | 
|---|
| 200 | // For rectangular matrices use the array stored by GeneralMatrix and | 
|---|
| 201 | // deduce the location from the location in the GeneralMatrix | 
|---|
| 202 |  | 
|---|
| 203 | // For other two dimensional matrices use the Matrix Row routine to find the | 
|---|
| 204 | // maximum or minimum for each row. | 
|---|
| 205 |  | 
|---|
| 206 | static void NullMatrixError(const GeneralMatrix* gm) | 
|---|
| 207 | { | 
|---|
| 208 |    ((GeneralMatrix&)*gm).tDelete(); | 
|---|
| 209 |    Throw(ProgramException("Maximum or minimum of null matrix")); | 
|---|
| 210 | } | 
|---|
| 211 |  | 
|---|
| 212 | Real GeneralMatrix::MaximumAbsoluteValue() const | 
|---|
| 213 | { | 
|---|
| 214 |    REPORT | 
|---|
| 215 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 216 |    Real maxval = 0.0; int l = storage; Real* s = store; | 
|---|
| 217 |    while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; } | 
|---|
| 218 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 219 | } | 
|---|
| 220 |  | 
|---|
| 221 | Real GeneralMatrix::MaximumAbsoluteValue1(int& i) const | 
|---|
| 222 | { | 
|---|
| 223 |    REPORT | 
|---|
| 224 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 225 |    Real maxval = 0.0; int l = storage; Real* s = store; int li = storage; | 
|---|
| 226 |    while (l--) | 
|---|
| 227 |       { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; }  } | 
|---|
| 228 |    i = storage - li; | 
|---|
| 229 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | Real GeneralMatrix::MinimumAbsoluteValue() const | 
|---|
| 233 | { | 
|---|
| 234 |    REPORT | 
|---|
| 235 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 236 |    int l = storage - 1; Real* s = store; Real minval = fabs(*s++); | 
|---|
| 237 |    while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; } | 
|---|
| 238 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 239 | } | 
|---|
| 240 |  | 
|---|
| 241 | Real GeneralMatrix::MinimumAbsoluteValue1(int& i) const | 
|---|
| 242 | { | 
|---|
| 243 |    REPORT | 
|---|
| 244 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 245 |    int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l; | 
|---|
| 246 |    while (l--) | 
|---|
| 247 |       { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; }  } | 
|---|
| 248 |    i = storage - li; | 
|---|
| 249 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 250 | } | 
|---|
| 251 |  | 
|---|
| 252 | Real GeneralMatrix::Maximum() const | 
|---|
| 253 | { | 
|---|
| 254 |    REPORT | 
|---|
| 255 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 256 |    int l = storage - 1; Real* s = store; Real maxval = *s++; | 
|---|
| 257 |    while (l--) { Real a = *s++; if (maxval < a) maxval = a; } | 
|---|
| 258 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | Real GeneralMatrix::Maximum1(int& i) const | 
|---|
| 262 | { | 
|---|
| 263 |    REPORT | 
|---|
| 264 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 265 |    int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l; | 
|---|
| 266 |    while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } } | 
|---|
| 267 |    i = storage - li; | 
|---|
| 268 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 269 | } | 
|---|
| 270 |  | 
|---|
| 271 | Real GeneralMatrix::Minimum() const | 
|---|
| 272 | { | 
|---|
| 273 |    REPORT | 
|---|
| 274 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 275 |    int l = storage - 1; Real* s = store; Real minval = *s++; | 
|---|
| 276 |    while (l--) { Real a = *s++; if (minval > a) minval = a; } | 
|---|
| 277 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 278 | } | 
|---|
| 279 |  | 
|---|
| 280 | Real GeneralMatrix::Minimum1(int& i) const | 
|---|
| 281 | { | 
|---|
| 282 |    REPORT | 
|---|
| 283 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 284 |    int l = storage - 1; Real* s = store; Real minval = *s++; int li = l; | 
|---|
| 285 |    while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } } | 
|---|
| 286 |    i = storage - li; | 
|---|
| 287 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 288 | } | 
|---|
| 289 |  | 
|---|
| 290 | Real GeneralMatrix::MaximumAbsoluteValue2(int& i, int& j) const | 
|---|
| 291 | { | 
|---|
| 292 |    REPORT | 
|---|
| 293 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 294 |    Real maxval = 0.0; int nr = Nrows(); | 
|---|
| 295 |    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); | 
|---|
| 296 |    for (int r = 1; r <= nr; r++) | 
|---|
| 297 |    { | 
|---|
| 298 |       int c; maxval = mr.MaximumAbsoluteValue1(maxval, c); | 
|---|
| 299 |       if (c > 0) { i = r; j = c; } | 
|---|
| 300 |       mr.Next(); | 
|---|
| 301 |    } | 
|---|
| 302 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 303 | } | 
|---|
| 304 |  | 
|---|
| 305 | Real GeneralMatrix::MinimumAbsoluteValue2(int& i, int& j) const | 
|---|
| 306 | { | 
|---|
| 307 |    REPORT | 
|---|
| 308 |    if (storage == 0)  NullMatrixError(this); | 
|---|
| 309 |    Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); | 
|---|
| 310 |    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); | 
|---|
| 311 |    for (int r = 1; r <= nr; r++) | 
|---|
| 312 |    { | 
|---|
| 313 |       int c; minval = mr.MinimumAbsoluteValue1(minval, c); | 
|---|
| 314 |       if (c > 0) { i = r; j = c; } | 
|---|
| 315 |       mr.Next(); | 
|---|
| 316 |    } | 
|---|
| 317 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 318 | } | 
|---|
| 319 |  | 
|---|
| 320 | Real GeneralMatrix::Maximum2(int& i, int& j) const | 
|---|
| 321 | { | 
|---|
| 322 |    REPORT | 
|---|
| 323 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 324 |    Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows(); | 
|---|
| 325 |    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); | 
|---|
| 326 |    for (int r = 1; r <= nr; r++) | 
|---|
| 327 |    { | 
|---|
| 328 |       int c; maxval = mr.Maximum1(maxval, c); | 
|---|
| 329 |       if (c > 0) { i = r; j = c; } | 
|---|
| 330 |       mr.Next(); | 
|---|
| 331 |    } | 
|---|
| 332 |    ((GeneralMatrix&)*this).tDelete(); return maxval; | 
|---|
| 333 | } | 
|---|
| 334 |  | 
|---|
| 335 | Real GeneralMatrix::Minimum2(int& i, int& j) const | 
|---|
| 336 | { | 
|---|
| 337 |    REPORT | 
|---|
| 338 |    if (storage == 0) NullMatrixError(this); | 
|---|
| 339 |    Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows(); | 
|---|
| 340 |    MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart); | 
|---|
| 341 |    for (int r = 1; r <= nr; r++) | 
|---|
| 342 |    { | 
|---|
| 343 |       int c; minval = mr.Minimum1(minval, c); | 
|---|
| 344 |       if (c > 0) { i = r; j = c; } | 
|---|
| 345 |       mr.Next(); | 
|---|
| 346 |    } | 
|---|
| 347 |    ((GeneralMatrix&)*this).tDelete(); return minval; | 
|---|
| 348 | } | 
|---|
| 349 |  | 
|---|
| 350 | Real Matrix::MaximumAbsoluteValue2(int& i, int& j) const | 
|---|
| 351 | { | 
|---|
| 352 |    REPORT | 
|---|
| 353 |    int k; Real m = GeneralMatrix::MaximumAbsoluteValue1(k); k--; | 
|---|
| 354 |    i = k / Ncols(); j = k - i * Ncols(); i++; j++; | 
|---|
| 355 |    return m; | 
|---|
| 356 | } | 
|---|
| 357 |  | 
|---|
| 358 | Real Matrix::MinimumAbsoluteValue2(int& i, int& j) const | 
|---|
| 359 | { | 
|---|
| 360 |    REPORT | 
|---|
| 361 |    int k; Real m = GeneralMatrix::MinimumAbsoluteValue1(k); k--; | 
|---|
| 362 |    i = k / Ncols(); j = k - i * Ncols(); i++; j++; | 
|---|
| 363 |    return m; | 
|---|
| 364 | } | 
|---|
| 365 |  | 
|---|
| 366 | Real Matrix::Maximum2(int& i, int& j) const | 
|---|
| 367 | { | 
|---|
| 368 |    REPORT | 
|---|
| 369 |    int k; Real m = GeneralMatrix::Maximum1(k); k--; | 
|---|
| 370 |    i = k / Ncols(); j = k - i * Ncols(); i++; j++; | 
|---|
| 371 |    return m; | 
|---|
| 372 | } | 
|---|
| 373 |  | 
|---|
| 374 | Real Matrix::Minimum2(int& i, int& j) const | 
|---|
| 375 | { | 
|---|
| 376 |    REPORT | 
|---|
| 377 |    int k; Real m = GeneralMatrix::Minimum1(k); k--; | 
|---|
| 378 |    i = k / Ncols(); j = k - i * Ncols(); i++; j++; | 
|---|
| 379 |    return m; | 
|---|
| 380 | } | 
|---|
| 381 |  | 
|---|
| 382 | Real SymmetricMatrix::SumSquare() const | 
|---|
| 383 | { | 
|---|
| 384 |    REPORT | 
|---|
| 385 |    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; | 
|---|
| 386 |    for (int i = 0; i<nr; i++) | 
|---|
| 387 |    { | 
|---|
| 388 |       int j = i; | 
|---|
| 389 |       while (j--) sum2 += square(*s++); | 
|---|
| 390 |       sum1 += square(*s++); | 
|---|
| 391 |    } | 
|---|
| 392 |    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; | 
|---|
| 393 | } | 
|---|
| 394 |  | 
|---|
| 395 | Real SymmetricMatrix::SumAbsoluteValue() const | 
|---|
| 396 | { | 
|---|
| 397 |    REPORT | 
|---|
| 398 |    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; | 
|---|
| 399 |    for (int i = 0; i<nr; i++) | 
|---|
| 400 |    { | 
|---|
| 401 |       int j = i; | 
|---|
| 402 |       while (j--) sum2 += fabs(*s++); | 
|---|
| 403 |       sum1 += fabs(*s++); | 
|---|
| 404 |    } | 
|---|
| 405 |    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; | 
|---|
| 406 | } | 
|---|
| 407 |  | 
|---|
| 408 | Real IdentityMatrix::SumAbsoluteValue() const | 
|---|
| 409 |    { REPORT  return fabs(Trace()); }    // no need to do tDelete? | 
|---|
| 410 |  | 
|---|
| 411 | Real SymmetricMatrix::Sum() const | 
|---|
| 412 | { | 
|---|
| 413 |    REPORT | 
|---|
| 414 |    Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows; | 
|---|
| 415 |    for (int i = 0; i<nr; i++) | 
|---|
| 416 |    { | 
|---|
| 417 |       int j = i; | 
|---|
| 418 |       while (j--) sum2 += *s++; | 
|---|
| 419 |       sum1 += *s++; | 
|---|
| 420 |    } | 
|---|
| 421 |    ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2; | 
|---|
| 422 | } | 
|---|
| 423 |  | 
|---|
| 424 | Real IdentityMatrix::SumSquare() const | 
|---|
| 425 | { | 
|---|
| 426 |    Real sum = *store * *store * nrows; | 
|---|
| 427 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 428 | } | 
|---|
| 429 |  | 
|---|
| 430 |  | 
|---|
| 431 | Real BaseMatrix::SumSquare() const | 
|---|
| 432 | { | 
|---|
| 433 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 434 |    Real s = gm->SumSquare(); return s; | 
|---|
| 435 | } | 
|---|
| 436 |  | 
|---|
| 437 | Real BaseMatrix::NormFrobenius() const | 
|---|
| 438 |    { REPORT  return sqrt(SumSquare()); } | 
|---|
| 439 |  | 
|---|
| 440 | Real BaseMatrix::SumAbsoluteValue() const | 
|---|
| 441 | { | 
|---|
| 442 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 443 |    Real s = gm->SumAbsoluteValue(); return s; | 
|---|
| 444 | } | 
|---|
| 445 |  | 
|---|
| 446 | Real BaseMatrix::Sum() const | 
|---|
| 447 | { | 
|---|
| 448 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 449 |    Real s = gm->Sum(); return s; | 
|---|
| 450 | } | 
|---|
| 451 |  | 
|---|
| 452 | Real BaseMatrix::MaximumAbsoluteValue() const | 
|---|
| 453 | { | 
|---|
| 454 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 455 |    Real s = gm->MaximumAbsoluteValue(); return s; | 
|---|
| 456 | } | 
|---|
| 457 |  | 
|---|
| 458 | Real BaseMatrix::MaximumAbsoluteValue1(int& i) const | 
|---|
| 459 | { | 
|---|
| 460 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 461 |    Real s = gm->MaximumAbsoluteValue1(i); return s; | 
|---|
| 462 | } | 
|---|
| 463 |  | 
|---|
| 464 | Real BaseMatrix::MaximumAbsoluteValue2(int& i, int& j) const | 
|---|
| 465 | { | 
|---|
| 466 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 467 |    Real s = gm->MaximumAbsoluteValue2(i, j); return s; | 
|---|
| 468 | } | 
|---|
| 469 |  | 
|---|
| 470 | Real BaseMatrix::MinimumAbsoluteValue() const | 
|---|
| 471 | { | 
|---|
| 472 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 473 |    Real s = gm->MinimumAbsoluteValue(); return s; | 
|---|
| 474 | } | 
|---|
| 475 |  | 
|---|
| 476 | Real BaseMatrix::MinimumAbsoluteValue1(int& i) const | 
|---|
| 477 | { | 
|---|
| 478 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 479 |    Real s = gm->MinimumAbsoluteValue1(i); return s; | 
|---|
| 480 | } | 
|---|
| 481 |  | 
|---|
| 482 | Real BaseMatrix::MinimumAbsoluteValue2(int& i, int& j) const | 
|---|
| 483 | { | 
|---|
| 484 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 485 |    Real s = gm->MinimumAbsoluteValue2(i, j); return s; | 
|---|
| 486 | } | 
|---|
| 487 |  | 
|---|
| 488 | Real BaseMatrix::Maximum() const | 
|---|
| 489 | { | 
|---|
| 490 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 491 |    Real s = gm->Maximum(); return s; | 
|---|
| 492 | } | 
|---|
| 493 |  | 
|---|
| 494 | Real BaseMatrix::Maximum1(int& i) const | 
|---|
| 495 | { | 
|---|
| 496 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 497 |    Real s = gm->Maximum1(i); return s; | 
|---|
| 498 | } | 
|---|
| 499 |  | 
|---|
| 500 | Real BaseMatrix::Maximum2(int& i, int& j) const | 
|---|
| 501 | { | 
|---|
| 502 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 503 |    Real s = gm->Maximum2(i, j); return s; | 
|---|
| 504 | } | 
|---|
| 505 |  | 
|---|
| 506 | Real BaseMatrix::Minimum() const | 
|---|
| 507 | { | 
|---|
| 508 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 509 |    Real s = gm->Minimum(); return s; | 
|---|
| 510 | } | 
|---|
| 511 |  | 
|---|
| 512 | Real BaseMatrix::Minimum1(int& i) const | 
|---|
| 513 | { | 
|---|
| 514 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 515 |    Real s = gm->Minimum1(i); return s; | 
|---|
| 516 | } | 
|---|
| 517 |  | 
|---|
| 518 | Real BaseMatrix::Minimum2(int& i, int& j) const | 
|---|
| 519 | { | 
|---|
| 520 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 521 |    Real s = gm->Minimum2(i, j); return s; | 
|---|
| 522 | } | 
|---|
| 523 |  | 
|---|
| 524 | Real DotProduct(const Matrix& A, const Matrix& B) | 
|---|
| 525 | { | 
|---|
| 526 |    REPORT | 
|---|
| 527 |    int n = A.storage; | 
|---|
| 528 |    if (n != B.storage) Throw(IncompatibleDimensionsException(A,B)); | 
|---|
| 529 |    Real sum = 0.0; Real* a = A.store; Real* b = B.store; | 
|---|
| 530 |    while (n--) sum += *a++ * *b++; | 
|---|
| 531 |    return sum; | 
|---|
| 532 | } | 
|---|
| 533 |  | 
|---|
| 534 | Real Matrix::Trace() const | 
|---|
| 535 | { | 
|---|
| 536 |    REPORT | 
|---|
| 537 |    Tracer trace("Trace"); | 
|---|
| 538 |    int i = nrows; int d = i+1; | 
|---|
| 539 |    if (i != ncols) Throw(NotSquareException(*this)); | 
|---|
| 540 |    Real sum = 0.0; Real* s = store; | 
|---|
| 541 | //   while (i--) { sum += *s; s += d; } | 
|---|
| 542 |    if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; } | 
|---|
| 543 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 544 | } | 
|---|
| 545 |  | 
|---|
| 546 | Real DiagonalMatrix::Trace() const | 
|---|
| 547 | { | 
|---|
| 548 |    REPORT | 
|---|
| 549 |    int i = nrows; Real sum = 0.0; Real* s = store; | 
|---|
| 550 |    while (i--) sum += *s++; | 
|---|
| 551 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 552 | } | 
|---|
| 553 |  | 
|---|
| 554 | Real SymmetricMatrix::Trace() const | 
|---|
| 555 | { | 
|---|
| 556 |    REPORT | 
|---|
| 557 |    int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; | 
|---|
| 558 |    // while (i--) { sum += *s; s += j++; } | 
|---|
| 559 |    if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } | 
|---|
| 560 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 561 | } | 
|---|
| 562 |  | 
|---|
| 563 | Real LowerTriangularMatrix::Trace() const | 
|---|
| 564 | { | 
|---|
| 565 |    REPORT | 
|---|
| 566 |    int i = nrows; Real sum = 0.0; Real* s = store; int j = 2; | 
|---|
| 567 |    // while (i--) { sum += *s; s += j++; } | 
|---|
| 568 |    if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; } | 
|---|
| 569 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 570 | } | 
|---|
| 571 |  | 
|---|
| 572 | Real UpperTriangularMatrix::Trace() const | 
|---|
| 573 | { | 
|---|
| 574 |    REPORT | 
|---|
| 575 |    int i = nrows; Real sum = 0.0; Real* s = store; | 
|---|
| 576 |    while (i) { sum += *s; s += i--; }             // won t cause a problem | 
|---|
| 577 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 578 | } | 
|---|
| 579 |  | 
|---|
| 580 | Real BandMatrix::Trace() const | 
|---|
| 581 | { | 
|---|
| 582 |    REPORT | 
|---|
| 583 |    int i = nrows; int w = lower+upper+1; | 
|---|
| 584 |    Real sum = 0.0; Real* s = store+lower; | 
|---|
| 585 |    // while (i--) { sum += *s; s += w; } | 
|---|
| 586 |    if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } | 
|---|
| 587 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 588 | } | 
|---|
| 589 |  | 
|---|
| 590 | Real SymmetricBandMatrix::Trace() const | 
|---|
| 591 | { | 
|---|
| 592 |    REPORT | 
|---|
| 593 |    int i = nrows; int w = lower+1; | 
|---|
| 594 |    Real sum = 0.0; Real* s = store+lower; | 
|---|
| 595 |    // while (i--) { sum += *s; s += w; } | 
|---|
| 596 |    if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; } | 
|---|
| 597 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 598 | } | 
|---|
| 599 |  | 
|---|
| 600 | Real IdentityMatrix::Trace() const | 
|---|
| 601 | { | 
|---|
| 602 |    Real sum = *store * nrows; | 
|---|
| 603 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 604 | } | 
|---|
| 605 |  | 
|---|
| 606 |  | 
|---|
| 607 | Real BaseMatrix::Trace() const | 
|---|
| 608 | { | 
|---|
| 609 |    REPORT | 
|---|
| 610 |    MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK(); | 
|---|
| 611 |    GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag); | 
|---|
| 612 |    Real sum = gm->Trace(); return sum; | 
|---|
| 613 | } | 
|---|
| 614 |  | 
|---|
| 615 | void LogAndSign::operator*=(Real x) | 
|---|
| 616 | { | 
|---|
| 617 |    if (x > 0.0) { log_value += log(x); } | 
|---|
| 618 |    else if (x < 0.0) { log_value += log(-x); sign = -sign; } | 
|---|
| 619 |    else sign = 0; | 
|---|
| 620 | } | 
|---|
| 621 |  | 
|---|
| 622 | void LogAndSign::PowEq(int k) | 
|---|
| 623 | { | 
|---|
| 624 |    if (sign) | 
|---|
| 625 |    { | 
|---|
| 626 |       log_value *= k; | 
|---|
| 627 |       if ( (k & 1) == 0 ) sign = 1; | 
|---|
| 628 |    } | 
|---|
| 629 | } | 
|---|
| 630 |  | 
|---|
| 631 | Real LogAndSign::Value() const | 
|---|
| 632 | { | 
|---|
| 633 |    Tracer et("LogAndSign::Value"); | 
|---|
| 634 |    if (log_value >= FloatingPointPrecision::LnMaximum()) | 
|---|
| 635 |       Throw(OverflowException("Overflow in exponential")); | 
|---|
| 636 |    return sign * exp(log_value); | 
|---|
| 637 | } | 
|---|
| 638 |  | 
|---|
| 639 | LogAndSign::LogAndSign(Real f) | 
|---|
| 640 | { | 
|---|
| 641 |    if (f == 0.0) { log_value = 0.0; sign = 0; return; } | 
|---|
| 642 |    else if (f < 0.0) { sign = -1; f = -f; } | 
|---|
| 643 |    else sign = 1; | 
|---|
| 644 |    log_value = log(f); | 
|---|
| 645 | } | 
|---|
| 646 |  | 
|---|
| 647 | LogAndSign DiagonalMatrix::LogDeterminant() const | 
|---|
| 648 | { | 
|---|
| 649 |    REPORT | 
|---|
| 650 |    int i = nrows; LogAndSign sum; Real* s = store; | 
|---|
| 651 |    while (i--) sum *= *s++; | 
|---|
| 652 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 653 | } | 
|---|
| 654 |  | 
|---|
| 655 | LogAndSign LowerTriangularMatrix::LogDeterminant() const | 
|---|
| 656 | { | 
|---|
| 657 |    REPORT | 
|---|
| 658 |    int i = nrows; LogAndSign sum; Real* s = store; int j = 2; | 
|---|
| 659 |    // while (i--) { sum *= *s; s += j++; } | 
|---|
| 660 |    if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; } | 
|---|
| 661 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 662 | } | 
|---|
| 663 |  | 
|---|
| 664 | LogAndSign UpperTriangularMatrix::LogDeterminant() const | 
|---|
| 665 | { | 
|---|
| 666 |    REPORT | 
|---|
| 667 |    int i = nrows; LogAndSign sum; Real* s = store; | 
|---|
| 668 |    while (i) { sum *= *s; s += i--; } | 
|---|
| 669 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 670 | } | 
|---|
| 671 |  | 
|---|
| 672 | LogAndSign IdentityMatrix::LogDeterminant() const | 
|---|
| 673 | { | 
|---|
| 674 |    REPORT | 
|---|
| 675 |    int i = nrows; LogAndSign sum; | 
|---|
| 676 |    if (i > 0) { sum = *store; sum.PowEq(i); } | 
|---|
| 677 |    ((GeneralMatrix&)*this).tDelete(); return sum; | 
|---|
| 678 | } | 
|---|
| 679 |  | 
|---|
| 680 | LogAndSign BaseMatrix::LogDeterminant() const | 
|---|
| 681 | { | 
|---|
| 682 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 683 |    LogAndSign sum = gm->LogDeterminant(); return sum; | 
|---|
| 684 | } | 
|---|
| 685 |  | 
|---|
| 686 | LogAndSign GeneralMatrix::LogDeterminant() const | 
|---|
| 687 | { | 
|---|
| 688 |    REPORT | 
|---|
| 689 |    Tracer tr("LogDeterminant"); | 
|---|
| 690 |    if (nrows != ncols) Throw(NotSquareException(*this)); | 
|---|
| 691 |    CroutMatrix C(*this); return C.LogDeterminant(); | 
|---|
| 692 | } | 
|---|
| 693 |  | 
|---|
| 694 | LogAndSign CroutMatrix::LogDeterminant() const | 
|---|
| 695 | { | 
|---|
| 696 |    REPORT | 
|---|
| 697 |    if (sing) return 0.0; | 
|---|
| 698 |    int i = nrows; int dd = i+1; LogAndSign sum; Real* s = store; | 
|---|
| 699 |    if (i) for(;;) | 
|---|
| 700 |    { | 
|---|
| 701 |       sum *= *s; | 
|---|
| 702 |       if (!(--i)) break; | 
|---|
| 703 |       s += dd; | 
|---|
| 704 |    } | 
|---|
| 705 |    if (!d) sum.ChangeSign(); return sum; | 
|---|
| 706 |  | 
|---|
| 707 | } | 
|---|
| 708 |  | 
|---|
| 709 | Real BaseMatrix::Determinant() const | 
|---|
| 710 | { | 
|---|
| 711 |    REPORT | 
|---|
| 712 |    Tracer tr("Determinant"); | 
|---|
| 713 |    REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(); | 
|---|
| 714 |    LogAndSign ld = gm->LogDeterminant(); | 
|---|
| 715 |    return ld.Value(); | 
|---|
| 716 | } | 
|---|
| 717 |  | 
|---|
| 718 |  | 
|---|
| 719 |  | 
|---|
| 720 |  | 
|---|
| 721 |  | 
|---|
| 722 | LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm) | 
|---|
| 723 | : gm( ( ((BaseMatrix&)bm).Evaluate() )->MakeSolver() ) | 
|---|
| 724 | { | 
|---|
| 725 |    if (gm==&bm) { REPORT  gm = gm->Image(); } | 
|---|
| 726 |    // want a copy if  *gm is actually bm | 
|---|
| 727 |    else { REPORT  gm->Protect(); } | 
|---|
| 728 | } | 
|---|
| 729 |  | 
|---|
| 730 |  | 
|---|
| 731 | #ifdef use_namespace | 
|---|
| 732 | } | 
|---|
| 733 | #endif | 
|---|
| 734 |  | 
|---|