00001 #ifndef JAMA_LU_H
00002 #define JAMA_LU_H
00003
00004 #include "tnt.h"
00005 #include <algorithm>
00006
00007
00008 using namespace TNT;
00009 using namespace std;
00010
00011 namespace JAMA
00012 {
00013
00026 template <class Real>
00027 class LU
00028 {
00029
00030
00031
00032
00033 Array2D<Real> LU_;
00034 int m, n, pivsign;
00035 Array1D<int> piv;
00036
00037
00038 Array2D<Real> permute_copy(const Array2D<Real> &A,
00039 const Array1D<int> &piv, int j0, int j1)
00040 {
00041 int piv_length = piv.dim();
00042
00043 Array2D<Real> X(piv_length, j1-j0+1);
00044
00045
00046 for (int i = 0; i < piv_length; i++)
00047 for (int j = j0; j <= j1; j++)
00048 X[i][j-j0] = A[piv[i]][j];
00049
00050 return X;
00051 }
00052
00053 Array1D<Real> permute_copy(const Array1D<Real> &A,
00054 const Array1D<int> &piv)
00055 {
00056 int piv_length = piv.dim();
00057 if (piv_length != A.dim())
00058 return Array1D<Real>();
00059
00060 Array1D<Real> x(piv_length);
00061
00062
00063 for (int i = 0; i < piv_length; i++)
00064 x[i] = A[piv[i]];
00065
00066 return x;
00067 }
00068
00069
00070 public :
00071
00077 LU (const Array2D<Real> &A) : LU_(A.copy()), m(A.dim1()), n(A.dim2()),
00078 piv(A.dim1())
00079
00080 {
00081
00082
00083
00084
00085 for (int i = 0; i < m; i++) {
00086 piv[i] = i;
00087 }
00088 pivsign = 1;
00089 Real *LUrowi = 0;;
00090 Array1D<Real> LUcolj(m);
00091
00092
00093
00094 for (int j = 0; j < n; j++) {
00095
00096
00097
00098 for (int i = 0; i < m; i++) {
00099 LUcolj[i] = LU_[i][j];
00100 }
00101
00102
00103
00104 for (int i = 0; i < m; i++) {
00105 LUrowi = LU_[i];
00106
00107
00108
00109 int kmax = min(i,j);
00110 double s = 0.0;
00111 for (int k = 0; k < kmax; k++) {
00112 s += LUrowi[k]*LUcolj[k];
00113 }
00114
00115 LUrowi[j] = LUcolj[i] -= s;
00116 }
00117
00118
00119
00120 int p = j;
00121 for (int i = j+1; i < m; i++) {
00122 if (abs(LUcolj[i]) > abs(LUcolj[p])) {
00123 p = i;
00124 }
00125 }
00126 if (p != j) {
00127 int k=0;
00128 for (k = 0; k < n; k++) {
00129 double t = LU_[p][k];
00130 LU_[p][k] = LU_[j][k];
00131 LU_[j][k] = t;
00132 }
00133 k = piv[p];
00134 piv[p] = piv[j];
00135 piv[j] = k;
00136 pivsign = -pivsign;
00137 }
00138
00139
00140
00141 if ((j < m) && (LU_[j][j] != 0.0)) {
00142 for (int i = j+1; i < m; i++) {
00143 LU_[i][j] /= LU_[j][j];
00144 }
00145 }
00146 }
00147 }
00148
00149
00155 int isNonsingular () {
00156 for (int j = 0; j < n; j++) {
00157 if (LU_[j][j] == 0)
00158 return 0;
00159 }
00160 return 1;
00161 }
00162
00167 Array2D<Real> getL () {
00168 Array2D<Real> L_(m,n);
00169 for (int i = 0; i < m; i++) {
00170 for (int j = 0; j < n; j++) {
00171 if (i > j) {
00172 L_[i][j] = LU_[i][j];
00173 } else if (i == j) {
00174 L_[i][j] = 1.0;
00175 } else {
00176 L_[i][j] = 0.0;
00177 }
00178 }
00179 }
00180 return L_;
00181 }
00182
00187 Array2D<Real> getU () {
00188 Array2D<Real> U_(n,n);
00189 for (int i = 0; i < n; i++) {
00190 for (int j = 0; j < n; j++) {
00191 if (i <= j) {
00192 U_[i][j] = LU_[i][j];
00193 } else {
00194 U_[i][j] = 0.0;
00195 }
00196 }
00197 }
00198 return U_;
00199 }
00200
00205 Array1D<int> getPivot () {
00206 return piv;
00207 }
00208
00209
00214 Real det () {
00215 if (m != n) {
00216 return Real(0);
00217 }
00218 Real d = Real(pivsign);
00219 for (int j = 0; j < n; j++) {
00220 d *= LU_[j][j];
00221 }
00222 return d;
00223 }
00224
00231 Array2D<Real> solve (const Array2D<Real> &B)
00232 {
00233
00234
00235
00236 if (B.dim1() != m) {
00237 return Array2D<Real>(0,0);
00238 }
00239 if (!isNonsingular()) {
00240 return Array2D<Real>(0,0);
00241 }
00242
00243
00244 int nx = B.dim2();
00245
00246
00247 Array2D<Real> X = permute_copy(B, piv, 0, nx-1);
00248
00249
00250 for (int k = 0; k < n; k++) {
00251 for (int i = k+1; i < n; i++) {
00252 for (int j = 0; j < nx; j++) {
00253 X[i][j] -= X[k][j]*LU_[i][k];
00254 }
00255 }
00256 }
00257
00258 for (int k = n-1; k >= 0; k--) {
00259 for (int j = 0; j < nx; j++) {
00260 X[k][j] /= LU_[k][k];
00261 }
00262 for (int i = 0; i < k; i++) {
00263 for (int j = 0; j < nx; j++) {
00264 X[i][j] -= X[k][j]*LU_[i][k];
00265 }
00266 }
00267 }
00268 return X;
00269 }
00270
00271
00281 Array1D<Real> solve (const Array1D<Real> &b)
00282 {
00283
00284
00285
00286 if (b.dim1() != m) {
00287 return Array1D<Real>();
00288 }
00289 if (!isNonsingular()) {
00290 return Array1D<Real>();
00291 }
00292
00293
00294 Array1D<Real> x = permute_copy(b, piv);
00295
00296
00297 for (int k = 0; k < n; k++) {
00298 for (int i = k+1; i < n; i++) {
00299 x[i] -= x[k]*LU_[i][k];
00300 }
00301 }
00302
00303
00304 for (int k = n-1; k >= 0; k--) {
00305 x[k] /= LU_[k][k];
00306 for (int i = 0; i < k; i++)
00307 x[i] -= x[k]*LU_[i][k];
00308 }
00309
00310
00311 return x;
00312 }
00313
00314 };
00315
00316 }
00317
00318 #endif
00319