00001
00005 #include <cmath>
00006 #include "utility.h"
00007
00008 typedef std::vector<REAL> RVEC;
00009 typedef std::vector<RVEC> RMAT;
00010
00011
00012 bool Cholesky_decomp (RMAT& A, RVEC& p) {
00013 const UINT n = A.size();
00014 assert(p.size() == n);
00015 for (UINT i = 0; i < n; ++i) {
00016 for (UINT j = i; j < n; ++j) {
00017 REAL sum = A[i][j];
00018 for (UINT k = 0; k < i; ++k)
00019 sum -= A[i][k] * A[j][k];
00020 if (i == j) {
00021 if (sum <= 0)
00022 return false;
00023 p[i] = std::sqrt(sum);
00024 } else
00025 A[j][i] = sum / p[i];
00026 }
00027 }
00028 return true;
00029 }
00030
00031
00032 void Cholesky_linsol (const RMAT& A, const RVEC& p, const RVEC& b, RVEC& x) {
00033 const UINT n = A.size();
00034 assert(p.size() == n && b.size() == n);
00035 x.resize(n);
00036
00037 for (UINT i = 0; i < n; ++i) {
00038 REAL sum = b[i];
00039 for (UINT k = 0; k < i; ++k)
00040 sum -= A[i][k] * x[k];
00041 x[i] = sum / p[i];
00042 }
00043 for (UINT i = n; i--;) {
00044 REAL sum = x[i];
00045 for (UINT k = i+1; k < n; ++k)
00046 sum -= A[k][i] * x[k];
00047 x[i] = sum / p[i];
00048 }
00049 }
00050
00051 bool ldivide (RMAT& A, const RVEC& b, RVEC& x) {
00052 const UINT n = A.size();
00053 assert(b.size() == n);
00054 RVEC p(n);
00055 if (!Cholesky_decomp(A, p)) return false;
00056 Cholesky_linsol(A, p, b, x);
00057 return true;
00058 }