00001
00002 #include <math.h>
00003 #include <assert.h>
00004 #include "LA_Lu_decomp.h"
00005 #include "LA_Vector.h"
00006 #include "LA_Exception.h"
00007
00008 namespace LA
00009 {
00010
00011 LU::LU(const Matrix& M)
00012 : LU_(M), m(M.rows()), n(M.columns()), piv(M.rows())
00013 {
00014
00015 int i = 0;
00016 int j = 0;
00017 int k = 0;
00018
00019 for (i = 0; i < m; i++)
00020 {
00021 piv[i] = i;
00022 }
00023 pivsign = 1;
00024 Vector LUcolj(m);
00025
00026
00027 for (j = 0; j < n; j++)
00028 {
00029
00030 for (i = 0; i < m; i++)
00031 {
00032 LUcolj[i] = LU_[i][j];
00033 }
00034
00035
00036 for (i = 0; i < m; i++)
00037 {
00038 Vector& LUrowi = LU_[i];
00039
00040
00041 int kmax = (i < j)? i: j;
00042 double s = 0.0;
00043 for (k = 0; k < kmax; k++)
00044 {
00045 s += LUrowi[k]*LUcolj[k];
00046 }
00047
00048 LUrowi[j] = LUcolj[i] -= s;
00049 }
00050
00051
00052 int p = j;
00053 for (i = j+1; i < m; i++)
00054 {
00055 if (fabs(LUcolj[i]) > fabs(LUcolj[p]))
00056 {
00057 p = i;
00058 }
00059 }
00060 if (p != j)
00061 {
00062 for (k = 0; k < n; k++)
00063 {
00064 double t = LU_[p][k];
00065 LU_[p][k] = LU_[j][k];
00066 LU_[j][k] = t;
00067 }
00068 k = piv[p];
00069 piv[p] = piv[j];
00070 piv[j] = k;
00071 pivsign = -pivsign;
00072 }
00073
00074
00075 if ((j < m) && (LU_[j][j] != 0.0))
00076 {
00077 for (i = j+1; i < m; i++)
00078 {
00079 LU_[i][j] /= LU_[j][j];
00080 }
00081 }
00082 }
00083 }
00084
00085 bool LU::singular() const
00086 {
00087 for (int j = 0; j < n; j++)
00088 {
00089 if (LU_[j][j] == 0.0)
00090 return true;
00091 }
00092 return false;
00093 }
00094
00095 double LU::det() const
00096 {
00097 assert(m == n);
00098 double d = (double)pivsign;
00099 for (int j = 0; j < n; j++)
00100 {
00101 d *= LU_[j][j];
00102 }
00103 return d;
00104 }
00105
00106 Vector LU::solve(const Vector& b) const
00107 {
00108 assert(b.dim() == m);
00109 if (singular())
00110 throw Exception(Exception::SingularMatrix);
00111
00112 Vector x = permute_copy(b, piv);
00113 int i, k;
00114
00115 for (k = 0; k < (int)n; k++)
00116 {
00117 for (i = k+1; i < (int)n; i++)
00118 {
00119 x[i] -= x[k]*LU_[i][k];
00120 }
00121 }
00122
00123 for (k = (int)n-1; k >= 0; k--)
00124 {
00125 x[k] /= LU_[k][k];
00126 for (int i = 0; i < k; i++)
00127 x[i] -= x[k]*LU_[i][k];
00128 }
00129 return x;
00130 }
00131
00132 Matrix LU::inverse() const
00133 {
00134 assert(m == n);
00135
00136 Matrix M(n, n);
00137 for (int i = 0; i < n; ++i)
00138 {
00139 Vector b(n);
00140 b[i] = 1.0;
00141 M.set_column(i + 1, solve(b));
00142 }
00143 return M;
00144 }
00145
00146 Vector LU::permute_copy(const Vector& A, const std::vector<int>& piv) const
00147 {
00148 int piv_length = (int)piv.size();
00149 assert(piv_length == A.dim());
00150
00151 Vector x(piv_length);
00152 for (int i = 0; i < piv_length; i++)
00153 x[i] = A[piv[i]];
00154
00155 return x;
00156 }
00157
00158 }
00159