1 | //$$ cholesky.cpp cholesky decomposition |
---|
2 | |
---|
3 | // Copyright (C) 1991,2,3,4: R B Davies |
---|
4 | |
---|
5 | #define WANT_MATH |
---|
6 | //#define WANT_STREAM |
---|
7 | |
---|
8 | #include "include.h" |
---|
9 | |
---|
10 | #include "newmat.h" |
---|
11 | |
---|
12 | #ifdef use_namespace |
---|
13 | namespace NEWMAT { |
---|
14 | #endif |
---|
15 | |
---|
16 | #ifdef DO_REPORT |
---|
17 | #define REPORT { static ExeCounter ExeCount(__LINE__,14); ++ExeCount; } |
---|
18 | #else |
---|
19 | #define REPORT {} |
---|
20 | #endif |
---|
21 | |
---|
22 | /********* Cholesky decomposition of a positive definite matrix *************/ |
---|
23 | |
---|
24 | // Suppose S is symmetrix and positive definite. Then there exists a unique |
---|
25 | // lower triangular matrix L such that L L.t() = S; |
---|
26 | |
---|
27 | inline Real square(Real x) { return x*x; } |
---|
28 | |
---|
29 | ReturnMatrix Cholesky(const SymmetricMatrix& S) |
---|
30 | { |
---|
31 | REPORT |
---|
32 | Tracer trace("Cholesky"); |
---|
33 | int nr = S.Nrows(); |
---|
34 | LowerTriangularMatrix T(nr); |
---|
35 | Real* s = S.Store(); Real* t = T.Store(); Real* ti = t; |
---|
36 | for (int i=0; i<nr; i++) |
---|
37 | { |
---|
38 | Real* tj = t; Real sum; int k; |
---|
39 | for (int j=0; j<i; j++) |
---|
40 | { |
---|
41 | Real* tk = ti; sum = 0.0; k = j; |
---|
42 | while (k--) { sum += *tj++ * *tk++; } |
---|
43 | *tk = (*s++ - sum) / *tj++; |
---|
44 | } |
---|
45 | sum = 0.0; k = i; |
---|
46 | while (k--) { sum += square(*ti++); } |
---|
47 | Real d = *s++ - sum; |
---|
48 | if (d<=0.0) Throw(NPDException(S)); |
---|
49 | *ti++ = sqrt(d); |
---|
50 | } |
---|
51 | T.Release(); return T.ForReturn(); |
---|
52 | } |
---|
53 | |
---|
54 | ReturnMatrix Cholesky(const SymmetricBandMatrix& S) |
---|
55 | { |
---|
56 | REPORT |
---|
57 | Tracer trace("Band-Cholesky"); |
---|
58 | int nr = S.Nrows(); int m = S.lower; |
---|
59 | LowerBandMatrix T(nr,m); |
---|
60 | Real* s = S.Store(); Real* t = T.Store(); Real* ti = t; |
---|
61 | |
---|
62 | for (int i=0; i<nr; i++) |
---|
63 | { |
---|
64 | Real* tj = t; Real sum; int l; |
---|
65 | if (i<m) { REPORT l = m-i; s += l; ti += l; l = i; } |
---|
66 | else { REPORT t += (m+1); l = m; } |
---|
67 | |
---|
68 | for (int j=0; j<l; j++) |
---|
69 | { |
---|
70 | Real* tk = ti; sum = 0.0; int k = j; tj += (m-j); |
---|
71 | while (k--) { sum += *tj++ * *tk++; } |
---|
72 | *tk = (*s++ - sum) / *tj++; |
---|
73 | } |
---|
74 | sum = 0.0; |
---|
75 | while (l--) { sum += square(*ti++); } |
---|
76 | Real d = *s++ - sum; |
---|
77 | if (d<=0.0) Throw(NPDException(S)); |
---|
78 | *ti++ = sqrt(d); |
---|
79 | } |
---|
80 | |
---|
81 | T.Release(); return T.ForReturn(); |
---|
82 | } |
---|
83 | |
---|
84 | |
---|
85 | #ifdef use_namespace |
---|
86 | } |
---|
87 | #endif |
---|
88 | |
---|